diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md index a4dab0c4fff4..10178d7caeed 100644 --- a/ACKNOWLEDGEMENTS.md +++ b/ACKNOWLEDGEMENTS.md @@ -1,5 +1,5 @@ -Acknowlegements -=============== +Acknowledgements +================ Please see our [Thanks!][] page for the current acknowledgements. diff --git a/AUTHORS.md b/AUTHORS.md index dc6b534b82a5..5b036a0d8358 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,6 +12,7 @@ Groups * OpenSSL Software Services, Inc. * OpenSSL Software Foundation, Inc. + * Google LLC Individuals ----------- @@ -48,4 +49,5 @@ Individuals * Tim Hudson * Tomáš Mráz * Ulf Möller + * Valerii Krygin * Viktor Dukhovni diff --git a/CHANGES.md b/CHANGES.md index 5b0193bc3955..aaf3fea1ca5e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,22 @@ 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. +This is a detailed breakdown of significant changes. For a high-level overview +of changes in each release, see [NEWS.md](./NEWS.md). + +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.5](#openssl-35) + - [OpenSSL 3.4](#openssl-34) + - [OpenSSL 3.3](#openssl-33) + - [OpenSSL 3.2](#openssl-32) + - [OpenSSL 3.1](#openssl-31) - [OpenSSL 3.0](#openssl-30) - [OpenSSL 1.1.1](#openssl-111) - [OpenSSL 1.1.0](#openssl-110) @@ -18,17 +25,305 @@ OpenSSL Releases - [OpenSSL 1.0.0](#openssl-100) - [OpenSSL 0.9.x](#openssl-09x) -OpenSSL 3.0 +OpenSSL 3.5 ----------- -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. +### Changes between 3.4 and 3.5.0 [8 Apr 2025] -[Migration guide]: https://github.com/openssl/openssl/tree/master/doc/man7/migration_guide.pod + * Added server side support for QUIC -### Changes between 3.0.15 and 3.0.16 [11 Feb 2025] + *Hugo Landau, Matt Caswell, Tomáš Mráz, Neil Horman, Sasha Nedvedicky, Andrew Dinh* + + * Tolerate PKCS#8 version 2 with optional public keys. The public key data + is currently ignored. + + *Viktor Dukhovni* + + * Signature schemes without an explicit signing digest in CMS are now supported. + Examples of such schemes are ED25519 or ML-DSA. + + *Michael Schroeder* + + * The TLS Signature algorithms defaults now include all three ML-DSA variants as + first algorithms. + + *Viktor Dukhovni* + + * Added a `no-tls-deprecated-ec` configuration option. + + The `no-tls-deprecated-ec` option disables support for TLS elliptic curve + groups deprecated in RFC8422 at compile time. This does not affect use of + the associated curves outside TLS. By default support for these groups is + compiled in, but, as before, they are not included in the default run-time + list of supported groups. + + With the `enable-tls-deprecated-ec` option these TLS groups remain enabled at + compile time even if the default configuration is changed, provided the + underlying EC curves remain implemented. + + *Viktor Dukhovni* + + * Added new API to enable 0-RTT for 3rd party QUIC stacks. + + *Cheng Zhang* + + * Added support for a new callback registration `SSL_CTX_set_new_pending_conn_cb`, + which allows for application notification of new connection SSL object + creation, which occurs independently of calls to `SSL_accept_connection()`. + Note: QUIC objects passed through SSL callbacks should not have their state + mutated via calls back into the SSL api until such time as they have been + received via a call to `SSL_accept_connection()`. + + *Neil Horman* + + * Add SLH-DSA as specified in FIPS 205. + + *Shane Lontis and Dr Paul Dale* + + * ML-KEM as specified in FIPS 203. + + Based on the original implementation in BoringSSL, ported from C++ to C, + refactored, and integrated into the OpenSSL default and FIPS providers. + Including also the X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024 + TLS hybrid key post-quantum/classical key agreement schemes. + + *Michael Baentsch, Viktor Dukhovni, Shane Lontis and Paul Dale* + + * Add ML-DSA as specified in FIPS 204. + + The base code was derived from BoringSSL C++ code. + + *Shane Lontis, Viktor Dukhovni and Paul Dale* + + * Added new API calls to enable 3rd party QUIC stacks to use the OpenSSL TLS + implementation. + + *Matt Caswell* + + * The default DRBG implementations have been changed to prefer to fetch + algorithm implementations from the default provider (the provider the + DRBG implementation is built in) regardless of the default properties + set in the configuration file. The code will still fallback to find + an implementation, as done previously, if needed. + + *Simo Sorce* + + * Initial support for opaque symmetric keys objects (EVP_SKEY). These + replace the ad-hoc byte arrays that are pervasive throughout the library. + + *Dmitry Belyavskiy and Simo Sorce* + + * The default TLS group list setting is now set to: + `?*X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072` + + This means two key shares (X25519MLKEM768 and X25519) will be sent by + default by the TLS client. GOST groups and FFDHE groups larger than 3072 + bits are no longer enabled by default. + + The group names in the group list setting are now also case insensitive. + + *Viktor Dukhovni* + + * For TLSv1.3: Add capability for a client to send multiple key shares. + Extend the scope of `SSL_OP_CIPHER_SERVER_PREFERENCE` to cover + server-side key exchange group selection. + + Extend the server-side key exchange group selection algorithm and related + group list syntax to support multiple group priorities, e.g. to prioritize + (hybrid-)KEMs. + + *David Kelsey*, *Martin Schmatz* + + * A new random generation API has been introduced which modifies all + of the L family of calls so they are routed through a + specific named provider instead of being resolved via the normal DRBG + chaining. In a future OpenSSL release, this will obsolete RAND_METHOD. + + *Dr Paul Dale* + + * New inline functions were added to support loads and stores of unsigned + 16-bit, 32-bit and 64-bit integers in either little-endian or big-endian + form, regardless of the host byte-order. See the `OPENSSL_load_u16_le(3)` + manpage for details. + + *Viktor Dukhovni* + + * All the `BIO_meth_get_*()` functions allowing reuse of the internal OpenSSL + BIO method implementations were deprecated. The reuse is unsafe due to + dependency on the code of the internal methods not changing. + + *Tomáš Mráz* + + * Support DEFAULT keyword and '-' prefix in `SSL_CTX_set1_groups_list()`. + `SSL_CTX_set1_groups_list()` now supports the DEFAULT keyword which sets the + available groups to the default selection. The '-' prefix allows the calling + application to remove a group from the selection. + + *Frederik Wedel-Heinen* + + * Updated the default encryption cipher for the `req`, `cms`, and `smime` applications + from `des-ede3-cbc` to `aes-256-cbc`. + + AES-256 provides a stronger 256-bit key encryption than legacy 3DES. + + *Aditya* + + * Enhanced PKCS#7 inner contents verification. + In the `PKCS7_verify()` function, the BIO *indata parameter refers to the + signed data if the content is detached from p7. Otherwise, indata should be + NULL, and then the signed data must be in p7. + + The previous OpenSSL implementation only supported MIME inner content + [RFC 5652, section 5.2]. + + The added functionality now enables support for PKCS#7 inner content + [RFC 2315, section 7]. + + *Małgorzata Olszówka* + + * The `-rawin` option of the `pkeyutl` command is now implied (and thus no + longer required) when using `-digest` or when signing or verifying with an + Ed25519 or Ed448 key. + The `-digest` and `-rawin` option may only be given with `-sign` or `verify`. + + *David von Oheimb* + + * `X509_PURPOSE_add()` has been modified + to take `sname` instead of `id` as the primary purpose identifier. + For its convenient use, `X509_PURPOSE_get_unused_id()` has been added. + + This work was sponsored by Siemens AG. + + *David von Oheimb* + + * Added support for central key generation in CMP. + + This work was sponsored by Siemens AG. + + *Rajeev Ranjan* + + * Optionally allow the FIPS provider to use the `JITTER` entropy source. + Note that using this option will require the resulting FIPS provider + to undergo entropy source validation [ESV] by the [CMVP], without this + the FIPS provider will not be FIPS compliant. Enable this using the + configuration option `enable-fips-jitter`. + + *Paul Dale* + + * Extended `OPENSSL_ia32cap` support to accommodate additional `CPUID` + feature/capability bits in leaf `0x7` (Extended Feature Flags) as well + as leaf `0x24` (Converged Vector ISA). + + *Dan Zimmerman, Alina Elizarova* + + * Cipher pipelining support for provided ciphers with new API functions + EVP_CIPHER_can_pipeline(), EVP_CipherPipelineEncryptInit(), + EVP_CipherPipelineDecryptInit(), EVP_CipherPipelineUpdate(), + and EVP_CipherPipelineFinal(). Cipher pipelining support allows application to + submit multiple chunks of data in one cipher update call, thereby allowing the + provided implementation to take advantage of parallel computing. There are + currently no built-in ciphers that support pipelining. This new API replaces + the legacy pipeline API [SSL_CTX_set_max_pipelines](https://docs.openssl.org/3.3/man3/SSL_CTX_set_split_send_fragment/) used with Engines. + + *Ramkumar* + + * Add CMS_NO_SIGNING_TIME flag to CMS_sign(), CMS_add1_signer() + + Previously there was no way to create a CMS SignedData signature without a + signing time attribute, because CMS_SignerInfo_sign added it unconditionally. + However, there is a use case (PAdES signatures [ETSI EN 319 142-1](https://www.etsi.org/deliver/etsi_en/319100_319199/31914201/01.01.01_60/en_31914201v010101p.pdf) ) + where this attribute is not allowed, so a new flag was added to the CMS API + that causes this attribute to be omitted at signing time. + + The new `-no_signing_time` option of the `cms` command enables this flag. + + *Juhász Péter* + + * Parallel dual-prime 1024/1536/2048-bit modular exponentiation for + AVX_IFMA capable processors (Intel Sierra Forest and its successor). + + This optimization brings performance enhancement, ranging from 1.8 to 2.2 + times, for the sign/decryption operations of rsaz-2k/3k/4k (`openssl speed rsa`) + on the Intel Sierra Forest. + + *Zhiguo Zhou, Wangyang Guo (Intel Corp)* + + * VAES/AVX-512 support for AES-XTS. + + For capable processors (>= Intel Icelake), this provides a + vectorized implementation of AES-XTS with a throughput improvement + between 1.3x to 2x, depending on the block size. + + *Pablo De Lara Guarch, Dan Pittman* + + * Fixed EVP_DecodeUpdate() to not write padding zeros to the decoded output. + + According to the documentation, for every 4 valid base64 bytes processed + (ignoring whitespace, carriage returns and line feeds), EVP_DecodeUpdate() + produces 3 bytes of binary output data (except at the end of data + terminated with one or two padding characters). However, the function + behaved like an EVP_DecodeBlock(). It produced exactly 3 output bytes for + every 4 input bytes. Such behaviour could cause writes to a non-allocated + output buffer if a user allocates its size based on the documentation and + knowing the padding size. + + The fix makes EVP_DecodeUpdate() produce exactly as many output bytes as + in the initial non-encoded message. + + *Valerii Krygin* + + * Added support for aAissuingDistributionPoint, allowedAttributeAssignments, + timeSpecification, attributeDescriptor, roleSpecCertIdentifier, + authorityAttributeIdentifier and attributeMappings X.509v3 extensions. + + *Jonathan M. Wilbur* + + * Added a new CLI option `-provparam` and API functions for setting of + provider configuration parameters. + + *Viktor Dukhovni* + + * Added a new trace category for PROVIDER calls and added new tracing calls + in provider and algorithm fetching API functions. + + *Neil Horman* + + * Fixed benchmarking for AEAD ciphers in the `openssl speed` utility. + + *Mohammed Alhabib* + + * Added a build configuration option `enable-sslkeylog` for enabling support + for SSLKEYLOGFILE environment variable to log TLS connection secrets. + + *Neil Horman* + + * Added EVP_get_default_properties() function to retrieve the current default + property query string. + + *Dmitry Belyavskiy* + +OpenSSL 3.4 +----------- + +### Changes between 3.4.1 and 3.4.2 [xx XXX xxxx] + + * When displaying distinguished names in the openssl application escape control + characters by default. + + *Tomáš Mráz* + +### Changes between 3.4.0 and 3.4.1 [11 Feb 2025] + + * Fixed RFC7250 handshakes with unauthenticated servers don't abort as expected. + + Clients using RFC7250 Raw Public Keys (RPKs) to authenticate a + server may fail to notice that the server was not authenticated, because + handshakes don't abort as expected when the SSL_VERIFY_PEER verification mode + is set. + + ([CVE-2024-12797]) + + *Viktor Dukhovni* * Fixed timing side-channel in ECDSA signature computation. @@ -43,6 +338,191 @@ breaking changes, and mappings for the large list of deprecated functions. *Tomáš Mráz* + * Reverted the behavior change of CMS_get1_certs() and CMS_get1_crls() + that happened in the 3.4.0 release. These functions now return NULL + again if there are no certs or crls in the CMS object. + + *Tomáš Mráz* + +### Changes between 3.3 and 3.4.0 [22 Oct 2024] + + * For the FIPS provider only, replaced the primary DRBG with a continuous + health check module. This also removes the now forbidden DRBG chaining. + + *Paul Dale* + + * Improved base64 BIO correctness and error reporting. + + *Viktor Dukhovni* + + * Added support for directly fetched composite signature algorithms such as + RSA-SHA2-256 including new API functions in the EVP_PKEY_sign, + EVP_PKEY_verify and EVP_PKEY_verify_recover groups. + + *Richard Levitte* + + * XOF Digest API improvements + + EVP_MD_CTX_get_size() and EVP_MD_CTX_size are macros that were aliased to + EVP_MD_get_size which returns a constant value. XOF Digests such as SHAKE + have an output size that is not fixed, so calling EVP_MD_get_size() is not + sufficent. The existing macros now point to the new function + EVP_MD_CTX_get_size_ex() which will retrieve the "size" for a XOF digest, + otherwise it falls back to calling EVP_MD_get_size(). Note that the SHAKE + implementation did not have a context getter previously, so the "size" will + only be able to be retrieved with new providers. + + Also added a EVP_xof() helper. + + *Shane Lontis* + + * Added FIPS indicators to the FIPS provider. + + FIPS 140-3 requires indicators to be used if the FIPS provider allows + non-approved algorithms. An algorithm is approved if it passes all + required checks such as minimum key size. By default an error will + occur if any check fails. For backwards compatibility individual + algorithms may override the checks by using either an option in the + FIPS configuration OR in code using an algorithm context setter. + Overriding the check means that the algorithm is not FIPS compliant. + OSSL_INDICATOR_set_callback() can be called to register a callback + to log unapproved algorithms. At the end of any algorithm operation + the approved status can be queried using an algorithm context getter. + FIPS provider configuration options are set using 'openssl fipsinstall'. + + Note that new FIPS 140-3 restrictions have been enforced such as + RSA Encryption using PKCS1 padding is no longer approved. + Documentation related to the changes can be found on the [fips_module(7)] + manual page. + + [fips_module(7)]: https://docs.openssl.org/master/man7/fips_module/#FIPS indicators + + *Shane Lontis, Paul Dale, Po-Hsing Wu and Dimitri John Ledkov* + + * Added support for hardware acceleration for HMAC on S390x architecture. + + *Ingo Franzki* + + * Added debuginfo Makefile target for unix platforms to produce + a separate DWARF info file from the corresponding shared libs. + + *Neil Horman* + + * Added support for encapsulation and decapsulation operations in the + pkeyutl command. + + *Dmitry Belyavskiy* + + * Added implementation of RFC 9579 (PBMAC1) in PKCS#12. + + *Dmitry Belyavskiy* + + * Add a new random seed source RNG `JITTER` using a statically linked + jitterentropy library. + + *Dimitri John Ledkov* + + * Added a feature to retrieve configured TLS signature algorithms, + e.g., via the openssl list command. + + *Michael Baentsch* + + * Deprecated TS_VERIFY_CTX_set_* functions and added replacement + TS_VERIFY_CTX_set0_* functions with improved semantics. + + *Tobias Erbsland* + + * Redesigned Windows use of OPENSSLDIR/ENGINESDIR/MODULESDIR such that + what were formerly build time locations can now be defined at run time + with registry keys. See NOTES-WINDOWS.md. + + *Neil Horman* + + * Added options `-not_before` and `-not_after` for explicit setting + start and end dates of certificates created with the `req` and `x509` + commands. Added the same options also to `ca` command as alias for + `-startdate` and `-enddate` options. + + *Stephan Wurm* + + * The X25519 and X448 key exchange implementation in the FIPS provider + is unapproved and has `fips=no` property. + + *Tomáš Mráz* + + * SHAKE-128 and SHAKE-256 implementations have no default digest length + anymore. That means these algorithms cannot be used with + EVP_DigestFinal/_ex() unless the `xoflen` param is set before. + + This change was necessary because the preexisting default lengths were + half the size necessary for full collision resistance supported by these + algorithms. + + *Tomáš Mráz* + + * Setting `config_diagnostics=1` in the config file will cause errors to + be returned from SSL_CTX_new() and SSL_CTX_new_ex() if there is an error + in the ssl module configuration. + + *Tomáš Mráz* + + * An empty renegotiate extension will be used in TLS client hellos instead + of the empty renegotiation SCSV, for all connections with a minimum TLS + version > 1.0. + + *Tim Perry* + + * Added support for integrity-only cipher suites TLS_SHA256_SHA256 and + TLS_SHA384_SHA384 in TLS 1.3, as defined in RFC 9150. + + This work was sponsored by Siemens AG. + + *Rajeev Ranjan* + + * Added support for retrieving certificate request templates and CRLs in CMP, + with the respective CLI options `-template`, + `-crlcert`, `-oldcrl`, `-crlout`, `-crlform>`, and `-rsp_crl`. + + This work was sponsored by Siemens AG. + + *Rajeev Ranjan* + + * Added support for issuedOnBehalfOf, auditIdentity, basicAttConstraints, + userNotice, acceptablePrivilegePolicies, acceptableCertPolicies, + subjectDirectoryAttributes, associatedInformation, delegatedNameConstraints, + holderNameConstraints and targetingInformation X.509v3 extensions. + + *Jonathan M. Wilbur* + + * Added Attribute Certificate (RFC 5755) support. Attribute + Certificates can be created, parsed, modified and printed via the + public API. There is no command-line tool support at this time. + + *Damian Hobson-Garcia* + + * Added support to build Position Independent Executables (PIE). Configuration + option `enable-pie` configures the cflag '-fPIE' and ldflag '-pie' to + support Address Space Layout Randomization (ASLR) in the openssl executable, + removes reliance on external toolchain configurations. + + *Craig Lorentzen* + + * SSL_SESSION_get_time()/SSL_SESSION_set_time()/SSL_CTX_flush_sessions() have + been deprecated in favour of their respective ..._ex() replacement functions + which are Y2038-safe. + + *Alexander Kanavin* + + * ECC groups may now customize their initialization to save CPU by using + precomputed values. This is used by the P-256 implementation. + + *Watson Ladd* + +OpenSSL 3.3 +----------- + +### Changes between 3.3.2 and 3.3.3 [xx XXX xxxx] + * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic curve parameters. @@ -59,7 +539,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Viktor Dukhovni* -### Changes between 3.0.14 and 3.0.15 [3 Sep 2024] +### Changes between 3.3.1 and 3.3.2 [3 Sep 2024] * Fixed possible denial of service in X.509 name checks. @@ -83,7 +563,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Matt Caswell* -### Changes between 3.0.13 and 3.0.14 [4 Jun 2024] +### Changes between 3.3.0 and 3.3.1 [4 Jun 2024] * Fixed potential use after free after SSL_free_buffers() is called. @@ -133,6 +613,203 @@ breaking changes, and mappings for the large list of deprecated functions. *Tomáš Mráz and Paul Dale* +### Changes between 3.2 and 3.3.0 [9 Apr 2024] + + * The `-verify` option to the `openssl crl` and `openssl req` will make + the program exit with 1 on failure. + + *Vladimír Kotal* + + * The BIO_get_new_index() function can only be called 127 times before it + reaches its upper bound of BIO_TYPE_MASK. It will now correctly return an + error of -1 once it is exhausted. Users may need to reserve using this + function for cases where BIO_find_type() is required. Either BIO_TYPE_NONE + or BIO_get_new_index() can be used to supply a type to BIO_meth_new(). + + *Shane Lontis* + + * Added API functions SSL_SESSION_get_time_ex(), SSL_SESSION_set_time_ex() + using time_t which is Y2038 safe on 32 bit systems when 64 bit time + is enabled (e.g via setting glibc macro _TIME_BITS=64). + + *Ijtaba Hussain* + + * The d2i_ASN1_GENERALIZEDTIME(), d2i_ASN1_UTCTIME(), ASN1_TIME_check(), and + related functions have been augmented to check for a minimum length of + the input string, in accordance with ITU-T X.690 section 11.7 and 11.8. + + *Job Snijders* + + * Unknown entries in TLS SignatureAlgorithms, ClientSignatureAlgorithms + config options and the respective calls to SSL[_CTX]_set1_sigalgs() and + SSL[_CTX]_set1_client_sigalgs() that start with `?` character are + ignored and the configuration will still be used. + + Similarly unknown entries that start with `?` character in a TLS + Groups config option or set with SSL[_CTX]_set1_groups_list() are ignored + and the configuration will still be used. + + In both cases if the resulting list is empty, an error is returned. + + *Tomáš Mráz* + + * The EVP_PKEY_fromdata function has been augmented to allow for the derivation + of CRT (Chinese Remainder Theorem) parameters when requested. See the + OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ param in the EVP_PKEY-RSA documentation. + + *Neil Horman* + + * The activate and soft_load configuration settings for providers in + openssl.cnf have been updated to require a value of [1|yes|true|on] + (in lower or UPPER case) to enable the setting. Conversely a value + of [0|no|false|off] will disable the setting. All other values, or the + omission of a value for these settings will result in an error. + + *Neil Horman* + + * Added `-set_issuer` and `-set_subject` options to `openssl x509` to + override the Issuer and Subject when creating a certificate. The `-subj` + option now is an alias for `-set_subject`. + + *Job Snijders, George Michaelson* + + * OPENSSL_sk_push() and sk__push() functions now return 0 instead of -1 + if called with a NULL stack argument. + + *Tomáš Mráz* + + * In `openssl speed`, changed the default hash function used with `hmac` from + `md5` to `sha256`. + + *James Muir* + + * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483: + - `certProfile` request message header and respective `-profile` CLI option + - support for delayed delivery of all types of response messages + + This work was sponsored by Siemens AG. + + *David von Oheimb* + + * The build of exporters (such as `.pc` files for pkg-config) cleaned up to + be less hard coded in the build file templates, and to allow easier + addition of more exporters. With that, an exporter for CMake is also + added. + + *Richard Levitte* + + * The BLAKE2s hash algorithm matches BLAKE2b's support + for configurable output length. + + *Ahelenia Ziemiańska* + + * New option `SSL_OP_PREFER_NO_DHE_KEX`, which allows configuring a TLS1.3 + server to prefer session resumption using PSK-only key exchange over PSK + with DHE, if both are available. + + *Markus Minichmayr, Tapkey GmbH* + + * New API `SSL_write_ex2`, which can be used to send an end-of-stream (FIN) + condition in an optimised way when using QUIC. + + *Hugo Landau* + + * New atexit configuration switch, which controls whether the OPENSSL_cleanup + is registered when libcrypto is unloaded. This is turned off on NonStop + configurations because of loader differences on that platform compared to + Linux. + + *Randall S. Becker* + + * Support for qlog for tracing QUIC connections has been added. + + The qlog output from OpenSSL currently uses a pre-standard draft version of + qlog. The output from OpenSSL will change in incompatible ways in future + releases, and is not subject to any format stability or compatibility + guarantees at this time. This functionality can be + disabled with the build-time option `no-unstable-qlog`. See the + openssl-qlog(7) manpage for details. + + *Hugo Landau* + + * Added APIs to allow configuring the negotiated idle timeout for QUIC + connections, and to allow determining the number of additional streams + that can currently be created for a QUIC connection. + + *Hugo Landau* + + * Added APIs to allow disabling implicit QUIC event processing for + QUIC SSL objects, allowing applications to control when event handling + occurs. Refer to the SSL_get_value_uint(3) manpage for details. + + *Hugo Landau* + + * Limited support for polling of QUIC connection and stream objects in a + non-blocking manner. Refer to the SSL_poll(3) manpage for details. + + *Hugo Landau* + + * Added APIs to allow querying the size and utilisation of a QUIC stream's + write buffer. Refer to the SSL_get_value_uint(3) manpage for details. + + *Hugo Landau* + + * New limit on HTTP response headers is introduced to HTTP client. The + default limit is set to 256 header lines. If limit is exceeded the + response processing stops with error HTTP_R_RESPONSE_TOO_MANY_HDRLINES. + Application may call OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(3) + to change the default. Setting the value to 0 disables the limit. + + *Alexandr Nedvedicky* + + * Applied AES-GCM unroll8 optimisation to Microsoft Azure Cobalt 100 + + *Tom Cosgrove* + + * Added X509_STORE_get1_objects to avoid issues with the existing + X509_STORE_get0_objects API in multi-threaded applications. Refer to the + documentation for details. + + *David Benjamin* + + * Added assembly implementation for md5 on loongarch64 + + *Min Zhou* + + * Optimized AES-CTR for ARM Neoverse V1 and V2 + + *Fisher Yu* + + * Enable AES and SHA3 optimisations on Apple Silicon M3-based MacOS systems + similar to M1/M2. + + *Tom Cosgrove* + + * Added a new EVP_DigestSqueeze() API. This allows SHAKE to squeeze multiple + times with different output sizes. + + *Shane Lontis, Holger Dengler* + + * Various optimizations for cryptographic routines using RISC-V vector crypto + extensions + + *Christoph Müllner, Charalampos Mitrodimas, Ard Biesheuvel, Phoebe Chen, + Jerry Shih* + + * Accept longer context for TLS 1.2 exporters + + While RFC 5705 implies that the maximum length of a context for exporters is + 65535 bytes as the length is embedded in uint16, the previous implementation + enforced a much smaller limit, which is less than 1024 bytes. This + restriction has been removed. + + *Daiki Ueno* + +OpenSSL 3.2 +----------- + +### Changes between 3.2.1 and 3.2.2 [xx XXX xxxx] + * Fixed an issue where some non-default TLS server configurations can cause unbounded memory growth when processing TLSv1.3 sessions. An attacker may exploit certain server configurations to trigger unbounded memory growth that @@ -151,13 +828,12 @@ breaking changes, and mappings for the large list of deprecated functions. *Matt Caswell* - * New atexit configuration switch, which controls whether the OPENSSL_cleanup - is registered when libcrypto is unloaded. This can be used on platforms - where using atexit() from shared libraries causes crashes on exit. + * Fixed bug where SSL_export_keying_material() could not be used with QUIC + connections. (#23560) - *Randall S. Becker* + *Hugo Landau* -### Changes between 3.0.12 and 3.0.13 [30 Jan 2024] +### Changes between 3.2.0 and 3.2.1 [30 Jan 2024] * A file in PKCS12 format can contain certificates and keys and may come from an untrusted source. The PKCS12 specification allows certain fields to be @@ -227,6 +903,13 @@ breaking changes, and mappings for the large list of deprecated functions. *Rohan McLure* + * Disable building QUIC server utility when OpenSSL is configured with + `no-apps`. + + *Vitalii Koshura* + +### Changes between 3.1 and 3.2.0 [23 Nov 2023] + * Fix excessive time spent in DH check / generation with large Q parameter value. @@ -241,7 +924,455 @@ breaking changes, and mappings for the large list of deprecated functions. *Richard Levitte* -### Changes between 3.0.11 and 3.0.12 [24 Oct 2023] + * The BLAKE2b hash algorithm supports a configurable output length + by setting the "size" parameter. + + *Čestmír Kalina and Tomáš Mráz* + + * Enable extra Arm64 optimization on Windows for GHASH, RAND and AES. + + *Evgeny Karpov* + + * Added a function to delete objects from store by URI - OSSL_STORE_delete() + and the corresponding provider-storemgmt API function + OSSL_FUNC_store_delete(). + + *Dmitry Belyavskiy* + + * Added OSSL_FUNC_store_open_ex() provider-storemgmt API function to pass + a passphrase callback when opening a store. + + *Simo Sorce* + + * Changed the default salt length used by PBES2 KDF's (PBKDF2 and scrypt) + from 8 bytes to 16 bytes. + The PKCS5 (RFC 8018) standard uses a 64 bit salt length for PBE, and + recommends a minimum of 64 bits for PBES2. For FIPS compliance PBKDF2 + requires a salt length of 128 bits. This affects OpenSSL command line + applications such as "genrsa" and "pkcs8" and API's such as + PEM_write_bio_PrivateKey() that are reliant on the default value. + The additional commandline option 'saltlen' has been added to the + OpenSSL command line applications for "pkcs8" and "enc" to allow the + salt length to be set to a non default value. + + *Shane Lontis* + + * Changed the default value of the `ess_cert_id_alg` configuration + option which is used to calculate the TSA's public key certificate + identifier. The default algorithm is updated to be sha256 instead + of sha1. + + *Małgorzata Olszówka* + + * Added optimization for SM2 algorithm on aarch64. It uses a huge precomputed + table for point multiplication of the base point, which increases the size of + libcrypto from 4.4 MB to 4.9 MB. A new configure option `no-sm2-precomp` has + been added to disable the precomputed table. + + *Xu Yizhou* + + * Added client side support for QUIC + + *Hugo Landau, Matt Caswell, Paul Dale, Tomáš Mráz, Richard Levitte* + + * Added multiple tutorials on the OpenSSL library and in particular + on writing various clients (using TLS and QUIC protocols) with libssl. + + *Matt Caswell* + + * Added secp384r1 implementation using Solinas' reduction to improve + speed of the NIST P-384 elliptic curve. To enable the implementation + the build option `enable-ec_nistp_64_gcc_128` must be used. + + *Rohan McLure* + + * Improved RFC7468 compliance of the asn1parse command. + + *Matthias St. Pierre* + + * Added SHA256/192 algorithm support. + + *Fergus Dall* + + * Improved contention on global write locks by using more read locks where + appropriate. + + *Matt Caswell* + + * Improved performance of OSSL_PARAM lookups in performance critical + provider functions. + + *Paul Dale* + + * Added the SSL_get0_group_name() function to provide access to the + name of the group used for the TLS key exchange. + + *Alex Bozarth* + + * Provide a new configure option `no-http` that can be used to disable the + HTTP support. Provide new configure options `no-apps` and `no-docs` to + disable building the openssl command line application and the documentation. + + *Vladimír Kotal* + + * Provide a new configure option `no-ecx` that can be used to disable the + X25519, X448, and EdDSA support. + + *Yi Li* + + * When multiple OSSL_KDF_PARAM_INFO parameters are passed to + the EVP_KDF_CTX_set_params() function they are now concatenated not just + for the HKDF algorithm but also for SSKDF and X9.63 KDF algorithms. + + *Paul Dale* + + * Added OSSL_FUNC_keymgmt_im/export_types_ex() provider functions that get + the provider context as a parameter. + + *Ingo Franzki* + + * TLS round-trip time calculation was added by a Brigham Young University + Capstone team partnering with Sandia National Laboratories. A new function + in ssl_lib titled SSL_get_handshake_rtt will calculate and retrieve this + value. + + *Jairus Christensen* + + * Added the "-quic" option to s_client to enable connectivity to QUIC servers. + QUIC requires the use of ALPN, so this must be specified via the "-alpn" + option. Use of the "advanced" s_client command command via the "-adv" option + is recommended. + + *Matt Caswell* + + * Added an "advanced" command mode to s_client. Use this with the "-adv" + option. The old "basic" command mode recognises certain letters that must + always appear at the start of a line and cannot be escaped. The advanced + command mode enables commands to be entered anywhere and there is an + escaping mechanism. After starting s_client with "-adv" type "{help}" + to show a list of available commands. + + *Matt Caswell* + + * Add Raw Public Key (RFC7250) support. Authentication is supported + by matching keys against either local policy (TLSA records synthesised + from the expected keys) or DANE (TLSA records obtained by the + application from DNS). TLSA records will also match the same key in + the server certificate, should RPK use not happen to be negotiated. + + *Todd Short* + + * Added support for modular exponentiation and CRT offloading for the + S390x architecture. + + *Juergen Christ* + + * Added further assembler code for the RISC-V architecture. + + *Christoph Müllner* + + * Added EC_GROUP_to_params() which creates an OSSL_PARAM array + from a given EC_GROUP. + + *Oliver Mihatsch* + + * Improved support for non-default library contexts and property queries + when parsing PKCS#12 files. + + *Shane Lontis* + + * Implemented support for all five instances of EdDSA from RFC8032: + Ed25519, Ed25519ctx, Ed25519ph, Ed448, and Ed448ph. + The streaming is not yet supported for the HashEdDSA variants + (Ed25519ph and Ed448ph). + + *James Muir* + + * Added SM4 optimization for ARM processors using ASIMD and AES HW + instructions. + + *Xu Yizhou* + + * Implemented SM4-XTS support. + + *Xu Yizhou* + + * Added platform-agnostic OSSL_sleep() function. + + *Richard Levitte* + + * Implemented deterministic ECDSA signatures (RFC6979) support. + + *Shane Lontis* + + * Implemented AES-GCM-SIV (RFC8452) support. + + *Todd Short* + + * Added support for pluggable (provider-based) TLS signature algorithms. + This enables TLS 1.3 authentication operations with algorithms embedded + in providers not included by default in OpenSSL. In combination with + the already available pluggable KEM and X.509 support, this enables + for example suitable providers to deliver post-quantum or quantum-safe + cryptography to OpenSSL users. + + *Michael Baentsch* + + * Added support for pluggable (provider-based) CMS signature algorithms. + This enables CMS sign and verify operations with algorithms embedded + in providers not included by default in OpenSSL. + + *Michael Baentsch* + + * Added support for Hybrid Public Key Encryption (HPKE) as defined + in RFC9180. HPKE is required for TLS Encrypted ClientHello (ECH), + Message Layer Security (MLS) and other IETF specifications. + HPKE can also be used by other applications that require + encrypting "to" an ECDH public key. External APIs are defined in + include/openssl/hpke.h and documented in doc/man3/OSSL_HPKE_CTX_new.pod + + *Stephen Farrell* + + * Implemented HPKE DHKEM support in providers used by HPKE (RFC9180) + API. + + *Shane Lontis* + + * Add support for certificate compression (RFC8879), including + library support for Brotli and Zstandard compression. + + *Todd Short* + + * Add the ability to add custom attributes to PKCS12 files. Add a new API + PKCS12_create_ex2, identical to the existing PKCS12_create_ex but allows + for a user specified callback and optional argument. + Added a new PKCS12_SAFEBAG_set0_attr, which allows for a new attr to be + added to the existing STACK_OF attrs. + + *Graham Woodward* + + * Major refactor of the libssl record layer. + + *Matt Caswell* + + * Add a mac salt length option for the pkcs12 command. + + *Xinping Chen* + + * Add more SRTP protection profiles from RFC8723 and RFC8269. + + *Kijin Kim* + + * Extended Kernel TLS (KTLS) to support TLS 1.3 receive offload. + + *Daiki Ueno, John Baldwin and Dmitry Podgorny* + + * Add support for TCP Fast Open (RFC7413) to macOS, Linux, and FreeBSD where + supported and enabled. + + *Todd Short* + + * 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* + + * Add new SSL APIs to aid in efficiently implementing TLS/SSL fingerprinting. + The SSL_CTRL_GET_IANA_GROUPS control code, exposed as the + SSL_get0_iana_groups() function-like macro, retrieves the list of + supported groups sent by the peer. + The function SSL_client_hello_get_extension_order() populates + a caller-supplied array with the list of extension types present in the + ClientHello, in order of appearance. + + *Phus Lu* + + * Fixed PEM_write_bio_PKCS8PrivateKey() and PEM_write_bio_PKCS8PrivateKey_nid() + to make it possible to use empty passphrase strings. + + *Darshan Sen* + + * The PKCS12_parse() function now supports MAC-less PKCS12 files. + + *Daniel Fiala* + + * Added ASYNC_set_mem_functions() and ASYNC_get_mem_functions() calls to be able + to change functions used for allocating the memory of asynchronous call stack. + + *Arran Cudbard-Bell* + + * Added support for signed BIGNUMs in the OSSL_PARAM APIs. + + *Richard Levitte* + + * A failure exit code is returned when using the openssl x509 command to check + certificate attributes and the checks fail. + + *Rami Khaldi* + + * The default SSL/TLS security level has been changed from 1 to 2. RSA, + DSA and DH keys of 1024 bits and above and less than 2048 bits and ECC keys + of 160 bits and above and less than 224 bits were previously accepted by + default but are now no longer allowed. By default TLS compression was + already disabled in previous OpenSSL versions. At security level 2 it cannot + be enabled. + + *Matt Caswell* + + * The SSL_CTX_set_cipher_list family functions now accept ciphers using their + IANA standard names. + + *Erik Lax* + + * The PVK key derivation function has been moved from b2i_PVK_bio_ex() into + the legacy crypto provider as an EVP_KDF. Applications requiring this KDF + will need to load the legacy crypto provider. + + *Paul Dale* + + * CCM8 cipher suites in TLS have been downgraded to security level zero + because they use a short authentication tag which lowers their strength. + + *Paul Dale* + + * Subject or issuer names in X.509 objects are now displayed as UTF-8 strings + by default. Also spaces surrounding `=` in DN output are removed. + + *Dmitry Belyavskiy* + + * Add X.509 certificate codeSigning purpose and related checks on key usage and + extended key usage of the leaf certificate according to the CA/Browser Forum. + + * Lutz Jänicke* + + * The `x509`, `ca`, and `req` commands now produce X.509 v3 certificates. + The `-x509v1` option of `req` prefers generation of X.509 v1 certificates. + `X509_sign()` and `X509_sign_ctx()` make sure that the certificate has + X.509 version 3 if the certificate information includes X.509 extensions. + + *David von Oheimb* + + * Fix and extend certificate handling and the commands `x509`, `verify` etc. + such as adding a trace facility for debugging certificate chain building. + + *David von Oheimb* + + * Various fixes and extensions to the CMP+CRMF implementation and the `cmp` app + in particular supporting various types of genm/genp exchanges such as getting + CA certificates and root CA cert updates defined in CMP Updates [RFC 9480], + as well as the `-srvcertout` and `-serial` CLI options. + + This work was sponsored by Siemens AG. + + *David von Oheimb* + + * Fixes and extensions to the HTTP client and to the HTTP server in `apps/` + like correcting the TLS and proxy support and adding tracing for debugging. + + *David von Oheimb* + + * Extended the CMS API for handling `CMS_SignedData` and `CMS_EnvelopedData`. + + *David von Oheimb* + + * `CMS_add0_cert()` and `CMS_add1_cert()` no longer throw an error if + a certificate to be added is already present. `CMS_sign_ex()` and + `CMS_sign()` now ignore any duplicate certificates in their `certs` argument + and no longer throw an error for them. + + *David von Oheimb* + + * Fixed and extended `util/check-format.pl` for checking adherence to the + coding style . + The checks are meanwhile more complete and yield fewer false positives. + + *David von Oheimb* + + * Added BIO_s_dgram_pair() and BIO_s_dgram_mem() that provide memory-based + BIOs with datagram semantics and support for BIO_sendmmsg() and BIO_recvmmsg() + calls. They can be used as the transport BIOs for QUIC. + + *Hugo Landau, Matt Caswell and Tomáš Mráz* + + * Add new BIO_sendmmsg() and BIO_recvmmsg() BIO methods which allow + sending and receiving multiple messages in a single call. An implementation + is provided for BIO_dgram. For further details, see BIO_sendmmsg(3). + + *Hugo Landau* + + * Support for loading root certificates from the Windows certificate store + has been added. The support is in the form of a store which recognises the + URI string of `org.openssl.winstore://`. This URI scheme currently takes no + arguments. This store is built by default and can be disabled using the new + compile-time option `no-winstore`. This store is not currently used by + default and must be loaded explicitly using the above store URI. It is + expected to be loaded by default in the future. + + *Hugo Landau* + + * Enable KTLS with the TLS 1.3 CCM mode ciphersuites. Note that some linux + kernel versions that support KTLS have a known bug in CCM processing. That + has been fixed in stable releases starting from 5.4.164, 5.10.84, 5.15.7, + and all releases since 5.16. KTLS with CCM ciphersuites should be only used + on these releases. + + *Tianjia Zhang* + + * Added `-ktls` option to `s_server` and `s_client` commands to enable the + KTLS support. + + *Tianjia Zhang* + + * Zerocopy KTLS sendfile() support on Linux. + + *Maxim Mikityanskiy* + + * The OBJ_ calls are now thread safe using a global lock. + + *Paul Dale* + + * New parameter `-digest` for openssl cms command allowing signing + pre-computed digests and new CMS API functions supporting that + functionality. + + *Viktor Söderqvist* + + * OPENSSL_malloc() and other allocation functions now raise errors on + allocation failures. The callers do not need to explicitly raise errors + unless they want to for tracing purposes. + + *David von Oheimb* + + * Added and enabled by default implicit rejection in RSA PKCS#1 v1.5 + decryption as a protection against Bleichenbacher-like attacks. + The RSA decryption API will now return a randomly generated deterministic + message instead of an error in case it detects an error when checking + padding during PKCS#1 v1.5 decryption. This is a general protection against + issues like CVE-2020-25659 and CVE-2020-25657. This protection can be + disabled by calling + `EVP_PKEY_CTX_ctrl_str(ctx, "rsa_pkcs1_implicit_rejection". "0")` + on the RSA decryption context. + + *Hubert Kario* + + * Added support for Brainpool curves in TLS-1.3. + + *Bernd Edlinger and Matt Caswell* + + * Added OpenBSD specific build targets. + + *David Carlier* + + * Support for Argon2d, Argon2i, Argon2id KDFs has been added along with + a basic thread pool implementation for select platforms. + + *Čestmír Kalina* + +OpenSSL 3.1 +----------- + +### Changes between 3.1.3 and 3.1.4 [24 Oct 2023] * Fix incorrect key and IV resizing issues when calling EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2() or EVP_CipherInit_ex2() with OSSL_PARAM parameters @@ -249,7 +1380,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Paul Dale* -### Changes between 3.0.10 and 3.0.11 [19 Sep 2023] +### Changes between 3.1.2 and 3.1.3 [19 Sep 2023] * Fix POLY1305 MAC implementation corrupting XMM registers on Windows. @@ -273,7 +1404,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Bernd Edlinger* -### Changes between 3.0.9 and 3.0.10 [1 Aug 2023] +### Changes between 3.1.1 and 3.1.2 [1 Aug 2023] * Fix excessive time spent checking DH q parameter value. @@ -331,7 +1462,14 @@ breaking changes, and mappings for the large list of deprecated functions. *Tomáš Mráz* -### Changes between 3.0.8 and 3.0.9 [30 May 2023] + * When building with the `enable-fips` option and using the resulting + FIPS provider, TLS 1.2 will, by default, mandate the use of an extended + master secret (FIPS 140-3 IG G.Q) and the Hash and HMAC DRBGs will + not operate with truncated digests (FIPS 140-3 IG G.R). + + *Paul Dale* + +### Changes between 3.1.0 and 3.1.1 [30 May 2023] * Mitigate for the time it takes for `OBJ_obj2txt` to translate gigantic OBJECT IDENTIFIER sub-identifiers to canonical numeric text form. @@ -357,6 +1495,16 @@ breaking changes, and mappings for the large list of deprecated functions. *Richard Levitte* + * Multiple algorithm implementation fixes for ARM BE platforms. + + *Liu-ErMeng* + + * Added a -pedantic option to fipsinstall that adjusts the various + settings to ensure strict FIPS compliance rather than backwards + compatibility. + + *Paul Dale* + * 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 @@ -377,6 +1525,13 @@ breaking changes, and mappings for the large list of deprecated functions. *Bernd Edlinger* + * Add FIPS provider configuration option to disallow the use of + truncated digests with Hash and HMAC DRBGs (q.v. FIPS 140-3 IG D.R.). + The option '-no_drbg_truncated_digests' can optionally be + supplied to 'openssl fipsinstall'. + + *Paul Dale* + * 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. @@ -403,6 +1558,94 @@ breaking changes, and mappings for the large list of deprecated functions. *Paul Dale* +### Changes between 3.0 and 3.1.0 [14 Mar 2023] + + * Add FIPS provider configuration option to enforce the + Extended Master Secret (EMS) check during the TLS1_PRF KDF. + The option '-ems_check' can optionally be supplied to + 'openssl fipsinstall'. + + *Shane Lontis* + + * The FIPS provider includes a few non-approved algorithms for + backward compatibility purposes and the "fips=yes" property query + must be used for all algorithm fetches to ensure FIPS compliance. + + The algorithms that are included but not approved are Triple DES ECB, + Triple DES CBC and EdDSA. + + *Paul Dale* + + * Added support for KMAC in KBKDF. + + *Shane Lontis* + + * RNDR and RNDRRS support in provider functions to provide + random number generation for Arm CPUs (aarch64). + + *Orr Toledano* + + * `s_client` and `s_server` commands now explicitly say when the TLS version + does not include the renegotiation mechanism. This avoids confusion + between that scenario versus when the TLS version includes secure + renegotiation but the peer lacks support for it. + + *Felipe Gasper* + + * AES-GCM enabled with AVX512 vAES and vPCLMULQDQ. + + *Tomasz Kantecki, Andrey Matyukov* + + * The various OBJ_* functions have been made thread safe. + + *Paul Dale* + + * Parallel dual-prime 1536/2048-bit modular exponentiation for + AVX512_IFMA capable processors. + + *Sergey Kirillov, Andrey Matyukov (Intel Corp)* + + * The functions `OPENSSL_LH_stats`, `OPENSSL_LH_node_stats`, + `OPENSSL_LH_node_usage_stats`, `OPENSSL_LH_stats_bio`, + `OPENSSL_LH_node_stats_bio` and `OPENSSL_LH_node_usage_stats_bio` are now + marked deprecated from OpenSSL 3.1 onwards and can be disabled by defining + `OPENSSL_NO_DEPRECATED_3_1`. + + The macro `DEFINE_LHASH_OF` is now deprecated in favour of the macro + `DEFINE_LHASH_OF_EX`, which omits the corresponding type-specific function + definitions for these functions regardless of whether + `OPENSSL_NO_DEPRECATED_3_1` is defined. + + Users of `DEFINE_LHASH_OF` may start receiving deprecation warnings for these + functions regardless of whether they are using them. It is recommended that + users transition to the new macro, `DEFINE_LHASH_OF_EX`. + + *Hugo Landau* + + * When generating safe-prime DH parameters set the recommended private key + length equivalent to minimum key lengths as in RFC 7919. + + *Tomáš Mráz* + + * Change the default salt length for PKCS#1 RSASSA-PSS signatures to the + maximum size that is smaller or equal to the digest length to comply with + FIPS 186-4 section 5. This is implemented by a new option + `OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX` ("auto-digestmax") for the + `rsa_pss_saltlen` parameter, which is now the default. Signature + verification is not affected by this change and continues to work as before. + + *Clemens Lang* + +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.7 and 3.0.8 [7 Feb 2023] * Fixed NULL dereference during PKCS7 data verification. @@ -872,7 +2115,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Matt Caswell* * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory - occuppied by the removed hash table entries. + occupied 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 @@ -1023,7 +2266,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Richard Levitte* -### Changes between 1.1.1 and 3.0.0 [7 sep 2021] +### 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. @@ -1069,7 +2312,7 @@ breaking changes, and mappings for the large list of deprecated functions. * 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() + previously only accessible via low-level interfaces. Use EVP_CIPHER_fetch() instead to retrieve these algorithms from a provider. *Shane Lontis* @@ -1393,7 +2636,8 @@ breaking changes, and mappings for the large list of deprecated functions. *Nicola Tuveri* - * Behavior of the `pkey` app is changed, when using the `-check` or `-pubcheck` + * Behavior of the `pkey` command 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. @@ -1416,7 +2660,7 @@ breaking changes, and mappings for the large list of deprecated functions. *David von Oheimb* - * All of the low level EC_KEY functions have been deprecated. + * All of the low-level EC_KEY functions have been deprecated. *Shane Lontis, Paul Dale, Richard Levitte, and Tomáš Mráz* @@ -1697,7 +2941,7 @@ breaking changes, and mappings for the large list of deprecated functions. *David von Oheimb* - * All of the low level RSA functions have been deprecated. + * All of the low-level RSA functions have been deprecated. *Paul Dale* @@ -1722,11 +2966,11 @@ breaking changes, and mappings for the large list of deprecated functions. *Paul Dale* - * All of the low level DH functions have been deprecated. + * 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. + * All of the low-level DSA functions have been deprecated. *Paul Dale* @@ -1735,7 +2979,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Richard Levitte* - * Deprecated low level ECDH and ECDSA functions. + * Deprecated low-level ECDH and ECDSA functions. *Paul Dale* @@ -1754,7 +2998,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Paul Dale* - * All of the low level HMAC functions have been deprecated. + * All of the low-level HMAC functions have been deprecated. *Paul Dale and David von Oheimb* @@ -1770,7 +3014,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Rich Salz* - * All of the low level CMAC functions have been deprecated. + * All of the low-level CMAC functions have been deprecated. *Paul Dale* @@ -1789,7 +3033,7 @@ breaking changes, and mappings for the large list of deprecated functions. *Richard Levitte* - * All of the low level cipher functions have been deprecated. + * All of the low-level cipher functions have been deprecated. *Matt Caswell and Paul Dale* @@ -1820,7 +3064,7 @@ breaking changes, and mappings for the large list of deprecated functions. 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. + have to reuse 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]) @@ -2059,7 +3303,7 @@ breaking changes, and mappings for the large list of deprecated functions. 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. + certificate 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. @@ -2079,7 +3323,7 @@ breaking changes, and mappings for the large list of deprecated functions. 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 + `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. @@ -2309,7 +3553,7 @@ breaking changes, and mappings for the large list of deprecated functions. 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. + reused X509_PUBKEY object if the second PUBKEY is malformed. *Bernd Edlinger* @@ -2448,7 +3692,9 @@ breaking changes, and mappings for the large list of deprecated functions. OpenSSL 1.1.1 ------------- -### Changes between 1.1.1l and 1.1.1m [xx XXX xxxx] +### Changes between 1.1.1m and 1.1.1n [xx XXX xxxx] + +### Changes between 1.1.1l and 1.1.1m [14 Dec 2021] * Avoid loading of a dynamic engine twice. @@ -2498,7 +3744,7 @@ OpenSSL 1.1.1 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 + are represented 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 @@ -2586,7 +3832,7 @@ OpenSSL 1.1.1 * 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 + 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 @@ -2604,7 +3850,7 @@ OpenSSL 1.1.1 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 + cases where the input length is close to the maximum permissible 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. @@ -2706,7 +3952,7 @@ OpenSSL 1.1.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 + 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. @@ -2765,7 +4011,7 @@ OpenSSL 1.1.1 * 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 + 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 @@ -2807,7 +4053,7 @@ OpenSSL 1.1.1 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. + certificate 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]) @@ -3273,7 +4519,7 @@ OpenSSL 1.1.1 * 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: - + *Matt Caswell* @@ -3577,7 +4823,7 @@ OpenSSL 1.1.0 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. + certificate 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]) @@ -3641,7 +4887,7 @@ OpenSSL 1.1.0 *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. + reused X509_PUBKEY object if the second PUBKEY is malformed. *Bernd Edlinger* @@ -3812,7 +5058,7 @@ OpenSSL 1.1.0 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 + 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. @@ -3903,7 +5149,7 @@ OpenSSL 1.1.0 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 + this can cause OpenSSL to crash (dependent on ciphersuite). Both clients and servers are affected. This issue was reported to OpenSSL by Joe Orton (Red Hat). @@ -4075,7 +5321,7 @@ OpenSSL 1.1.0 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 + 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 @@ -4561,7 +5807,7 @@ OpenSSL 1.1.0 * 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: . Libssl still retains + See: . Libssl still retains support for GOST ciphersuites (these are only activated if a GOST engine is present). @@ -4842,7 +6088,7 @@ OpenSSL 1.1.0 * 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. + not well tested). Therefore, the OPENSSL_NO_TLSEXT option has been removed. *Matt Caswell* @@ -4920,7 +6166,7 @@ OpenSSL 1.1.0 *Matt Caswell* - * SSLv2 support has been removed. It still supports receiving a SSLv2 + * SSLv2 support has been removed. It still supports receiving an SSLv2 compatible client hello. *Kurt Roeckx* @@ -5374,7 +6620,7 @@ OpenSSL 1.0.2 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. + certificate 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]) @@ -5850,8 +7096,8 @@ OpenSSL 1.0.2 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 + a message is 100k. Therefore, the attacker could force an additional 1500k + to be consumed per connection. By opening many simultaneous connections an attacker could cause a DoS attack through memory exhaustion. This issue was reported to OpenSSL by Quan Luo. @@ -7015,7 +8261,7 @@ OpenSSL 1.0.1 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 + defined where len <= SIZE. Therefore, the above idiom is actually undefined behaviour. For example this could cause problems if some malloc implementation @@ -7051,8 +8297,8 @@ OpenSSL 1.0.1 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 + a message is 100k. Therefore, the attacker could force an additional 1500k + to be consumed per connection. By opening many simultaneous connections an attacker could cause a DoS attack through memory exhaustion. This issue was reported to OpenSSL by Quan Luo. @@ -7118,7 +8364,7 @@ OpenSSL 1.0.1 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 + 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 @@ -7410,7 +8656,7 @@ OpenSSL 1.0.1 * Alternate chains certificate forgery - During certificate verfification, OpenSSL will attempt to find an + 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 @@ -7631,7 +8877,7 @@ OpenSSL 1.0.1 *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 + built with the no-ssl3 option and an 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]) @@ -7784,7 +9030,7 @@ OpenSSL 1.0.1 * 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 + could accept and complete an SSL 3.0 handshake, and clients could be configured to send them. ([CVE-2014-3568]) @@ -8696,7 +9942,7 @@ OpenSSL 1.0.0 *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 + built with the no-ssl3 option and an 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]) @@ -8769,7 +10015,7 @@ OpenSSL 1.0.0 3. Check DSA/ECDSA signatures use DER. - Reencode DSA/ECDSA signatures and compare with the original received + 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 @@ -8801,7 +10047,7 @@ OpenSSL 1.0.0 * 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 + could accept and complete an SSL 3.0 handshake, and clients could be configured to send them. ([CVE-2014-3568]) @@ -8816,7 +10062,7 @@ OpenSSL 1.0.0 * Add additional DigestInfo checks. - Reencode DigestInto in DER and check against the original when + Re-encode DigestInto in DER and check against the original when verifying RSA signature: this will reject any improperly encoded DigestInfo structures. @@ -10050,7 +11296,7 @@ OpenSSL 1.0.1.] * 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 + have new members for a hostname. 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 @@ -10074,7 +11320,7 @@ OpenSSL 1.0.1.] 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' + testing the HostName extension for a specific single hostname ('-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' @@ -10577,7 +11823,7 @@ OpenSSL 0.9.x 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 + Therefore, it does not make any sense to ship an arbitrary selection of root CA certificates with the OpenSSL software. *Lutz Jaenicke* @@ -10757,7 +12003,7 @@ OpenSSL 0.9.x * 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 + have new members for a hostname. 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 @@ -10781,7 +12027,7 @@ OpenSSL 0.9.x 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' + testing the HostName extension for a specific single hostname ('-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' @@ -14827,7 +16073,7 @@ s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k *stefank@valicert.com via Richard Levitte* - * Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half + * Add an 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 @@ -15376,7 +16622,7 @@ s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k ### 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 + to avoid an SSLeay/OpenSSL PRNG weakness pointed out by Markku-Juhani O. Saarinen : PRNG state recovery was possible based on the output of one PRNG request appropriately sized to gain knowledge on @@ -15761,7 +17007,7 @@ s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k *Bodo Moeller* * Store verify_result within SSL_SESSION also for client side to - avoid potential security hole. (Re-used sessions on the client side + avoid potential security hole. (Reused sessions on the client side always resulted in verify_result==X509_V_OK, not using the original result of the server certificate verification.) @@ -17977,7 +19223,7 @@ s-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k * 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, + an SSLv2-compatible client hello for SSLv3 or TLSv1 could be read, but a retry condition occurred while trying to read the rest. *Bodo Moeller* @@ -20148,3 +21394,5 @@ ndif [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 +[CMVP]: https://csrc.nist.gov/projects/cryptographic-module-validation-program +[ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cced15347d05..35c45a319fb9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -100,13 +100,5 @@ guidelines: with a specific release without having to sift through the higher noise ratio in git-log. - 8. For larger or more important user visible changes, as well as - security fixes, please add a line in [NEWS.md](NEWS.md). - On exception, it might be worth adding a multi-line entry (such as - the entry that announces all the types that became opaque with - OpenSSL 1.1.0). - This file helps users get a very quick summary of what comes with a - specific release, to see if an upgrade is worth the effort. - - 9. Guidelines how to integrate error output of new crypto library modules + 8. Guidelines on how to integrate error output of new crypto library modules can be found in [crypto/err/README.md](crypto/err/README.md). diff --git a/Configurations/00-base-templates.conf b/Configurations/00-base-templates.conf index 0e5d38d5a632..86287c3a25a3 100644 --- a/Configurations/00-base-templates.conf +++ b/Configurations/00-base-templates.conf @@ -48,15 +48,25 @@ my %targets=( defines => sub { my @defs = ( 'OPENSSL_BUILDING_OPENSSL' ); + push @defs, "BROTLI" unless $disabled{brotli}; + push @defs, "BROTLI_SHARED" unless $disabled{"brotli-dynamic"}; push @defs, "ZLIB" unless $disabled{zlib}; push @defs, "ZLIB_SHARED" unless $disabled{"zlib-dynamic"}; + push @defs, "ZSTD" unless $disabled{zstd}; + push @defs, "ZSTD_SHARED" unless $disabled{"zstd-dynamic"}; return [ @defs ]; }, includes => sub { my @incs = (); + push @incs, $withargs{jitter_include} + if !$disabled{jitter} && $withargs{jitter_include}; + push @incs, $withargs{brotli_include} + if !$disabled{brotli} && $withargs{brotli_include}; push @incs, $withargs{zlib_include} if !$disabled{zlib} && $withargs{zlib_include}; + push @incs, $withargs{zstd_include} + if !$disabled{zstd} && $withargs{zstd_include}; return [ @incs ]; }, }, @@ -68,12 +78,46 @@ my %targets=( AR => "ar", ARFLAGS => "qc", CC => "cc", + OBJCOPY => "objcopy", + bin_cflags => + sub { + my @flags = (); + if (!defined($disabled{pie})) { + push(@flags, "-fPIE"); + } + return join(" ", @flags); + }, + bin_lflags => + sub { + my @flags = (); + if (!defined($disabled{pie})) { + push(@flags, "-pie"); + } + return join(" ", @flags); + }, lflags => - sub { $withargs{zlib_lib} ? "-L".$withargs{zlib_lib} : () }, + sub { + my @libs = (); + push(@libs, "-L".$withargs{jitter_lib}) if $withargs{jitter_lib}; + push(@libs, "-L".$withargs{zlib_lib}) if $withargs{zlib_lib}; + push(@libs, "-L".$withargs{brotli_lib}) if $withargs{brotli_lib}; + push(@libs, "-L".$withargs{zstd_lib}) if $withargs{zstd_lib}; + return join(" ", @libs); + }, ex_libs => - sub { !defined($disabled{zlib}) - && defined($disabled{"zlib-dynamic"}) - ? "-lz" : () }, + sub { + my @libs = (); + push(@libs, "-l:libjitterentropy.a") if !defined($disabled{jitter}); + push(@libs, "-lz") if !defined($disabled{zlib}) && defined($disabled{"zlib-dynamic"}); + if (!defined($disabled{brotli}) && defined($disabled{"brotli-dynamic"})) { + push(@libs, "-lbrotlienc"); + push(@libs, "-lbrotlidec"); + push(@libs, "-lbrotlicommon"); + push(@libs, "-lm"); + } + push(@libs, "-lzstd") if !defined($disabled{zstd}) && defined($disabled{"zstd-dynamic"}); + return join(" ", @libs); + }, HASHBANGPERL => "/usr/bin/env perl", # Only Unix actually cares RANLIB => sub { which("$config{cross_compile_prefix}ranlib") ? "ranlib" : "" }, @@ -100,12 +144,29 @@ my %targets=( }, ex_libs => sub { + my @libs = (); unless ($disabled{zlib}) { if (defined($disabled{"zlib-dynamic"})) { - return $withargs{zlib_lib} // "ZLIB1"; + push(@libs, $withargs{zlib_lib} // "ZLIB1"); } } - return (); + unless ($disabled{zstd}) { + if (defined($disabled{"zstd-dynamic"})) { + push(@libs, $withargs{zstd_lib} // "libzstd"); + } + } + unless ($disabled{brotli}) { + if (defined($disabled{"brotli-dynamic"})) { + my $path = ""; + if (defined($withargs{brotli_lib})) { + $path = $withargs{brotli_lib} . "\\"; + } + push(@libs, $path . "brotlicommon.lib"); + push(@libs, $path . "brotlidec.lib"); + push(@libs, $path . "brotlienc.lib"); + } + } + return join(" ", @libs); }, MT => "mt", diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index e74adb50cc3c..cba57b41273f 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -242,9 +242,7 @@ my %targets = ( CFLAGS => add_before(picker(default => "-Wall", debug => "-O0 -g", release => "-O3 -fomit-frame-pointer")), - cflags => add(threads("-pthread")), lib_cppflags => add("-DL_ENDIAN"), - ex_libs => add(threads("-pthread")), bn_ops => "BN_LLONG", shared_cflag => "-fPIC", shared_ldflag => add_before("-shared -static-libgcc"), @@ -265,9 +263,8 @@ my %targets = ( CFLAGS => add_before(picker(default => "-Wall", debug => "-O0 -g", release => "-O3")), - cflags => add_before("-m64", threads("-pthread")), + cflags => add("-m64"), lib_cppflags => add("-DL_ENDIAN"), - ex_libs => add(threads("-pthread")), bn_ops => "SIXTY_FOUR_BIT_LONG", asm_arch => 'x86_64', perlasm_scheme => "elf", @@ -299,7 +296,6 @@ my %targets = ( lib_cppflags => add("-DL_ENDIAN"), thread_scheme => "pthreads", lflags => add(threads("-mt")), - ex_libs => add(threads("-lpthread")), bn_ops => "SIXTY_FOUR_BIT_LONG", asm_arch => 'x86_64', perlasm_scheme => "elf", @@ -315,12 +311,10 @@ my %targets = ( CFLAGS => add_before(picker(default => "-Wall", debug => "-O0 -g", release => "-O3")), - cflags => add(threads("-pthread")), lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), - ex_libs => add(threads("-pthread")), bn_ops => "BN_LLONG RC4_CHAR", shared_cflag => "-fPIC", - shared_ldflag => add_before("-shared"), + shared_ldflag => add_before("-shared -static-libgcc"), }, "solaris-sparcv8-gcc" => { inherit_from => [ "solaris-sparcv7-gcc" ], @@ -356,7 +350,6 @@ my %targets = ( cppflags => add(threads("-D_REENTRANT")), lib_cppflags => add("-DB_ENDIAN -DBN_DIV2W"), lflags => add(threads("-mt")), - ex_libs => add(threads("-lpthread")), bn_ops => "BN_LLONG RC4_CHAR", shared_cflag => "-KPIC", shared_ldflag => add_before("-G -dy -z text"), @@ -821,11 +814,18 @@ my %targets = ( multilib => "64", }, - # riscv64 below refers to contemporary RISCV Architecture + # riscv below refers to contemporary RISCV Architecture # specifications, "linux64-riscv64" => { inherit_from => [ "linux-generic64"], perlasm_scheme => "linux64", + asm_arch => 'riscv64', + }, + + "linux32-riscv32" => { + inherit_from => [ "linux-latomic" ], + perlasm_scheme => "linux32", + asm_arch => 'riscv32', }, # loongarch64 below refers to contemporary LoongArch Architecture @@ -833,6 +833,8 @@ my %targets = ( "linux64-loongarch64" => { inherit_from => [ "linux-generic64"], perlasm_scheme => "linux64", + asm_arch => 'loongarch64', + lib_cppflags => add("-DL_ENDIAN"), }, #### IA-32 targets... @@ -870,6 +872,10 @@ my %targets = ( asm_arch => 'x86', perlasm_scheme => "elf", }, + "linux-x86-latomic" => { + inherit_from => [ "linux-x86" ], + ex_libs => add(threads("-latomic")), + }, "linux-x86-clang" => { inherit_from => [ "linux-x86" ], CC => "clang", @@ -1087,11 +1093,80 @@ my %targets = ( perlasm_scheme => "linux64", }, - # riscv64 below refers to contemporary RISCV Architecture + "BSD-ppc" => { + inherit_from => [ "BSD-generic32" ], + asm_arch => 'ppc32', + perlasm_scheme => "linux32", + lib_cppflags => add("-DB_ENDIAN"), + }, + + "BSD-ppc64" => { + inherit_from => [ "BSD-generic64" ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DB_ENDIAN"), + asm_arch => 'ppc64', + perlasm_scheme => "linux64", + }, + + "BSD-ppc64le" => { + inherit_from => [ "BSD-generic64" ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DL_ENDIAN"), + asm_arch => 'ppc64', + perlasm_scheme => "linux64le", + }, + + # riscv below refers to contemporary RISCV Architecture # specifications, "BSD-riscv64" => { inherit_from => [ "BSD-generic64"], perlasm_scheme => "linux64", + asm_arch => 'riscv64', + }, + + "BSD-riscv32" => { + inherit_from => [ "BSD-generic32"], + perlasm_scheme => "linux32", + asm_arch => 'riscv32', + }, + + "BSD-armv4" => { + ################################################################ + # Note that -march is not among compiler options in linux-armv4 + # target description. Not specifying one is intentional to give + # you choice to: + # + # a) rely on your compiler default by not specifying one; + # b) specify your target platform explicitly for optimal + # performance, e.g. -march=armv6 or -march=armv7-a; + # c) build "universal" binary that targets *range* of platforms + # by specifying minimum and maximum supported architecture; + # + # As for c) option. It actually makes no sense to specify + # maximum to be less than ARMv7, because it's the least + # requirement for run-time switch between platform-specific + # code paths. And without run-time switch performance would be + # equivalent to one for minimum. Secondly, there are some + # natural limitations that you'd have to accept and respect. + # Most notably you can *not* build "universal" binary for + # big-endian platform. This is because ARMv7 processor always + # picks instructions in little-endian order. Another similar + # limitation is that -mthumb can't "cross" -march=armv6t2 + # boundary, because that's where it became Thumb-2. Well, this + # limitation is a bit artificial, because it's not really + # impossible, but it's deemed too tricky to support. And of + # course you have to be sure that your binutils are actually + # up to the task of handling maximum target platform. With all + # this in mind here is an example of how to configure + # "universal" build: + # + # ./Configure BSD-armv4 -march=armv6 -D__ARM_MAX_ARCH__=8 + # + inherit_from => [ "BSD-generic32" ], + asm_arch => 'armv4', + perlasm_scheme => "linux32", }, "bsdi-elf-gcc" => { @@ -1108,6 +1183,81 @@ my %targets = ( shared_target => "bsd-gcc-shared", shared_cflag => "-fPIC", }, +#### *BSD-nodef + "BSD-nodef-generic32" => { + # As for thread cflag. 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? + inherit_from => [ "BASE_unix" ], + CC => "cc", + CFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + cflags => threads("-pthread"), + cppflags => threads("-D_THREAD_SAFE -D_REENTRANT"), + ex_libs => add(threads("-pthread")), + enable => add("devcryptoeng"), + bn_ops => "BN_LLONG", + thread_scheme => "pthreads", + dso_scheme => "dlfcn", + shared_target => "bsd-gcc-nodef-shared", + shared_cflag => "-fPIC", + }, + "BSD-nodef-generic64" => { + inherit_from => [ "BSD-nodef-generic32" ], + bn_ops => "SIXTY_FOUR_BIT_LONG", + }, + + "BSD-nodef-x86" => { + inherit_from => [ "BSD-nodef-generic32" ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + asm_arch => 'x86', + perlasm_scheme => "a.out", + }, + "BSD-nodef-x86-elf" => { + inherit_from => [ "BSD-nodef-x86" ], + perlasm_scheme => "elf", + }, + + "BSD-nodef-sparcv8" => { + inherit_from => [ "BSD-nodef-generic32" ], + cflags => add("-mcpu=v8"), + lib_cppflags => add("-DB_ENDIAN"), + asm_arch => 'sparcv8', + perlasm_scheme => 'void', + }, + "BSD-nodef-sparc64" => { + # -DMD32_REG_T=int doesn't actually belong in sparc64 target, it + # simply *happens* to work around a compiler bug in gcc 3.3.3, + # triggered by RIPEMD160 code. + inherit_from => [ "BSD-nodef-generic64" ], + lib_cppflags => add("-DB_ENDIAN -DMD32_REG_T=int"), + bn_ops => "BN_LLONG", + asm_arch => 'sparcv9', + perlasm_scheme => 'void', + }, + + "BSD-nodef-ia64" => { + inherit_from => [ "BSD-nodef-generic64" ], + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + asm_arch => 'ia64', + perlasm_scheme => 'void', + }, + + "BSD-nodef-x86_64" => { + inherit_from => [ "BSD-nodef-generic64" ], + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + asm_arch => 'x86_64', + perlasm_scheme => "elf", + }, #### SCO/Caldera targets. # @@ -1283,6 +1433,19 @@ my %targets = ( AR => add("-X32"), RANLIB => add("-X32"), }, + # shared_target of "aix-solib" builds shared libraries packaged + # without archives. This improves the behavior of inter-library + # references (libssl depending on libcrypto) when building with + # shlib_variant. + # You'll get: libxxx.so (import library, used when linking applications) + # libxxx.so.ver (shared object) + # libxxx.a (static library archive) + # and for runtime, you only need libxxx.so.ver. libxxx.so and libxxx.a + # can be installed along with include files to make an SDK + "aix-cc-solib" => { + inherit_from => [ "aix-cc" ], + shared_target => "aix-solib", + }, "aix64-cc" => { inherit_from => [ "aix-common" ], CC => "cc", @@ -1318,6 +1481,10 @@ my %targets = ( AR => add("-X64"), RANLIB => add("-X64"), }, + "aix64-cc-solib" => { + inherit_from => [ "aix64-cc" ], + shared_target => "aix-solib", + }, # SIEMENS BS2000/OSD: an EBCDIC-based mainframe "BS2000-OSD" => { @@ -1618,6 +1785,7 @@ my %targets = ( CFLAGS => picker(default => "-Wall", debug => "-g -O0", release => "-O3"), + ex_libs => add("-lcrypt32"), lib_cppflags => "-DTERMIOS -DL_ENDIAN", sys_id => "CYGWIN", thread_scheme => "pthread", @@ -1731,20 +1899,53 @@ my %targets = ( }, ##### GNU Hurd - "hurd-x86" => { + "hurd-generic32" => { inherit_from => [ "BASE_unix" ], CC => "gcc", - CFLAGS => "-O3 -fomit-frame-pointer -Wall", + CXX => "g++", + CFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), + CXXFLAGS => picker(default => "-Wall", + debug => "-O0 -g", + release => "-O3"), cflags => threads("-pthread"), - lib_cppflags => "-DL_ENDIAN", + cxxflags => combine("-std=c++11", threads("-pthread")), ex_libs => add("-ldl", threads("-pthread")), - bn_ops => "BN_LLONG", - asm_arch => 'x86', - perlasm_scheme => 'elf', + bn_ops => "BN_LLONG RC4_CHAR", thread_scheme => "pthreads", dso_scheme => "dlfcn", shared_target => "linux-shared", shared_cflag => "-fPIC", + shared_ldflag => sub { $disabled{pinshared} ? () : "-Wl,-znodelete" }, + }, + + "hurd-generic64" => { + inherit_from => [ "hurd-generic32" ], + bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", + }, + + #### X86 / X86_64 targets + "hurd-x86" => { + inherit_from => [ "hurd-generic32" ], + CFLAGS => add(picker(release => "-fomit-frame-pointer")), + cflags => add("-m32"), + cxxflags => add("-m32"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "BN_LLONG", + asm_arch => 'x86', + perlasm_scheme => 'elf', + }, + + "hurd-x86_64" => { + inherit_from => [ "hurd-generic64" ], + cflags => add("-m64"), + cxxflags => add("-m64"), + lib_cppflags => add("-DL_ENDIAN"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + asm_arch => 'x86_64', + perlasm_scheme => 'elf', + multilib => "64", }, ##### VxWorks for various targets @@ -1897,6 +2098,7 @@ my %targets = ( cflag_incfirst => '/FIRST_INCLUDE=', lib_defines => add("OPENSSL_USE_NODELETE", + "_XOPEN_SOURCE", "_XOPEN_SOURCE_EXTENDED=1", sub { return vms_info()->{def_zlib} ? "LIBZ=\"\"\"".vms_info()->{def_zlib}."\"\"\"" : (); diff --git a/Configurations/15-android.conf b/Configurations/15-android.conf index 41ad9223e094..1de6b7a91571 100644 --- a/Configurations/15-android.conf +++ b/Configurations/15-android.conf @@ -12,6 +12,7 @@ arm64 => "aarch64-linux-android", mips => "mipsel-linux-android", mips64 => "mips64el-linux-android", + riscv64 => "riscv64-linux-android", x86 => "i686-linux-android", x86_64 => "x86_64-linux-android", ); @@ -270,6 +271,12 @@ my %targets = ( perlasm_scheme => "elf", }, + "android-riscv64" => { + inherit_from => [ "android" ], + asm_arch => 'riscv64', + perlasm_scheme => "linux64", + }, + #################################################################### # Backward compatible targets, (might) require $CROSS_SYSROOT # diff --git a/Configurations/15-ios.conf b/Configurations/15-ios.conf index 84c9cfeb3a14..6f33df381f7c 100644 --- a/Configurations/15-ios.conf +++ b/Configurations/15-ios.conf @@ -1,9 +1,10 @@ #### iPhoneOS/iOS # -# It takes recent enough Xcode to use following two targets. It shouldn't -# be a problem by now, but if they don't work, original targets below -# that depend on manual definition of environment variables should still -# work... +# `xcrun` targets require an Xcode that can determine the correct C compiler via +# `xcrun -sdk iphoneos`. This has been standard in Xcode for a while now - any recent +# Xcode should do. If the Xcode on the build machine doesn't support this then use +# the legacy targets at the end of this file. These require manual definition of +# environment variables. # my %targets = ( "ios-common" => { @@ -18,14 +19,14 @@ my %targets = ( # thus targeting iPhone pre-3GS, but it's assumed to be irrelevant # at this point. CC => "xcrun -sdk iphoneos cc", - cflags => add("-arch armv7 -mios-version-min=6.0.0 -fno-common"), + cflags => add("-arch armv7 -fno-common"), asm_arch => 'armv4', perlasm_scheme => "ios32", }, "ios64-xcrun" => { inherit_from => [ "ios-common" ], CC => "xcrun -sdk iphoneos cc", - cflags => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"), + cflags => add("-arch arm64 -fno-common"), bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR", asm_arch => 'aarch64', perlasm_scheme => "ios64", @@ -34,6 +35,30 @@ my %targets = ( inherit_from => [ "ios-common" ], CC => "xcrun -sdk iphonesimulator cc", }, + "iossimulator-arm64-xcrun" => { + inherit_from => [ "ios-common" ], + CC => "xcrun -sdk iphonesimulator cc", + cflags => add("-arch arm64 -fno-common"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + asm_arch => 'aarch64', + perlasm_scheme => "ios64", + }, + "iossimulator-i386-xcrun" => { + inherit_from => [ "ios-common" ], + CC => "xcrun -sdk iphonesimulator cc", + cflags => add("-arch i386 -fno-common"), + bn_ops => "BN_LLONG", + asm_arch => 'x86', + perlasm_scheme => "macosx", + }, + "iossimulator-x86_64-xcrun" => { + inherit_from => [ "ios-common" ], + CC => "xcrun -sdk iphonesimulator cc", + cflags => add("-arch x86_64 -fno-common"), + bn_ops => "SIXTY_FOUR_BIT_LONG", + asm_arch => 'x86_64', + perlasm_scheme => "macosx", + }, # It takes three prior-set environment variables to make it work: # # CROSS_COMPILE=/where/toolchain/is/usr/bin/ [note ending slash] diff --git a/Configurations/50-cppbuilder.conf b/Configurations/50-cppbuilder.conf index f19928cb03a2..92196857d38a 100644 --- a/Configurations/50-cppbuilder.conf +++ b/Configurations/50-cppbuilder.conf @@ -58,5 +58,64 @@ my %targets = ( shared_defflag => '', perl_platform => 'Windows::cppbuilder', uplink_arch => 'common', + }, + "BC-64" => { + inherit_from => [ "BASE_Windows" ], + sys_id => "WIN64", + bn_ops => "BN_LLONG", + thread_scheme => "winthreads", + cc => "bcc64", + CPP => "cpp64 -oCON -Sc -Sr", + defines => add("WIN32_LEAN_AND_MEAN", "OPENSSL_SYS_WIN64", + "L_ENDIAN", "DSO_WIN32", "_stricmp=stricmp", + "_strnicmp=strnicmp", "_setmode=setmode"), + cflags => picker(default => add("-q -c", + threads("-tM"), + shared("-tR")), + debug => "-Od -v -vi- -D_DEBUG", + release => "-O2"), + bin_cflags => "-tWC", + lib_cflags => shared("-tWD -D_WINDLL -D_DLL"), + coutflag => "-o", + + # -Sx isn't documented, but 'cpp64 -H -S' explains it: + # + # -Sx Omit preprocessed text in output + makedepcmd => "cpp64 -oCON -Sx -Hp", + makedep_scheme => "embarcadero", + + LD => "ilink64", + LDFLAGS => picker(default => "-x -Gn -q -w-dup", + debug => '-j"$(BDS)\lib\win64\debug" ' . + '-L"$(BDS)\lib\win64\debug" -v', + release => '-j"$(BDS)\lib\win64\release" ' . + '-L"$(BDS)\lib\win64\release"'), + bin_lflags => "-ap -Tpe c0x64.o wildargs.o", + ldoutflag => ",", + ldpostoutflag => ",,", + ld_resp_delim => " +\n", + ex_libs => add(sub { + my @ex_libs = ("import64.a", + ($disabled{shared} + ? ($disabled{threads} ? "cw64.a" : "cw64mt.a") + : ($disabled{threads} ? "cw64i.a" : "cw64mti.a"))); + push @ex_libs, "ws2_32.a" unless $disabled{sock}; + return join(" ", @ex_libs); + }), + AR => "tlib", + ARFLAGS => "/P256 /N /u", + ar_resp_delim => " &\n", + RC => "brcc32", + RCFLAGS => '-i"$(BDS)\include\windows\sdk"', + rcoutflag => "-fo", + shared_target => "win-shared", + shared_ldflag => "-aa -Tpd c0d64.o", + lddefflag => ",", + ldresflag => ",", + ld_implib_rule => 'implib -a $< $**', + dso_scheme => "win64", + shared_defflag => '', + perl_platform => 'Windows::cppbuilder', + uplink_arch => 'common', } ); diff --git a/Configurations/50-nonstop.conf b/Configurations/50-nonstop.conf index ed3fe828b318..a68f20085623 100644 --- a/Configurations/50-nonstop.conf +++ b/Configurations/50-nonstop.conf @@ -14,12 +14,15 @@ '_XOPEN_SOURCE', '_XOPEN_SOURCE_EXTENDED=1', '_TANDEM_SOURCE', + '__NSK_OPTIONAL_TYPES__', 'B_ENDIAN'), perl => '/usr/bin/perl', shared_target => 'nonstop-shared', shared_extension => ".so", ex_libs => add('-lrld'), enable => ['egd'], + # Not currently inherited + disable => ['atexit'], dso_scheme => 'DLFCN', sys_id => 'TANDEM', }, @@ -58,7 +61,7 @@ # Itanium + guardian: 'nonstop-archenv-itanium-guardian' => { template => 1, - defines => ['NO_GETPID', '_TANDEM_ARCH=2'], + defines => ['NO_GETPID'], cflags => '-Wtarget=tns/e -Wsystype=guardian', lflags => '-Weld="-set systype guardian"', shared_ldflag => '-Wshared -Weld="-soname $(@:lib%.so=%)"', @@ -69,7 +72,7 @@ # x86 + guardian: 'nonstop-archenv-x86_64-guardian' => { template => 1, - defines => ['NO_GETPID', '_TANDEM_ARCH=3'], + defines => ['NO_GETPID'], cflags => '-Wtarget=tns/x -Wsystype=guardian', lflags => '-Wxld="-set systype guardian"', shared_ldflag => '-Wshared -Wxld="-soname $(@:lib%.so=%)"', @@ -89,7 +92,6 @@ # Itanium + oss: 'nonstop-archenv-itanium-oss' => { template => 1, - defines => ['_TANDEM_ARCH=2'], cflags => '-Wtarget=tns/e -Wsystype=oss', lflags => '-Weld="-set systype oss"', shared_ldflag => '-Wshared', @@ -99,7 +101,6 @@ # x86_64 + oss: 'nonstop-archenv-x86_64-oss' => { template => 1, - defines => ['_TANDEM_ARCH=3'], cflags => '-Wtarget=tns/x -Wsystype=oss', lflags => '-Wxld="-set systype oss"', shared_ldflag => '-Wshared', @@ -171,21 +172,14 @@ '_REENTRANT', '_THREAD_SUPPORT_FUNCTIONS'], ex_libs => '-lput', }, - 'nonstop-model-spt' => { - template => 1, - defines => ['_SPT_MODEL_', - '_REENTRANT', '_ENABLE_FLOSS_THREADS'], - ex_libs => '-lspt', - }, - # Additional floss model that can be combined with any of the other models. - # If used without any of the other models, the entry that does so must - # disable threads. - 'nonstop-model-floss' => { + ###################################################################### + # Build models + 'nonstop-model-klt' => { template => 1, - defines => ['OPENSSL_TANDEM_FLOSS'], - includes => ['/usr/local/include'], - ex_libs => '-lfloss', + defines => ['_KLT_MODEL_', + '_REENTRANT', '_THREAD_SUPPORT_FUNCTIONS'], + ex_libs => '-lklt', }, ###################################################################### @@ -195,7 +189,7 @@ 'nonstop-archenv-x86_64-oss', 'nonstop-ilp32', 'nonstop-efloat-x86_64' ], - disable => ['threads'], + disable => ['threads','atexit'], }, 'nonstop-nsx_put' => { inherit_from => [ 'nonstop-common', @@ -204,6 +198,8 @@ 'nonstop-efloat-x86_64', 'nonstop-model-put' ], multilib => '-put', + multibin => '-put', + disable => ['atexit'], }, 'nonstop-nsx_64' => { inherit_from => [ 'nonstop-common', @@ -211,7 +207,8 @@ 'nonstop-lp64-x86_64', 'nonstop-efloat-x86_64' ], multilib => '64', - disable => ['threads'], + multibin => '64', + disable => ['threads','atexit'], }, 'nonstop-nsx_64_put' => { inherit_from => [ 'nonstop-common', @@ -220,35 +217,30 @@ 'nonstop-efloat-x86_64', 'nonstop-model-put' ], multilib => '64-put', + multibin => '64-put', + disable => ['atexit'], }, - 'nonstop-nsx_spt' => { + 'nonstop-nsx_64_klt' => { inherit_from => [ 'nonstop-common', 'nonstop-archenv-x86_64-oss', - 'nonstop-ilp32', + 'nonstop-lp64-x86_64', 'nonstop-efloat-x86_64', - 'nonstop-model-spt' ], - multilib => '-spt', - }, - 'nonstop-nsx_spt_floss' => { - inherit_from => [ 'nonstop-common', - 'nonstop-archenv-x86_64-oss', - 'nonstop-ilp32', - 'nonstop-efloat-x86_64', - 'nonstop-model-floss', - 'nonstop-model-spt'], - multilib => '-spt', + 'nonstop-model-klt' ], + multilib => '64-klt', + multibin => '64-klt', + disable => ['atexit'], }, 'nonstop-nsx_g' => { inherit_from => [ 'nonstop-common', 'nonstop-archenv-x86_64-guardian', 'nonstop-ilp32', 'nonstop-nfloat-x86_64' ], - disable => ['threads'], + disable => ['threads','atexit'], }, 'nonstop-nsx_g_tandem' => { inherit_from => [ 'nonstop-common', 'nonstop-archenv-x86_64-guardian', 'nonstop-ilp32', 'nonstop-tfloat-x86_64' ], - disable => ['threads'], + disable => ['threads','atexit'], }, 'nonstop-nsv' => { inherit_from => [ 'nonstop-nsx' ], @@ -258,7 +250,7 @@ 'nonstop-archenv-itanium-oss', 'nonstop-ilp32', 'nonstop-efloat-itanium' ], - disable => ['threads'], + disable => ['threads','atexit'], }, 'nonstop-nse_put' => { inherit_from => [ 'nonstop-common', @@ -267,6 +259,8 @@ 'nonstop-efloat-itanium', 'nonstop-model-put' ], multilib => '-put', + multibin => '-put', + disable => ['atexit'], }, 'nonstop-nse_64' => { inherit_from => [ 'nonstop-common', @@ -274,7 +268,8 @@ 'nonstop-lp64-itanium', 'nonstop-efloat-itanium' ], multilib => '64', - disable => ['threads'], + multibin => '64', + disable => ['threads','atexit'], }, 'nonstop-nse_64_put' => { inherit_from => [ 'nonstop-common', @@ -283,33 +278,6 @@ 'nonstop-efloat-itanium', 'nonstop-model-put' ], multilib => '64-put', - }, - 'nonstop-nse_spt' => { - inherit_from => [ 'nonstop-common', - 'nonstop-archenv-itanium-oss', - 'nonstop-ilp32', - 'nonstop-efloat-itanium', - 'nonstop-model-spt' ], - multilib => '-spt', - }, - 'nonstop-nse_spt_floss' => { - inherit_from => [ 'nonstop-common', - 'nonstop-archenv-itanium-oss', - 'nonstop-ilp32', - 'nonstop-efloat-itanium', - 'nonstop-model-floss', 'nonstop-model-spt' ], - multilib => '-spt', - }, - 'nonstop-nse_g' => { - inherit_from => [ 'nonstop-common', - 'nonstop-archenv-itanium-guardian', - 'nonstop-ilp32', 'nonstop-nfloat-itanium' ], - disable => ['threads'], - }, - - 'nonstop-nse_g_tandem' => { - inherit_from => [ 'nonstop-common', - 'nonstop-archenv-itanium-guardian', - 'nonstop-ilp32', 'nonstop-tfloat-itanium' ], - disable => ['threads'], + multibin => '64-put', + disable => ['atexit'], }, diff --git a/Configurations/50-win-onecore.conf b/Configurations/50-win-onecore.conf index efa2c837bcba..91e77b663fae 100644 --- a/Configurations/50-win-onecore.conf +++ b/Configurations/50-win-onecore.conf @@ -36,14 +36,13 @@ my %targets = ( # /NODEFAULTLIB:kernel32.lib is needed, because MSVCRT.LIB has # hidden reference to kernel32.lib, but we don't actually want # it in "onecore" build. - # /APPCONTAINER is needed for Universal Windows Platform compat - lflags => add("/NODEFAULTLIB:kernel32.lib /APPCONTAINER"), + lflags => add("/NODEFAULTLIB:kernel32.lib"), defines => add("OPENSSL_SYS_WIN_CORE"), ex_libs => "onecore.lib", }, "VC-WIN64A-ONECORE" => { inherit_from => [ "VC-WIN64A" ], - lflags => add("/NODEFAULTLIB:kernel32.lib /APPCONTAINER"), + lflags => add("/NODEFAULTLIB:kernel32.lib"), defines => add("OPENSSL_SYS_WIN_CORE"), ex_libs => "onecore.lib", }, @@ -69,7 +68,7 @@ my %targets = ( defines => add("_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE", "OPENSSL_SYS_WIN_CORE"), bn_ops => "BN_LLONG RC4_CHAR", - lflags => add("/NODEFAULTLIB:kernel32.lib /APPCONTAINER"), + lflags => add("/NODEFAULTLIB:kernel32.lib"), ex_libs => "onecore.lib", multilib => "-arm", }, @@ -78,7 +77,7 @@ my %targets = ( defines => add("_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE", "OPENSSL_SYS_WIN_CORE"), bn_ops => "SIXTY_FOUR_BIT RC4_CHAR", - lflags => add("/NODEFAULTLIB:kernel32.lib /APPCONTAINER"), + lflags => add("/NODEFAULTLIB:kernel32.lib"), ex_libs => "onecore.lib", multilib => "-arm64", }, diff --git a/Configurations/README.md b/Configurations/README.md index de3d8bad8a02..83bcc960626b 100644 --- a/Configurations/README.md +++ b/Configurations/README.md @@ -145,7 +145,7 @@ In each table entry, the following keys are significant: would then be 'OPENSSL_ABC_' rather than the default 'OPENSSL_'. The string inserted into symbol versions is obtained by mapping all - letters in the "variant" identifier to upper case + letters in the "variant" identifier to uppercase and all non-alphanumeric characters to '_'. thread_scheme => The type of threads is used on the @@ -203,6 +203,13 @@ In each table entry, the following keys are significant: to have the different variants in different directories. + multibin => On systems that support having multiple + implementations of a library and binaries + (typically a 32-bit and a 64-bit variant), + this is used to have the different variants + in different binary directories. This setting + works in conjunction with multilib. + bn_ops => Building options (was just bignum options in the earlier history of this option, hence the name). This is a string of words that describe @@ -561,7 +568,7 @@ They are all expected to return a string with the lines they produce. obj2lib(lib => "PATH/TO/libfile", objs => [ "PATH/TO/objectfile", ... ]); - 'lib' has the intended library file name *without* + 'lib' has the intended library filename *without* extension, obj2lib is expected to add that. 'objs' has the list of object files to build this library. @@ -584,7 +591,7 @@ They are all expected to return a string with the lines they produce. objs => [ "PATH/TO/objectfile", ... ], deps => [ "PATH/TO/otherlibfile", ... ]); - 'lib' has the base (static) library ffile name + 'lib' has the base (static) library filename *without* extension. This is useful in case supporting files are needed (such as import libraries on Windows). @@ -617,7 +624,7 @@ They are all expected to return a string with the lines they produce. objs => [ "PATH/TO/objectfile", ... ], deps => [ "PATH/TO/libfile", ... ]); - 'bin' has the intended executable file name + 'bin' has the intended executable filename *without* extension, obj2bin is expected to add that. 'objs' has the list of object files to build this library. 'deps' has the list of library files @@ -632,7 +639,7 @@ They are all expected to return a string with the lines they produce. in2script(script => "PATH/TO/scriptfile", sources => [ "PATH/TO/infile", ... ]); - 'script' has the intended script file name. + 'script' has the intended script filename. 'sources' has the list of source files to build the resulting script from. diff --git a/Configurations/descrip.mms.tmpl b/Configurations/descrip.mms.tmpl index c722a754b75e..db6a1b17997c 100644 --- a/Configurations/descrip.mms.tmpl +++ b/Configurations/descrip.mms.tmpl @@ -205,13 +205,16 @@ @cnf_ldflags, '$(LDFLAGS)'); our $bin_ex_libs = join('', @cnf_ex_libs, '$(EX_LIBS)'); - # This is a horrible hack, but is needed because recursive inclusion of files - # in different directories does not work well with VMS C. We try to help by - # specifying extra relative directories. They must always be in Unix format, - # relative to the directory where the .c file is located. The logic is that - # any inclusion, merged with one of these relative directories, will find the - # requested inclusion file. - foreach (grep /\[\.crypto\.async\.arch\].*\.o$/, keys %{$unified_info{sources}}) { + # These are horrible hacks, but are needed because recursive inclusion of + # files in different directories does not work well with VMS C. We try to + # help by specifying extra relative directories. They must always be in Unix + # format, relative to the directory where the .c file is located. The logic + # is that any inclusion, merged with one of these relative directories, will + # find the requested inclusion file. + # In the regexps, it's advisable to always start the file name with .*?, as + # the C source to OBJ file translation adds stuff at the beginning of the, + # name, such as [.ssl]bio_ssl.c -> [.ssl]libssl-shlib-bio_ssl.OBJ + foreach (grep /\[\.crypto\.async\.arch\].*?\.o$/, keys %{$unified_info{sources}}) { my $obj = platform->obj($_); push @{$unified_info{includes_extra}->{$obj}}, qw(../); } @@ -223,7 +226,20 @@ my $obj = platform->obj($_); push @{$unified_info{includes_extra}->{$obj}}, qw(../); } - foreach (grep /\[\.ssl\.(?:record|statem)\].*?\.o$/, keys %{$unified_info{sources}}) { + foreach (grep /\[\.ssl\].*?\.o$/, keys %{$unified_info{sources}}) { + my $obj = platform->obj($_); + # Most of the files in [.ssl] include "ssl_local.h" which includes things + # like "record/record.h". Adding "./" as an inclusion directory helps + # making this sort of header from these directories. + push @{$unified_info{includes_extra}->{$obj}}, qw(./); + + # Additionally, an increasing amount of files in [.ssl] include + # "quic/quic_local.h", which in turn includes "../ssl_local.h". Adding + # "./quic" as an inclusion directory helps making this sort of header + # from these directories. + push @{$unified_info{includes_extra}->{$obj}}, qw(./quic); + } + foreach (grep /\[\.ssl\.(?:quic|record|statem|rio)\].*?\.o$/, keys %{$unified_info{sources}}) { my $obj = platform->obj($_); # Most of the files in [.ssl.record] and [.ssl.statem] include # "../ssl_local.h", which includes things like "record/record.h". @@ -232,13 +248,35 @@ push @{$unified_info{includes_extra}->{$obj}}, qw(../); } + foreach (grep /\[\.ssl\.record\.methods\].*?\.o$/, keys %{$unified_info{sources}}) { + my $obj = platform->obj($_); + # Most of the files in [.ssl.record.methods] include "../../ssl_local.h" + # which includes things like "record/record.h". Adding "../../" as an + # inclusion directory helps making this sort of header from these + # directories. But this gets worse; through a series of inclusions, + # all of them based on the relative directory of the object file, there's + # a need to deal with an inclusion of "../ssl_local.h" as well. + push @{$unified_info{includes_extra}->{$obj}}, qw(../../), qw(../); + } foreach (grep /\[\.test\].*?\.o$/, keys %{$unified_info{sources}}) { my $obj = platform->obj($_); push @{$unified_info{includes_extra}->{$obj}}, qw(../ssl ./helpers); + # Some of the sources in [.test] also include headers like + # "../ssl/record/methods/recmethod_local.h", which in turn might include + # "../../ssl_local.h", so these object files need yet another hack. + # We could make this specific to just the object files that are affected + # directly, but that would end up with more whack-a-mole of this sort, so + # nah, we do it broadly. + push @{$unified_info{includes_extra}->{$obj}}, qw(../ssl/record/methods); + # Similarly, some include "../ssl/ssl_local.h", and somewhere down the + # line, "quic/quic_local.h" gets included, which includes "../ssl_local.h" + # The problem is fixed by adding ../ssl/quic too. + push @{$unified_info{includes_extra}->{$obj}}, qw(../ssl/quic); } foreach (grep /\[\.test\.helpers\].*?\.o$/, keys %{$unified_info{sources}}) { my $obj = platform->obj($_); - push @{$unified_info{includes_extra}->{$obj}}, qw(../../ssl); + push @{$unified_info{includes_extra}->{$obj}}, + qw(../../ssl ../../ssl/quic); } # This makes sure things get built in the order they need @@ -436,7 +474,7 @@ NODEBUG=@ $(NODEBUG) ! Set up logical names for the libraries, so LINK and $(NODEBUG) ! running programs can use them. $(NODEBUG) ! - $(NODEBUG) {- join("\n\t\$(NODEBUG) ", map { "DEFINE ".uc($_)." 'F\$ENV(\"DEFAULT\")'".uc($_)."\$(SHLIB_EXT)" } @shlibs) || "!" -} + $(NODEBUG) {- join("\n\t\$(NODEBUG) ", map { "DEFINE ".uc($_)." 'F\$ENV(\"DEFAULT\")'".uc($_).".EXE" } @shlibs) || "!" -} .LAST : $(NODEBUG) {- join("\n\t\$(NODEBUG) ", map { "DEASSIGN ".uc($_) } @shlibs) || "!" -} @@ -1030,16 +1068,48 @@ EOF my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, "util", "dofile.pl")), rel2abs($config{builddir})); - my @perlmodules = ( 'configdata.pm', - grep { $_ =~ m|\.pm$| } @{$args{deps}} ); - my %perlmoduleincs = map { '"-I'.dirname($_).'"' => 1 } @perlmodules; + my @perlmodules = (); + my %perlmoduleincs = (); + my %perlmoduledeps = (); + foreach my $x (('configdata.pm', @{$args{deps}})) { + # Compute (i)nclusion directory, (m)odule name and (d)ependency + my $i, $m, $d; + if ($x =~ /\|/) { + $i = $`; + $d = $'; + + # Massage the module part to become a real perl module spec + $m = $d; + $m =~ s|\.pm$||; + # Directory specs are :: in perl package names + $m =~ s|/|::|g; + + # Full file name of the dependency + $d = catfile($i, $d) if $i; + } elsif ($x =~ /\.pm$/) { + $i = dirname($x); + $m = basename($x, '.pm'); + $d = $x; + } else { + # All other dependencies are simply collected + $d = $x; + } + push @perlmodules, '"-M'.$m.'"' if $m; + $perlmoduledeps{$d} = 1; + $perlmoduleincs{'"-I'.$i.'"'} = 1 if $i; + } + my @decc_include_data = make_decc_include_files(dirname($args{src}), dirname($gen0)); my $decc_include_scripture = pop @decc_include_data; - $deps = join(' ', $deps, @decc_include_data, - compute_platform_depends(@perlmodules)); - @perlmodules = map { '"-M'.basename($_, '.pm').'"' } @perlmodules; - my $perlmodules = join(' ', '', sort keys %perlmoduleincs, @perlmodules); + # Because of the special treatment of dependencies, we need to + # recompute $deps completely + my $deps + = join(" ", @decc_include_data, + compute_platform_depends(@{$args{generator_deps}}, + sort keys %perlmoduledeps)); + my $perlmodules = join(' ', '', ( sort keys %perlmoduleincs ), @perlmodules); + return <<"EOF"; $args{src} : $gen0 $deps @@ -1241,16 +1311,28 @@ EOF # previous line's file spec as default, so if no directory spec # is present in the current line and the previous line has one that # doesn't apply, you're in for a surprise. + # Furthermore, we collect all object files and static libraries in + # an explicit cluster, to make it clear to the linker that these files + # shall be processed before shareable images. + # The shareable images are used with /SELECTIVE, to avoid warnings of + # multiply defined symbols when the module object files override some + # symbols that are present in the shareable image. my $write_opt1 = - join(",-\"\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; - "WRITE OPT_FILE \"$x" } @objs). - "\""; + join(",-\"\n\t", + "\@ WRITE OPT_FILE \"CLUSTER=_,,", + (map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + "\@ WRITE OPT_FILE \"$x" } @objs), + (map { my $x = ($_->{lib} =~ /\[/) ? $_->{lib} : "[]".$_->{lib}; + "\@ WRITE OPT_FILE \"$x/LIB" } + grep { $_->{lib} =~ m|\.OLB$| } + @deps)) + ."\""; my $write_opt2 = - join("\n\t", map { my $x = $_->{lib} =~ /\[/ - ? $_->{lib} : "[]".$_->{lib}; - $x =~ s|(\.EXE)|$1/SHARE|; - $x =~ s|(\.OLB)|$1/LIB|; - "WRITE OPT_FILE \"$x\"" } @deps) + join("\n\t", + (map { my $x = ($_->{lib} =~ /\[/) ? $_->{lib} : "[]".$_->{lib}; + "\@ WRITE OPT_FILE \"$x/SHARE/SELECTIVE\"" } + grep { $_->{lib} =~ m|\.EXE$| } + @deps)) || "\@ !"; return <<"EOF" $dso : $deps @@ -1305,30 +1387,30 @@ EOF # is present in the current line and the previous line has one that # doesn't apply, you're in for a surprise. my $write_opt1 = - join(",-\"\n\t", map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; - "\@ WRITE OPT_FILE \"$x" } @objs). - "\""; + "\@ WRITE OPT_FILE \"CASE_SENSITIVE=YES\"\n\t" + .join(",-\"\n\t", + "\@ WRITE OPT_FILE \"CLUSTER=_,,", + (map { my $x = $_ =~ /\[/ ? $_ : "[]".$_; + "\@ WRITE OPT_FILE \"$x" } @objs), + (map { my $x = ($_->{lib} =~ /\[/) ? $_->{lib} : "[]".$_->{lib}; + # Special hack to include the MAIN object module + # explicitly, if it's known that there is one. + # |incmain| is defined in the rule generation further + # down, with the necessary /INCLUDE=main option unless + # the program has been determined to have a main function + # already. + $_->{attrs}->{has_main} + ? "\@ WRITE OPT_FILE \"$x/LIB''incmain'" + : "\@ WRITE OPT_FILE \"$x/LIB" } + grep { $_->{lib} =~ m|\.OLB$| } + @deps)) + ."\""; my $write_opt2 = - join("\n\t", "WRITE OPT_FILE \"CASE_SENSITIVE=YES\"", - map { my @lines = (); - use Data::Dumper; - my $x = $_->{lib} =~ /\[/ - ? $_->{lib} : "[]".$_->{lib}; - if ($x =~ m|\.EXE$|) { - push @lines, "\@ WRITE OPT_FILE \"$x/SHARE\""; - } elsif ($x =~ m|\.OLB$|) { - # Special hack to include the MAIN object - # module explicitly. This will only be done - # if there isn't a 'main' in the program's - # object modules already. - my $main = $_->{attrs}->{has_main} - ? '/INCLUDE=main' : ''; - push @lines, - "\@ IF nomain THEN WRITE OPT_FILE \"$x/LIB$main\"", - "\@ IF .NOT. nomain THEN WRITE OPT_FILE \"$x/LIB\"" - } - @lines - } @deps) + join("\n\t", + (map { my $x = $_->{lib} =~ /\[/ ? $_->{lib} : "[]".$_->{lib}; + "\@ WRITE OPT_FILE \"$x/SHARE/SELECTIVE\"" } + grep { $_->{lib} =~ m|\.EXE$| } + @deps)) || "\@ !"; # The linking commands looks a bit complex, but it's for good reason. # When you link, say, foo.obj, bar.obj and libsomething.exe/share, and @@ -1351,6 +1433,8 @@ EOF return <<"EOF" $bin : $deps $analyse_objs + @ incmain = "/INCLUDE=main" + @ IF .NOT. nomain THEN incmain = "" @ OPEN/WRITE/SHARE=READ OPT_FILE $binname.OPT $write_opt1 $write_opt2 diff --git a/Configurations/platform/AIX.pm b/Configurations/platform/AIX.pm index c6c1437f962a..709242712de0 100644 --- a/Configurations/platform/AIX.pm +++ b/Configurations/platform/AIX.pm @@ -13,12 +13,16 @@ require platform::Unix; use configdata; sub dsoext { '.so' } -sub shlibextsimple { '.a' } +sub shlibextsimple { return '.so' if $target{shared_target} eq "aix-solib"; + '.a'} # In shared mode, the default static library names clashes with the final # "simple" full shared library name, so we add '_a' to the basename of the -# static libraries in that case. +# static libraries in that case, unless in solib mode (using only .so +# files for shared libraries, and not packaging them inside archives) sub staticname { + return platform::Unix->staticname($_[1]) if $target{shared_target} eq "aix-solib"; + # Non-installed libraries are *always* static, and their names remain # the same, except for the mandatory extension my $in_libname = platform::BASE->staticname($_[1]); @@ -27,3 +31,17 @@ sub staticname { return platform::BASE->staticname($_[1]) . ($disabled{shared} ? '' : '_a'); } + +# In solib mode, we do not install the simple symlink (we install the import +# library). In regular mode, we install the symlink. +sub sharedlib_simple { + return undef if $target{shared_target} eq "aix-solib"; + return platform::Unix->sharedlib_simple($_[1], $_[0]->shlibextsimple()); +} + +# In solib mode, we install the import library. In regular mode, we have +# no import library. +sub sharedlib_import { + return platform::Unix->sharedlib_simple($_[1]) if $target{shared_target} eq "aix-solib"; + return undef; +} diff --git a/Configurations/platform/Unix.pm b/Configurations/platform/Unix.pm index 8db0ed912e3a..6746af8c71ec 100644 --- a/Configurations/platform/Unix.pm +++ b/Configurations/platform/Unix.pm @@ -73,7 +73,9 @@ sub sharedlib_simple { my $name = $_[0]->sharedname($_[1]); my $simplename = $_[0]->sharedname_simple($_[1]); my $ext = $_[0]->shlibext(); - my $simpleext = $_[0]->shlibextsimple(); + # Allow override of the extension passed in as parameter + my $simpleext = $_[2]; + $simpleext = $_[0]->shlibextsimple() unless defined $simpleext; return undef unless defined $simplename && defined $name; return undef if ($name eq $simplename && $ext eq $simpleext); diff --git a/Configurations/shared-info.pl b/Configurations/shared-info.pl index edd16f405594..caf6f901261f 100644 --- a/Configurations/shared-info.pl +++ b/Configurations/shared-info.pl @@ -1,6 +1,6 @@ #! /usr/bin/env perl # -*- mode: perl; -*- -# 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 @@ -40,6 +40,12 @@ my %shared_info; }; }, 'bsd-gcc-shared' => sub { return $shared_info{'linux-shared'}; }, + 'bsd-gcc-nodef-shared' => sub { + return { + %{$shared_info{'gnu-shared'}}, + shared_defflags => '-Wl,--version-script=', + }; + }, 'darwin-shared' => { module_ldflags => '-bundle', shared_ldflag => '-dynamiclib -current_version $(SHLIB_VERSION_NUMBER) -compatibility_version $(SHLIB_VERSION_NUMBER)', diff --git a/Configurations/unix-Makefile.tmpl b/Configurations/unix-Makefile.tmpl index d2b0797a7edf..e85763ccf835 100644 --- a/Configurations/unix-Makefile.tmpl +++ b/Configurations/unix-Makefile.tmpl @@ -11,8 +11,13 @@ sub windowsdll { $config{target} =~ /^(?:Cygwin|mingw)/ } # Shared AIX support is special. We put libcrypto[64].so.ver into - # libcrypto.a and use libcrypto_a.a as static one. - sub sharedaix { !$disabled{shared} && $config{target} =~ /^aix/ } + # libcrypto.a and use libcrypto_a.a as static one, unless using + # shared_target style aix-solib. In that mode, create + # libcrypto.so as a link-import library that inserts runtime + # dependencies on libcrypto.so.ver, and the static library is + # named libcrypto.a. + sub sharedaix { !$disabled{shared} && $target{shared_target} =~ /^aix(?!-solib$)/ } + sub sharedaix_solib { !$disabled{shared} && $target{shared_target} =~ /^aix-solib$/ } our $sover_dirname = platform->shlib_version_as_filename(); @@ -20,8 +25,9 @@ # to. You're welcome. sub dependmagic { my $target = shift; + my $help = shift; - return "$target: build_generated\n\t\"\$(MAKE)\" depend && \"\$(MAKE)\" _$target\n_$target"; + return "$target: build_generated ## $help\n\t\"\$(MAKE)\" depend && \"\$(MAKE)\" _$target\n_$target"; } our $COLUMNS = $ENV{COLUMNS}; @@ -198,6 +204,18 @@ INSTALL_PROGRAMS={- grep { !$unified_info{attributes}->{programs}->{$_}->{noinst} } @{$unified_info{programs}})) -} +INSTALL_EXPORTERS_PKGCONFIG={- + join(" \\\n" . ' ' x 28, + fill_lines(" ", $COLUMNS - 28, + grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'pkg-config'} + sort keys %{$unified_info{generate}})) +-} +INSTALL_EXPORTERS_CMAKE={- + join(" \\\n" . ' ' x 24, + fill_lines(" ", $COLUMNS - 24, + grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'cmake'} + sort keys %{$unified_info{generate}})) +-} BIN_SCRIPTS={- join(" \\\n" . ' ' x 12, fill_lines(" ", $COLUMNS - 12, @@ -311,6 +329,17 @@ MODULESDIR=$(libdir)/ossl-modules # libraries and applications LIBRPATH=$(libdir) +BINDIR={- our $bindir = $config{bindir}; + unless ($bindir) { + $bindir = "bin$target{multibin}"; + } + file_name_is_absolute($bindir) ? "" : $bindir -} +bindir={- file_name_is_absolute($bindir) + ? $bindir : '$(INSTALLTOP)/$(BINDIR)' -} + +PKGCONFIGDIR=$(libdir)/pkgconfig +CMAKECONFIGDIR=$(libdir)/cmake/OpenSSL + MANDIR=$(INSTALLTOP)/share/man DOCDIR=$(INSTALLTOP)/share/doc/$(BASENAME) HTMLDIR=$(DOCDIR)/html @@ -344,6 +373,7 @@ CFLAGS={- join(' ', @{$config{CFLAGS}}) -} CXXFLAGS={- join(' ', @{$config{CXXFLAGS}}) -} LDFLAGS= {- join(' ', @{$config{LDFLAGS}}) -} EX_LIBS= {- join(' ', @{$config{LDLIBS}}) -} +OBJCOPY={- $config{OBJCOPY} -} MAKEDEPEND={- $config{makedepcmd} -} @@ -496,18 +526,28 @@ LANG=C # The main targets ################################################### -{- dependmagic('build_sw'); -}: build_libs_nodep build_modules_nodep build_programs_nodep link-utils -{- dependmagic('build_libs'); -}: build_libs_nodep -{- dependmagic('build_modules'); -}: build_modules_nodep -{- dependmagic('build_programs'); -}: build_programs_nodep +##@ Software +{- dependmagic('build_sw', 'Build all the software (default target)'); -}: build_libs_nodep build_modules_nodep build_programs_nodep link-utils +{- dependmagic('build_libs', 'Build the libraries libssl and libcrypto'); -}: build_libs_nodep +{- dependmagic('build_modules', 'Build the modules (i.e. providers and engines)'); -}: build_modules_nodep +{- dependmagic('build_programs', 'Build the openssl executables and scripts'); -}: build_programs_nodep + +all: build_sw {- "build_docs" if !$disabled{docs}; -} ## Build software and documentation +debuginfo: $(SHLIBS) + @set -e; for i in $(SHLIBS); do \ + $(OBJCOPY) --only-keep-debug $$i $$i.debug; \ + $(OBJCOPY) --strip-debug --add-gnu-debuglink=$$i.debug $$i; \ + done; + +##@ Documentation build_generated_pods: $(GENERATED_PODS) -build_docs: build_man_docs build_html_docs -build_man_docs: $(MANDOCS1) $(MANDOCS3) $(MANDOCS5) $(MANDOCS7) -build_html_docs: $(HTMLDOCS1) $(HTMLDOCS3) $(HTMLDOCS5) $(HTMLDOCS7) +build_docs: build_man_docs build_html_docs ## Create documentation +build_man_docs: $(MANDOCS1) $(MANDOCS3) $(MANDOCS5) $(MANDOCS7) ## Create manpages +build_html_docs: $(HTMLDOCS1) $(HTMLDOCS3) $(HTMLDOCS5) $(HTMLDOCS7) ## Create HTML documentation build_generated: $(GENERATED_MANDATORY) -build_libs_nodep: libcrypto.pc libssl.pc openssl.pc +build_libs_nodep: $(LIBS) {- join(" ",map { platform->sharedlib_simple($_) // platform->sharedlib_import($_) // platform->sharedlib($_) // () } @{$unified_info{libraries}}) -} build_modules_nodep: $(MODULES) build_programs_nodep: $(PROGRAMS) $(SCRIPTS) @@ -523,10 +563,14 @@ build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) build_docs @echo " then make will fail..." @ : {- output_on() if $disabled{makedepend}; "" -} -all: build_sw build_docs +##@ Help +.PHONY: help +help: ## Show this help screen + @$(PERL) $(SRCDIR)/util/help.pl $(BLDDIR)/Makefile -test: tests -{- dependmagic('tests'); -}: build_programs_nodep build_modules_nodep link-utils +##@ Testing +test: tests ## Run tests (alias of "tests") +{- dependmagic('tests', 'Run tests'); -}: build_programs_nodep build_modules_nodep link-utils "$(MAKE)" run_tests run_tests: FORCE @ : {- output_off() if $disabled{tests}; "" -} @@ -540,16 +584,14 @@ run_tests: FORCE @echo "Tests are not supported with your chosen Configure options" @ : {- output_on() if !$disabled{tests}; "" -} -list-tests: +list-tests: ## List available tests that can be invoked via "make test TESTS=" @ : {- output_off() if $disabled{tests}; "" -} "$(MAKE)" run_tests TESTS=list @ : {- if ($disabled{tests}) { output_on(); } else { output_off(); } "" -} @echo "Tests are not supported with your chosen Configure options" @ : {- output_on() if !$disabled{tests}; "" -} -install: install_sw install_ssldirs install_docs {- $disabled{fips} ? "" : "install_fips" -} - -uninstall: uninstall_docs uninstall_sw {- $disabled{fips} ? "" : "uninstall_fips" -} +##@ Workspace cleaning libclean: @set -e; for s in $(SHLIB_INFO); do \ @@ -574,7 +616,7 @@ libclean: $(RM) $(LIBS) $(RM) *{- platform->defext() -} -clean: libclean +clean: libclean ## Clean the workspace, keep the configuration $(RM) $(HTMLDOCS1) $(RM) $(HTMLDOCS3) $(RM) $(HTMLDOCS5) @@ -591,10 +633,9 @@ clean: libclean $(RM) tags TAGS doc-nits md-nits $(RM) -r test/test-runs $(RM) providers/fips*.new - $(RM) openssl.pc libcrypto.pc libssl.pc -find . -type l \! -name '.*' -exec $(RM) {} \; -distclean: clean +distclean: clean ## Clean and remove the configuration $(RM) include/openssl/configuration.h $(RM) configdata.pm $(RM) Makefile @@ -607,14 +648,19 @@ depend: Makefile @: {- output_on() if $disabled{makedepend}; "" -} # Install helper targets ############################################# +##@ Installation -install_sw: install_dev install_engines install_modules install_runtime +install: install_sw install_ssldirs {- "install_docs" if !$disabled{docs}; -} {- $disabled{fips} ? "" : "install_fips" -} ## Install software and documentation, create OpenSSL directories -uninstall_sw: uninstall_runtime uninstall_modules uninstall_engines uninstall_dev +uninstall: {- "uninstall_docs" if !$disabled{docs}; -} uninstall_sw {- $disabled{fips} ? "" : "uninstall_fips" -} ## Uninstall software and documentation -install_docs: install_man_docs install_html_docs +install_sw: install_dev install_engines install_modules install_runtime ## Install just the software and libraries -uninstall_docs: uninstall_man_docs uninstall_html_docs +uninstall_sw: uninstall_runtime uninstall_modules uninstall_engines uninstall_dev ## Uninstall the software and libraries + +install_docs: install_man_docs install_html_docs ## Install manpages and HTML documentation + +uninstall_docs: uninstall_man_docs uninstall_html_docs ## Uninstall manpages and HTML documentation $(RM) -r "$(DESTDIR)$(DOCDIR)" {- output_off() if $disabled{fips}; "" -} @@ -725,12 +771,12 @@ install_dev: install_runtime_libs fn1=`basename "$$s1"`; \ fn2=`basename "$$s2"`; \ fn3=`basename "$$s3"`; \ - : {- output_off(); output_on() unless windowsdll() or sharedaix(); "" -}; \ + : {- output_off(); output_on() unless windowsdll() or sharedaix() or sharedaix_solib(); "" -}; \ if [ "$$fn2" != "" ]; then \ $(ECHO) "link $(DESTDIR)$(libdir)/$$fn2 -> $(DESTDIR)$(libdir)/$$fn1"; \ ln -sf $$fn1 "$(DESTDIR)$(libdir)/$$fn2"; \ fi; \ - : {- output_off() unless windowsdll() or sharedaix(); output_on() if windowsdll(); "" -}; \ + : {- output_off() unless windowsdll() or sharedaix() or sharedaix_solib(); output_on() if windowsdll() or sharedaix_solib(); "" -}; \ if [ "$$fn3" != "" ]; then \ $(ECHO) "install $$s3 -> $(DESTDIR)$(libdir)/$$fn3"; \ cp $$s3 "$(DESTDIR)$(libdir)/$$fn3.new"; \ @@ -738,7 +784,7 @@ install_dev: install_runtime_libs mv -f "$(DESTDIR)$(libdir)/$$fn3.new" \ "$(DESTDIR)$(libdir)/$$fn3"; \ fi; \ - : {- output_off() if windowsdll(); output_on() if sharedaix(); "" -}; \ + : {- output_off() if windowsdll() or sharedaix_solib(); output_on() if sharedaix(); "" -}; \ a="$(DESTDIR)$(libdir)/$$fn2"; \ $(ECHO) "install $$s1 -> $$a"; \ if [ -f $$a ]; then ( trap "rm -rf /tmp/ar.$$$$" INT 0; \ @@ -756,16 +802,20 @@ install_dev: install_runtime_libs : {- output_off() if sharedaix(); output_on(); "" -}; \ done @ : {- output_on() if $disabled{shared}; "" -} - @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)/pkgconfig" - @$(ECHO) "install libcrypto.pc -> $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc" - @cp libcrypto.pc "$(DESTDIR)$(libdir)/pkgconfig" - @chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc" - @$(ECHO) "install libssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/libssl.pc" - @cp libssl.pc "$(DESTDIR)$(libdir)/pkgconfig" - @chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc" - @$(ECHO) "install openssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/openssl.pc" - @cp openssl.pc "$(DESTDIR)$(libdir)/pkgconfig" - @chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc" + @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(PKGCONFIGDIR)" + @for e in $(INSTALL_EXPORTERS_PKGCONFIG); do \ + fn=`basename $$e`; \ + $(ECHO) "install $$e -> $(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \ + cp $$e "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \ + chmod 644 "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \ + done + @$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(CMAKECONFIGDIR) + @for e in $(INSTALL_EXPORTERS_CMAKE); do \ + fn=`basename $$e`; \ + $(ECHO) "install $$e -> $(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \ + cp $$e $(DESTDIR)$(CMAKECONFIGDIR)/$$fn; \ + chmod 644 $(DESTDIR)$(CMAKECONFIGDIR)/$$fn; \ + done uninstall_dev: uninstall_runtime_libs @$(ECHO) "*** Uninstalling development files" @@ -809,10 +859,16 @@ uninstall_dev: uninstall_runtime_libs : {- output_on() unless windowsdll(); "" -}; \ done @ : {- output_on() if $disabled{shared}; "" -} - $(RM) "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc" - $(RM) "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc" - $(RM) "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc" - -$(RMDIR) "$(DESTDIR)$(libdir)/pkgconfig" + @for e in $(INSTALL_EXPORTERS_PKGCONFIG); do \ + fn=`basename "$$e"`; \ + $(RM) "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \ + done + @for e in $(INSTALL_EXPORTERS_CMAKE); do \ + fn=`basename "$$e"`; \ + $(RM) "$(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \ + done + -$(RMDIR) "$(DESTDIR)$(PKGCONFIGDIR)" + -$(RMDIR) "$(DESTDIR)$(CMAKECONFIGDIR)" -$(RMDIR) "$(DESTDIR)$(libdir)" _install_modules_deps: install_runtime_libs build_modules @@ -872,18 +928,18 @@ install_runtime_libs: build_libs @ : {- output_off() if windowsdll(); "" -} @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)" @ : {- output_on() if windowsdll(); output_off() unless windowsdll(); "" -} - @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin" + @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(bindir)/" @ : {- output_on() unless windowsdll(); "" -} @$(ECHO) "*** Installing runtime libraries" @set -e; for s in dummy $(INSTALL_SHLIBS); do \ if [ "$$s" = "dummy" ]; then continue; fi; \ fn=`basename $$s`; \ : {- output_off() unless windowsdll(); "" -}; \ - $(ECHO) "install $$s -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - cp $$s "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \ - "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "install $$s -> $(DESTDIR)$(bindir)/$$fn"; \ + cp $$s "$(DESTDIR)$(bindir)/$$fn.new"; \ + chmod 755 "$(DESTDIR)$(bindir)/$$fn.new"; \ + mv -f "$(DESTDIR)$(bindir)/$$fn.new" \ + "$(DESTDIR)$(bindir)/$$fn"; \ : {- output_on() unless windowsdll(); "" -}{- output_off() if windowsdll(); "" -}; \ $(ECHO) "install $$s -> $(DESTDIR)$(libdir)/$$fn"; \ cp $$s "$(DESTDIR)$(libdir)/$$fn.new"; \ @@ -895,25 +951,25 @@ install_runtime_libs: build_libs install_programs: install_runtime_libs build_programs @[ -n "$(INSTALLTOP)" ] || (echo INSTALLTOP should not be empty; exit 1) - @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(INSTALLTOP)/bin" + @$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(bindir)" @$(ECHO) "*** Installing runtime programs" @set -e; for x in dummy $(INSTALL_PROGRAMS); do \ if [ "$$x" = "dummy" ]; then continue; fi; \ fn=`basename $$x`; \ - $(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \ - "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "install $$x -> $(DESTDIR)$(bindir)/$$fn"; \ + cp $$x "$(DESTDIR)$(bindir)/$$fn.new"; \ + chmod 755 "$(DESTDIR)$(bindir)/$$fn.new"; \ + mv -f "$(DESTDIR)$(bindir)/$$fn.new" \ + "$(DESTDIR)$(bindir)/$$fn"; \ done @set -e; for x in dummy $(BIN_SCRIPTS); do \ if [ "$$x" = "dummy" ]; then continue; fi; \ fn=`basename $$x`; \ - $(ECHO) "install $$x -> $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - cp $$x "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - chmod 755 "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new"; \ - mv -f "$(DESTDIR)$(INSTALLTOP)/bin/$$fn.new" \ - "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "install $$x -> $(DESTDIR)$(bindir)/$$fn"; \ + cp $$x "$(DESTDIR)$(bindir)/$$fn.new"; \ + chmod 755 "$(DESTDIR)$(bindir)/$$fn.new"; \ + mv -f "$(DESTDIR)$(bindir)/$$fn.new" \ + "$(DESTDIR)$(bindir)/$$fn"; \ done uninstall_runtime: uninstall_programs uninstall_runtime_libs @@ -924,17 +980,17 @@ uninstall_programs: do \ if [ "$$x" = "dummy" ]; then continue; fi; \ fn=`basename $$x`; \ - $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - $(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "$(RM) $(DESTDIR)$(bindir)/$$fn"; \ + $(RM) "$(DESTDIR)$(bindir)/$$fn"; \ done; @set -e; for x in dummy $(BIN_SCRIPTS); \ do \ if [ "$$x" = "dummy" ]; then continue; fi; \ fn=`basename $$x`; \ - $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - $(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "$(RM) $(DESTDIR)$(bindir)/$$fn"; \ + $(RM) "$(DESTDIR)$(bindir)/$$fn"; \ done - -$(RMDIR) "$(DESTDIR)$(INSTALLTOP)/bin" + -$(RMDIR) "$(DESTDIR)$(bindir)" uninstall_runtime_libs: @$(ECHO) "*** Uninstalling runtime libraries" @@ -942,8 +998,8 @@ uninstall_runtime_libs: @set -e; for s in dummy $(INSTALL_SHLIBS); do \ if [ "$$s" = "dummy" ]; then continue; fi; \ fn=`basename $$s`; \ - $(ECHO) "$(RM) $(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ - $(RM) "$(DESTDIR)$(INSTALLTOP)/bin/$$fn"; \ + $(ECHO) "$(RM) $(DESTDIR)$(bindir)/$$fn"; \ + $(RM) "$(DESTDIR)$(bindir)/$$fn"; \ done @ : {- output_on() unless windowsdll(); "" -} @@ -1101,19 +1157,23 @@ uninstall_image_docs: done # Developer targets (note: these are only available on Unix) ######### +##@ Code maintenance # It's important that generate_buildinfo comes after ordinals, as ordinals # is sensitive to build.info changes. -update: generate errors ordinals generate_buildinfo +update: generate errors ordinals generate_buildinfo ## Update errors, ordinals and build info +.PHONY: generate generate_apps generate_crypto_bn generate_crypto_objects \ + generate_crypto_conf generate_crypto_asn1 generate_fuzz_oids generate: generate_apps generate_crypto_bn generate_crypto_objects \ generate_crypto_conf generate_crypto_asn1 generate_fuzz_oids +.PHONY: generate_buildinfo generate_doc_buildinfo generate_buildinfo: generate_doc_buildinfo .PHONY: doc-nits md-nits -doc-nits: build_generated_pods - $(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e +doc-nits: build_generated_pods ## Evaluate OpenSSL documentation + $(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e -i # This uses "mdl", the markdownlint application, which is written in ruby. # The source is at https://github.com/markdownlint/markdownlint @@ -1121,15 +1181,23 @@ doc-nits: build_generated_pods # Another option is at https://snapcraft.io/install/mdl/debian # Finally, there's a Node.js version, which we haven't tried, that # can be found at https://github.com/DavidAnson/markdownlint -md-nits: - mdl -s util/markdownlint.rb . +md-nits: ## Evaluate markdown files via "mdl" + mdl -s $(SRCDIR)/util/markdownlint.rb . # Test coverage is a good idea for the future #coverage: $(PROGRAMS) $(TESTPROGRAMS) # ... -lint: - lint -DLINT $(INCLUDES) $(SRCS) +.PHONY: lint +lint: ## Evaluate C code via "splint" + @( cd $(SRCDIR); \ + echo splint -DLINT -posixlib -preproc -D__gnuc_va_list=void \ + -I. -Iinclude -Iapps/include $(CRYPTOHEADERS) $(SSLHEADERS) $(SRCS) ) + +.PHONY: check-format +check-format: ## Evaluate C code according to OpenSSL coding standards + ( cd $(SRCDIR); $(PERL) util/check-format.pl \ + $(SRCS) \$(CRYPTOHEADERS) $(SSLHEADERS) ) generate_apps: ( cd $(SRCDIR); $(PERL) VMS/VMSify-conf.pl \ @@ -1232,7 +1300,7 @@ providers/fips.module.sources.new: configdata.pm crypto/*cap.c; do \ echo "$$x"; \ done \ - ) | sort | uniq > providers/fips.module.sources.new + ) | grep -v sm2p256 | sort | uniq > providers/fips.module.sources.new rm -rf sources-tmp # Set to -force to force a rebuild @@ -1259,6 +1327,7 @@ errors: include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h + include/openssl/quic.h include/openssl/sslerr_legacy.h ); my @cryptoheaders_tmpl = qw( include/internal/dso.h @@ -1304,6 +1373,14 @@ errors: } ""; -} +SRCS={- +sub uniq { my %seen; grep !$seen{$_}++, @_; } +sub flat(@) { return map { ref eq 'ARRAY' ? @$_ : $_ } @_; } +join(" \\\n" . ' ' x 5, fill_lines(" ", $COLUMNS - 5, + uniq(grep /\.(c|cc|cpp)$/, + flat (map { $unified_info{sources}->{$_} } + (sort keys %{$unified_info{sources}}))))) +-} CRYPTOHEADERS={- join(" \\\n" . ' ' x 14, fill_lines(" ", $COLUMNS - 14, sort keys %cryptoheaders)) -} SSLHEADERS={- join(" \\\n" . ' ' x 11, @@ -1321,6 +1398,7 @@ renumber: build_generated --renumber \ $(SSLHEADERS) +.PHONY: ordinals ordinals: build_generated $(PERL) $(SRCDIR)/util/mknum.pl --version $(VERSION_NUMBER) --no-warnings \ --ordinals $(SRCDIR)/util/libcrypto.num \ @@ -1336,7 +1414,7 @@ test_ordinals: tags TAGS: FORCE rm -f TAGS tags - -ctags -R . + -( cd $(SRCDIR); util/ctags.sh ) -etags `find . -name '*.[ch]' -o -name '*.pm'` providers/fips.checksum.new: providers/fips.module.sources.new @@ -1390,59 +1468,6 @@ FORCE: # Building targets ################################################### -libcrypto.pc libssl.pc openssl.pc: Makefile $(LIBS) {- join(" ",map { platform->sharedlib_simple($_) // platform->sharedlib_import($_) // platform->sharedlib($_) // () } @{$unified_info{libraries}}) -} - -libcrypto.pc: - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - if [ -n "$(LIBDIR)" ]; then \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - else \ - echo 'libdir=$(libdir)'; \ - fi; \ - echo 'includedir=$${prefix}/include'; \ - echo 'enginesdir=$${libdir}/engines-{- $sover_dirname -}'; \ - echo 'modulesdir=$${libdir}/ossl-modules'; \ - echo ''; \ - echo 'Name: OpenSSL-libcrypto'; \ - echo 'Description: OpenSSL cryptography library'; \ - echo 'Version: '$(VERSION); \ - echo 'Libs: -L$${libdir} -lcrypto'; \ - echo 'Libs.private: $(LIB_EX_LIBS)'; \ - echo 'Cflags: -I$${includedir}' ) > libcrypto.pc - -libssl.pc: - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - if [ -n "$(LIBDIR)" ]; then \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - else \ - echo 'libdir=$(libdir)'; \ - fi; \ - echo 'includedir=$${prefix}/include'; \ - echo ''; \ - echo 'Name: OpenSSL-libssl'; \ - echo 'Description: Secure Sockets Layer and cryptography libraries'; \ - echo 'Version: '$(VERSION); \ - echo 'Requires.private: libcrypto'; \ - echo 'Libs: -L$${libdir} -lssl'; \ - echo 'Cflags: -I$${includedir}' ) > libssl.pc - -openssl.pc: - @ ( echo 'prefix=$(INSTALLTOP)'; \ - echo 'exec_prefix=$${prefix}'; \ - if [ -n "$(LIBDIR)" ]; then \ - echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \ - else \ - echo 'libdir=$(libdir)'; \ - fi; \ - echo 'includedir=$${prefix}/include'; \ - echo ''; \ - echo 'Name: OpenSSL'; \ - echo 'Description: Secure Sockets Layer and cryptography libraries and tools'; \ - echo 'Version: '$(VERSION); \ - echo 'Requires: libssl libcrypto' ) > openssl.pc - Makefile: configdata.pm \ {- join(" \\\n" . ' ' x 10, fill_lines(" ", $COLUMNS - 10, @@ -1596,12 +1621,44 @@ EOF my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, "util", "dofile.pl")), rel2abs($config{builddir})); - my @perlmodules = ( 'configdata.pm', - grep { $_ =~ m|\.pm$| } @{$args{deps}} ); - my %perlmoduleincs = map { '"-I'.dirname($_).'"' => 1 } @perlmodules; - $deps = join(' ', $deps, compute_platform_depends(@perlmodules)); - @perlmodules = map { "-M".basename($_, '.pm') } @perlmodules; - my $perlmodules = join(' ', '', sort keys %perlmoduleincs, @perlmodules); + my @perlmodules = (); + my %perlmoduleincs = (); + my %perlmoduledeps = (); + foreach my $x (('configdata.pm', @{$args{deps}})) { + # Compute (i)nclusion directory, (m)odule name and (d)ependency + my $i, $m, $d; + if ($x =~ /\|/) { + $i = $`; + $d = $'; + + # Massage the module part to become a real perl module spec + $m = $d; + $m =~ s|\.pm$||; + # Directory specs are :: in perl package names + $m =~ s|/|::|g; + + # Full file name of the dependency + $d = catfile($i, $d) if $i; + } elsif ($x =~ /\.pm$/) { + $i = dirname($x); + $m = basename($x, '.pm'); + $d = $x; + } else { + # All other dependencies are simply collected + $d = $x; + } + push @perlmodules, '"-M'.$m.'"' if $m; + $perlmoduledeps{$d} = 1; + $perlmoduleincs{'"-I'.$i.'"'} = 1 if $i; + } + + # Because of the special treatment of dependencies, we need to + # recompute $deps completely + my $deps + = join(" ", compute_platform_depends(@{$args{generator_deps}}, + sort keys %perlmoduledeps)); + my $perlmodules = join(' ', '', ( sort keys %perlmoduleincs ), @perlmodules); + return <<"EOF"; $args{src}: $gen0 $deps \$(PERL)$perlmodules "$dofile" "-o$target{build_file}" $gen0$gen_args > \$@ @@ -1743,6 +1800,8 @@ EOF # libraries for DLLs are a thing. On platforms that have this mechanism, # $import has the name of this import library. On platforms that don't # have this mechanism, $import will be |undef|. + # It's also used on AIX in solib mode, which creates import libraries + # for the shared libraries. my $import = platform->sharedlib_import($args{lib}); # $simple is for platforms where full shared library names include the # shared library version, and there's a simpler name that doesn't include @@ -1803,9 +1862,18 @@ EOF } } if (defined $import) { + if (sharedaix_solib()) { + $recipe .= <<"EOF"; +$import: $full $defs[0] + rm -f $import && \\ + echo \\#!$full > $import && \\ + cat $defs[0] >>$import +EOF + } else { $recipe .= <<"EOF"; $import: $full EOF + } } $recipe .= <<"EOF"; $full: $fulldeps diff --git a/Configurations/windows-makefile.tmpl b/Configurations/windows-makefile.tmpl index c36efc7d8a64..894834cfb7ef 100644 --- a/Configurations/windows-makefile.tmpl +++ b/Configurations/windows-makefile.tmpl @@ -155,6 +155,11 @@ MISC_SCRIPTS={- && $unified_info{attributes}->{scripts}->{$_}->{misc} } @{$unified_info{scripts}}) -} +INSTALL_EXPORTERS_CMAKE={- + join(" ", map { quotify1($_) } + grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'cmake'} + sort keys %{$unified_info{generate}}) +-} IMAGEDOCS1={- our @IMAGEDOCS1 = @{$unified_info{imagedocs}->{man1}}; join(" ", @IMAGEDOCS1) -} IMAGEDOCS3={- our @IMAGEDOCS3 = @{$unified_info{imagedocs}->{man3}}; @@ -249,6 +254,8 @@ MODULESDIR=$(MODULESDIR_dev)$(MODULESDIR_dir) libdir={- file_name_is_absolute($libdir) ? $libdir : '$(INSTALLTOP)\$(LIBDIR)' -} +CMAKECONFIGDIR=$(libdir)\cmake\OpenSSL + ##### User defined commands and flags ################################ CC="{- $config{CC} -}" @@ -436,7 +443,7 @@ build_all_generated: $(GENERATED_MANDATORY) $(GENERATED) build_docs @$(ECHO) " then make will fail..." @{- output_on() if $disabled{makedepend}; "\@rem" -} -all: build_sw build_docs +all: build_sw {- "build_docs" if !$disabled{docs}; -} test: tests {- dependmagic('tests'); -}: build_programs_nodep build_modules_nodep copy-utils @@ -455,9 +462,9 @@ list-tests: @$(ECHO) "Tests are not supported with your chosen Configure options" @{- output_on() if !$disabled{tests}; "\@rem" -} -install: install_sw install_ssldirs install_docs {- $disabled{fips} ? "" : "install_fips" -} +install: install_sw install_ssldirs {- "install_docs" if !$disabled{docs}; -} {- $disabled{fips} ? "" : "install_fips" -} -uninstall: uninstall_docs uninstall_sw {- $disabled{fips} ? "" : "uninstall_fips" -} +uninstall: {- "uninstall_docs" if !$disabled{docs}; -} uninstall_sw {- $disabled{fips} ? "" : "uninstall_fips" -} libclean: "$(PERL)" -e "map { m/(.*)\.dll$$/; unlink glob """{.,apps,test,fuzz}/$$1.*"""; } @ARGV" $(SHLIBS) @@ -559,6 +566,8 @@ install_dev: install_runtime_libs @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_LIBS) "$(libdir)" @if "$(SHLIBS)"=="" \ "$(PERL)" "$(SRCDIR)\util\copy.pl" ossl_static.pdb "$(libdir)" + @"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(CMAKECONFIGDIR)" + @"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_EXPORTERS_CMAKE) "$(CMAKECONFIGDIR)" uninstall_dev: @@ -782,7 +791,7 @@ EOF } return <<"EOF"; $target: "$gen0" $deps - \$(CPP) $incs $cppflags $defs "$gen0" > \$@.i + \$(CPP) /D__ASSEMBLER__ $incs $cppflags $defs "$gen0" > \$@.i move /Y \$@.i \$@ EOF } elsif ($gen0 =~ m|^.*\.in$|) { @@ -792,12 +801,44 @@ EOF my $dofile = abs2rel(rel2abs(catfile($config{sourcedir}, "util", "dofile.pl")), rel2abs($config{builddir})); - my @perlmodules = ( 'configdata.pm', - grep { $_ =~ m|\.pm$| } @{$args{deps}} ); - my %perlmoduleincs = map { '"-I'.dirname($_).'"' => 1 } @perlmodules; - $deps = join(' ', $deps, compute_platform_depends(@perlmodules)); - @perlmodules = map { "-M".basename($_, '.pm') } @perlmodules; - my $perlmodules = join(' ', '', sort keys %perlmoduleincs, @perlmodules); + my @perlmodules = (); + my %perlmoduleincs = (); + my %perlmoduledeps = (); + foreach my $x (('configdata.pm', @{$args{deps}})) { + # Compute (i)nclusion directory, (m)odule name and (d)ependency + my $i, $m, $d; + if ($x =~ /\|/) { + $i = $`; + $d = $'; + + # Massage the module part to become a real perl module spec + $m = $d; + $m =~ s|\.pm$||; + # Directory specs are :: in perl package names + $m =~ s|/|::|g; + + # Full file name of the dependency + $d = catfile($i, $d) if $i; + } elsif ($x =~ /\.pm$/) { + $i = dirname($x); + $m = basename($x, '.pm'); + $d = $x; + } else { + # All other dependencies are simply collected + $d = $x; + } + push @perlmodules, '"-M'.$m.'"' if $m; + $perlmoduledeps{$d} = 1; + $perlmoduleincs{'"-I'.$i.'"'} = 1 if $i; + } + + # Because of the special treatment of dependencies, we need to + # recompute $deps completely + my $deps + = join(" ", compute_platform_depends(@{$args{generator_deps}}, + sort keys %perlmoduledeps)); + my $perlmodules = join(' ', '', ( sort keys %perlmoduleincs ), @perlmodules); + return <<"EOF"; $args{src}: "$gen0" $deps "\$(PERL)"$perlmodules "$dofile" "-o$target{build_file}" "$gen0"$gen_args > \$@ diff --git a/Configure b/Configure index 0c60d1da1659..15054f94034a 100755 --- a/Configure +++ b/Configure @@ -1,6 +1,6 @@ #! /usr/bin/env perl # -*- mode: perl; -*- -# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -27,7 +27,7 @@ use OpenSSL::config; my $orig_death_handler = $SIG{__DIE__}; $SIG{__DIE__} = \&death_handler; -my $usage="Usage: Configure [no- ...] [enable- ...] [-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 $usage="Usage: Configure [no- ...] [enable- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]thread-pool] [[no-]default-thread-pool] [[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"; @@ -77,10 +77,23 @@ EOF # Generic OpenSSL-style methods relating to this support # are always compiled but return NULL if the hardware # support isn't compiled. +# +# enable-demos Enable the building of the example code in the demos directory +# enable-h3demo Enable the http3 demo, which currently only links to the +# external nghttp3 library on unix platforms +# +# enable-hqinterop +# Enable the building of the hq-interop code for construction +# of the interop container +# # 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-]thread-pool +# [don't] allow thread pool functionality +# [no-]default-thread-pool +# [don't] allow default thread pool functionality # [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. @@ -88,8 +101,9 @@ EOF # 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. +# library and will be loaded at run-time by the OpenSSL library. # sctp include SCTP support +# no-quic disable QUIC support # no-uplink Don't build support for UPLINK interface. # enable-weak-ssl-ciphers # Enable weak ciphers that are disabled by default. @@ -161,7 +175,7 @@ my @gcc_devteam_warn = qw( -Wsign-compare -Wshadow -Wformat - -Wtype-limits + -Wno-type-limits -Wundef -Werror -Wmissing-prototypes @@ -181,6 +195,8 @@ my @clang_devteam_warn = qw( -Wno-parentheses-equality -Wno-language-extension-token -Wno-extended-offsetof + -Wno-missing-braces + -Wno-tautological-constant-out-of-range-compare -Wconditional-uninitialized -Wincompatible-pointer-types-discards-qualifiers -Wmissing-variable-declarations @@ -377,6 +393,12 @@ if (defined env($local_config_envname)) { } } +# Fail if no configuration is apparent +if (!%table) { + print "Failed to find any os/compiler configurations. Please make sure the Configurations directory is included.\n"; + &usage; +} + # Save away perl command information $config{perl_cmd} = $^X; $config{perl_version} = $Config{version}; @@ -400,6 +422,8 @@ my @dtls = qw(dtls1 dtls1_2); my @disablables = ( "acvp-tests", "afalgeng", + "apps", + "argon2", "aria", "asan", "asm", @@ -410,11 +434,14 @@ my @disablables = ( "autoload-config", "bf", "blake2", + "brotli", + "brotli-dynamic", "buildtest-c++", "bulk", "cached-fetch", "camellia", "capieng", + "winstore", "cast", "chacha", "cmac", @@ -423,11 +450,16 @@ my @disablables = ( "comp", "crypto-mdebug", "ct", + "default-thread-pool", + "demos", + "h3demo", + "hqinterop", "deprecated", "des", "devcryptoeng", "dgram", "dh", + "docs", "dsa", "dso", "dtls", @@ -437,6 +469,7 @@ my @disablables = ( "ec_nistp_64_gcc_128", "ecdh", "ecdsa", + "ecx", "egd", "engine", "err", @@ -444,10 +477,15 @@ my @disablables = ( "filenames", "fips", "fips-securitychecks", + "fips-post", + "fips-jitter", "fuzz-afl", "fuzz-libfuzzer", "gost", + "http", "idea", + "integrity-only-ciphers", + "jitter", "ktls", "legacy", "loadereng", @@ -455,6 +493,8 @@ my @disablables = ( "md2", "md4", "mdc2", + "ml-dsa", + "ml-kem", "module", "msan", "multiblock", @@ -463,10 +503,13 @@ my @disablables = ( "ocsp", "padlockeng", "pic", + "pie", "pinshared", "poly1305", "posix-io", "psk", + "quic", + "unstable-qlog", "rc2", "rc4", "rc5", @@ -480,7 +523,9 @@ my @disablables = ( "shared", "siphash", "siv", + "slh-dsa", "sm2", + "sm2-precomp", "sm3", "sm4", "sock", @@ -491,9 +536,13 @@ my @disablables = ( "ssl-trace", "static-engine", "stdio", + "sslkeylog", "tests", + "tfo", + "thread-pool", "threads", "tls", + "tls-deprecated-ec", "trace", "ts", "ubsan", @@ -504,6 +553,8 @@ my @disablables = ( "whirlpool", "zlib", "zlib-dynamic", + "zstd", + "zstd-dynamic", ); foreach my $proto ((@tls, @dtls)) { @@ -534,16 +585,24 @@ my %deprecated_disablables = ( our %disabled = ( # "what" => "comment" "fips" => "default", + "fips-jitter" => "default", "asan" => "default", + "brotli" => "default", + "brotli-dynamic" => "default", "buildtest-c++" => "default", "crypto-mdebug" => "default", "crypto-mdebug-backtrace" => "default", + "demos" => "default", + "h3demo" => "default", + "hqinterop" => "default", "devcryptoeng" => "default", "ec_nistp_64_gcc_128" => "default", "egd" => "default", "external-tests" => "default", "fuzz-afl" => "default", "fuzz-libfuzzer" => "default", + "pie" => "default", + "jitter" => "default", "ktls" => "default", "md2" => "default", "msan" => "default", @@ -551,31 +610,36 @@ our %disabled = ( # "what" => "comment" "sctp" => "default", "ssl3" => "default", "ssl3-method" => "default", + "sslkeylog" => "default", + "tfo" => "default", "trace" => "default", "ubsan" => "default", "unit-test" => "default", "weak-ssl-ciphers" => "default", "zlib" => "default", "zlib-dynamic" => "default", + "zstd" => "default", + "zstd-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", + "aria", "async", "atexit", "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", + "md4", "ml-dsa", "ml-kem", "multiblock", + "nextprotoneg", "ocsp", "ocb", "poly1305", "psk", "rc2", "rc4", "rmd160", "seed", "siphash", "siv", "sm3", "sm4", "srp", "srtp", "ssl3-method", "ssl-trace", + "tfo", "ts", "ui-console", "whirlpool", "fips-securitychecks" ], sub { $config{processor} eq "386" } @@ -583,10 +647,13 @@ my @disable_cascades = ( "ssl" => [ "ssl3" ], "ssl3-method" => [ "ssl3" ], "zlib" => [ "zlib-dynamic" ], + "brotli" => [ "brotli-dynamic" ], + "zstd" => [ "zstd-dynamic" ], "des" => [ "mdc2" ], - "ec" => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost" ], - "dgram" => [ "dtls", "sctp" ], - "sock" => [ "dgram" ], + "deprecated" => [ "tls-deprecated-ec" ], + "ec" => [ qw(ec2m ecdsa ecdh sm2 gost ecx tls-deprecated-ec) ], + "dgram" => [ "dtls", "quic", "sctp" ], + "sock" => [ "dgram", "tfo" ], "dtls" => [ @dtls ], sub { 0 == scalar grep { !$disabled{$_} } @dtls } => [ "dtls" ], @@ -594,6 +661,8 @@ my @disable_cascades = ( "tls" => [ @tls ], sub { 0 == scalar grep { !$disabled{$_} } @tls } => [ "tls" ], + "tls1_3" => [ "quic" ], + "quic" => [ "unstable-qlog" ], "crypto-mdebug" => [ "crypto-mdebug-backtrace" ], @@ -602,7 +671,7 @@ my @disable_cascades = ( # 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, + # those *have* to be exactly 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) @@ -625,7 +694,7 @@ my @disable_cascades = ( "stdio" => [ "apps", "capieng", "egd" ], "apps" => [ "tests" ], "tests" => [ "external-tests" ], - "comp" => [ "zlib" ], + "comp" => [ "zlib", "brotli", "zstd" ], "sm3" => [ "sm2" ], sub { !$disabled{"unit-test"} } => [ "heartbeats" ], @@ -636,9 +705,17 @@ my @disable_cascades = ( "cmp" => [ "crmf" ], - "fips" => [ "fips-securitychecks", "acvp-tests" ], + "fips" => [ "fips-securitychecks", "fips-post", "acvp-tests", + "fips-jitter" ], - "deprecated-3.0" => [ "engine", "srp" ] + "threads" => [ "thread-pool" ], + "thread-pool" => [ "default-thread-pool" ], + + "blake2" => [ "argon2" ], + + "deprecated-3.0" => [ "engine", "srp" ], + + "http" => [ "ocsp" ] ); # Avoid protocol support holes. Also disable all versions below N, if version @@ -698,6 +775,7 @@ my %user = ( RANLIB => env('RANLIB'), RC => env('RC') || env('WINDRES'), RCFLAGS => [ env('RCFLAGS') || () ], + OBJCOPY => undef, RM => undef, ); # Info about what "make variables" may be prefixed with the cross compiler @@ -707,6 +785,7 @@ my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC ); # input, as opposed to the VAR=string option that override the corresponding # config target attributes my %useradd = ( + ASFLAGS => [], CPPDEFINES => [], CPPINCLUDES => [], CPPFLAGS => [], @@ -757,7 +836,7 @@ 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 @known_seed_sources = qw(getrandom devrandom os egd none rdcpu); my @seed_sources = (); while (@argvcopy) { @@ -883,6 +962,23 @@ while (@argvcopy) { delete $disabled{"zlib"}; } + elsif ($1 eq "brotli-dynamic") + { + delete $disabled{"brotli"}; + } + elsif ($1 eq "pie") + { + delete $disabled{"pie"}; + } + elsif ($1 eq "zstd-dynamic") + { + delete $disabled{"zstd"}; + } + elsif ($1 eq "fips-jitter") + { + delete $disabled{"fips"}; + delete $disabled{"jitter"}; + } my $algo = $1; delete $disabled{$algo}; @@ -949,6 +1045,14 @@ while (@argvcopy) { $config{openssldir}=$1; } + elsif (/^--with-jitter-include=(.*)$/) + { + $withargs{jitter_include}=$1; + } + elsif (/^--with-jitter-lib=(.*)$/) + { + $withargs{jitter_lib}=$1; + } elsif (/^--with-zlib-lib=(.*)$/) { $withargs{zlib_lib}=$1; @@ -957,6 +1061,22 @@ while (@argvcopy) { $withargs{zlib_include}=$1; } + elsif (/^--with-brotli-lib=(.*)$/) + { + $withargs{brotli_lib}=$1; + } + elsif (/^--with-brotli-include=(.*)$/) + { + $withargs{brotli_include}=$1; + } + elsif (/^--with-zstd-lib=(.*)$/) + { + $withargs{zstd_lib}=$1; + } + elsif (/^--with-zstd-include=(.*)$/) + { + $withargs{zstd_include}=$1; + } elsif (/^--with-fuzzer-lib=(.*)$/) { $withargs{fuzzer_lib}=$1; @@ -1225,11 +1345,15 @@ if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) { ============================== WARNING =============================== You have selected the --with-rand-seed=none option, which effectively -disables automatic reseeding of the OpenSSL random generator. +disables automatic reseeding of the OpenSSL SEED-SRC 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. +Instead of manually seeding, a different random generator can be set +at runtime in openssl.cnf or configured at build time with +-DOPENSSL_DEFAULT_SEED_SRC. + Please read the 'Note on random number generation' section in the INSTALL.md instructions and the RAND_DRBG(7) manual page for more details. @@ -1241,6 +1365,11 @@ push @{$config{openssl_feature_defines}}, map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" } @seed_sources; +my $provider_string = $disabled{"fips-post"} ? "non-compliant FIPS Provider" : "FIPS Provider"; + +$config{FIPS_VENDOR} = + (defined $version{FIPS_VENDOR} ? "$version{FIPS_VENDOR} $provider_string for OpenSSL" : "OpenSSL $provider_string"); + # Backward compatibility? if ($target =~ m/^CygWin32(-.*)$/) { $target = "Cygwin".$1; @@ -1483,6 +1612,10 @@ unless($disabled{threads}) { push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS"; } +if ($disabled{"unstable-qlog"}) { + $disabled{"qlog"} = 1; +} + my $no_shared_warn=0; if (($target{shared_target} // '') eq "") { @@ -1547,7 +1680,7 @@ my %predefined_CXX = $config{CXX} unless ($disabled{asm}) { # big endian systems can use ELFv2 ABI - if ($target eq "linux-ppc64") { + if ($target eq "linux-ppc64" || $target eq "BSD-ppc64") { $target{perlasm_scheme} = "linux64v2" if ($predefined_C{_CALL_ELF} == 2); } } @@ -1678,20 +1811,7 @@ $config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings' 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'); - } + push @{$config{engdirs}}, "afalg"; } else { disable('not-linux', 'afalgeng'); } @@ -1730,6 +1850,12 @@ unless ($disabled{ktls}) { } } +unless ($disabled{winstore}) { + unless ($target =~ /^(?:Cygwin|mingw|VC-|BC-)/) { + disable('not-windows', 'winstore'); + } +} + push @{$config{openssl_other_defines}}, "OPENSSL_NO_KTLS" if ($disabled{ktls}); # Get the extra flags used when building shared libraries and modules. We @@ -1791,7 +1917,7 @@ 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. + # They cause disabling cascades, but should otherwise not register. next if $deprecated_disablables{$what}; # The generated $disabled{"deprecated-x.y"} entries are special # and treated properly elsewhere @@ -1801,7 +1927,7 @@ foreach my $what (sort keys %disabled) { if (!grep { $what eq $_ } ( 'buildtest-c++', 'fips', 'threads', 'shared', 'module', 'pic', 'dynamic-engine', 'makedepend', - 'zlib-dynamic', 'zlib', 'sse2', 'legacy' )) { + 'sse2', 'legacy' )) { (my $WHAT = uc $what) =~ s|-|_|g; my $skipdir = $what; @@ -1814,7 +1940,7 @@ foreach my $what (sort keys %disabled) { $skipdir{engines} = $what if $what eq 'engine'; $skipdir{"crypto/$skipdir"} = $what - unless $what eq 'async' || $what eq 'err' || $what eq 'dso'; + unless $what eq 'async' || $what eq 'err' || $what eq 'dso' || $what eq 'http'; } } @@ -2392,17 +2518,40 @@ EOF } elsif ($dest eq '') { $ddest = ''; } else { - $ddest = cleanfile($sourced, $_, $blddir, 1); + $ddest = cleanfile($sourced, $dest, $blddir, 1); # 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); + $ddest = cleanfile($buildd, $dest, $blddir); } } - foreach (@{$depends{$dest}}) { - my $d = cleanfile($sourced, $_, $blddir, 1); - my $d2 = cleanfile($buildd, $_, $blddir); + foreach my $f (@{$depends{$dest}}) { + # If the dependency destination is generated, dependencies + # may have an extra syntax to separate the intended inclusion + # directory from the module to be loaded: a | instead of a + # / as directory separator. + # Do note that this has to be handled in the build file + # template as well. + # $i = inclusion path in source directory + # $i2 = inclusion path in build directory + # $m = module path (within the inclusion path) + # $i = full module path in source directory + # $i2 = full module path in build directory + my $i; my $i2; my $m; my $d; my $d2; + if ($unified_info{generate}->{$ddest} + && $f =~ m/^(.*?)\|(.*)$/) { + $i = $1; + $m = $2; + # We must be very careful to modify $i last + $d = cleanfile($sourced, "$i/$m", $blddir, 1); + $d2 = cleanfile($buildd, "$i/$m", $blddir); + $i2 = cleandir($buildd, $i, $blddir); + $i = cleandir($sourced, $i, $blddir, 1); + } else { + $d = cleanfile($sourced, $f, $blddir, 1); + $d2 = cleanfile($buildd, $f, $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 @@ -2412,13 +2561,20 @@ EOF keys %{$unified_info{generate}}) || ! -f $d) { $d = $d2; + $i = $i2; + } + if ($i) { + # Put together the computed inclusion dir with the + # original module name. Do note that we conserve the + # Unixly path syntax for the module path. + $d = "$i|$m"; } $unified_info{depends}->{$ddest}->{$d} = 1; # Fix up associated attributes $unified_info{attributes}->{depends}->{$ddest}->{$d} = - $attributes{depends}->{$dest}->{$_} - if defined $attributes{depends}->{$dest}->{$_}; + $attributes{depends}->{$dest}->{$f} + if defined $attributes{depends}->{$dest}->{$f}; } } @@ -2588,7 +2744,9 @@ EOF next if $dest eq ""; foreach my $d (keys %{$unified_info{depends}->{$dest}}) { next unless $d =~ /\.(h|pm)$/; - my $i = dirname($d); + # Take into account when a dependency uses the inclusion|module + # syntax + my $i = $d =~ m/\|/ ? $` : dirname($d); my $spot = $d eq "configdata.pm" || defined($unified_info{generate}->{$d}) ? 'build' : 'source'; diff --git a/HACKING.md b/HACKING.md index 6375450c2413..9a1f7b9f5036 100644 --- a/HACKING.md +++ b/HACKING.md @@ -9,7 +9,7 @@ This document describes the way to add custom modifications to OpenSSL sources. [Configurations/unix-Makefile.tmpl](Configurations/unix-Makefile.tmpl) to pick up that file. - After that perform the following steps: + After that, perform the following steps: ./Configure -Werror --strict-warnings [your-options] make update @@ -27,7 +27,7 @@ This document describes the way to add custom modifications to OpenSSL sources. `make update` also generates files related to OIDs (in the `crypto/objects/` folder) and errors. - If a merge error occurs in one of these generated files then the + If a merge error occurs in one of these generated files, then the generated files need to be removed and regenerated using `make update`. - To aid in this process the generated files can be committed separately + To aid in this process, the generated files can be committed separately so they can be removed easily. diff --git a/INSTALL.md b/INSTALL.md index 47d64b1a39d8..983f6aad1369 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -19,7 +19,7 @@ Table of Contents - [Build Type](#build-type) - [Directories](#directories) - [Compiler Warnings](#compiler-warnings) - - [ZLib Flags](#zlib-flags) + - [Compression Algorithm Flags](#compression-algorithm-flags) - [Seeding the Random Generator](#seeding-the-random-generator) - [Setting the FIPS HMAC key](#setting-the-FIPS-HMAC-key) - [Enable and Disable Features](#enable-and-disable-features) @@ -52,6 +52,8 @@ To install OpenSSL, you will need: * Perl 5 with core modules (please read [NOTES-PERL.md](NOTES-PERL.md)) * The Perl module `Text::Template` (please read [NOTES-PERL.md](NOTES-PERL.md)) * an ANSI C compiler + * POSIX C library (at least POSIX.1-2008), or compatible types and + functionality. * a development environment in the form of development libraries and C header files * a supported operating system @@ -64,6 +66,8 @@ issues and other details, please read one of these: * [Notes for Windows platforms](NOTES-WINDOWS.md) * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md) * [Notes for the OpenVMS platform](NOTES-VMS.md) + * [Notes for the HPE NonStop platform](NOTES-NONSTOP.md) + * [Notes on POSIX](NOTES-POSIX.md) * [Notes on Perl](NOTES-PERL.md) * [Notes on Valgrind](NOTES-VALGRIND.md) @@ -120,21 +124,11 @@ represents one of the four commands Arguments --------- -**Mandatory arguments** are enclosed in double curly braces. -A simple example would be +**Optional Arguments** are enclosed in square brackets. - $ type {{ filename }} + [option...] -which is to be understood to use the command `type` on some file name -determined by the user. - -**Optional Arguments** are enclosed in double square brackets. - - [[ options ]] - -Note that the notation assumes spaces around `{`, `}`, `[`, `]`, `{{`, `}}` and -`[[`, `]]`. This is to differentiate from OpenVMS directory -specifications, which also use [ and ], but without spaces. +A trailing ellipsis means that more than one could be specified. Quick Installation Guide ======================== @@ -151,7 +145,7 @@ Use the following commands to configure, build and test OpenSSL. The testing is optional, but recommended if you intend to install OpenSSL for production use. -### Unix / Linux / macOS +### Unix / Linux / macOS / NonStop $ ./Configure $ make @@ -177,8 +171,9 @@ issue the following commands to build OpenSSL. As mentioned in the [Choices](#choices) section, you need to pick one of the four Configure targets in the first command. -Most likely you will be using the `VC-WIN64A` target for 64bit Windows -binaries (AMD64) or `VC-WIN32` for 32bit Windows binaries (X86). +Most likely you will be using the `VC-WIN64A`/`VC-WIN64A-HYBRIDCRT` target for +64bit Windows binaries (AMD64) or `VC-WIN32`/`VC-WIN32-HYBRIDCRT` for 32bit +Windows binaries (X86). The other two options are `VC-WIN64I` (Intel IA64, Itanium) and `VC-CE` (Windows CE) are rather uncommon nowadays. @@ -207,7 +202,7 @@ the global search path for system libraries. Finally, if you plan on using the FIPS module, you need to read the [Post-installation Notes](#post-installation-notes) further down. -### Unix / Linux / macOS +### Unix / Linux / macOS / NonStop Depending on your distribution, you need to run the following command as root user or prepend `sudo` to the command: @@ -391,8 +386,39 @@ for OpenSSL development. It only works when using gcc or clang as the compiler. If you are developing a patch for OpenSSL then it is recommended that you use this option where possible. -ZLib Flags ----------- +Compression Algorithm Flags +--------------------------- + +### with-brotli-include + + --with-brotli-include=DIR + +The directory for the location of the brotli include files (i.e. the location +of the **brotli** include directory). This option is only necessary if +[enable-brotli](#enable-brotli) is used and the include files are not already +on the system include path. + +### with-brotli-lib + + --with-brotli-lib=LIB + +**On Unix**: this is the directory containing the brotli libraries. +If not provided, the system library path will be used. + +The names of the libraries are: + +* libbrotlicommon.a or libbrotlicommon.so +* libbrotlidec.a or libbrotlidec.so +* libbrotlienc.a or libbrotlienc.so + +**On Windows:** this is the directory containing the brotli libraries. +If not provided, the system library path will be used. + +The names of the libraries are: + +* brotlicommon.lib +* brotlidec.lib +* brotlienc.lib ### with-zlib-include @@ -418,6 +444,32 @@ then this flag is optional and defaults to `ZLIB1` if not provided. This flag is optional and if not provided then `GNV$LIBZSHR`, `GNV$LIBZSHR32` or `GNV$LIBZSHR64` is used by default depending on the pointer size chosen. +### with-zstd-include + + --with-zstd-include=DIR + +The directory for the location of the Zstd include file. This option is only +necessary if [enable-std](#enable-zstd) is used and the include file is not +already on the system include path. + +OpenSSL requires Zstd 1.4 or greater. The Linux kernel source contains a +*zstd.h* file that is not compatible with the 1.4.x Zstd distribution, the +compilation will generate an error if the Linux *zstd.h* is included before +(or instead of) the Zstd distribution header. + +### with-zstd-lib + + --with-zstd-lib=LIB + +**On Unix**: this is the directory containing the Zstd library. +If not provided the system library path will be used. + +**On Windows:** this is the filename of the Zstd library (with or +without a path). This flag must be provided if the +[enable-zstd-dynamic](#enable-zstd-dynamic) option is not also used. +If `zstd-dynamic` is used then this flag is optional and defaults +to `LIBZSTD` if not provided. + Seeding the Random Generator ---------------------------- @@ -455,12 +507,8 @@ This source is ignored by the FIPS provider. ### rdcpu -Use the `RDSEED` or `RDRAND` command if provided by the CPU. - -### librandom - -Use librandom (not implemented yet). -This source is ignored by the FIPS provider. +Use the `RDSEED` or `RDRAND` command on x86 or `RNDRRS` command on aarch64 +if provided by the CPU. ### none @@ -473,6 +521,35 @@ at the end of this document. [rng]: #notes-on-random-number-generation +### jitter + +When configured with `enable-jitter`, a "JITTER" RNG is compiled that +can provide an alternative software seed source. It can be configured +by setting `seed` option in `openssl.cnf`. A minimal `openssl.cnf` is +shown below: + + openssl_conf = openssl_init + + [openssl_init] + random = random + + [random] + seed=JITTER + +It uses a statically linked [jitterentropy-library] as the seed source. + +Additional configuration flags available: + + --with-jitter-include=DIR + +The directory for the location of the jitterentropy.h include file, if +it is outside the system include path. + + --with-jitter-lib=DIR + +This is the directory containing the static libjitterentropy.a +library, if it is outside the system library path. + Setting the FIPS HMAC key ------------------------- @@ -534,6 +611,11 @@ access to algorithm internals that are not normally accessible. Additional information related to ACVP can be found at . +### no-apps + +Do not build apps, e.g. the openssl program. This is handy for minimization. +This option also disables tests. + ### no-asm Do not use assembler code. @@ -552,6 +634,7 @@ Do not use `atexit()` in libcrypto builds. `atexit()` has varied semantics between platforms and can cause SIGSEGV in some circumstances. This option disables the atexit registration of OPENSSL_cleanup. +By default, NonStop configurations use `no-atexit`. ### no-autoalginit @@ -571,6 +654,17 @@ Typically OpenSSL will automatically load human readable error strings. For a statically linked application this may be undesirable if small executable size is an objective. +### enable-brotli + +Build with support for brotli compression/decompression. + +### enable-brotli-dynamic + +Like the enable-brotli option, but has OpenSSL load the brotli library dynamically +when needed. + +This is only supported on systems where loading of shared libraries is supported. + ### no-autoload-config Don't automatically load the default `openssl.cnf` file. @@ -658,6 +752,10 @@ Don't build support for datagram based BIOs. Selecting this option will also force the disabling of DTLS. +### no-docs + +Don't build and install documentation, i.e. manual pages in various forms. + ### no-dso Don't build support for loading Dynamic Shared Objects (DSO) @@ -683,6 +781,12 @@ Don't build support for Elliptic Curves. Don't build support for binary Elliptic Curves +### no-tls-deprecated-ec + +Disable legacy TLS EC groups that were deprecated in RFC8422. These are the +Koblitz curves, B, B, B, B, and the +binary Elliptic curves that would also be disabled by C. + ### enable-ec_nistp_64_gcc_128 Enable support for optimised implementations of some commonly used NIST @@ -736,6 +840,26 @@ Build (and install) the FIPS provider Don't perform FIPS module run-time checks related to enforcement of security parameters such as minimum security strength of keys. +### no-fips-post + +Don't perform FIPS module Power On Self Tests. + +This option MUST be used for debugging only as it makes the FIPS provider +non-compliant. It is useful when setting breakpoints in FIPS algorithms. + +### enable-fips-jitter + +Use the CPU Jitter library as a FIPS validated entropy source. + +This option will only produce a compliant FIPS provider if you have: + +1. independently performed the required [SP 800-90B] entropy assessments; +2. meet the minimum required entropy as specified by [jitterentropy-library]; +3. obtain an [ESV] certificate for the [jitterentropy-library] and +4. have had the resulting FIPS provider certified by the [CMVP]. + +Failure to do all of these will produce a non-compliant FIPS provider. + ### enable-fuzz-libfuzzer, enable-fuzz-afl Build with support for fuzzing using either libfuzzer or AFL. @@ -753,6 +877,10 @@ Note that if this feature is enabled then GOST ciphersuites are only available if the GOST algorithms are also available through loading an externally supplied engine. +### no-http + +Disable HTTP support. + ### no-legacy Don't build the legacy provider. @@ -763,6 +891,16 @@ Disabling this also disables the legacy algorithms: MD2 (already disabled by def Don't generate dependencies. +### no-ml-dsa + +Disable Module-Lattice-Based Digital Signature Standard (ML-DSA) support. +ML-DSA is based on CRYSTALS-DILITHIUM. See [FIPS 204]. + +### no-ml-kem + +Disable Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM) +support. ML-KEM is based on CRYSTALS-KYBER. See [FIPS 203]. + ### no-module Don't build any dynamically loadable engines. @@ -795,6 +933,10 @@ As synonym for `no-padlockeng`. Deprecated and should not be used. Don't build with support for Position Independent Code. +### enable-pie + +Build with support for Position Independent Execution. + ### no-pinshared Don't pin the shared libraries. @@ -848,6 +990,15 @@ Do not create shared libraries, only static ones. See [Notes on shared libraries](#notes-on-shared-libraries) below. +### no-slh-dsa + +Disable Stateless Hash Based Digital Signature Standard support. +(SLH-DSA is based on SPHINCS+. See [FIPS 205]) + +### no-sm2-precomp + +Disable using the SM2 precomputed table on aarch64 to make the library smaller. + ### no-sock Don't build support for socket BIOs. @@ -901,6 +1052,14 @@ tests also use the command line applications, the tests will also be skipped. Don't build test programs or run any tests. +### enable-tfo + +Build with support for TCP Fast Open (RFC7413). Supported on Linux, macOS and FreeBSD. + +### no-quic + +Don't build with QUIC support. + ### no-threads Don't build with support for multi-threaded applications. @@ -913,12 +1072,44 @@ will usually require additional system-dependent options! See [Notes on multi-threading](#notes-on-multi-threading) below. +### no-thread-pool + +Don't build with support for thread pool functionality. + +### thread-pool + +Build with thread pool functionality. If enabled, OpenSSL algorithms may +use the thread pool to perform parallel computation. This option in itself +does not enable OpenSSL to spawn new threads. Currently the only supported +thread pool mechanism is the default thread pool. + +### no-default-thread-pool + +Don't build with support for default thread pool functionality. + +### default-thread-pool + +Build with default thread pool functionality. If enabled, OpenSSL may create +and manage threads up to a maximum number of threads authorized by the +application. Supported on POSIX compliant platforms and Windows. + ### enable-trace Build with support for the integrated tracing api. See manual pages OSSL_trace_set_channel(3) and OSSL_trace_enabled(3) for details. +### enable-sslkeylog + +Build with support for the SSLKEYLOGFILE environment variable + +When enabled, setting SSLKEYLOGFILE to a file path records the keys exchanged +during a TLS handshake for use in analysis tools like wireshark. Note that the +use of this mechanism allows for decryption of application payloads found in +captured packets using keys from the key log file and therefore has significant +security consequences. See Section 3 of +[the draft standard for SSLKEYLOGFILE](https://datatracker.ietf.org/doc/draft-ietf-tls-keylogfile/) + ### no-ts Don't build Time Stamping (TS) Authority support. @@ -965,6 +1156,25 @@ when needed. This is only supported on systems where loading of shared libraries is supported. +### enable-zstd + +Build with support for Zstd compression/decompression. + +### enable-zstd-dynamic + +Like the enable-zstd option, but has OpenSSL load the Zstd library dynamically +when needed. + +This is only supported on systems where loading of shared libraries is supported. + +### enable-unstable-qlog + +Enables qlog output support for the QUIC protocol. This functionality is +unstable and implements a draft version of the qlog specification. The qlog +output from OpenSSL will change in incompatible ways in future, and is not +subject to any format stability or compatibility guarantees at this time. See +the manpage openssl-qlog(7) for details. + ### 386 In 32-bit x86 builds, use the 80386 instruction set only in assembly modules @@ -986,6 +1196,10 @@ synonymous with `no-ssl3`. Note this only affects version negotiation. OpenSSL will still provide the methods for applications to explicitly select the individual protocol versions. +### no-integrity-only-ciphers + +Don't build support for integrity only ciphers in tls. + ### no-{protocol}-method no-{ssl3|tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method @@ -1007,9 +1221,9 @@ Build with support for the specified algorithm. ### no-{algorithm} no-{aria|bf|blake2|camellia|cast|chacha|cmac| - des|dh|dsa|ecdh|ecdsa|idea|md4|mdc2|ocb| - poly1305|rc2|rc4|rmd160|scrypt|seed| - siphash|siv|sm2|sm3|sm4|whirlpool} + des|dh|dsa|ecdh|ecdsa|idea|md4|mdc2|ml-dsa| + ml-kem|ocb|poly1305|rc2|rc4|rmd160|scrypt| + seed|siphash|siv|sm2|sm3|sm4|whirlpool} Build without support for the specified algorithm. @@ -1034,7 +1248,7 @@ below and how these flags interact with those variables. Additional options that are not otherwise recognised are passed through as they are to the compiler as well. Unix-style options beginning with a -`-` or `+` and Windows-style options beginning with a `/` are recognized. +`-` or `+` and Windows-style options beginning with a `/` are recognised. Again, consult your compiler documentation. If the option contains arguments separated by spaces, then the URL-style @@ -1169,15 +1383,15 @@ the same. #### Unix / Linux / macOS - $ ./Configure [[ options ]] + $ ./Configure [options...] #### OpenVMS - $ perl Configure [[ options ]] + $ perl Configure [options...] #### Windows - $ perl Configure [[ options ]] + $ perl Configure [options...] ### Manual Configuration @@ -1199,12 +1413,13 @@ When you have identified your system (and if necessary compiler) use this name as the argument to `Configure`. For example, a `linux-elf` user would run: - $ ./Configure linux-elf [[ options ]] + $ ./Configure linux-elf [options...] ### Creating your own Configuration If your system isn't listed, you will have to create a configuration -file named `Configurations/{{ something }}.conf` and add the correct +file named `Configurations/YOURFILENAME.conf` (replace `YOURFILENAME` +with a filename of your choosing) and add the correct configuration for your system. See the available configs as examples and read [Configurations/README.md](Configurations/README.md) and [Configurations/README-design.md](Configurations/README-design.md) @@ -1236,21 +1451,21 @@ directory and invoking the configuration commands from there. $ mkdir /var/tmp/openssl-build $ cd /var/tmp/openssl-build - $ /PATH/TO/OPENSSL/SOURCE/Configure [[ options ]] + $ /PATH/TO/OPENSSL/SOURCE/Configure [options...] #### OpenVMS example $ set default sys$login: $ create/dir [.tmp.openssl-build] $ set default [.tmp.openssl-build] - $ perl D:[PATH.TO.OPENSSL.SOURCE]Configure [[ options ]] + $ perl D:[PATH.TO.OPENSSL.SOURCE]Configure [options...] #### Windows example $ C: $ mkdir \temp-openssl $ cd \temp-openssl - $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure [[ options ]] + $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure [options...] Paths can be relative just as well as absolute. `Configure` will do its best to translate them to relative paths whenever possible. @@ -1471,7 +1686,7 @@ over the build process. Typically these should be defined prior to running PERL The name of the Perl executable to use when building OpenSSL. - Only needed if builing should use a different Perl executable + Only needed if building should use a different Perl executable than what is used to run the Configure script. RANLIB @@ -1506,6 +1721,12 @@ described here. Examine the Makefiles themselves for the full list. build_docs Build all documentation components. + debuginfo + On unix platforms, this target can be used to create .debug + libraries, which separate the DWARF information in the + shared library ELF files into a separate file for use + in post-mortem (core dump) debugging + clean Remove all build artefacts and return the directory to a "clean" state. @@ -1627,7 +1848,7 @@ working incorrectly. If you think you encountered a bug, please Along with a short description of the bug, please provide the complete configure command line and the relevant output including the error message. -Note: To make the output readable, pleace add a 'code fence' (three backquotes +Note: To make the output readable, please add a 'code fence' (three backquotes ` ``` ` on a separate line) before and after your output: ``` @@ -1830,3 +2051,24 @@ is used, as it is the version of the GNU assembler that will be checked. [10-main.conf]: Configurations/10-main.conf + +[CMVP]: + + +[ESV]: + + +[FIPS 203]: + + +[FIPS 204]: + + +[SP 800-90B]: + + +[jitterentropy-library]: + + +[FIPS 205]: + diff --git a/NEWS.md b/NEWS.md index 007fc9786ef8..62c52a852714 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,11 @@ release. For more details please read the CHANGES file. OpenSSL Releases ---------------- + - [OpenSSL 3.5](#openssl-35) + - [OpenSSL 3.4](#openssl-34) + - [OpenSSL 3.3](#openssl-33) + - [OpenSSL 3.2](#openssl-32) + - [OpenSSL 3.1](#openssl-31) - [OpenSSL 3.0](#openssl-30) - [OpenSSL 1.1.1](#openssl-111) - [OpenSSL 1.1.0](#openssl-110) @@ -15,26 +20,156 @@ OpenSSL Releases - [OpenSSL 1.0.0](#openssl-100) - [OpenSSL 0.9.x](#openssl-09x) -OpenSSL 3.0 +OpenSSL 3.5 ----------- -### Major changes between OpenSSL 3.0.15 and OpenSSL 3.0.16 [11 Feb 2025] +### Major changes between OpenSSL 3.4 and OpenSSL 3.5.0 [8 Apr 2025] -OpenSSL 3.0.16 is a security patch release. The most severe CVE fixed in this -release is Low. +OpenSSL 3.5.0 is a feature release adding significant new functionality to +OpenSSL. + +This release incorporates the following potentially significant or incompatible +changes: + + * Default encryption cipher for the `req`, `cms`, and `smime` applications + changed from `des-ede3-cbc` to `aes-256-cbc`. + + * The default TLS supported groups list has been changed to include and + prefer hybrid PQC KEM groups. Some practically unused groups were removed + from the default list. + + * The default TLS keyshares have been changed to offer X25519MLKEM768 and + and X25519. + + * All `BIO_meth_get_*()` functions were deprecated. + +This release adds the following new features: + + * Support for server side QUIC (RFC 9000) + + * Support for 3rd party QUIC stacks including 0-RTT support + + * Support for PQC algorithms (ML-KEM, ML-DSA and SLH-DSA) + + * A new configuration option `no-tls-deprecated-ec` to disable support for + TLS groups deprecated in RFC8422 + + * A new configuration option `enable-fips-jitter` to make the FIPS provider + to use the `JITTER` seed source + + * Support for central key generation in CMP + + * Support added for opaque symmetric key objects (EVP_SKEY) + + * Support for multiple TLS keyshares and improved TLS key establishment group + configurability + + * API support for pipelining in provided cipher algorithms + +Known issues in 3.5.0 + + * + Calling SSL_accept on objects returned from SSL_accept_connection + results in error. It is expected that making this call will advance + the SSL handshake for the passed connection, but currently it does not. + This can be handled by calling SSL_do_handshake instead. A fix is planned + for OpenSSL 3.5.1 + +OpenSSL 3.4 +----------- + +### Major changes between OpenSSL 3.4.0 and OpenSSL 3.4.1 [11 Feb 2025] + +OpenSSL 3.4.1 is a security patch release. The most severe CVE fixed in this +release is High. This release incorporates the following bug fixes and mitigations: + * Fixed RFC7250 handshakes with unauthenticated servers don't abort as expected. + ([CVE-2024-12797]) + * Fixed timing side-channel in ECDSA signature computation. ([CVE-2024-13176]) +### Major changes between OpenSSL 3.3 and OpenSSL 3.4.0 [22 Oct 2024] + +OpenSSL 3.4.0 is a feature release adding significant new functionality to +OpenSSL. + +This release incorporates the following potentially significant or incompatible +changes: + + * Deprecation of TS_VERIFY_CTX_set_* functions and addition of replacement + TS_VERIFY_CTX_set0_* functions with improved semantics + + * Redesigned use of OPENSSLDIR/ENGINESDIR/MODULESDIR on Windows such that + what were formerly build time locations can now be defined at run time + with registry keys + + * The X25519 and X448 key exchange implementation in the FIPS provider + is unapproved and has `fips=no` property. + + * SHAKE-128 and SHAKE-256 implementations have no default digest length + anymore. That means these algorithms cannot be used with + EVP_DigestFinal/_ex() unless the `xoflen` param is set before. + + * Setting `config_diagnostics=1` in the config file will cause errors to + be returned from SSL_CTX_new() and SSL_CTX_new_ex() if there is an error + in the ssl module configuration. + + * An empty renegotiate extension will be used in TLS client hellos instead + of the empty renegotiation SCSV, for all connections with a minimum TLS + version > 1.0. + + * Deprecation of SSL_SESSION_get_time(), SSL_SESSION_set_time() and + SSL_CTX_flush_sessions() functions in favor of their respective `_ex` + functions which are Y2038-safe on platforms with Y2038-safe `time_t` + +This release adds the following new features: + + * Support for directly fetched composite signature algorithms such as + RSA-SHA2-256 including new API functions + + * FIPS indicators support in the FIPS provider and various updates of the FIPS + provider required for future FIPS 140-3 validations + + * Implementation of RFC 9579 (PBMAC1) in PKCS#12 + + * An optional additional random seed source RNG `JITTER` using a statically + linked jitterentropy library + + * New options `-not_before` and `-not_after` for explicit setting start and + end dates of certificates created with the `req` and `x509` apps + + * Support for integrity-only cipher suites TLS_SHA256_SHA256 and + TLS_SHA384_SHA384 in TLS 1.3, as defined in RFC 9150 + + * Support for retrieving certificate request templates and CRLs in CMP + + * Support for additional X.509v3 extensions related to Attribute Certificates + + * Initial Attribute Certificate (RFC 5755) support + + * Possibility to customize ECC groups initialization to use precomputed values + to save CPU time and use of this feature by the P-256 implementation + +OpenSSL 3.3 +----------- + +### Major changes between OpenSSL 3.3.2 and OpenSSL 3.3.3 [under development] + +OpenSSL 3.3.3 is a security patch release. The most severe CVE fixed in this +release is Low. + +This release incorporates the following bug fixes and mitigations: + * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic curve parameters. ([CVE-2024-9143]) -### Major changes between OpenSSL 3.0.14 and OpenSSL 3.0.15 [3 Sep 2024] +### Major changes between OpenSSL 3.3.1 and OpenSSL 3.3.2 [3 Sep 2024] -OpenSSL 3.0.15 is a security patch release. The most severe CVE fixed in this +OpenSSL 3.3.2 is a security patch release. The most severe CVE fixed in this release is Moderate. This release incorporates the following bug fixes and mitigations: @@ -45,7 +180,12 @@ This release incorporates the following bug fixes and mitigations: * Fixed possible buffer overread in SSL_select_next_proto() ([CVE-2024-5535]) -### Major changes between OpenSSL 3.0.13 and OpenSSL 3.0.14 [4 Jun 2024] +### Major changes between OpenSSL 3.3.0 and OpenSSL 3.3.1 [4 Jun 2024] + +OpenSSL 3.3.1 is a security patch release. The most severe CVE fixed in this +release is Low. + +This release incorporates the following bug fixes and mitigations: * Fixed potential use after free after SSL_free_buffers() is called ([CVE-2024-4741]) @@ -54,38 +194,268 @@ This release incorporates the following bug fixes and mitigations: be very slow ([CVE-2024-4603]) +### Major changes between OpenSSL 3.2 and OpenSSL 3.3.0 [9 Apr 2024] + +OpenSSL 3.3.0 is a feature release adding significant new functionality to +OpenSSL. + +This release adds the following new features: + + * Support for qlog for tracing QUIC connections has been added + + * Added APIs to allow configuring the negotiated idle timeout for QUIC + connections, and to allow determining the number of additional streams + that can currently be created for a QUIC connection. + + * Added APIs to allow disabling implicit QUIC event processing for QUIC SSL + objects + + * Added APIs to allow querying the size and utilisation of a QUIC stream's + write buffer + + * New API `SSL_write_ex2`, which can be used to send an end-of-stream (FIN) + condition in an optimised way when using QUIC. + + * Limited support for polling of QUIC connection and stream objects in a + non-blocking manner. + + * Added a new EVP_DigestSqueeze() API. This allows SHAKE to squeeze multiple + times with different output sizes. + + * Added exporter for CMake on Unix and Windows, alongside the pkg-config + exporter. + + * The BLAKE2s hash algorithm matches BLAKE2b's support for configurable + output length. + + * The EVP_PKEY_fromdata function has been augmented to allow for the + derivation of CRT (Chinese Remainder Theorem) parameters when requested + + * Added API functions SSL_SESSION_get_time_ex(), SSL_SESSION_set_time_ex() + using time_t which is Y2038 safe on 32 bit systems when 64 bit time + is enabled + + * Unknown entries in TLS SignatureAlgorithms, ClientSignatureAlgorithms + config options and the respective calls to SSL[_CTX]_set1_sigalgs() and + SSL[_CTX]_set1_client_sigalgs() that start with `?` character are + ignored and the configuration will still be used. + + * Added `-set_issuer` and `-set_subject` options to `openssl x509` to + override the Issuer and Subject when creating a certificate. The `-subj` + option now is an alias for `-set_subject`. + + * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483 + + * New option `SSL_OP_PREFER_NO_DHE_KEX`, which allows configuring a TLS1.3 + server to prefer session resumption using PSK-only key exchange over PSK + with DHE, if both are available. + + * New atexit configuration switch, which controls whether the OPENSSL_cleanup + is registered when libcrypto is unloaded. + + * Added X509_STORE_get1_objects to avoid issues with the existing + X509_STORE_get0_objects API in multi-threaded applications. + + * Support for using certificate profiles and extened delayed delivery in CMP + +This release incorporates the following potentially significant or incompatible +changes: + + * Applied AES-GCM unroll8 optimisation to Microsoft Azure Cobalt 100 + + * Optimized AES-CTR for ARM Neoverse V1 and V2 + + * Enable AES and SHA3 optimisations on Apple Silicon M3-based MacOS systems + similar to M1/M2. + + * Various optimizations for cryptographic routines using RISC-V vector crypto + extensions + + * Added assembly implementation for md5 on loongarch64 + + * Accept longer context for TLS 1.2 exporters + + * The activate and soft_load configuration settings for providers in + openssl.cnf have been updated to require a value of [1|yes|true|on] + (in lower or UPPER case) to enable the setting. Conversely a value + of [0|no|false|off] will disable the setting. + + * In `openssl speed`, changed the default hash function used with `hmac` from + `md5` to `sha256`. + + * The `-verify` option to the `openssl crl` and `openssl req` will make the + program exit with 1 on failure. + + * The d2i_ASN1_GENERALIZEDTIME(), d2i_ASN1_UTCTIME(), ASN1_TIME_check(), and + related functions have been augmented to check for a minimum length of + the input string, in accordance with ITU-T X.690 section 11.7 and 11.8. + + * OPENSSL_sk_push() and sk__push() functions now return 0 instead of -1 + if called with a NULL stack argument. + + * New limit on HTTP response headers is introduced to HTTP client. The + default limit is set to 256 header lines. + +This release incorporates the following bug fixes and mitigations: + + * The BIO_get_new_index() function can only be called 127 times before it + reaches its upper bound of BIO_TYPE_MASK and will now return -1 once its + exhausted. + +A more detailed list of changes in this release can be found in the +[CHANGES.md] file. + +Users interested in using the new QUIC functionality are encouraged to read the +[README file for QUIC][README-QUIC.md], which provides links to relevant +documentation and example code. + +As always, bug reports and issues relating to OpenSSL can be [filed on our issue +tracker][issue tracker]. + +OpenSSL 3.2 +----------- + +### Major changes between OpenSSL 3.2.1 and OpenSSL 3.2.2 [under development] + +OpenSSL 3.2.2 is a security patch release. The most severe CVE fixed in this +release is Low. + +This release incorporates the following bug fixes and mitigations: + * Fixed unbounded memory growth with session handling in TLSv1.3 ([CVE-2024-2511]) -### Major changes between OpenSSL 3.0.12 and OpenSSL 3.0.13 [30 Jan 2024] +### Major changes between OpenSSL 3.2.0 and OpenSSL 3.2.1 [30 Jan 2024] + +OpenSSL 3.2.1 is a security patch release. The most severe CVE fixed in this +release is Low. + +This release incorporates the following bug fixes and mitigations: * Fixed PKCS12 Decoding crashes ([CVE-2024-0727]) - * Fixed Excessive time spent checking invalid RSA public keys + + * Fixed excessive time spent checking invalid RSA public keys ([CVE-2023-6237]) + * Fixed POLY1305 MAC implementation corrupting vector registers on PowerPC CPUs which support PowerISA 2.07 ([CVE-2023-6129]) - * Fix excessive time spent in DH check / generation with large Q parameter - value ([CVE-2023-5678]) -### Major changes between OpenSSL 3.0.11 and OpenSSL 3.0.12 [24 Oct 2023] +### Major changes between OpenSSL 3.1 and OpenSSL 3.2.0 [23 Nov 2023] + +OpenSSL 3.2.0 is a feature release adding significant new functionality to +OpenSSL. + +This release incorporates the following potentially significant or incompatible +changes: + + * The default SSL/TLS security level has been changed from 1 to 2. + + * The `x509`, `ca`, and `req` apps now always produce X.509v3 certificates. + + * Subject or issuer names in X.509 objects are now displayed as UTF-8 strings + by default. Also spaces surrounding `=` in DN output are removed. + +This release adds the following new features: + + * Support for client side QUIC, including support for + multiple streams (RFC 9000) + + * Support for Ed25519ctx, Ed25519ph and Ed448ph in addition + to existing support for Ed25519 and Ed448 (RFC 8032) + + * Support for deterministic ECDSA signatures (RFC 6979) + + * Support for AES-GCM-SIV, a nonce-misuse-resistant AEAD (RFC 8452) + + * Support for the Argon2 KDF, along with supporting thread pool + functionality (RFC 9106) + + * Support for Hybrid Public Key Encryption (HPKE) (RFC 9180) + + * Support for SM4-XTS + + * Support for Brainpool curves in TLS 1.3 + + * Support for TLS Raw Public Keys (RFC 7250) + + * Support for TCP Fast Open on Linux, macOS and FreeBSD, + where enabled and supported (RFC 7413) + + * Support for TLS certificate compression, including library + support for zlib, Brotli and zstd (RFC 8879) + + * Support for provider-based pluggable signature algorithms + in TLS 1.3 with supporting CMS and X.509 functionality + + With a suitable provider this enables the use of post-quantum/quantum-safe + cryptography. + + * Support for using the Windows system certificate store as a source of + trusted root certificates + + This is not yet enabled by default and must be activated using an + environment variable. This is likely to become enabled by default + in a future feature release. + + * Support for using the IANA standard names in TLS ciphersuite configuration + + * Multiple new features and improvements to CMP protocol support + +The following known issues are present in this release and will be rectified +in a future release: + + * Provider-based signature algorithms cannot be configured using the + SignatureAlgorithms configuration file parameter (#22761) + +This release incorporates the following documentation enhancements: + + * Added multiple tutorials on the OpenSSL library and in particular + on writing various clients (using TLS and QUIC protocols) with libssl + + See [OpenSSL Guide]. + +This release incorporates the following bug fixes and mitigations: + + * Fixed excessive time spent in DH check / generation with large Q parameter + value + ([CVE-2023-5678]) + +A more detailed list of changes in this release can be found in the +[CHANGES.md] file. + +Users interested in using the new QUIC functionality are encouraged to read the +[README file for QUIC][README-QUIC.md], which provides links to relevant +documentation and example code. + +As always, bug reports and issues relating to OpenSSL can be [filed on our issue +tracker][issue tracker]. + +OpenSSL 3.1 +----------- + +### Major changes between OpenSSL 3.1.3 and OpenSSL 3.1.4 [24 Oct 2023] * Mitigate incorrect resize handling for symmetric cipher keys and IVs. ([CVE-2023-5363]) -### Major changes between OpenSSL 3.0.10 and OpenSSL 3.0.11 [19 Sep 2023] +### Major changes between OpenSSL 3.1.2 and OpenSSL 3.1.3 [19 Sep 2023] * Fix POLY1305 MAC implementation corrupting XMM registers on Windows ([CVE-2023-4807]) -### Major changes between OpenSSL 3.0.9 and OpenSSL 3.0.10 [1 Aug 2023] +### Major changes between OpenSSL 3.1.1 and OpenSSL 3.1.2 [1 Aug 2023] * Fix excessive time spent checking DH q parameter value ([CVE-2023-3817]) * Fix DH_check() excessive time with over sized modulus ([CVE-2023-3446]) * Do not ignore empty associated data entries with AES-SIV ([CVE-2023-2975]) + * When building with the `enable-fips` option and using the resulting + FIPS provider, TLS 1.2 will, by default, mandate the use of an + extended master secret and the Hash and HMAC DRBGs will not operate + with truncated digests. -### Major changes between OpenSSL 3.0.8 and OpenSSL 3.0.9 [30 May 2023] +### Major changes between OpenSSL 3.1.0 and OpenSSL 3.1.1 [30 May 2023] * Mitigate for very slow `OBJ_obj2txt()` performance with gigantic OBJECT IDENTIFIER sub-identities. ([CVE-2023-2650]) @@ -96,6 +466,17 @@ This release incorporates the following bug fixes and mitigations: ([CVE-2023-0465]) * Limited the number of nodes created in a policy tree ([CVE-2023-0464]) +### Major changes between OpenSSL 3.0 and OpenSSL 3.1.0 [14 Mar 2023] + + * SSL 3, TLS 1.0, TLS 1.1, and DTLS 1.0 only work at security level 0. + * Performance enhancements and new platform support including new + assembler code algorithm implementations. + * Deprecated LHASH statistics functions. + * FIPS 140-3 compliance changes. + +OpenSSL 3.0 +----------- + ### 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]) @@ -142,7 +523,7 @@ This release incorporates the following bug fixes and mitigations: * 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]) + occupied by the removed hash table entries ([CVE-2022-1473]) ### Major changes between OpenSSL 3.0.1 and OpenSSL 3.0.2 [15 Mar 2022] @@ -161,7 +542,7 @@ This release incorporates the following bug fixes and mitigations: * 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). + * Added support 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. @@ -204,7 +585,7 @@ This release incorporates the following bug fixes and mitigations: * 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 OSSL_PROVIDER_available(), to check provider availability. * 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. @@ -329,7 +710,7 @@ OpenSSL 1.1.1 * 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. + https://github.com/openssl/openssl/wiki/TLS1.3) in the OpenSSL Wiki. * Complete rewrite of the OpenSSL random number generator to introduce the following capabilities @@ -1488,7 +1869,7 @@ OpenSSL 0.9.x * Overhauled Win32 builds * Cleanups and fixes to the Big Number (BN) library * Support for ASN.1 GeneralizedTime - * Splitted ASN.1 SETs from SEQUENCEs + * Split ASN.1 SETs from SEQUENCEs * ASN1 and PEM support for Netscape Certificate Sequences * Overhauled Perl interface * Lots of source tree cleanups. @@ -1684,3 +2065,10 @@ OpenSSL 0.9.x [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 +[OpenSSL Guide]: https://www.openssl.org/docs/manmaster/man7/ossl-guide-introduction.html +[CHANGES.md]: ./CHANGES.md +[README-QUIC.md]: ./README-QUIC.md +[issue tracker]: https://github.com/openssl/openssl/issues +[CMVP]: https://csrc.nist.gov/projects/cryptographic-module-validation-program +[ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations +[jitterentropy-library]: https://github.com/smuellerDD/jitterentropy-library diff --git a/NOTES-ANDROID.md b/NOTES-ANDROID.md index eebf03a4c496..b71365fe731e 100644 --- a/NOTES-ANDROID.md +++ b/NOTES-ANDROID.md @@ -4,7 +4,7 @@ Notes for Android platforms Requirement details ------------------- - Beside basic tools like perl and make you'll need to download the Android + Beside basic tools like perl and make, you'll need to download the Android NDK. It's available for Linux, macOS and Windows, but only Linux version was actually tested. There is no reason to believe that macOS wouldn't work. And as for Windows, it's unclear which "shell" would be @@ -17,8 +17,8 @@ Notes for Android platforms Android is a cross-compiled target and you can't rely on `./Configure` to find out the configuration target for you. You have to name your target explicitly; there are `android-arm`, `android-arm64`, `android-mips`, - `android-mip64`, `android-x86` and `android-x86_64` (`*MIPS` targets are no - longer supported with NDK R20+). + `android-mip64`, `android-x86`, `android-x86_64` and `android-riscv64` + (`*MIPS` targets are no longer supported with NDK R20+). Do not pass --cross-compile-prefix (as you might be tempted), as it will be "calculated" automatically based on chosen platform. However, @@ -26,13 +26,13 @@ Notes for Android platforms invoke `$(CROSS_COMPILE)clang` [`*gcc` on NDK 19 and lower] and company. (`./Configure` will fail and give you a hint if you get it wrong.) - Apart from `PATH` adjustment you need to set `ANDROID_NDK_ROOT` environment + Apart from `PATH` adjustment, you need to set `ANDROID_NDK_ROOT` environment to point at the `NDK` directory. If you're using a side-by-side NDK the path will look something like `/some/where/android-sdk/ndk/`, and for a standalone NDK the path will be something like `/some/where/android-ndk-`. Both variables are significant at both configuration and compilation times. The NDK customarily supports multiple Android API levels, e.g. `android-14`, - `android-21`, etc. By default latest API level is chosen. If you need to target + `android-21`, etc. By default, latest API level is chosen. If you need to target an older platform pass the argument `-D__ANDROID_API__=N` to `Configure`, with `N` being the numerical value of the target platform version. For example, to compile for Android 10 arm64 with a side-by-side NDK r20.0.5594570 @@ -59,7 +59,7 @@ Notes for Android platforms conflict, and mixing the two is therefore not supported. Migration to `CROSS_SYSROOT`-less setup is recommended. - One can engage clang by adjusting PATH to cover same NDK's clang. Just + One can engage clang by adjusting PATH to cover the same NDK's clang. Just keep in mind that if you miss it, Configure will try to use gcc... Also, PATH would need even further adjustment to cover unprefixed, yet target-specific, ar and ranlib. It's possible that you don't need to @@ -67,7 +67,7 @@ Notes for Android platforms Another option is to create so called "standalone toolchain" tailored for single specific platform including Android API level, and assign its - location to `ANDROID_NDK_ROOT`. In such case you have to pass matching + location to `ANDROID_NDK_ROOT`. In such case, you have to pass matching target name to Configure and shouldn't use `-D__ANDROID_API__=N`. `PATH` adjustment becomes simpler, `$ANDROID_NDK_ROOT/bin:$PATH` suffices. diff --git a/NOTES-NONSTOP.md b/NOTES-NONSTOP.md index 9441647604c7..30deed20b8eb 100644 --- a/NOTES-NONSTOP.md +++ b/NOTES-NONSTOP.md @@ -19,22 +19,31 @@ 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. +prerequisite needed to build OpenSSL 3.0 on this platform. 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: +OpenSSL can be built either using the POSIX User Threads (PUT) threading model, +or with threading support disabled. 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` or default will select an unthreaded 32-bit build. + * `nonstop-nsx_64` selects an unthreaded 64-bit memory and file length build. + * `nonstop-nsx_64_klt` selects the 64-bit memory and file length KLT 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. + * `nonstop-nsx_64_put` selects the 64-bit memory and file length PUT build. + +The KLT threading model is a newly released model on NonStop. It implements +kernel-level threading. KLT provides much closer threading to what OpenSSL +uses for Linux-like threading models. KLT continues to use the pthread library +API. There is no supported 32-bit or Guardian builds for KLT. Note: KLT is +not currently available but is planned for post-2024. + +The SPT threading model is no longer supported as of OpenSSL 3.2. + +The PUT model is incompatible with the QUIC capability. This capability should +be disabled when building with PUT. ### TNS/E Considerations @@ -56,10 +65,13 @@ relating to `atexit()` processing when a shared library is unloaded and when the program terminates. This limitation applies to all OpenSSL shared library components. -It is possible to configure the build with `no-atexit` to avoid the SIGSEGV. -Preferably, you can explicitly call `OPENSSL_cleanup()` from your application. -It is not mandatory as it just deallocates various global data structures -OpenSSL allocated. +A control has been added as of 3.3.x to disable calls to `atexit()` within the +`libcrypto` builds (specifically in `crypto/init.c`). This switch can be +controlled using `disable-atexit` or `enable-atexit`, and is disabled by default +for NonStop builds. If you need to have `atexit()` functionality, set +`enabled-atexit` when configuring OpenSSL to enable the `atexit()` call to +register `OPENSSL_cleanup()` automatically. Preferably, you can explicitly call +`OPENSSL_cleanup()` from your application. About Prefix and OpenSSLDir --------------------------- @@ -145,9 +157,7 @@ update this list: - 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. +follow the same considerations as for TNS/X above. Also see the NSDEE discussion below for more historical information. @@ -211,30 +221,21 @@ 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. +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 \ @@ -245,15 +246,9 @@ assumes that your PWD is set according to your installation standards. ./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-PERL.md b/NOTES-PERL.md index b7fc83fc7d75..3a91f09c2d5e 100644 --- a/NOTES-PERL.md +++ b/NOTES-PERL.md @@ -33,12 +33,12 @@ Perl on Windows --------------- There are a number of build targets that can be viewed as "Windows". -Indeed, there are `VC-*` configs targeting VisualStudio C, as well as +Indeed, there are `VC-*` configs targeting Visual Studio C, as well as MinGW and Cygwin. The key recommendation is to use a Perl installation that matches the build environment. For example, if you will build on Cygwin be sure to use the Cygwin package manager to install Perl. For MSYS builds use the MSYS provided Perl. -For VC-* builds we recommend Strawberry Perl, from . +For VC-* builds, we recommend Strawberry Perl, from . An alternative is ActiveState Perl, from for which you may need to explicitly select the Perl module Win32/Console.pm available via . @@ -117,7 +117,7 @@ descriptions below, `Text::Template` will serve as an example. $ cpan -f -i Text::Template - Note: on VMS, you must quote any argument that contains upper case + Note: on VMS, you must quote any argument that contains uppercase characters, so the lines above would be: $ cpan -i "Text::Template" diff --git a/NOTES-UNIX.md b/NOTES-UNIX.md index 293793b60559..fa52de68abc6 100644 --- a/NOTES-UNIX.md +++ b/NOTES-UNIX.md @@ -101,14 +101,14 @@ Notes for UNIX-like platforms shared library face exactly the same problem with non-default locations. The OpenSSL config options mentioned above might or might not have bearing on linking of the target application. "Might" means that under some - circumstances it would be sufficient to link with OpenSSL shared library + circumstances, it would be sufficient to link with OpenSSL shared library "naturally", i.e. with `-L/whatever/path -lssl -lcrypto`. But there are also cases when you'd have to explicitly specify runtime search path when linking your application. Consult your system documentation and use above section as inspiration... Shared OpenSSL builds also install static libraries. Linking with the - latter is likely to require special care, because linkers usually look + latter is likely to require special care because linkers usually look for shared libraries first and tend to remain "blind" to static OpenSSL libraries. Referring to system documentation would suffice, if not for a corner case. On AIX static libraries (in shared build) are named diff --git a/NOTES-VALGRIND.md b/NOTES-VALGRIND.md index 2700324efa36..96f0df1d194d 100644 --- a/NOTES-VALGRIND.md +++ b/NOTES-VALGRIND.md @@ -1,9 +1,9 @@ Notes on Valgrind ================= -Valgrind is a test harness that includes many tools such as memcheck, +[Valgrind](https://valgrind.org/) is a test harness that includes many tools such as memcheck, which is commonly used to check for memory leaks, etc. The default tool -run by Valgrind is memcheck. There are other tools available, but this +run by Valgrind is memcheck. There are [other tools available](https://valgrind.org/info/tools.html), but this will focus on memcheck. Valgrind runs programs in a virtual machine, this means OpenSSL unit @@ -13,11 +13,11 @@ Requirements ------------ 1. Platform supported by Valgrind - See + - See [Valgrind Supported Platforms](http://valgrind.org/info/platforms.html) 2. Valgrind installed on the platform - See + - See [Valgrind Current Releases](http://valgrind.org/downloads/current.html) 3. OpenSSL compiled - See [INSTALL.md](INSTALL.md) + - See [INSTALL.md](INSTALL.md) Running Tests ------------- @@ -32,7 +32,7 @@ to allow programs to find shared libraries. The variable can be modified to specify a different executable environment. EXE_SHELL=\ - "`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 --leak-check=full -q" + "$(/bin/pwd)/util/wrap.pl valgrind --error-exitcode=1 --leak-check=full -q" This will start up Valgrind with the default checker (`memcheck`). The `--error-exitcode=1` option specifies that Valgrind should exit with an @@ -62,11 +62,11 @@ file [test/README.md](test/README.md). Example command line: - $ make test EXE_SHELL="`/bin/pwd`/util/wrap.pl valgrind --error-exitcode=1 \ + $ make test EXE_SHELL="$(/bin/pwd)/util/wrap.pl valgrind --error-exitcode=1 \ --leak-check=full -q" OPENSSL_ia32cap=":0" If an error occurs, you can then run the specific test via the `TESTS` variable with the `VERBOSE` or `VF` or `VFP` options to gather additional information. - $ make test VERBOSE=1 TESTS=test_test EXE_SHELL="`/bin/pwd`/util/wrap.pl \ + $ make test VERBOSE=1 TESTS=test_test EXE_SHELL="$(/bin/pwd)/util/wrap.pl \ valgrind --error-exitcode=1 --leak-check=full -q" OPENSSL_ia32cap=":0" diff --git a/NOTES-WINDOWS.md b/NOTES-WINDOWS.md index b1d6c4fe13bb..9beeb79be758 100644 --- a/NOTES-WINDOWS.md +++ b/NOTES-WINDOWS.md @@ -1,9 +1,9 @@ Notes for Windows platforms =========================== - - [Native builds using Visual C++](#native-builds-using-visual-c++) + - [Native builds using Visual C++](#native-builds-using-visual-c) - [Native builds using Embarcadero C++Builder]( - #native-builds-using-embarcadero-c++-builder) + #native-builds-using-embarcadero-cbuilder) - [Native builds using MinGW](#native-builds-using-mingw) - [Linking native applications](#linking-native-applications) - [Hosted builds using Cygwin](#hosted-builds-using-cygwin) @@ -23,7 +23,7 @@ or "Hosted" OpenSSL relies on an external POSIX compatibility layer for building (using GNU/Unix shell, compiler, and tools) and at run time. -For this option you can use Cygwin. +For this option, you can use Cygwin. Native builds using Visual C++ ============================== @@ -77,6 +77,14 @@ Quick start - `perl Configure VC-WIN64A` if you want 64-bit OpenSSL or - `perl Configure VC-WIN64-ARM` if you want Windows on Arm (win-arm64) OpenSSL or + - `perl Configure VC-WIN64-CLANGASM-ARM` if you want Windows on Arm (win-arm64) + OpenSSL with assembly support using clang-cl as assembler or + - `perl Configure VC-CLANG-WIN64-CLANGASM-ARM` if you want Windows on Arm (win-arm64) + OpenSSL using clang-cl as both compiler and assembler or + - `perl Configure VC-WIN32-HYBRIDCRT` if you want 32-bit OpenSSL dependent + on the Universal CRT or + - `perl Configure VC-WIN64A-HYBRIDCRT` if you want 64-bit OpenSSL dependent + on the Universal CRT or - `perl Configure` to let Configure figure out the platform 6. `nmake` @@ -91,31 +99,41 @@ check the INSTALL.md file. Installation directories ------------------------ -The default installation directories are derived from environment -variables. +On most Unix platforms installation directories are determined at build time via +constant defines. On Windows platforms however, installation directories are +determined via registry keys, as it is common practice to build OpenSSL and +install it to a variety of locations. -For VC-WIN32, the following defaults are use: +The following keys: - PREFIX: %ProgramFiles(x86)%\OpenSSL - OPENSSLDIR: %CommonProgramFiles(x86)%\SSL + `\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL--\OPENSSLDIR` + `\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL--\ENGINESDIR` + `\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL--\MODULESDIR` -For VC-WIN64, the following defaults are use: +Can be administratively set, and openssl will take the paths found there as the +values for OPENSSLDIR, ENGINESDIR and MODULESDIR respectively. - PREFIX: %ProgramW6432%\OpenSSL - OPENSSLDIR: %CommonProgramW6432%\SSL +To enable the reading of registry keys from windows builds, add +`-DOSSL_WINCTX=`to the Configure command line. This define is used +at build-time to construct library build specific registry key paths of the +format: +`\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432node\OpenSSL--` -Should those environment variables not exist (on a pure Win32 -installation for examples), these fallbacks are used: +Where `` is the major.minor version of the library being +built, and `` is the value specified by `-DOPENSSL_WINCTX`. This allows +for multiple openssl builds to be created and installed on a single system, in +which each library can use its own set of registry keys. - PREFIX: %ProgramFiles%\OpenSSL - OPENSSLDIR: %CommonProgramFiles%\SSL +Note the installer available at will set +these keys when the installer is run. -ALSO NOTE that those directories are usually write protected, even if -your account is in the Administrators group. To work around that, -start the command prompt by right-clicking on it and choosing "Run as -Administrator" before running `nmake install`. The other solution -is, of course, to choose a different set of directories by using -`--prefix` and `--openssldir` when configuring. +A summary table of behavior on Windows platforms + +|`OSSL_WINCTX`|Registry key|OpenSSL Behavior | +|-------------|------------|------------------------------------------| +|Defined | Defined |OpenSSL Reads Paths from Registry | +|Defined | Undefined |OpenSSL returns errors on module/conf load| +|Undefined | N/A |OpenSSL uses build time defaults | Special notes for Universal Windows Platform builds, aka `VC-*-UWP` ------------------------------------------------------------------- @@ -130,8 +148,8 @@ Native builds using Embarcadero C++Builder ========================================= This toolchain (a descendant of Turbo/Borland C++) is an alternative to MSVC. -OpenSSL currently includes an experimental 32-bit configuration targeting the -Clang-based compiler (`bcc32c.exe`) in v10.3.3 Community Edition. +OpenSSL currently includes experimental 32-bit and 64-bit configurations targeting the +Clang-based compiler (`bcc32c.exe` and `bcc64.exe`) in v10.3.3 Community Edition. 1. Install Perl. @@ -140,6 +158,8 @@ Clang-based compiler (`bcc32c.exe`) in v10.3.3 Community Edition. 3. Go to the root of the OpenSSL source directory and run: `perl Configure BC-32 --prefix=%CD%` + for Win64 builds use: + `perl Configure BC-64 --prefix=%CD%` 4. `make -N` @@ -212,7 +232,7 @@ Linking native applications This section applies to all native builds. -If you link with static OpenSSL libraries then you're expected to +If you link with static OpenSSL libraries, then you're expected to additionally link your application with `WS2_32.LIB`, `GDI32.LIB`, `ADVAPI32.LIB`, `CRYPT32.LIB` and `USER32.LIB`. Those developing non-interactive service applications might feel concerned about @@ -220,7 +240,7 @@ linking with `GDI32.LIB` and `USER32.LIB`, as they are justly associated with interactive desktop, which is not available to service processes. The toolkit is designed to detect in which context it's currently executed, GUI, console app or service, and act accordingly, -namely whether or not to actually make GUI calls. Additionally those +namely whether to actually make GUI calls. Additionally, those who wish to `/DELAYLOAD:GDI32.DLL` and `/DELAYLOAD:USER32.DLL` and actually keep them off service process should consider implementing and exporting from .exe image in question own `_OPENSSL_isservice` not @@ -261,5 +281,5 @@ Apart from that, follow the Unix / Linux instructions in INSTALL.md. NOTE: `make test` and normal file operations may fail in directories mounted as text (i.e. `mount -t c:\somewhere /home`) due to Cygwin -stripping of carriage returns. To avoid this ensure that a binary +stripping of carriage returns. To avoid this, ensure that a binary mount is used, e.g. `mount -b c:\somewhere /home`. diff --git a/README-ENGINES.md b/README-ENGINES.md index 9874276f1320..24ec748fe566 100644 --- a/README-ENGINES.md +++ b/README-ENGINES.md @@ -8,7 +8,7 @@ The ENGINE API was introduced in OpenSSL version 0.9.6 as a low level interface for adding alternative implementations of cryptographic primitives, most notably for integrating hardware crypto devices. -The ENGINE interface has its limitations and it has been superseeded +The ENGINE interface has its limitations and it has been superseded by the [PROVIDER API](README-PROVIDERS.md), it is deprecated in OpenSSL version 3.0. The following documentation is retained as an aid for users who need to maintain or support existing ENGINE implementations. @@ -22,9 +22,9 @@ Built-in ENGINE implementations There are currently built-in ENGINE implementations for the following crypto devices: - * Microsoft CryptoAPI - * VIA Padlock - * nCipher CHIL +- Microsoft CryptoAPI +- VIA Padlock +- nCipher CHIL In addition, dynamic binding to external ENGINE implementations is now provided by a special ENGINE called "dynamic". See the "DYNAMIC ENGINE" @@ -32,9 +32,9 @@ section below for details. At this stage, a number of things are still needed and are being worked on: - 1. Integration of EVP support. - 2. Configuration support. - 3. Documentation! +1. Integration of EVP support. +2. Configuration support. +3. Documentation! Integration of EVP support -------------------------- @@ -87,17 +87,17 @@ devices from common OpenSSL-based applications. Bugs and/or inexplicable behaviour in using a specific ENGINE implementation should be sent to the author of that implementation (if it is mentioned in the corresponding C file), and in the case of implementations for commercial hardware -devices, also through whatever vendor support channels are available. If +devices, also through whatever vendor support channels are available. If none of this is possible, or the problem seems to be something about the ENGINE API itself (ie. not necessarily specific to a particular ENGINE implementation) then you should mail complete details to the relevant OpenSSL mailing list. For a definition of "complete details", refer to the OpenSSL "README" file. As for which list to send it to: - * openssl-users: if you are *using* the ENGINE abstraction, either in an - pre-compiled application or in your own application code. +- openssl-users: if you are *using* the ENGINE abstraction, either in an + pre-compiled application or in your own application code. - * openssl-dev: if you are discussing problems with OpenSSL source code. +- openssl-dev: if you are discussing problems with OpenSSL source code. USAGE ===== @@ -185,7 +185,7 @@ the shared-library ENGINE implementation. If this command succeeds, the (copy of the) 'dynamic' ENGINE will magically morph into the ENGINE that has been loaded from the shared-library. As such, any control commands supported by the loaded ENGINE could then be executed as per -normal. Eg. if ENGINE "foo" is implemented in the shared-library +normal. For instance, if ENGINE "foo" is implemented in the shared-library "libfoo.so" and it supports some special control command "CMD_FOO", the following code would load and use it (NB: obviously this code has no error checking); @@ -270,35 +270,36 @@ This example will show building the "atalla" ENGINE in the crypto/engine/ directory as a shared-library for use via the "dynamic" ENGINE. - 1. "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL - source tree. +1. "cd" to the crypto/engine/ directory of a pre-compiled OpenSSL + source tree. - 2. Recompile at least one source file so you can see all the compiler - flags (and syntax) being used to build normally. Eg; +2. Recompile at least one source file so you can see all the compiler + flags (and syntax) being used to build normally. Eg; - touch hw_atalla.c ; make + touch hw_atalla.c ; make - will rebuild "hw_atalla.o" using all such flags. + will rebuild "hw_atalla.o" using all such flags. - 3. Manually enter the same compilation line to compile the - "hw_atalla.c" file but with the following two changes; - * add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches, - * change the output file from "hw_atalla.o" to something new, - eg. "tmp_atalla.o" +3. Manually enter the same compilation line to compile the + "hw_atalla.c" file but with the following two changes; - 4. Link "tmp_atalla.o" into a shared-library using the top-level - OpenSSL libraries to resolve any dependencies. The syntax for doing - this depends heavily on your system/compiler and is a nightmare - known well to anyone who has worked with shared-library portability - before. 'gcc' on Linux, for example, would use the following syntax; + - add "-DENGINE_DYNAMIC_SUPPORT" to the command line switches, + - change the output file from "hw_atalla.o" to something new, + eg. "tmp_atalla.o" - gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto +4. Link "tmp_atalla.o" into a shared-library using the top-level + OpenSSL libraries to resolve any dependencies. The syntax for doing + this depends heavily on your system/compiler and is a nightmare + known well to anyone who has worked with shared-library portability + before. 'gcc' on Linux, for example, would use the following syntax; - 5. Test your shared library using "openssl engine" as explained in the - previous section. Eg. from the top-level directory, you might try + gcc -shared -o dyn_atalla.so tmp_atalla.o -L../.. -lcrypto - apps/openssl engine -vvvv dynamic \ - -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD +5. Test your shared library using "openssl engine" as explained in the + previous section. Eg. from the top-level directory, you might try + + apps/openssl engine -vvvv dynamic \ + -pre SO_PATH:./crypto/engine/dyn_atalla.so -pre LOAD If the shared-library loads successfully, you will see both "-pre" commands marked as "SUCCESS" and the list of control commands diff --git a/README-FIPS.md b/README-FIPS.md index c79552b2d8ad..b31f8c65304b 100644 --- a/README-FIPS.md +++ b/README-FIPS.md @@ -34,7 +34,9 @@ Installing the FIPS provider In order to be FIPS compliant you must only use FIPS validated source code. Refer to for information related to which versions are FIPS validated. The instructions given below build OpenSSL -just using the FIPS validated source code. +just using the FIPS validated source code. Any FIPS validated version may be +used with any other openssl library. Please see +To determine which FIPS validated library version may be appropriate for you. If you want to use a validated FIPS provider, but also want to use the latest OpenSSL release to build everything else, then refer to the next section. @@ -71,14 +73,14 @@ the installation by doing the following two things: - Runs the FIPS module self tests - Generates the so-called FIPS module configuration file containing information - about the module such as the module checksum (and for OpenSSL 3.0 the + about the module such as the module checksum (and for OpenSSL 3.1.2 the self test status). The FIPS module must have the self tests run, and the FIPS module config file -output generated on every machine that it is to be used on. For OpenSSL 3.0, +output generated on every machine that it is to be used on. For OpenSSL 3.1.2 you must not copy the FIPS module config file output data from one machine to another. -On Unix the `openssl fipsinstall` command will be invoked as follows by default: +On Unix, the `openssl fipsinstall` command will be invoked as follows by default: $ openssl fipsinstall -out /usr/local/ssl/fipsmodule.cnf -module /usr/local/lib/ossl-modules/fips.so @@ -95,11 +97,11 @@ Download and build a validated FIPS provider -------------------------------------------- Refer to for information related to -which versions are FIPS validated. For this example we use OpenSSL 3.0.0. +which versions are FIPS validated. For this example we use OpenSSL 3.1.2. - $ wget https://www.openssl.org/source/openssl-3.0.0.tar.gz - $ tar -xf openssl-3.0.0.tar.gz - $ cd openssl-3.0.0 + $ wget https://www.openssl.org/source/openssl-3.1.2.tar.gz + $ tar -xf openssl-3.1.2.tar.gz + $ cd openssl-3.1.2 $ ./Configure enable-fips $ make $ cd .. @@ -107,44 +109,45 @@ which versions are FIPS validated. For this example we use OpenSSL 3.0.0. Download and build the latest release of OpenSSL ------------------------------------------------ -We use OpenSSL 3.1.0 here, (but you could also use the latest 3.0.X) +We use OpenSSL 3.5.0 here, (but you could also use the latest 3.5.X) - $ wget https://www.openssl.org/source/openssl-3.1.0.tar.gz - $ tar -xf openssl-3.1.0.tar.gz - $ cd openssl-3.1.0 + $ wget https://www.openssl.org/source/openssl-3.5.0.tar.gz + $ tar -xf openssl-3.5.0.tar.gz + $ cd openssl-3.5.0 $ ./Configure enable-fips $ make Use the OpenSSL FIPS provider for testing ----------------------------------------- -We do this by replacing the artifact for the OpenSSL 3.1.0 FIPS provider. -Note that the OpenSSL 3.1.0 FIPS provider has not been validated +We do this by replacing the artifact for the OpenSSL 3.5.0 FIPS provider. +Note that the OpenSSL 3.5.0 FIPS provider has not been validated so it must not be used for FIPS purposes. - $ cp ../openssl-3.0.0/providers/fips.so providers/. - $ cp ../openssl-3.0.0/providers/fipsmodule.cnf providers/. - // Note that for OpenSSL 3.0 that the `fipsmodule.cnf` file should not + $ cp ../openssl-3.1.2/providers/fips.so providers/. + $ cp ../openssl-3.1.2/providers/fipsmodule.cnf providers/. + // Note that for OpenSSL 3.1.2 that the `fipsmodule.cnf` file should not // be copied across multiple machines if it contains an entry for // `install-status`. (Otherwise the self tests would be skipped). // Validate the output of the following to make sure we are using the - // OpenSSL 3.0.0 FIPS provider + // OpenSSL 3.1.2 FIPS provider $ ./util/wrap.pl -fips apps/openssl list -provider-path providers \ -provider fips -providers - // Now run the current tests using the OpenSSL 3.0 FIPS provider. + // Now run the current tests using the OpenSSL 3.1.2 FIPS provider. $ make tests Copy the FIPS provider artifacts (`fips.so` & `fipsmodule.cnf`) to known locations ------------------------------------------------------------------------------------- - $ cd ../openssl-3.0.0 + $ cd ../openssl-3.1.2 $ sudo make install_fips Check that the correct FIPS provider is being used -------------------------------------------------- + $ cd ../openssl-3.5.0 $./util/wrap.pl -fips apps/openssl list -provider-path providers \ -provider fips -providers @@ -152,11 +155,11 @@ Check that the correct FIPS provider is being used Providers: base name: OpenSSL Base Provider - version: 3.1.0 + version: 3.5.0 status: active fips name: OpenSSL FIPS Provider - version: 3.0.0 + version: 3.1.2 status: active Using the FIPS Module in applications @@ -165,4 +168,34 @@ Using the FIPS Module in applications Documentation about using the FIPS module is available on the [fips_module(7)] manual page. - [fips_module(7)]: https://www.openssl.org/docs/man3.0/man7/fips_module.html + [fips_module(7)]: https://www.openssl.org/docs/manmaster/man7/fips_module.html + +Entropy Source +============== + +The FIPS provider typically relies on an external entropy source, +specified during OpenSSL build configuration (default: `os`). However, by +enabling the `enable-fips-jitter` option during configuration, an internal +jitter entropy source will be used instead. Note that this will cause +the FIPS provider to operate in a non-compliant mode unless an entropy +assessment [ESV] and validation through the [CMVP] are additionally conducted. + +Note that the `enable-fips-jitter` option is only available in OpenSSL +versions 3.5 and later. + + [CMVP]: https://csrc.nist.gov/projects/cryptographic-module-validation-program + [ESV]: https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations + +3rd-Party Vendor Builds +===================================== + +Some Vendors choose to patch/modify/build their own FIPS provider, +test it with a Security Laboratory and submit it under their own CMVP +certificate, instead of using OpenSSL Project submissions. When doing +so, FIPS provider should uniquely identify its own name and version +number. The build infrastructure allows to customize FIPS provider +build information via changes to strings in `VERSION.dat`. + +Setting "PRE_RELEASE_TAG" (dashed suffix), "BUILD_METADATA" (plus +suffix), and "FIPS_VENDOR" allow to control reported FIPS provider +name and build version as required for CMVP submission. diff --git a/README-PROVIDERS.md b/README-PROVIDERS.md index 25e49c8618f7..3b5476831b26 100644 --- a/README-PROVIDERS.md +++ b/README-PROVIDERS.md @@ -15,12 +15,12 @@ Standard Providers Providers are containers for algorithm implementations. Whenever a cryptographic algorithm is used via the high level APIs a provider is selected. It is that provider implementation that actually does the required work. There are five -providers distributed with OpenSSL. In the future we expect third parties to +providers distributed with OpenSSL. In the future, we expect third parties to distribute their own providers which can be added to OpenSSL dynamically. Documentation about writing providers is available on the [provider(7)] manual page. - [provider(7)]: https://www.openssl.org/docs/man3.0/man7/provider.html + [provider(7)]: https://www.openssl.org/docs/manmaster/man7/provider.html The Default Provider -------------------- @@ -31,10 +31,10 @@ explicitly (e.g. in the application or via config), then this is the provider that will be used. It is loaded automatically the first time that we try to get an algorithm from a provider if no other provider has been loaded yet. If another provider has already been loaded then it won't be loaded -automatically. Therefore if you want to use it in conjunction with other -providers then you must load it explicitly. +automatically. Therefore, if you want to use it in conjunction with other +providers, then you must load it explicitly. -This is a "built-in" provider which means that it is compiled and linked +This is a "built-in" provider, which means that it is compiled and linked into the libcrypto library and does not exist as a separate standalone module. The Legacy Provider @@ -58,7 +58,7 @@ The FIPS provider contains a sub-set of the algorithm implementations available from the default provider, consisting of algorithms conforming to FIPS standards. It is intended that this provider will be FIPS140-2 validated. -In some cases there may be minor behavioural differences between algorithm +In some cases, there may be minor behavioural differences between algorithm implementations in this provider compared to the equivalent algorithm in the default provider. This is typically in order to conform to FIPS standards. @@ -88,7 +88,7 @@ Providers to be loaded can be specified in the OpenSSL config file. See the [config(5)] manual page for information about how to configure providers via the config file, and how to automatically activate them. - [config(5)]: https://www.openssl.org/docs/man3.0/man5/config.html + [config(5)]: https://www.openssl.org/docs/manmaster/man5/config.html The following is a minimal config file example to load and activate both the legacy and the default provider in the default library context. diff --git a/README.md b/README.md index 477f5cbb7d12..f1dbadfe8ec6 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,17 @@ Welcome to the OpenSSL Project [![openssl logo]][www.openssl.org] [![github actions ci badge]][github actions ci] -[![appveyor badge]][appveyor jobs] +![Nightly OS Zoo ci badge](https://github.com/openssl/openssl/actions/workflows/os-zoo.yml/badge.svg) +![Provider Compatibility](https://github.com/openssl/openssl/actions/workflows/provider-compatibility.yml/badge.svg) +![Quic Interop](https://github.com/openssl/openssl/actions/workflows/run_quic_interop.yml/badge.svg) +![Daily checks](https://github.com/openssl/openssl/actions/workflows/run-checker-daily.yml/badge.svg) OpenSSL is a robust, commercial-grade, full-featured Open Source Toolkit -for the Transport Layer Security (TLS) protocol formerly known as the -Secure Sockets Layer (SSL) protocol. The protocol implementation is based -on a full-strength general purpose cryptographic library, which can also -be used stand-alone. +for the TLS (formerly SSL), DTLS and QUIC protocols. + +The protocol implementations are based on a full-strength general purpose +cryptographic library, which can also be used stand-alone. Also included is a +cryptographic module validated to conform with FIPS standards. OpenSSL is descended from the SSLeay library developed by Eric A. Young and Tim J. Hudson. @@ -35,7 +39,9 @@ Overview The OpenSSL toolkit includes: - **libssl** - an implementation of all TLS protocol versions up to TLSv1.3 ([RFC 8446]). + an implementation of all TLS protocol versions up to TLSv1.3 ([RFC 8446]), + DTLS protocol versions up to DTLSv1.2 ([RFC 6347]) and + the QUIC version 1 protocol ([RFC 9000]). - **libcrypto** a full-strength general purpose cryptographic library. It constitutes the @@ -48,7 +54,8 @@ The OpenSSL toolkit includes: - creation of X.509 certificates, CSRs and CRLs - calculation of message digests - encryption and decryption - - SSL/TLS client and server tests + - SSL/TLS/DTLS and client and server tests + - QUIC client tests - handling of S/MIME signed or encrypted mail - and more... @@ -63,10 +70,14 @@ Source code tarballs of the official releases can be downloaded from The OpenSSL project does not distribute the toolkit in binary form. However, for a large variety of operating systems precompiled versions -of the OpenSSL toolkit are available. In particular on Linux and other -Unix operating systems it is normally recommended to link against the +of the OpenSSL toolkit are available. In particular, on Linux and other +Unix operating systems, it is normally recommended to link against the precompiled shared libraries provided by the distributor or vendor. +We also maintain a list of third parties that produce OpenSSL binaries for +various Operating Systems (including Windows) on the [Binaries] page on our +wiki. + For Testing and Development --------------------------- @@ -90,7 +101,7 @@ instead. git clone https://github.com/yourname/openssl.git -This is necessary, because all development of OpenSSL nowadays is done via +This is necessary because all development of OpenSSL nowadays is done via GitHub pull requests. For more details, see [Contributing](#contributing). Build and Install @@ -109,12 +120,29 @@ document. * [Notes on Perl](NOTES-PERL.md) * [Notes on Valgrind](NOTES-VALGRIND.md) -Specific notes on upgrading to OpenSSL 3.0 from previous versions can be found -in the [migration_guide(7ossl)] manual page. +Specific notes on upgrading to OpenSSL 3.x from previous versions can be found +in the [ossl-guide-migration(7ossl)] manual page. Documentation ============= +README Files +------------ + +There are some README.md files in the top level of the source distribution +containing additional information on specific topics. + + * [Information about the OpenSSL QUIC protocol implementation](README-QUIC.md) + * [Information about the OpenSSL Provider architecture](README-PROVIDERS.md) + * [Information about using the OpenSSL FIPS validated module](README-FIPS.md) + * [Information about the legacy OpenSSL Engine architecture](README-ENGINES.md) + +The OpenSSL Guide +----------------- + +There are some tutorial and introductory pages on some important OpenSSL topics +within the [OpenSSL Guide]. + Manual Pages ------------ @@ -123,13 +151,19 @@ available online. - [OpenSSL master](https://www.openssl.org/docs/manmaster) - [OpenSSL 3.0](https://www.openssl.org/docs/man3.0) -- [OpenSSL 1.1.1](https://www.openssl.org/docs/man1.1.1) +- [OpenSSL 3.1](https://www.openssl.org/docs/man3.1) +- [OpenSSL 3.2](https://www.openssl.org/docs/man3.2) + +Demos +----- + +There are numerous source code demos for using various OpenSSL capabilities in the +[demos subfolder](./demos). Wiki ---- -There is a Wiki at [wiki.openssl.org] which is currently not very active. -It contains a lot of useful information, not all of which is up to date. +There is a [GitHub Wiki] which is currently not very active. License ======= @@ -144,7 +178,7 @@ Support ======= There are various ways to get in touch. The correct channel depends on -your requirement. see the [SUPPORT](SUPPORT.md) file for more details. +your requirement. See the [SUPPORT](SUPPORT.md) file for more details. Contributing ============ @@ -156,13 +190,13 @@ Legalities ========== A number of nations restrict the use or export of cryptography. If you are -potentially subject to such restrictions you should seek legal advice before +potentially subject to such restrictions, you should seek legal advice before attempting to develop or distribute cryptographic code. Copyright ========= -Copyright (c) 1998-2025 The OpenSSL Project +Copyright (c) 1998-2025 The OpenSSL Project Authors Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson @@ -178,17 +212,31 @@ All rights reserved. "OpenSSL GitHub Mirror" -[wiki.openssl.org]: - +[GitHub Wiki]: + "OpenSSL Wiki" -[migration_guide(7ossl)]: - +[ossl-guide-migration(7ossl)]: + "OpenSSL Migration Guide" [RFC 8446]: +[RFC 6347]: + + +[RFC 9000]: + + +[Binaries]: + + "List of third party OpenSSL binaries" + +[OpenSSL Guide]: + + "An introduction to OpenSSL" + [openssl logo]: diff --git a/VERSION.dat b/VERSION.dat index 4b7eb91a451a..9d13b630cc71 100644 --- a/VERSION.dat +++ b/VERSION.dat @@ -1,7 +1,7 @@ MAJOR=3 -MINOR=0 -PATCH=16 +MINOR=5 +PATCH=0 PRE_RELEASE_TAG= BUILD_METADATA= -RELEASE_DATE="11 Feb 2025" +RELEASE_DATE="8 Apr 2025" SHLIB_VERSION=3 diff --git a/apps/CA.pl.in b/apps/CA.pl.in index f029470005d9..2c31ee6c8de1 100644 --- a/apps/CA.pl.in +++ b/apps/CA.pl.in @@ -36,6 +36,8 @@ my $CACERT = "cacert.pem"; my $CACRL = "crl.pem"; my $DAYS = "-days 365"; my $CADAYS = "-days 1095"; # 3 years +my $EXTENSIONS = "-extensions v3_ca"; +my $POLICY = "-policy policy_anything"; my $NEWKEY = "newkey.pem"; my $NEWREQ = "newreq.pem"; my $NEWCERT = "newcert.pem"; @@ -179,7 +181,7 @@ if ($WHAT eq '-newcert' ) { $RET = run("$CA -create_serial" . " -out ${CATOP}/$CACERT $CADAYS -batch" . " -keyfile ${CATOP}/private/$CAKEY -selfsign" - . " -extensions v3_ca" + . " $EXTENSIONS" . " -infiles ${CATOP}/$CAREQ $EXTRA{ca}") if $RET == 0; print "CA certificate is in ${CATOP}/$CACERT\n" if $RET == 0; } @@ -191,19 +193,19 @@ if ($WHAT eq '-newcert' ) { . " -export -name \"$cname\" $EXTRA{pkcs12}"); print "PKCS #12 file is in $NEWP12\n" if $RET == 0; } elsif ($WHAT eq '-xsign' ) { - $RET = run("$CA -policy policy_anything -infiles $NEWREQ $EXTRA{ca}"); + $RET = run("$CA $POLICY -infiles $NEWREQ $EXTRA{ca}"); } elsif ($WHAT eq '-sign' ) { - $RET = run("$CA -policy policy_anything -out $NEWCERT" + $RET = run("$CA $POLICY -out $NEWCERT" . " -infiles $NEWREQ $EXTRA{ca}"); print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signCA' ) { - $RET = run("$CA -policy policy_anything -out $NEWCERT" - . " -extensions v3_ca -infiles $NEWREQ $EXTRA{ca}"); + $RET = run("$CA $POLICY -out $NEWCERT" + . " $EXTENSIONS -infiles $NEWREQ $EXTRA{ca}"); print "Signed CA certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-signcert' ) { $RET = run("$X509 -x509toreq -in $NEWREQ -signkey $NEWREQ" . " -out tmp.pem $EXTRA{x509}"); - $RET = run("$CA -policy policy_anything -out $NEWCERT" + $RET = run("$CA $POLICY -out $NEWCERT" . "-infiles tmp.pem $EXTRA{ca}") if $RET == 0; print "Signed certificate is in $NEWCERT\n" if $RET == 0; } elsif ($WHAT eq '-verify' ) { diff --git a/apps/asn1parse.c b/apps/asn1parse.c index 129b867c8cc7..4f882396d03d 100644 --- a/apps/asn1parse.c +++ b/apps/asn1parse.c @@ -32,7 +32,7 @@ const OPTIONS asn1parse_options[] = { {"oid", OPT_OID, '<', "file of extra oid definitions"}, OPT_SECTION("I/O"), - {"inform", OPT_INFORM, 'F', "input format - one of DER PEM"}, + {"inform", OPT_INFORM, 'A', "input format - one of DER PEM B64"}, {"in", OPT_IN, '<', "input file"}, {"out", OPT_OUT, '>', "output file (output format is always DER)"}, {"noout", OPT_NOOUT, 0, "do not produce any output"}, @@ -44,7 +44,7 @@ const OPTIONS asn1parse_options[] = { {OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"}, {"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"}, {"strictpem", OPT_STRICTPEM, 0, - "do not attempt base64 decode outside PEM markers"}, + "equivalent to '-inform pem' (obsolete)"}, {"item", OPT_ITEM, 's', "item to parse and print"}, {OPT_MORE_STR, 0, 0, "(-inform will be ignored)"}, @@ -69,7 +69,7 @@ int asn1parse_main(int argc, char **argv) unsigned char *str = NULL; char *name = NULL, *header = NULL, *prog; const unsigned char *ctmpbuf; - int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM; + int indent = 0, noout = 0, dump = 0, informat = FORMAT_PEM; int offset = 0, ret = 1, i, j; long num, tmplen; unsigned char *tmpbuf; @@ -96,7 +96,7 @@ int asn1parse_main(int argc, char **argv) ret = 0; goto end; case OPT_INFORM: - if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) + if (!opt_format(opt_arg(), OPT_FMT_ASN1, &informat)) goto opthelp; break; case OPT_IN: @@ -137,7 +137,7 @@ int asn1parse_main(int argc, char **argv) genconf = opt_arg(); break; case OPT_STRICTPEM: - strictpem = 1; + /* accepted for backward compatibility */ informat = FORMAT_PEM; break; case OPT_ITEM: @@ -160,8 +160,7 @@ int asn1parse_main(int argc, char **argv) } /* No extra args. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (oidfile != NULL) { @@ -180,7 +179,7 @@ int asn1parse_main(int argc, char **argv) if ((buf = BUF_MEM_new()) == NULL) goto end; - if (strictpem) { + if (genconf == NULL && genstr == NULL && informat == FORMAT_PEM) { if (PEM_read_bio(in, &name, &header, &str, &num) != 1) { BIO_printf(bio_err, "Error reading PEM file\n"); ERR_print_errors(bio_err); @@ -200,7 +199,7 @@ int asn1parse_main(int argc, char **argv) } } else { - if (informat == FORMAT_PEM) { + if (informat == FORMAT_BASE64) { BIO *tmp; if ((b64 = BIO_new(BIO_f_base64())) == NULL) @@ -218,6 +217,9 @@ int asn1parse_main(int argc, char **argv) i = BIO_read(in, &(buf->data[num]), BUFSIZ); if (i <= 0) break; + /* make sure num doesn't overflow */ + if (i > LONG_MAX - num) + goto end; num += i; } } diff --git a/apps/build.info b/apps/build.info index 020d129f8cac..e9565c45ee6d 100644 --- a/apps/build.info +++ b/apps/build.info @@ -16,7 +16,7 @@ $OPENSSLSRC=\ enc.c errstr.c \ genpkey.c kdf.c mac.c nseq.c passwd.c pkcs7.c \ pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \ - s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \ + s_client.c s_server.c s_time.c sess_id.c skeyutl.c smime.c speed.c \ spkac.c verify.c version.c x509.c rehash.c storeutl.c \ list.c info.c fipsinstall.c pkcs12.c IF[{- !$disabled{'ec'} -}] diff --git a/apps/ca.c b/apps/ca.c index a7a5ab1ecefb..6d1d1c0a6ea0 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -1,11 +1,13 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" + #include #include #include @@ -129,7 +131,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, CONF *conf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign, unsigned long dateopt); static int get_certificate_status(const char *ser_status, CA_DB *db); -static int do_updatedb(CA_DB *db); static int check_time_format(const char *str); static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, const char *extval); @@ -151,10 +152,10 @@ typedef enum OPTION_choice { OPT_IN, OPT_INFORM, OPT_OUT, OPT_DATEOPT, OPT_OUTDIR, OPT_VFYOPT, OPT_SIGOPT, OPT_NOTEXT, OPT_BATCH, OPT_PRESERVEDN, OPT_NOEMAILDN, OPT_GENCRL, OPT_MSIE_HACK, OPT_CRL_LASTUPDATE, OPT_CRL_NEXTUPDATE, - OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, + OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, OPT_NOT_BEFORE, OPT_NOT_AFTER, OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, - OPT_RAND_SERIAL, + OPT_RAND_SERIAL, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM, /* Do not change the order here; see related case statements below */ OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE @@ -166,9 +167,11 @@ const OPTIONS ca_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, + {"quiet", OPT_QUIET, '-', "Terse output during processing"}, {"outdir", OPT_OUTDIR, '/', "Where to put output cert"}, {"in", OPT_IN, '<', "The input cert request(s)"}, - {"inform", OPT_INFORM, 'F', "CSR input format (DER or PEM); default PEM"}, + {"inform", OPT_INFORM, 'F', + "CSR input format to use (PEM or DER; by default try PEM first)"}, {"infiles", OPT_INFILES, '-', "The last argument, requests to process"}, {"out", OPT_OUT, '>', "Where to put the output file(s)"}, {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, @@ -198,10 +201,13 @@ const OPTIONS ca_options[] = { "Always create a random serial; do not store it"}, {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', "Deprecated; multi-valued RDNs support is always on."}, - {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, + {"startdate", OPT_STARTDATE, 's', + "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"}, + {"not_before", OPT_NOT_BEFORE, 's', "An alias for -startdate"}, {"enddate", OPT_ENDDATE, 's', - "YYMMDDHHMMSSZ cert notAfter (overrides -days)"}, - {"days", OPT_DAYS, 'p', "Number of days to certify the cert for"}, + "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"}, + {"not_after", OPT_NOT_AFTER, 's', "An alias for -enddate"}, + {"days", OPT_DAYS, 'p', "Number of days from today to certify the cert for"}, {"extensions", OPT_EXTENSIONS, 's', "Extension section (override value in config file)"}, {"extfile", OPT_EXTFILE, '<', @@ -332,6 +338,9 @@ opthelp: case OPT_VERBOSE: verbose = 1; break; + case OPT_QUIET: + verbose = 0; + break; case OPT_CONFIG: configfile = opt_arg(); break; @@ -355,9 +364,11 @@ opthelp: /* obsolete */ break; case OPT_STARTDATE: + case OPT_NOT_BEFORE: startdate = opt_arg(); break; case OPT_ENDDATE: + case OPT_NOT_AFTER: enddate = opt_arg(); break; case OPT_DAYS: @@ -510,9 +521,7 @@ end_of_options: && (section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_CA)) == NULL) goto end; - p = NCONF_get_string(conf, NULL, "oid_file"); - if (p == NULL) - ERR_clear_error(); + p = app_conf_try_string(conf, NULL, "oid_file"); if (p != NULL) { BIO *oid_bio = BIO_new_file(p, "r"); @@ -530,29 +539,22 @@ end_of_options: if (!app_RAND_load()) goto end; - f = NCONF_get_string(conf, section, STRING_MASK); - if (f == NULL) - ERR_clear_error(); - + f = app_conf_try_string(conf, section, STRING_MASK); if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) { BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); goto end; } if (chtype != MBSTRING_UTF8) { - f = NCONF_get_string(conf, section, UTF8_IN); - if (f == NULL) - ERR_clear_error(); - else if (strcmp(f, "yes") == 0) + f = app_conf_try_string(conf, section, UTF8_IN); + if (f != NULL && strcmp(f, "yes") == 0) chtype = MBSTRING_UTF8; } db_attr.unique_subject = 1; - p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); + p = app_conf_try_string(conf, section, ENV_UNIQUE_SUBJECT); if (p != NULL) db_attr.unique_subject = parse_yesno(p, 1); - else - ERR_clear_error(); /*****************************************************************/ /* report status of cert with serial number given on command line */ @@ -615,21 +617,14 @@ end_of_options: if (!selfsign) x509p = x509; - f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE); - if (f == NULL) - ERR_clear_error(); - if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + f = app_conf_try_string(conf, BASE_SECTION, ENV_PRESERVE); + if (f != NULL && (*f == 'y' || *f == 'Y')) preserve = 1; - f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK); - if (f == NULL) - ERR_clear_error(); - if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + f = app_conf_try_string(conf, BASE_SECTION, ENV_MSIE_HACK); + if (f != NULL && (*f == 'y' || *f == 'Y')) msie_hack = 1; - f = NCONF_get_string(conf, section, ENV_NAMEOPT); - - if (f == NULL) - ERR_clear_error(); + f = app_conf_try_string(conf, section, ENV_NAMEOPT); if (f != NULL) { if (!set_nameopt(f)) { BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); @@ -638,27 +633,21 @@ end_of_options: default_op = 0; } - f = NCONF_get_string(conf, section, ENV_CERTOPT); - + f = app_conf_try_string(conf, section, ENV_CERTOPT); if (f != NULL) { if (!set_cert_ex(&certopt, f)) { BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); goto end; } default_op = 0; - } else { - ERR_clear_error(); } - f = NCONF_get_string(conf, section, ENV_EXTCOPY); - + f = app_conf_try_string(conf, section, ENV_EXTCOPY); if (f != NULL) { if (!set_ext_copy(&ext_copy, f)) { BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); goto end; } - } else { - ERR_clear_error(); } /*****************************************************************/ @@ -753,7 +742,7 @@ end_of_options: if (verbose) BIO_printf(bio_err, "Updating %s ...\n", dbfile); - i = do_updatedb(db); + i = do_updatedb(db, NULL); if (i == -1) { BIO_printf(bio_err, "Malloc failure\n"); goto end; @@ -786,11 +775,10 @@ end_of_options: /* We can have sections in the ext file */ if (extensions == NULL) { - extensions = NCONF_get_string(extfile_conf, "default", "extensions"); - if (extensions == NULL) { - ERR_clear_error(); + extensions = + app_conf_try_string(extfile_conf, "default", "extensions"); + if (extensions == NULL) extensions = "default"; - } } } @@ -832,9 +820,8 @@ end_of_options: if (email_dn == 1) { char *tmp_email_dn = NULL; - tmp_email_dn = NCONF_get_string(conf, section, ENV_DEFAULT_EMAIL_DN); - if (tmp_email_dn == NULL) - ERR_clear_error(); + tmp_email_dn = + app_conf_try_string(conf, section, ENV_DEFAULT_EMAIL_DN); if (tmp_email_dn != NULL && strcmp(tmp_email_dn, "no") == 0) email_dn = 0; } @@ -847,10 +834,9 @@ end_of_options: if (verbose) BIO_printf(bio_err, "policy is %s\n", policy); - if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) { + if (app_conf_try_string(conf, section, ENV_RAND_SERIAL) != NULL) { rand_ser = 1; } else { - ERR_clear_error(); serialfile = lookup_conf(conf, section, ENV_SERIAL); if (serialfile == NULL) goto end; @@ -874,11 +860,8 @@ end_of_options: * no '-extfile' option, so we look for extensions in the main * configuration file */ - if (extensions == NULL) { - extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS); - if (extensions == NULL) - ERR_clear_error(); - } + if (extensions == NULL) + extensions = app_conf_try_string(conf, section, ENV_EXTENSIONS); if (extensions != NULL) { /* Check syntax of config file section */ X509V3_CTX ctx; @@ -895,40 +878,22 @@ end_of_options: } } - if (startdate == NULL) { - startdate = NCONF_get_string(conf, section, ENV_DEFAULT_STARTDATE); - if (startdate == NULL) - ERR_clear_error(); - } - if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) { - BIO_printf(bio_err, - "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto end; - } if (startdate == NULL) - startdate = "today"; - - if (enddate == NULL) { - enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE); - if (enddate == NULL) - ERR_clear_error(); - } - if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) { - BIO_printf(bio_err, - "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); - goto end; - } - + startdate = + app_conf_try_string(conf, section, ENV_DEFAULT_STARTDATE); + if (enddate == NULL) + enddate = app_conf_try_string(conf, section, ENV_DEFAULT_ENDDATE); if (days == 0) { - if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days)) { - ERR_clear_error(); + if (!app_conf_try_number(conf, section, ENV_DEFAULT_DAYS, &days)) days = 0; - } } if (enddate == NULL && days == 0) { BIO_printf(bio_err, "cannot lookup how many days to certify for\n"); goto end; } + if (days != 0 && enddate != NULL) + BIO_printf(bio_err, + "Warning: -enddate or -not_after option overriding -days option\n"); if (rand_ser) { if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) { @@ -1156,11 +1121,9 @@ end_of_options: /*****************************************************************/ if (gencrl) { int crl_v2 = 0; - if (crl_ext == NULL) { - crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT); - if (crl_ext == NULL) - ERR_clear_error(); - } + + if (crl_ext == NULL) + crl_ext = app_conf_try_string(conf, section, ENV_CRLEXT); if (crl_ext != NULL) { /* Check syntax of file */ X509V3_CTX ctx; @@ -1175,28 +1138,22 @@ end_of_options: } } - crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER); + crlnumberfile = app_conf_try_string(conf, section, ENV_CRLNUMBER); if (crlnumberfile != NULL) { if ((crlnumber = load_serial(crlnumberfile, NULL, 0, NULL)) == NULL) { BIO_printf(bio_err, "error while loading CRL number\n"); goto end; } - } else { - ERR_clear_error(); } if (!crldays && !crlhours && !crlsec) { - if (!NCONF_get_number(conf, section, - ENV_DEFAULT_CRL_DAYS, &crldays)) { - ERR_clear_error(); + if (!app_conf_try_number(conf, section, + ENV_DEFAULT_CRL_DAYS, &crldays)) crldays = 0; - } - if (!NCONF_get_number(conf, section, - ENV_DEFAULT_CRL_HOURS, &crlhours)) { - ERR_clear_error(); + if (!app_conf_try_number(conf, section, + ENV_DEFAULT_CRL_HOURS, &crlhours)) crlhours = 0; - } } if ((crl_nextupdate == NULL) && (crldays == 0) && (crlhours == 0) && (crlsec == 0)) { @@ -1347,7 +1304,7 @@ end_of_options: BIO_free_all(Sout); BIO_free_all(out); BIO_free_all(in); - sk_X509_pop_free(cert_sk, X509_free); + OSSL_STACK_OF_X509_free(cert_sk); cleanse(passin); if (free_passin) @@ -1391,7 +1348,7 @@ static int certify(X509 **xret, const char *infile, int informat, EVP_PKEY *pktmp = NULL; int ok = -1, i; - req = load_csr(infile, informat, "certificate request"); + req = load_csr_autofmt(infile, informat, vfyopts, "certificate request"); if (req == NULL) goto end; if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { @@ -1710,7 +1667,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, goto end; } - if (!set_cert_times(ret, startdate, enddate, days)) + if (!set_cert_times(ret, startdate, enddate, days, 0)) goto end; if (enddate != NULL) { @@ -1731,7 +1688,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, /* Initialize the context structure */ X509V3_set_ctx(&ext_ctx, selfsign ? ret : x509, - ret, req, NULL, X509V3_CTX_REPLACE); + ret, NULL /* no need to give req, needed info is in ret */, + NULL, X509V3_CTX_REPLACE); + /* prepare fallback for AKID, but only if issuer cert equals subject cert */ + if (selfsign) { + if (!X509V3_set_issuer_pkey(&ext_ctx, pkey)) + goto end; + if (!cert_matches_key(ret, pkey)) + BIO_printf(bio_err, + "Warning: Signature key and public key of cert do not match\n"); + } /* Lets add the extensions, if there are any */ if (ext_sect) { @@ -1868,7 +1834,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, p = "Valid"; else p = "\ninvalid type, Database error\n"; - BIO_printf(bio_err, "Type :%s\n", p);; + BIO_printf(bio_err, "Type :%s\n", p); if (rrow[DB_type][0] == DB_TYPE_REV) { p = rrow[DB_exp_date]; if (p == NULL) @@ -1933,7 +1899,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, !EVP_PKEY_missing_parameters(pkey)) EVP_PKEY_copy_parameters(pktmp, pkey); - if (!do_X509_sign(ret, pkey, dgst, sigopts, &ext_ctx)) + if (!do_X509_sign(ret, 0, pkey, dgst, sigopts, &ext_ctx)) goto end; /* We now just add it to the database as DB_TYPE_VAL('V') */ @@ -2299,7 +2265,7 @@ static int get_certificate_status(const char *serial, CA_DB *db) return ok; } -static int do_updatedb(CA_DB *db) +int do_updatedb(CA_DB *db, time_t *now) { ASN1_TIME *a_tm = NULL; int i, cnt = 0; @@ -2310,7 +2276,7 @@ static int do_updatedb(CA_DB *db) return -1; /* get actual time */ - if (X509_gmtime_adj(a_tm, 0) == NULL) { + if (X509_time_adj(a_tm, 0, now) == NULL) { ASN1_TIME_free(a_tm); return -1; } diff --git a/apps/ciphers.c b/apps/ciphers.c index 42a0bb79f651..c33685d8ced6 100644 --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -174,10 +174,9 @@ int ciphers_main(int argc, char **argv) /* Optional arg is cipher name. */ argv = opt_rest(); - argc = opt_num_rest(); - if (argc == 1) + if (opt_num_rest() == 1) ciphers = argv[0]; - else if (argc != 0) + else if (!opt_check_rest_arg(NULL)) goto opthelp; if (convert != NULL) { diff --git a/apps/cmp.c b/apps/cmp.c index c479b1549660..291d62bfcb80 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -10,6 +10,7 @@ */ /* This app is disabled when OPENSSL_NO_CMP is defined. */ +#include "internal/e_os.h" #include #include @@ -68,7 +69,7 @@ typedef enum { } cmp_cmd_t; /* message transfer */ -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) static char *opt_server = NULL; static char *opt_proxy = NULL; static char *opt_no_proxy = NULL; @@ -86,8 +87,19 @@ static char *opt_srvcert = NULL; static char *opt_expect_sender = NULL; static int opt_ignore_keyusage = 0; static int opt_unprotected_errors = 0; +static int opt_no_cache_extracerts = 0; +static char *opt_srvcertout = NULL; static char *opt_extracertsout = NULL; static char *opt_cacertsout = NULL; +static char *opt_oldwithold = NULL; +static char *opt_newwithnew = NULL; +static char *opt_newwithold = NULL; +static char *opt_oldwithnew = NULL; +static char *opt_crlcert = NULL; +static char *opt_oldcrl = NULL; +static char *opt_crlout = NULL; +static char *opt_template = NULL; +static char *opt_keyspec = NULL; /* client authentication */ static char *opt_ref = NULL; @@ -107,12 +119,14 @@ static int opt_cmd = -1; static char *opt_geninfo = NULL; static char *opt_infotype_s = NULL; static int opt_infotype = NID_undef; +static char *opt_profile = NULL; /* certificate enrollment */ static char *opt_newkey = NULL; static char *opt_newkeypass = NULL; +static int opt_centralkeygen = 0; +static char *opt_newkeyout = 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; @@ -130,17 +144,25 @@ static char *opt_chainout = NULL; /* certificate enrollment and revocation */ static char *opt_oldcert = NULL; +static char *opt_issuer = NULL; +static char *opt_serial = NULL; static int opt_revreason = CRL_REASON_NONE; /* credentials format */ static char *opt_certform_s = "PEM"; static int opt_certform = FORMAT_PEM; +/* + * DER format is the preferred choice for saving a CRL because it allows for + * more efficient storage, especially when dealing with large CRLs. + */ +static char *opt_crlform_s = "DER"; +static int opt_crlform = FORMAT_ASN1; 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 +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) /* TLS connection */ static int opt_tls_used = 0; static char *opt_tls_cert = NULL; @@ -157,13 +179,15 @@ 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_reqout_only = NULL; +static int reqout_only_done = 0; 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 +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) static char *opt_port = NULL; static int opt_max_msgs = 0; #endif @@ -175,9 +199,17 @@ static char *opt_srv_keypass = NULL; static char *opt_srv_trusted = NULL; static char *opt_srv_untrusted = NULL; +static char *opt_ref_cert = NULL; static char *opt_rsp_cert = NULL; +static char *opt_rsp_key = NULL; +static char *opt_rsp_keypass = NULL; +static char *opt_rsp_crl = NULL; static char *opt_rsp_extracerts = NULL; static char *opt_rsp_capubs = NULL; +static char *opt_rsp_newwithnew = NULL; +static char *opt_rsp_newwithold = NULL; +static char *opt_rsp_oldwithnew = NULL; + static int opt_poll_count = 0; static int opt_check_after = 1; static int opt_grant_implicitconf = 0; @@ -199,9 +231,11 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY, - OPT_CMD, OPT_INFOTYPE, OPT_GENINFO, + OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO, + OPT_TEMPLATE, OPT_KEYSPEC, - OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_ISSUER, + OPT_NEWKEY, OPT_NEWKEYPASS, OPT_CENTRALKEYGEN, + OPT_NEWKEYOUT, OPT_SUBJECT, OPT_DAYS, OPT_REQEXTS, OPT_SANS, OPT_SAN_NODEFAULT, OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL, @@ -209,9 +243,9 @@ typedef enum OPTION_choice { OPT_OUT_TRUSTED, OPT_IMPLICIT_CONFIRM, OPT_DISABLE_CONFIRM, OPT_CERTOUT, OPT_CHAINOUT, - OPT_OLDCERT, OPT_REVREASON, + OPT_OLDCERT, OPT_ISSUER, OPT_SERIAL, OPT_REVREASON, -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) OPT_SERVER, OPT_PROXY, OPT_NO_PROXY, #endif OPT_RECIPIENT, OPT_PATH, @@ -219,14 +253,16 @@ typedef enum OPTION_choice { OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT, OPT_EXPECT_SENDER, - OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, - OPT_EXTRACERTSOUT, OPT_CACERTSOUT, + OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS, + OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT, + OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW, + OPT_CRLCERT, OPT_OLDCRL, OPT_CRLOUT, 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_CERTFORM, OPT_CRLFORM, OPT_KEYFORM, OPT_OTHERPASS, #ifndef OPENSSL_NO_ENGINE OPT_ENGINE, @@ -234,23 +270,26 @@ typedef enum OPTION_choice { OPT_PROV_ENUM, OPT_R_ENUM, -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) 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_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_REQOUT_ONLY, + OPT_RSPIN, OPT_RSPOUT, OPT_USE_MOCK_SRV, -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) 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_REF_CERT, OPT_RSP_CERT, OPT_RSP_KEY, OPT_RSP_KEYPASS, + OPT_RSP_CRL, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS, + OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD, OPT_RSP_OLDWITHNEW, OPT_POLL_COUNT, OPT_CHECK_AFTER, OPT_GRANT_IMPLICITCONF, OPT_PKISTATUS, OPT_FAILURE, @@ -275,26 +314,34 @@ const OPTIONS cmp_options[] = { 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"}, + "InfoType name for requesting specific info in genm, with specific support"}, {OPT_MORE_STR, 0, 0, - "specified in the form :int:, e.g. \"1.2.3.4:int:56789\""}, + "for 'caCerts' and 'rootCaCert'"}, + {"profile", OPT_PROFILE, 's', + "Certificate profile name to place in generalInfo field of request PKIHeader"}, + {"geninfo", OPT_GENINFO, 's', + "Comma-separated list of OID and value to place in generalInfo PKIHeader"}, + {OPT_MORE_STR, 0, 0, + "of form :int: or :str:, e.g. \'1.2.3.4:int:56789, id-kp:str:name'"}, + { "template", OPT_TEMPLATE, 's', + "File to save certTemplate received in genp of type certReqTemplate"}, + { "keyspec", OPT_KEYSPEC, 's', + "Optional file to save Key specification received in genp of type certReqTemplate"}, 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"}, + {"centralkeygen", OPT_CENTRALKEYGEN, '-', + "Request central (server-side) key generation. Default is local generation"}, + {"newkeyout", OPT_NEWKEYOUT, 's', + "File to save centrally generated key, in PEM format"}, {"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', @@ -338,15 +385,21 @@ const OPTIONS cmp_options[] = { "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"}, + {"issuer", OPT_ISSUER, 's', + "DN of the issuer to place in the certificate template of ir/cr/kur/rr;"}, + {OPT_MORE_STR, 0, 0, + "also used as recipient if neither -recipient nor -srvcert are given"}, + {"serial", OPT_SERIAL, 's', + "Serial number of certificate to be revoked in revocation request (rr)"}, {"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 +#if defined(OPENSSL_NO_SOCK) || defined(OPENSSL_NO_HTTP) {OPT_MORE_STR, 0, 0, - "NOTE: -server, -proxy, and -no_proxy not supported due to no-sock build"}, + "NOTE: -server, -proxy, and -no_proxy not supported due to no-sock/no-http build"}, #else {"server", OPT_SERVER, 's', "[http[s]://]address[:port][/path] of CMP server. Default port 80 or 443."}, @@ -388,10 +441,28 @@ const OPTIONS cmp_options[] = { "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"}, + {"no_cache_extracerts", OPT_NO_CACHE_EXTRACERTS, '-', + "Do not keep certificates received in the extraCerts CMP message field"}, + { "srvcertout", OPT_SRVCERTOUT, 's', + "File to save the server cert used and validated for CMP response protection"}, {"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"}, + "File to save CA certs received in caPubs field or genp with id-it-caCerts"}, + { "oldwithold", OPT_OLDWITHOLD, 's', + "Root CA certificate to request update for in genm of type rootCaCert"}, + { "newwithnew", OPT_NEWWITHNEW, 's', + "File to save NewWithNew cert received in genp of type rootCaKeyUpdate"}, + { "newwithold", OPT_NEWWITHOLD, 's', + "File to save NewWithOld cert received in genp of type rootCaKeyUpdate"}, + { "oldwithnew", OPT_OLDWITHNEW, 's', + "File to save OldWithNew cert received in genp of type rootCaKeyUpdate"}, + { "crlcert", OPT_CRLCERT, 's', + "certificate to request a CRL for in genm of type crlStatusList"}, + { "oldcrl", OPT_OLDCRL, 's', + "CRL to request update for in genm of type crlStatusList"}, + { "crlout", OPT_CRLOUT, 's', + "File to save new CRL received in genp of type 'crls'"}, OPT_SECTION("Client authentication"), {"ref", OPT_REF, 's', @@ -423,6 +494,8 @@ const OPTIONS cmp_options[] = { OPT_SECTION("Credentials format"), {"certform", OPT_CERTFORM, 's', "Format (PEM or DER) to use when saving a certificate to a file. Default PEM"}, + {"crlform", OPT_CRLFORM, 's', + "Format (PEM or DER) to use when saving a CRL to a file. Default DER"}, {"keyform", OPT_KEYFORM, 's', "Format of the key input (ENGINE, other values ignored)"}, {"otherpass", OPT_OTHERPASS, 's', @@ -437,9 +510,9 @@ const OPTIONS cmp_options[] = { OPT_R_OPTIONS, OPT_SECTION("TLS connection"), -#ifdef OPENSSL_NO_SOCK +#if defined(OPENSSL_NO_SOCK) || defined(OPENSSL_NO_HTTP) {OPT_MORE_STR, 0, 0, - "NOTE: -tls_used and all other TLS options not supported due to no-sock build"}, + "NOTE: -tls_used and all other TLS options not supported due to no-sock/no-http build"}, #else {"tls_used", OPT_TLS_USED, '-', "Enable using TLS (also when other TLS options are not set)"}, @@ -453,9 +526,9 @@ const OPTIONS cmp_options[] = { "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"}, + {OPT_MORE_STR, 0, 0, "this implies hostname validation"}, {"tls_host", OPT_TLS_HOST, 's', - "Address to be checked (rather than -server) during TLS host name validation"}, + "Address to be checked (rather than -server) during TLS hostname validation"}, #endif OPT_SECTION("Client-side debugging"), @@ -469,6 +542,8 @@ const OPTIONS cmp_options[] = { "Use fresh transactionID for CMP requests read from -reqin"}, {"reqout", OPT_REQOUT, 's', "Save sequence of CMP requests created by the client to file(s)"}, + {"reqout_only", OPT_REQOUT_ONLY, 's', + "Save first CMP request created by the client to file and exit"}, {"rspin", OPT_RSPIN, 's', "Process sequence of CMP responses provided in file(s), skipping server"}, {"rspout", OPT_RSPOUT, 's', @@ -478,9 +553,9 @@ const OPTIONS cmp_options[] = { "Use internal mock server at API level, bypassing socket-based HTTP"}, OPT_SECTION("Mock server"), -#ifdef OPENSSL_NO_SOCK +#if defined(OPENSSL_NO_SOCK) || defined(OPENSSL_NO_HTTP) {OPT_MORE_STR, 0, 0, - "NOTE: -port and -max_msgs not supported due to no-sock build"}, + "NOTE: -port and -max_msgs not supported due to no-sock/no-http build"}, #else {"port", OPT_PORT, 's', "Act as HTTP-based mock server listening on given port"}, @@ -502,12 +577,28 @@ const OPTIONS cmp_options[] = { "Trusted certificates for client authentication"}, {"srv_untrusted", OPT_SRV_UNTRUSTED, 's', "Intermediate certs that may be useful for verifying CMP protection"}, + {"ref_cert", OPT_RSP_CERT, 's', + "Certificate to be expected for rr and any oldCertID in kur messages"}, {"rsp_cert", OPT_RSP_CERT, 's', "Certificate to be returned as mock enrollment result"}, + {"rsp_key", OPT_RSP_KEY, 's', + "Private key for the certificate to be returned as mock enrollment result"}, + {OPT_MORE_STR, 0, 0, + "Key to be returned for central key pair generation"}, + {"rsp_keypass", OPT_RSP_KEYPASS, 's', + "Response private key (and cert) pass phrase source"}, + {"rsp_crl", OPT_RSP_CRL, 's', + "CRL to be returned in genp of type crls"}, {"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"}, + {"rsp_newwithnew", OPT_RSP_NEWWITHNEW, 's', + "New root CA certificate to include in genp of type rootCaKeyUpdate"}, + {"rsp_newwithold", OPT_RSP_NEWWITHOLD, 's', + "NewWithOld transition cert to include in genp of type rootCaKeyUpdate"}, + {"rsp_oldwithnew", OPT_RSP_OLDWITHNEW, 's', + "OldWithNew transition cert to include in genp of type rootCaKeyUpdate"}, {"poll_count", OPT_POLL_COUNT, 'N', "Number of times the client must poll before receiving a certificate"}, {"check_after", OPT_CHECK_AFTER, 'N', @@ -552,10 +643,11 @@ typedef union { 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_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo}, + {&opt_template}, {&opt_keyspec}, - {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {&opt_issuer}, - {(char **)&opt_days}, {&opt_reqexts}, + {&opt_newkey}, {&opt_newkeypass}, {(char **)&opt_centralkeygen}, + {&opt_newkeyout}, {&opt_subject}, {(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}, @@ -563,9 +655,9 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {(char **)&opt_implicit_confirm}, {(char **)&opt_disable_confirm}, {&opt_certout}, {&opt_chainout}, - {&opt_oldcert}, {(char **)&opt_revreason}, + {&opt_oldcert}, {&opt_issuer}, {&opt_serial}, {(char **)&opt_revreason}, -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) {&opt_server}, {&opt_proxy}, {&opt_no_proxy}, #endif {&opt_recipient}, {&opt_path}, {(char **)&opt_keep_alive}, @@ -574,20 +666,23 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert}, {&opt_expect_sender}, {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors}, - {&opt_extracertsout}, {&opt_cacertsout}, + {(char **)&opt_no_cache_extracerts}, + {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout}, + {&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew}, + {&opt_crlcert}, {&opt_oldcrl}, {&opt_crlout}, {&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_certform_s}, {&opt_crlform_s}, {&opt_keyform_s}, {&opt_otherpass}, #ifndef OPENSSL_NO_ENGINE {&opt_engine}, #endif -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) {(char **)&opt_tls_used}, {&opt_tls_cert}, {&opt_tls_key}, {&opt_tls_keypass}, {&opt_tls_extra}, {&opt_tls_trusted}, {&opt_tls_host}, @@ -595,16 +690,19 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {(char **)&opt_batch}, {(char **)&opt_repeat}, {&opt_reqin}, {(char **)&opt_reqin_new_tid}, - {&opt_reqout}, {&opt_rspin}, {&opt_rspout}, + {&opt_reqout}, {&opt_reqout_only}, {&opt_rspin}, {&opt_rspout}, {(char **)&opt_use_mock_srv}, -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) {&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}, + {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_key}, {&opt_rsp_keypass}, + {&opt_rsp_crl}, {&opt_rsp_extracerts}, {&opt_rsp_capubs}, + {&opt_rsp_newwithnew}, {&opt_rsp_newwithold}, {&opt_rsp_oldwithnew}, + {(char **)&opt_poll_count}, {(char **)&opt_check_after}, {(char **)&opt_grant_implicitconf}, {(char **)&opt_pkistatus}, {(char **)&opt_failure}, @@ -689,40 +787,12 @@ static X509 *load_cert_pwd(const char *uri, const char *pass, const char *desc) 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 */ +/* set expected hostname/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 */ + /* first clear any hostnames, 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)) @@ -797,8 +867,15 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr; const char *prev_opt_rspin = opt_rspin; - if (req != NULL && opt_reqout != NULL - && !write_PKIMESSAGE(req, &opt_reqout)) + if (opt_reqout_only != NULL) { + if (OSSL_CMP_MSG_write(opt_reqout_only, req) < 0) + CMP_err1("cannot write request PKIMessage to file '%s'", + opt_reqout_only); + else + reqout_only_done = 1; + return NULL; /* stop at this point, not contacting any server */ + } + if (opt_reqout != NULL && !write_PKIMESSAGE(req, &opt_reqout)) goto err; if (opt_reqin != NULL && opt_rspin == NULL) { if ((req_new = read_PKIMESSAGE("actually sending", &opt_reqin)) == NULL) @@ -830,7 +907,7 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx, 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 !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) if (opt_server == NULL) { CMP_err("missing -server or -use_mock_srv option, or too few -rspin filename arguments"); goto err; @@ -839,7 +916,7 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx, 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"); + CMP_err("-server not supported on no-sock/no-http build; missing -use_mock_srv option or too few -rspin filename arguments"); #endif } rspin_in_use = 0; @@ -907,11 +984,12 @@ static int set_gennames(OSSL_CMP_CTX *ctx, char *names, const char *desc) continue; } - /* try IP address first, then URI or domain name */ + /* try IP address first, then email/URI/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_EMAIL : strchr(names, ':') != NULL ? GEN_URI : GEN_DNS, names, 0); (void)ERR_pop_to_mark(); @@ -948,8 +1026,23 @@ static X509_STORE *load_trusted(char *input, int for_new_cert, const char *desc) return NULL; } -typedef int (*add_X509_stack_fn_t)(void *ctx, const STACK_OF(X509) *certs); +typedef int (*add_X509_fn_t)(void *ctx, const X509 *cert); +static int setup_cert(void *ctx, const char *file, const char *pass, + const char *desc, add_X509_fn_t set1_fn) +{ + X509 *cert; + int ok; + if (file == NULL) + return 1; + if ((cert = load_cert_pwd(file, pass, desc)) == NULL) + return 0; + ok = (*set1_fn)(ctx, cert); + X509_free(cert); + return ok; +} + +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) { @@ -961,11 +1054,23 @@ static int setup_certs(char *files, const char *desc, void *ctx, 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); + OSSL_STACK_OF_X509_free(certs); return ok; } +static int setup_mock_crlout(void *ctx, const char *file, const char *desc) +{ + X509_CRL *crl; + int ok; + if (file == NULL) + return 1; + if ((crl = load_crl(file, FORMAT_UNDEF, 0, desc)) == NULL) + return 0; + ok = ossl_cmp_mock_srv_set1_crlOut(ctx, crl); + X509_CRL_free(crl); + return ok; +} /* * parse and transform some options, checking their syntax. * Returns 1 on success, 0 on error @@ -1013,6 +1118,11 @@ static int transform_opts(void) CMP_err("unknown option given for certificate storing format"); return 0; } + if (opt_crlform_s != NULL + && !opt_format(opt_crlform_s, OPT_FMT_PEMDER, &opt_crlform)) { + CMP_err("unknown option given for CRL storing format"); + return 0; + } return 1; } @@ -1063,16 +1173,10 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) 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 (!setup_cert(ctx, opt_srv_cert, opt_srv_keypass, + "signer certificate of the mock server", + (add_X509_fn_t)OSSL_CMP_CTX_set1_cert)) + goto err; if (opt_srv_key != NULL) { EVP_PKEY *pkey = load_key_pwd(opt_srv_key, opt_keyform, opt_srv_keypass, @@ -1090,7 +1194,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) X509_STORE *ts = load_trusted(opt_srv_trusted, 0, "certs trusted by mock server"); - if (ts == NULL || !OSSL_CMP_CTX_set0_trustedStore(ctx, ts)) { + if (ts == NULL || !OSSL_CMP_CTX_set0_trusted(ctx, ts)) { X509_STORE_free(ts); goto err; } @@ -1102,21 +1206,35 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) (add_X509_stack_fn_t)OSSL_CMP_CTX_set1_untrusted)) goto err; + if (!setup_cert(srv_ctx, opt_ref_cert, opt_otherpass, + "reference cert to be expected by the mock server", + (add_X509_fn_t)ossl_cmp_mock_srv_set1_refCert)) + 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) + if (!setup_cert(srv_ctx, opt_rsp_cert, opt_rsp_keypass, + "cert the mock server returns on certificate requests", + (add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut)) goto err; - /* from server perspective the server is the client */ - if (!ossl_cmp_mock_srv_set1_certOut(srv_ctx, cert)) { - X509_free(cert); + } + if (opt_rsp_key != NULL) { + EVP_PKEY *pkey = load_key_pwd(opt_rsp_key, opt_keyform, + opt_rsp_keypass, engine, + "private key for enrollment cert"); + + if (pkey == NULL + || !ossl_cmp_mock_srv_set1_keyOut(srv_ctx, pkey)) { + EVP_PKEY_free(pkey); goto err; } - X509_free(cert); + EVP_PKEY_free(pkey); } + cleanse(opt_rsp_keypass); + + if (!setup_mock_crlout(srv_ctx, opt_rsp_crl, + "CRL to be returned by the mock server")) + goto err; 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)) @@ -1124,12 +1242,22 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine) 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; + if (!setup_cert(srv_ctx, opt_rsp_newwithnew, opt_otherpass, + "NewWithNew cert the mock server returns in rootCaKeyUpdate", + (add_X509_fn_t)ossl_cmp_mock_srv_set1_newWithNew) + || !setup_cert(srv_ctx, opt_rsp_newwithold, opt_otherpass, + "NewWithOld cert the mock server returns in rootCaKeyUpdate", + (add_X509_fn_t)ossl_cmp_mock_srv_set1_newWithOld) + || !setup_cert(srv_ctx, opt_rsp_oldwithnew, opt_otherpass, + "OldWithNew cert the mock server returns in rootCaKeyUpdate", + (add_X509_fn_t)ossl_cmp_mock_srv_set1_oldWithNew)) + 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 != INT_MIN) { /* option has been set explicitly */ 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); @@ -1180,10 +1308,6 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx) 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"); @@ -1193,30 +1317,27 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx) 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) + if (!setup_cert(ctx, opt_srvcert, opt_otherpass, + "directly trusted CMP server certificate", + (add_X509_fn_t)OSSL_CMP_CTX_set1_srvCert)) return 0; } if (opt_trusted != NULL) { + X509_STORE *ts; + /* * 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)) { + if (ts == NULL || !OSSL_CMP_CTX_set0_trusted(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); @@ -1244,7 +1365,7 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx) return 1; } -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) /* * set up ssl_ctx for the OSSL_CMP_CTX based on options from config file/CLI. * Returns pointer on success, NULL on error @@ -1267,6 +1388,9 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host, if (trust_store == NULL) goto err; SSL_CTX_set_cert_store(ssl_ctx, trust_store); + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + } else { + CMP_warn("-tls_used given without -tls_trusted; will not authenticate the TLS server"); } if (opt_tls_cert != NULL && opt_tls_key != NULL) { @@ -1290,7 +1414,7 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host, 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); + OSSL_STACK_OF_X509_free(certs); goto err; } for (i = 0; i < sk_X509_num(untrusted); i++) { @@ -1377,13 +1501,18 @@ static SSL_CTX *setup_ssl_ctx(OSSL_CMP_CTX *ctx, const char *host, goto err; } EVP_PKEY_free(pkey); /* we do not need the handle any more */ + } else { + CMP_warn("-tls_used given without -tls_key; cannot authenticate to the TLS server"); } - if (opt_tls_trusted != NULL) { - /* enable and parameterize server hostname/IP address check */ + if (trust_store != NULL) { + /* + * Enable and parameterize server hostname/IP address check. + * If we did this before checking our own TLS cert + * the expected hostname would mislead the 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: @@ -1409,7 +1538,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) CMP_err("must give -ref if no -cert and no -subject given"); return 0; } - if (!opt_secret && ((opt_cert == NULL) != (opt_key == NULL))) { + if (opt_secret == NULL && ((opt_cert == NULL) != (opt_key == NULL))) { CMP_err("must give both -cert and -key options or neither"); return 0; } @@ -1471,7 +1600,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) ok = ok && OSSL_CMP_CTX_build_cert_chain(ctx, own_trusted, certs); } X509_STORE_free(own_trusted); - sk_X509_pop_free(certs, X509_free); + OSSL_STACK_OF_X509_free(certs); if (!ok) return 0; } else if (opt_own_trusted != NULL) { @@ -1502,6 +1631,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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; @@ -1511,10 +1641,52 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) return 1; } +static int set_fallback_pubkey(OSSL_CMP_CTX *ctx) +{ + char *file = opt_reqin, *end = file, bak; + OSSL_CMP_MSG *req; + const X509_PUBKEY *pubkey; + EVP_PKEY *pkey; + EVP_PKEY *pkey1; + int res = 0; + + /* temporarily separate first file name in opt_reqin */ + while (*end != ',' && !isspace(_UC(*end)) && *end != '\0') + end++; + bak = *end; + *end = '\0'; + req = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq()); + *end = bak; + + if (req == NULL) { + CMP_err1("failed to load ir/cr/kur file '%s' attempting to get fallback public key", + file); + return 0; + } + if ((pubkey = OSSL_CMP_MSG_get0_certreq_publickey(req)) == NULL + || (pkey = X509_PUBKEY_get0(pubkey)) == NULL) { + CMP_err1("failed to get fallback public key from ir/cr/kur file '%s'", + file); + goto err; + } + pkey1 = EVP_PKEY_dup(pkey); + if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, 0 /* priv */, pkey1)) { + EVP_PKEY_free(pkey1); + CMP_err1("failed to get fallback public key obtained from ir/cr/kur file '%s'", + file); + goto err; + } + res = 1; + + err: + OSSL_CMP_MSG_free(req); + return res; +} + /* - * 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 + * Set up IR/CR/P10CR/KUR/CertConf/RR/GENM specific parts of the OSSL_CMP_CTX + * based on options from CLI and/or config file. + * Returns 1 on success, 0 on error */ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) { @@ -1527,47 +1699,67 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) && opt_cmd != CMP_RR && opt_cmd != CMP_GENM) CMP_warn("no -subject given; no -csr or -oldcert or -cert available for fallback"); + if (!set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer")) + return 0; if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) { - if (opt_newkey == NULL + if (opt_reqin == NULL && opt_newkey == NULL && !opt_centralkeygen && 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"); + CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key." + " Neither central key generation is requested."); return 0; } + if (opt_popo == OSSL_CRMF_POPO_NONE && !opt_centralkeygen) { + CMP_info("POPO is disabled, which implies -centralkeygen"); + opt_centralkeygen = 1; + } + if (opt_centralkeygen) { + if (opt_popo > OSSL_CRMF_POPO_NONE) { + CMP_err1("-popo value %d is inconsistent with -centralkeygen", opt_popo); + return 0; + } + if (opt_newkeyout == NULL) { + CMP_err("-newkeyout not given, nowhere to save centrally generated key"); + return 0; + } + opt_popo = OSSL_CRMF_POPO_NONE; + } 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"); + CMP_err1("no -newkey option given with private key for POPO, -csr option provides just public key%s", + opt_key == NULL ? "" : + ", and -key option superseded by -csr"); + if (opt_reqin != NULL) + CMP_info("since -reqin is used, may use -popo -1 or -popo 0 to disable the needless generation of a POPO"); return 0; } if (opt_key == NULL) { - CMP_err("missing -newkey (or -key) option for POPO"); + CMP_err("missing -newkey (or -key) option for key to be certified and for POPO"); return 0; } } - if (opt_certout == NULL) { + if (opt_certout == NULL && opt_reqout_only == 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")) + if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject")) 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 */ + /* will use subject as 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); + CMP_warn1("-subject %s since sender is taken from -ref or -cert", + msg); } } - if (opt_issuer != NULL) - CMP_warn1("-issuer %s", msg); + if (opt_issuer != NULL && opt_cmd != CMP_RR) + CMP_warn1("-issuer %s and 'rr'", msg); if (opt_reqexts != NULL) CMP_warn1("-reqexts %s", msg); if (opt_san_nodefault) @@ -1578,6 +1770,22 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) CMP_warn1("-policies %s", msg); if (opt_policy_oids != NULL) CMP_warn1("-policy_oids %s", msg); + if (opt_popo != OSSL_CRMF_POPO_NONE - 1) + CMP_warn1("-popo %s", msg); + if (opt_centralkeygen) + CMP_warn1("-popo -1 or -centralkeygen %s", msg); + if (opt_newkeyout != NULL) + CMP_warn1("-newkeyout %s", msg); + if (opt_cmd != CMP_P10CR) { + if (opt_implicit_confirm) + CMP_warn1("-implicit_confirm %s, and 'p10cr'", msg); + if (opt_disable_confirm) + CMP_warn1("-disable_confirm %s, and 'p10cr'", msg); + if (opt_certout != NULL) + CMP_warn1("-certout %s, and 'p10cr'", msg); + if (opt_chainout != NULL) + CMP_warn1("-chainout %s, and 'p10cr'", msg); + } } if (opt_cmd == CMP_KUR) { char *ref_cert = opt_oldcert != NULL ? opt_oldcert : opt_cert; @@ -1591,12 +1799,44 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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_issuer == NULL && opt_serial == NULL) { + if (opt_oldcert == NULL && opt_csr == NULL) { + CMP_err("missing -oldcert or -issuer and -serial 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"); + } else { +#define OSSL_CMP_RR_MSG "since -issuer and -serial is given for command 'rr'" + if (opt_issuer == NULL || opt_serial == NULL) { + CMP_err("Must give both -issuer and -serial options or neither"); + return 0; + } + if (opt_oldcert != NULL) + CMP_warn("Ignoring -oldcert " OSSL_CMP_RR_MSG); + if (opt_csr != NULL) + CMP_warn("Ignoring -csr " OSSL_CMP_RR_MSG); } - if (opt_oldcert != NULL && opt_csr != NULL) - CMP_warn("ignoring -csr since certificate to be revoked is given"); + if (opt_serial != NULL) { + ASN1_INTEGER *sno; + + if ((sno = s2i_ASN1_INTEGER(NULL, opt_serial)) == NULL) { + CMP_err1("cannot read serial number: '%s'", opt_serial); + return 0; + } + if (!OSSL_CMP_CTX_set1_serialNumber(ctx, sno)) { + ASN1_INTEGER_free(sno); + CMP_err("out of memory"); + return 0; + } + ASN1_INTEGER_free(sno); + } + if (opt_revreason > CRL_REASON_NONE) + (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_REVOCATION_REASON, + opt_revreason); + } else { + if (opt_serial != NULL) + CMP_warn("Ignoring -serial for command other than 'rr'"); } if (opt_cmd == CMP_P10CR && opt_csr == NULL) { CMP_err("missing PKCS#10 CSR for p10cr"); @@ -1605,19 +1845,21 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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\""); + CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient for any requests not covered by -reqin 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_cmd == CMP_P10CR || opt_cmd == CMP_RR || opt_cmd == CMP_GENM) { + const char *msg = "option is ignored for 'p10cr', 'rr', and 'genm' commands"; if (opt_newkeypass != NULL) - CMP_warn1("-newkeytype %s", msg); + CMP_warn1("-newkeypass %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); + if (opt_out_trusted != NULL) + CMP_warn1("-out_trusted %s", msg); } else if (opt_newkey != NULL) { const char *file = opt_newkey; const int format = opt_keyform; @@ -1633,16 +1875,21 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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"; + ? "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; } + } else if (opt_reqin != NULL + && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL + && !opt_centralkeygen) { + if (!set_fallback_pubkey(ctx)) + return 0; } if (opt_days > 0 @@ -1659,9 +1906,10 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_csr != NULL) { if (opt_cmd == CMP_GENM) { - CMP_warn("-csr option is ignored for command 'genm'"); + CMP_warn("-csr option is ignored for 'genm' command"); } else { - if ((csr = load_csr_autofmt(opt_csr, "PKCS#10 CSR")) == NULL) + csr = load_csr_autofmt(opt_csr, FORMAT_UNDEF, NULL, "PKCS#10 CSR"); + if (csr == NULL) return 0; if (!OSSL_CMP_CTX_set1_p10CSR(ctx, csr)) goto oom; @@ -1715,9 +1963,11 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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); + CMP_err1("Invalid -policy_oids arg '%s'", opt_policy_oids); return 0; } + if (OBJ_obj2nid(policy) == NID_undef) + CMP_warn1("Unknown -policy_oids arg: %.40s", opt_policy_oids); if ((pinfo = POLICYINFO_new()) == NULL) { ASN1_OBJECT_free(policy); @@ -1732,36 +1982,23 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) } 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'"); + CMP_warn("-oldcert option is ignored for 'genm' command"); } 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) + if (!setup_cert(ctx, opt_oldcert, opt_keypass, + /* needed if opt_oldcert is encrypted PKCS12 file */ + opt_cmd == CMP_KUR ? "certificate to be updated" : + opt_cmd == CMP_RR ? "certificate to be revoked" : + "reference certificate (oldcert)", + (add_X509_fn_t)OSSL_CMP_CTX_set1_oldCert)) 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; @@ -1773,68 +2010,129 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) return 0; } -static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) +static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name) { - long value; - ASN1_OBJECT *type; - ASN1_INTEGER *aint; - ASN1_TYPE *val; - OSSL_CMP_ITAV *itav; - char *endstr; - char *valptr = strchr(opt_geninfo, ':'); + OSSL_CMP_ITAV *itav = NULL; + STACK_OF(ASN1_UTF8STRING) *sk; + ASN1_UTF8STRING *utf8string; - if (valptr == NULL) { - CMP_err("missing ':' in -geninfo option"); + if (ctx == NULL || name == NULL) return 0; - } - valptr[0] = '\0'; - valptr++; - if (OPENSSL_strncasecmp(valptr, "int:", 4) != 0) { - CMP_err("missing 'int:' in -geninfo option"); + if ((sk = sk_ASN1_UTF8STRING_new_reserve(NULL, 1)) == NULL) return 0; + if ((utf8string = ASN1_UTF8STRING_new()) == NULL) + goto err; + if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) { + ASN1_STRING_free(utf8string); + goto err; } - valptr += 4; + /* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */ + (void)sk_ASN1_UTF8STRING_push(sk, utf8string); + if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL) + goto err; + if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) + return 1; + OSSL_CMP_ITAV_free(itav); + return 0; - 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"); + err: + sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free); return 0; } +static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) +{ + ASN1_OBJECT *obj = NULL; + ASN1_TYPE *type = NULL; + long value; + ASN1_INTEGER *aint = NULL; + ASN1_UTF8STRING *text = NULL; + OSSL_CMP_ITAV *itav; + char *ptr = opt_geninfo, *oid, *end; + + do { + while (isspace(_UC(*ptr))) + ptr++; + oid = ptr; + if ((ptr = strchr(oid, ':')) == NULL) { + CMP_err1("Missing ':' in -geninfo arg %.40s", oid); + return 0; + } + *ptr++ = '\0'; + if ((obj = OBJ_txt2obj(oid, 0)) == NULL) { + CMP_err1("Invalid OID in -geninfo arg %.40s", oid); + return 0; + } + if (OBJ_obj2nid(obj) == NID_undef) + CMP_warn1("Unknown OID in -geninfo arg: %.40s", oid); + if ((type = ASN1_TYPE_new()) == NULL) + goto oom; + + if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "int:")) { + value = strtol(ptr, &end, 10); + if (end == ptr) { + CMP_err1("Cannot parse int in -geninfo arg %.40s", ptr); + goto err; + } + ptr = end; + if (*ptr != '\0') { + if (*ptr != ',') { + CMP_err1("Missing ',' or end of -geninfo arg after int at %.40s", + ptr); + goto err; + } + ptr++; + } + + if ((aint = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(aint, value)) + goto oom; + ASN1_TYPE_set(type, V_ASN1_INTEGER, aint); + aint = NULL; + + } else if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "str:")) { + end = strchr(ptr, ','); + if (end == NULL) + end = ptr + strlen(ptr); + else + *end++ = '\0'; + if ((text = ASN1_UTF8STRING_new()) == NULL + || !ASN1_STRING_set(text, ptr, -1)) + goto oom; + ptr = end; + ASN1_TYPE_set(type, V_ASN1_UTF8STRING, text); + text = NULL; + + } else { + CMP_err1("Missing 'int:' or 'str:' in -geninfo arg %.40s", ptr); + goto err; + } + + if ((itav = OSSL_CMP_ITAV_create(obj, type)) == NULL) { + CMP_err("Unable to create 'OSSL_CMP_ITAV' structure"); + goto err; + } + obj = NULL; + type = NULL; + + if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) { + CMP_err("Failed to add ITAV for geninfo of the PKI message header"); + OSSL_CMP_ITAV_free(itav); + return 0; + } + } while (*ptr != '\0'); + return 1; + + oom: + CMP_err("out of memory"); + err: + ASN1_OBJECT_free(obj); + ASN1_TYPE_free(type); + ASN1_INTEGER_free(aint); + ASN1_UTF8STRING_free(text); + return 0; +} /* * set up the client-side OSSL_CMP_CTX based on options from config file/CLI @@ -1846,17 +2144,19 @@ 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; +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) + int portnum, use_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) + strcpy(server_buf, "no server"); if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */ -#ifndef OPENSSL_NO_SOCK - if (opt_server == NULL) { +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) + if (opt_server == NULL && opt_reqout_only == NULL) { CMP_err("missing -server or -use_mock_srv or -rspin option"); goto err; } @@ -1865,27 +2165,26 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) goto err; #endif } -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) 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 */)) { + if (!OSSL_HTTP_parse_url(opt_server, &use_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; + if (use_ssl && !opt_tls_used) { + CMP_warn("assuming -tls_used since -server URL indicates HTTPS"); + opt_tls_used = 1; } + if (!OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_USE_TLS, opt_tls_used)) + goto err; BIO_snprintf(server_port, sizeof(server_port), "%s", port); if (opt_path == NULL) @@ -1901,7 +2200,7 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) 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); + proxy_host = OSSL_HTTP_adapt_proxy(opt_proxy, opt_no_proxy, host, use_ssl); if (proxy_host != NULL) (void)BIO_snprintf(proxy_buf, sizeof(proxy_buf), " via %s", proxy_host); @@ -1913,7 +2212,12 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (!transform_opts()) goto err; - if (opt_infotype_s != NULL) { + if (opt_infotype_s == NULL) { + if (opt_cmd == CMP_GENM) + CMP_warn("no -infotype option given for genm"); + } else if (opt_cmd != CMP_GENM) { + CMP_warn("-infotype option is ignored for commands other than 'genm'"); + } else { char id_buf[100] = "id-it-"; strncat(id_buf, opt_infotype_s, sizeof(id_buf) - strlen(id_buf) - 1); @@ -1922,6 +2226,29 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) goto err; } } + if (opt_cmd != CMP_GENM || opt_infotype != NID_id_it_rootCaCert) { + const char *msg = "option is ignored unless -cmd 'genm' and -infotype rootCaCert is given"; + + if (opt_oldwithold != NULL) + CMP_warn1("-oldwithold %s", msg); + if (opt_newwithnew != NULL) + CMP_warn1("-newwithnew %s", msg); + if (opt_newwithold != NULL) + CMP_warn1("-newwithold %s", msg); + if (opt_oldwithnew != NULL) + CMP_warn1("-oldwithnew %s", msg); + } + if (opt_cmd != CMP_GENM || opt_infotype != NID_id_it_certReqTemplate) { + const char *msg = "option is ignored unless -cmd 'genm' and -infotype 'certReqTemplate' is given"; + + if (opt_template != NULL) + CMP_warn1("-template %s", msg); + if (opt_keyspec != NULL) + CMP_warn1("-keyspec %s", msg); + } else { + if (opt_template == NULL) + CMP_err("missing -template option for genm with infotype certReqTemplate"); + } if (!setup_verification_ctx(ctx)) goto err; @@ -1953,7 +2280,7 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) || 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 !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) if (opt_tls_used) { APP_HTTP_TLS_INFO *info; @@ -1970,6 +2297,7 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if ((info = OPENSSL_zalloc(sizeof(*info))) == NULL) goto err; + APP_HTTP_TLS_INFO_free(OSSL_CMP_CTX_get_http_cb_arg(ctx)); (void)OSSL_CMP_CTX_set_http_cb_arg(ctx, info); info->ssl_ctx = setup_ssl_ctx(ctx, host, engine); info->server = host; @@ -1999,14 +2327,14 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_geninfo != NULL && !handle_opt_geninfo(ctx)) goto err; + if (opt_profile != NULL && !add_certProfile(ctx, opt_profile)) + goto err; /* not printing earlier, to minimize confusion in case setup fails before */ - if (opt_rspin != NULL) - 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); + if (opt_reqout_only == NULL) + CMP_info3("will contact %s%s%s ", server_buf, proxy_buf, + opt_rspin == NULL ? "" : + " only if -rspin argument gives too few filenames"); ret = 1; @@ -2037,37 +2365,54 @@ static int write_cert(BIO *bio, X509 *cert) return 0; } +static int write_crl(BIO *bio, X509_CRL *crl) +{ + if (opt_crlform != FORMAT_PEM && opt_crlform != FORMAT_ASN1) { + BIO_printf(bio_err, "error: unsupported type '%s' for writing CRLs\n", + opt_crlform_s); + return 0; + } + + return opt_crlform == FORMAT_PEM ? PEM_write_bio_X509_CRL(bio, crl) + : i2d_X509_CRL_bio(bio, crl); +} + /* - * If destFile != NULL writes out a stack of certs to the given file. - * In any case frees the certs. + * If file != NULL writes out a stack of certs to the given file. + * If certs is NULL, the file is emptied. + * Frees the certs if present. * 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) +static int save_free_certs(STACK_OF(X509) *certs, + const char *file, const char *desc) { BIO *bio = NULL; int i; - int n = sk_X509_num(certs); + int n = sk_X509_num(certs /* may be NULL */); - if (destFile == NULL) + if (n < 0) + n = 0; + if (file == NULL) goto end; - CMP_info3("received %d %s certificate(s), saving to file '%s'", - n, desc, destFile); + if (certs != NULL) + CMP_info3("received %d %s certificate(s), saving to file '%s'", + n, desc, file); 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); + if ((bio = BIO_new(BIO_s_file())) == NULL + || !BIO_write_filename(bio, (char *)file)) { + CMP_err3("could not open file '%s' for %s %s certificate(s)", + file, certs == NULL ? "deleting" : "writing", desc); 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); + CMP_err2("cannot write %s certificate to file '%s'", desc, file); n = -1; goto end; } @@ -2075,32 +2420,158 @@ static int save_free_certs(OSSL_CMP_CTX *ctx, end: BIO_free(bio); - sk_X509_pop_free(certs, X509_free); + OSSL_STACK_OF_X509_free(certs); return n; } -static void print_itavs(STACK_OF(OSSL_CMP_ITAV) *itavs) +static int save_crl(X509_CRL *crl, + const char *file, const char *desc) { - OSSL_CMP_ITAV *itav = NULL; - char buf[128]; - int i, r; - int n = sk_OSSL_CMP_ITAV_num(itavs); /* itavs == NULL leads to 0 */ + BIO *bio = NULL; + int res = 0; - if (n == 0) { - CMP_info("genp contains no ITAV"); - return; + if (file == NULL) + return 1; + if (crl != NULL) + CMP_info2("received %s, saving to file '%s'", desc, file); + + if ((bio = BIO_new(BIO_s_file())) == NULL + || !BIO_write_filename(bio, (char *)file)) { + CMP_err2("could not open file '%s' for writing %s", + file, desc); + goto end; } - 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); + if (!write_crl(bio, crl)) { + CMP_err2("cannot write %s to file '%s'", desc, file); + goto end; } + res = 1; + + end: + BIO_free(bio); + return res; +} + +static int delete_file(const char *file, const char *desc) +{ + if (file == NULL) + return 1; + + if (unlink(file) != 0 && errno != ENOENT) { + CMP_err2("Failed to delete %s, which should be done to indicate there is no %s", + file, desc); + return 0; + } + return 1; +} + +static int save_cert_or_delete(X509 *cert, const char *file, const char *desc) +{ + if (file == NULL) + return 1; + if (cert == NULL) { + char desc_cert[80]; + + BIO_snprintf(desc_cert, sizeof(desc_cert), "%s certificate", desc); + return delete_file(file, desc_cert); + } else { + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!X509_add_cert(certs, cert, X509_ADD_FLAG_UP_REF)) { + sk_X509_free(certs); + return 0; + } + return save_free_certs(certs, file, desc) >= 0; + } +} + +static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc) +{ + if (file == NULL) + return 1; + return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc); +} + +static int save_template(const char *file, const OSSL_CRMF_CERTTEMPLATE *tmpl) +{ + BIO *bio = BIO_new_file(file, "wb"); + + if (bio == NULL) { + CMP_err1("error saving certTemplate from genp: cannot open file %s", + file); + return 0; + } + if (!ASN1_i2d_bio_of(OSSL_CRMF_CERTTEMPLATE, i2d_OSSL_CRMF_CERTTEMPLATE, + bio, tmpl)) { + CMP_err1("error saving certTemplate from genp: cannot write file %s", + file); + return 0; + } else { + CMP_info1("stored certTemplate from genp to file '%s'", file); + } + BIO_free(bio); + return 1; +} + +static int save_keyspec(const char *file, const OSSL_CMP_ATAVS *keyspec) +{ + BIO *bio = BIO_new_file(file, "wb"); + + if (bio == NULL) { + CMP_err1("error saving keySpec from genp: cannot open file %s", file); + return 0; + } + + if (!ASN1_i2d_bio_of(OSSL_CMP_ATAVS, i2d_OSSL_CMP_ATAVS, bio, keyspec)) { + CMP_err1("error saving keySpec from genp: cannot write file %s", file); + return 0; + } else { + CMP_info1("stored keySpec from genp to file '%s'", file); + } + BIO_free(bio); + return 1; +} + +static const char *nid_name(int nid) +{ + const char *name = OBJ_nid2ln(nid); + + if (name == NULL) + name = OBJ_nid2sn(nid); + if (name == NULL) + name = ""; + return name; +} + +static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs) +{ + int i, ret = 1; + int n = sk_OSSL_CMP_ITAV_num(itavs); + + if (n <= 0) { /* also in case itavs == NULL */ + CMP_info("genp does not contain any ITAV"); + return ret; + } + + for (i = 1; i <= n; i++) { + OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_value(itavs, i - 1); + ASN1_OBJECT *type = OSSL_CMP_ITAV_get0_type(itav); + char name[80]; + + if (itav == NULL) { + CMP_err1("could not get ITAV #%d from genp", i); + ret = 0; + continue; + } + if (i2t_ASN1_OBJECT(name, sizeof(name), type) <= 0) { + CMP_err1("error parsing type of ITAV #%d from genp", i); + ret = 0; + } else { + CMP_info2("ITAV #%d from genp infoType=%s", i, name); + } + } + return ret; } static char opt_item[SECTION_NAME_MAX + 1]; @@ -2146,9 +2617,8 @@ static char *conf_get_string(const CONF *src_conf, const char *groups, const char *end = groups + strlen(groups); while ((end = prev_item(groups, end)) != NULL) { - if ((res = NCONF_get_string(src_conf, opt_item, name)) != NULL) + if ((res = app_conf_try_string(src_conf, opt_item, name)) != NULL) return res; - ERR_clear_error(); } return res; } @@ -2197,9 +2667,9 @@ static int read_config(void) || !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); + + 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 @@ -2346,7 +2816,7 @@ static int get_opts(int argc, char **argv) if (!set_verbosity(opt_int_arg())) goto opthelp; break; -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) case OPT_SERVER: opt_server = opt_str(); break; @@ -2376,7 +2846,7 @@ static int get_opts(int argc, char **argv) case OPT_TOTAL_TIMEOUT: opt_total_timeout = opt_int_arg(); break; -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) case OPT_TLS_USED: opt_tls_used = 1; break; @@ -2449,12 +2919,39 @@ static int get_opts(int argc, char **argv) case OPT_UNPROTECTED_ERRORS: opt_unprotected_errors = 1; break; + case OPT_NO_CACHE_EXTRACERTS: + opt_no_cache_extracerts = 1; + break; + case OPT_SRVCERTOUT: + opt_srvcertout = opt_str(); + break; case OPT_EXTRACERTSOUT: opt_extracertsout = opt_str(); break; case OPT_CACERTSOUT: opt_cacertsout = opt_str(); break; + case OPT_OLDWITHOLD: + opt_oldwithold = opt_str(); + break; + case OPT_NEWWITHNEW: + opt_newwithnew = opt_str(); + break; + case OPT_NEWWITHOLD: + opt_newwithold = opt_str(); + break; + case OPT_OLDWITHNEW: + opt_oldwithnew = opt_str(); + break; + case OPT_CRLCERT: + opt_crlcert = opt_str(); + break; + case OPT_OLDCRL: + opt_oldcrl = opt_str(); + break; + case OPT_CRLOUT: + opt_crlout = opt_str(); + break; case OPT_V_CASES: if (!opt_verify(o, vpm)) @@ -2466,22 +2963,33 @@ static int get_opts(int argc, char **argv) case OPT_INFOTYPE: opt_infotype_s = opt_str(); break; + case OPT_PROFILE: + opt_profile = opt_str(); + break; case OPT_GENINFO: opt_geninfo = opt_str(); break; - + case OPT_TEMPLATE: + opt_template = opt_str(); + break; + case OPT_KEYSPEC: + opt_keyspec = opt_str(); + break; case OPT_NEWKEY: opt_newkey = opt_str(); break; case OPT_NEWKEYPASS: opt_newkeypass = opt_str(); break; + case OPT_CENTRALKEYGEN: + opt_centralkeygen = 1; + break; + case OPT_NEWKEYOUT: + opt_newkeyout = 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; @@ -2534,16 +3042,25 @@ static int get_opts(int argc, char **argv) break; case OPT_REVREASON: opt_revreason = opt_int_arg(); - if (opt_revreason < CRL_REASON_NONE + 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_ISSUER: + opt_issuer = opt_str(); + break; + case OPT_SERIAL: + opt_serial = opt_str(); + break; case OPT_CERTFORM: opt_certform_s = opt_str(); break; + case OPT_CRLFORM: + opt_crlform_s = opt_str(); + break; case OPT_KEYFORM: opt_keyform_s = opt_str(); break; @@ -2579,6 +3096,9 @@ static int get_opts(int argc, char **argv) case OPT_REQOUT: opt_reqout = opt_str(); break; + case OPT_REQOUT_ONLY: + opt_reqout_only = opt_str(); + break; case OPT_RSPIN: opt_rspin = opt_str(); break; @@ -2589,7 +3109,7 @@ static int get_opts(int argc, char **argv) opt_use_mock_srv = 1; break; -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) case OPT_PORT: opt_port = opt_str(); break; @@ -2618,15 +3138,36 @@ static int get_opts(int argc, char **argv) case OPT_SRV_UNTRUSTED: opt_srv_untrusted = opt_str(); break; + case OPT_REF_CERT: + opt_ref_cert = opt_str(); + break; case OPT_RSP_CERT: opt_rsp_cert = opt_str(); break; + case OPT_RSP_KEY: + opt_rsp_key = opt_str(); + break; + case OPT_RSP_KEYPASS: + opt_rsp_keypass = opt_str(); + break; + case OPT_RSP_CRL: + opt_rsp_crl = 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_RSP_NEWWITHNEW: + opt_rsp_newwithnew = opt_str(); + break; + case OPT_RSP_NEWWITHOLD: + opt_rsp_newwithold = opt_str(); + break; + case OPT_RSP_OLDWITHNEW: + opt_rsp_oldwithnew = opt_str(); + break; case OPT_POLL_COUNT: opt_poll_count = opt_int_arg(); break; @@ -2670,15 +3211,14 @@ static int get_opts(int argc, char **argv) } /* No extra args. */ - argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; return 1; } -#ifndef OPENSSL_NO_SOCK -static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) +static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) +{ BIO *acbio; BIO *cbio = NULL; int keep_alive = 0; @@ -2686,7 +3226,7 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { int retry = 1; int ret = 1; - if ((acbio = http_server_init_bio(prog, opt_port)) == NULL) + if ((acbio = http_server_init(prog, opt_port, opt_verbosity)) == NULL) return 0; while (opt_max_msgs <= 0 || msgs < opt_max_msgs) { char *path = NULL; @@ -2696,10 +3236,10 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { 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); + prog, 0, 0); if (ret == 0) { /* no request yet */ if (retry) { - ossl_sleep(1000); + OSSL_sleep(1000); retry = 0; continue; } @@ -2713,7 +3253,7 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { msgs++; if (req != NULL) { if (strcmp(path, "") != 0 && strcmp(path, "pkix/") != 0) { - (void)http_server_send_status(cbio, 404, "Not Found"); + (void)http_server_send_status(prog, cbio, 404, "Not Found"); CMP_err1("expecting empty path or 'pkix/' but got '%s'", path); OPENSSL_free(path); @@ -2724,11 +3264,11 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { resp = OSSL_CMP_CTX_server_perform(cmp_ctx, req); OSSL_CMP_MSG_free(req); if (resp == NULL) { - (void)http_server_send_status(cbio, + (void)http_server_send_status(prog, cbio, 500, "Internal Server Error"); break; /* treated as fatal error */ } - ret = http_server_send_asn1_resp(cbio, keep_alive, + ret = http_server_send_asn1_resp(prog, cbio, keep_alive, "application/pkixcmp", ASN1_ITEM_rptr(OSSL_CMP_MSG), (const ASN1_VALUE *)resp); @@ -2755,6 +3295,71 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx) { } #endif +static void print_keyspec(OSSL_CMP_ATAVS *keySpec) +{ + const char *desc = "specifications contained in keySpec from genp"; + BIO *mem; + int i; + const char *p; + long len; + + if (keySpec == NULL) { + CMP_info1("No %s", desc); + return; + } + + mem = BIO_new(BIO_s_mem()); + if (mem == NULL) { + CMP_err1("Out of memory - cannot dump key %s", desc); + return; + } + BIO_printf(mem, "Key %s:\n", desc); + + for (i = 0; i < sk_OSSL_CMP_ATAV_num(keySpec); i++) { + OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(keySpec, i); + ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */); + int nid = OBJ_obj2nid(type); + + switch (nid) { + case NID_id_regCtrl_algId: + { + X509_ALGOR *alg = OSSL_CMP_ATAV_get0_algId(atav); + const ASN1_OBJECT *oid; + int paramtype; + const void *param; + + X509_ALGOR_get0(&oid, ¶mtype, ¶m, alg); + BIO_printf(mem, "Key algorithm: "); + i2a_ASN1_OBJECT(mem, oid); + if (paramtype == V_ASN1_UNDEF || alg->parameter == NULL) { + BIO_printf(mem, "\n"); + } else { + BIO_printf(mem, " - "); + ASN1_item_print(mem, (ASN1_VALUE *)alg, + 0, ASN1_ITEM_rptr(X509_ALGOR), NULL); + } + } + break; + case NID_id_regCtrl_rsaKeyLen: + BIO_printf(mem, "Key algorithm: RSA %d\n", + OSSL_CMP_ATAV_get_rsaKeyLen(atav)); + break; + default: + BIO_printf(mem, "Invalid key spec: %s\n", nid_name(nid)); + break; + } + } + BIO_printf(mem, "End of key %s", desc); + + len = BIO_get_mem_data(mem, &p); + if (len > INT_MAX) + CMP_err1("Info too large - cannot dump key %s", desc); + else + CMP_info2("%.*s", (int)len, p); + BIO_free(mem); + return; +} + static void print_status(void) { /* print PKIStatusInfo */ @@ -2764,7 +3369,7 @@ static void print_status(void) OSSL_CMP_CTX_snprint_PKIStatus(cmp_ctx, buf, OSSL_CMP_PKISI_BUFLEN); const char *from = "", *server = ""; -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) if (opt_server != NULL) { from = " from "; server = opt_server; @@ -2784,25 +3389,198 @@ static void print_status(void) OPENSSL_free(buf); } -int cmp_main(int argc, char **argv) +static int do_genm(OSSL_CMP_CTX *ctx) +{ + if (opt_infotype == NID_id_it_caCerts) { + STACK_OF(X509) *cacerts = NULL; + + if (opt_cacertsout == NULL) { + CMP_err("Missing -cacertsout option for -infotype caCerts"); + return 0; + } + + if (!OSSL_CMP_get1_caCerts(ctx, &cacerts)) + return 0; + + /* could check authorization of sender/origin at this point */ + if (cacerts == NULL) { + CMP_warn("no CA certificates provided by server"); + } else if (save_free_certs(cacerts, opt_cacertsout, "CA") < 0) { + CMP_err1("Failed to store CA certificates from genp in %s", + opt_cacertsout); + return 0; + } + return 1; + } else if (opt_infotype == NID_id_it_rootCaCert) { + X509 *oldwithold = NULL; + X509 *newwithnew = NULL; + X509 *newwithold = NULL; + X509 *oldwithnew = NULL; + int res = 0; + + if (opt_newwithnew == NULL) { + CMP_err("Missing -newwithnew option for -infotype rootCaCert"); + return 0; + } + if (opt_oldwithold == NULL) { + CMP_warn("No -oldwithold given, will use all certs given with -trusted as trust anchors for verifying the newWithNew cert"); + } else { + oldwithold = load_cert_pwd(opt_oldwithold, opt_otherpass, + "OldWithOld cert for genm with -infotype rootCaCert"); + if (oldwithold == NULL) + goto end_upd; + } + if (!OSSL_CMP_get1_rootCaKeyUpdate(ctx, oldwithold, &newwithnew, + &newwithold, &oldwithnew)) + goto end_upd; + /* At this point might check authorization of response sender/origin */ + + if (newwithnew == NULL) + CMP_info("no root CA certificate update available"); + else if (oldwithold == NULL && oldwithnew != NULL) + CMP_warn("oldWithNew certificate received in genp for verifying oldWithOld, but oldWithOld was not provided"); + + if (save_cert_or_delete(newwithnew, opt_newwithnew, + "NewWithNew cert from genp") + && save_cert_or_delete(newwithold, opt_newwithold, + "NewWithOld cert from genp") + && save_cert_or_delete(oldwithnew, opt_oldwithnew, + "OldWithNew cert from genp")) + res = 1; + + X509_free(newwithnew); + X509_free(newwithold); + X509_free(oldwithnew); + end_upd: + X509_free(oldwithold); + return res; + } else if (opt_infotype == NID_id_it_crlStatusList) { + X509_CRL *oldcrl = NULL, *crl = NULL; + X509 *crlcert = NULL; + int res = 0; + const char *desc = "CRL from genp of type 'crls'"; + + if (opt_oldcrl == NULL && opt_crlcert == NULL) { + CMP_err("Missing -oldcrl and no -crlcert given for -infotype crlStatusList"); + return 0; + } + if (opt_crlout == NULL) { + CMP_err("Missing -crlout for -infotype crlStatusList"); + return 0; + } + + if (opt_crlcert != NULL) { + crlcert = load_cert_pwd(opt_crlcert, opt_otherpass, + "Cert for genm with -infotype crlStatusList"); + if (crlcert == NULL) + goto end_crlupd; + } + + if (opt_oldcrl != NULL) { + oldcrl = load_crl(opt_oldcrl, FORMAT_UNDEF, 0, + "CRL for genm with -infotype crlStatusList"); + if (oldcrl == NULL) + goto end_crlupd; + } + + if (opt_oldcrl != NULL && opt_crlcert != NULL) { + if (X509_NAME_cmp(X509_CRL_get_issuer(oldcrl), + X509_get_issuer_name(crlcert)) + != 0) + CMP_warn("-oldcrl and -crlcert have different issuer"); + } + + if (!OSSL_CMP_get1_crlUpdate(ctx, crlcert, oldcrl, &crl)) + goto end_crlupd; + + if (crl == NULL) + CMP_info("no CRL update available"); + if (!save_crl_or_delete(crl, opt_crlout, desc)) + goto end_crlupd; + + res = 1; + + end_crlupd: + X509_free(crlcert); + X509_CRL_free(oldcrl); + X509_CRL_free(crl); + return res; + + } else if (opt_infotype == NID_id_it_certReqTemplate) { + OSSL_CRMF_CERTTEMPLATE *certTemplate; + OSSL_CMP_ATAVS *keySpec; + int res = 0; + + if (!OSSL_CMP_get1_certReqTemplate(ctx, &certTemplate, &keySpec)) + return 0; + + if (certTemplate == NULL) { + CMP_warn("no certificate request template available"); + if (!delete_file(opt_template, "certTemplate from genp")) + return 0; + if (opt_keyspec != NULL + && !delete_file(opt_keyspec, "keySpec from genp")) + return 0; + return 1; + } + if (!save_template(opt_template, certTemplate)) + goto tmpl_end; + + print_keyspec(keySpec); + if (opt_keyspec != NULL) { + if (keySpec == NULL) { + CMP_warn("no key specifications available"); + if (!delete_file(opt_keyspec, "keySpec from genp")) + goto tmpl_end; + } else if (!save_keyspec(opt_keyspec, keySpec)) { + goto tmpl_end; + } + } + + res = 1; + tmpl_end: + OSSL_CRMF_CERTTEMPLATE_free(certTemplate); + sk_OSSL_CMP_ATAV_pop_free(keySpec, OSSL_CMP_ATAV_free); + return res; + } else { + OSSL_CMP_ITAV *req; + STACK_OF(OSSL_CMP_ITAV) *itavs; + + if (opt_infotype != NID_undef) { + CMP_warn1("No specific support for -infotype %s available", + opt_infotype_s); + + req = OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL); + if (req == NULL || !OSSL_CMP_CTX_push0_genm_ITAV(ctx, req)) { + CMP_err1("Failed to create genm for -infotype %s", + opt_infotype_s); + return 0; + } + } + + if ((itavs = OSSL_CMP_exec_GENM_ses(ctx)) != NULL) { + int res = print_itavs(itavs); + + sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free); + return res; + } + if (OSSL_CMP_CTX_get_status(ctx) != OSSL_CMP_PKISTATUS_request) + CMP_err("Did not receive response on genm or genp is not valid"); + return 0; + } +} + +static int handle_opts_upfront(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; + return 0; } - /* - * handle options -config, -section, and -verbosity upfront - * to take effect for other options - */ + /* handle -config, -section, and -verbosity to take effect for other opts */ for (i = 1; i < argc - 1; i++) { if (*argv[i] == '-') { if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name)) @@ -2813,11 +3591,25 @@ int cmp_main(int argc, char **argv) else if (strcmp(argv[i] + 1, cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0 && !set_verbosity(atoi(argv[++i]))) - goto err; + return 0; } } if (opt_section[0] == '\0') /* empty string */ opt_section = DEFAULT_SECTION; + return 1; +} + +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 */ + + if (!handle_opts_upfront(argc, argv)) + goto err; vpm = X509_VERIFY_PARAM_new(); if (vpm == NULL) { @@ -2828,7 +3620,8 @@ int cmp_main(int argc, char **argv) /* 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)) { + && (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); @@ -2842,6 +3635,7 @@ int cmp_main(int argc, char **argv) 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'", @@ -2862,9 +3656,14 @@ int cmp_main(int argc, char **argv) } (void)BIO_flush(bio_err); /* prevent interference with opt_help() */ + cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); + if (cmp_ctx == NULL) + goto err; + ret = get_opts(argc, argv); if (ret <= 0) goto err; + ret = 0; if (!app_RAND_load()) goto err; @@ -2873,28 +3672,29 @@ int cmp_main(int argc, char **argv) set_base_ui_method(UI_null()); if (opt_engine != NULL) { - engine = setup_engine_methods(opt_engine, 0 /* not: ENGINE_METHOD_ALL */, 0); + 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 !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) + 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) { + if (opt_tls_used) + CMP_warn("-tls_used given without any other TLS options"); + } else if (!opt_tls_used) { + CMP_warn("ignoring 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"); @@ -2919,11 +3719,17 @@ int cmp_main(int argc, char **argv) } #endif - if (opt_use_mock_srv -#ifndef OPENSSL_NO_SOCK - || opt_port != NULL + if (opt_ignore_keyusage) + (void)OSSL_CMP_CTX_set_option(cmp_ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1); + if (opt_no_cache_extracerts) + (void)OSSL_CMP_CTX_set_option(cmp_ctx, OSSL_CMP_OPT_NO_CACHE_EXTRACERTS, + 1); + + if (opt_reqout_only == NULL && (opt_use_mock_srv +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) + || opt_port != NULL #endif - ) { + )) { OSSL_CMP_SRV_CTX *srv_ctx; if ((srv_ctx = setup_srv_ctx(engine)) == NULL) @@ -2937,7 +3743,7 @@ int cmp_main(int argc, char **argv) OSSL_CMP_CTX_set_log_verbosity(srv_cmp_ctx, opt_verbosity); } -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) 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; @@ -2950,6 +3756,23 @@ int cmp_main(int argc, char **argv) /* act as CMP client, possibly using internal mock server */ + if (opt_reqout_only != NULL) { + const char *msg = "option is ignored since -reqout_only option is given"; + +# if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) + if (opt_server != NULL) + CMP_warn1("-server %s", msg); +# endif + if (opt_use_mock_srv) + CMP_warn1("-use_mock_srv %s", msg); + if (opt_reqout != NULL) + CMP_warn1("-reqout %s", msg); + if (opt_rspin != NULL) + CMP_warn1("-rspin %s", msg); + if (opt_rspout != NULL) + CMP_warn1("-rspout %s", msg); + opt_reqout = opt_reqout_only; + } if (opt_rspin != NULL) { if (opt_server != NULL) CMP_warn("-server option is not used if enough filenames given for -rspin"); @@ -2989,54 +3812,80 @@ int cmp_main(int argc, char **argv) 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; - } + ret = do_genm(cmp_ctx); 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 */ - + if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted) { + /* we got no response, maybe even did not send request */ + ret = 0; + if (reqout_only_done) { + ERR_clear_error(); + ret = 1; + } + goto err; + } print_status(); - if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx), - opt_extracertsout, "extra") < 0) + if (!save_cert_or_delete(OSSL_CMP_CTX_get0_validatedSrvCert(cmp_ctx), + opt_srvcertout, "validated server")) 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) + if (save_free_certs(OSSL_CMP_CTX_get1_extraCertsIn(cmp_ctx), + opt_extracertsout, "extra") < 0) goto err; - if (newcert != NULL) { - STACK_OF(X509) *certs = sk_X509_new_null(); + if (newcert != NULL && (opt_cmd == CMP_IR || opt_cmd == CMP_CR + || opt_cmd == CMP_KUR || opt_cmd == CMP_P10CR)) { + STACK_OF(X509) *newchain = OSSL_CMP_CTX_get1_newChain(cmp_ctx); - if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) { - sk_X509_free(certs); - goto err; + if (newcert != NULL && newchain != NULL /* NULL is on error only */ + && opt_certout != NULL && opt_chainout != NULL + && strcmp(opt_certout, opt_chainout) == 0) { + if (!X509_add_cert(newchain, newcert, X509_ADD_FLAG_PREPEND + | X509_ADD_FLAG_UP_REF)) { + sk_X509_pop_free(newchain, X509_free); + goto err; + } + if (!save_free_certs(newchain, opt_chainout, "newly enrolled cert and chain")) + goto err; + } else { + if (save_free_certs(newchain, opt_chainout, "chain") < 0 + || !save_cert_or_delete(newcert, opt_certout, "newly enrolled")) + goto err; } - if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0) + if (save_free_certs(OSSL_CMP_CTX_get1_caPubs(cmp_ctx), + opt_cacertsout, "CA") < 0) goto err; - } - if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx), - opt_chainout, "chain") < 0) - goto err; + if (opt_centralkeygen) { + EVP_CIPHER *cipher = NULL; + char *pass_string = NULL; + BIO *out; + int result = 1; + EVP_PKEY *new_key = OSSL_CMP_CTX_get0_newPkey(cmp_ctx, 1 /* priv */); + if (new_key == NULL) + goto err; + if ((out = bio_open_owner(opt_newkeyout, FORMAT_PEM, 1)) == NULL) + goto err; + if (opt_newkeypass != NULL) { + pass_string = get_passwd(opt_newkeypass, + "Centrally generated private key password"); + cipher = EVP_CIPHER_fetch(app_get0_libctx(), SN_aes_256_cbc, app_get0_propq()); + } + + CMP_info1("saving centrally generated key to file '%s'", opt_newkeyout); + if (PEM_write_bio_PrivateKey(out, new_key, cipher, NULL, 0, NULL, + (void *)pass_string) <= 0) + result = 0; + + BIO_free(out); + clear_free(pass_string); + EVP_CIPHER_free(cipher); + if (!result) + goto err; + } + } if (!OSSL_CMP_CTX_reinit(cmp_ctx)) goto err; } @@ -3047,7 +3896,7 @@ int cmp_main(int argc, char **argv) cleanse(opt_keypass); cleanse(opt_newkeypass); cleanse(opt_otherpass); -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) cleanse(opt_tls_keypass); #endif cleanse(opt_secret); @@ -3058,15 +3907,16 @@ int cmp_main(int argc, char **argv) OSSL_CMP_CTX_print_errors(cmp_ctx); if (cmp_ctx != NULL) { -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) APP_HTTP_TLS_INFO *info = OSSL_CMP_CTX_get_http_cb_arg(cmp_ctx); + (void)OSSL_CMP_CTX_set_http_cb_arg(cmp_ctx, NULL); #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 +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) if (info != NULL) { OPENSSL_free((char *)info->server); OPENSSL_free((char *)info->port); diff --git a/apps/cms.c b/apps/cms.c index dce227ef2db5..919d306ff687 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -66,10 +66,11 @@ typedef enum OPTION_choice { OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN, OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT, OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY, - OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, + OPT_DIGEST, OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS, OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT, OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS, - OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID, + OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_NO_SIGNING_TIME, + OPT_BINARY, OPT_KEYID, OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF, OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT, OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE, @@ -106,6 +107,7 @@ const OPTIONS cms_options[] = { "Generate a signed receipt for a message"}, {"verify_receipt", OPT_VERIFY_RECEIPT, '<', "Verify receipts; exit if receipt signatures do not verify"}, + {"digest", OPT_DIGEST, 's', "Sign a pre-computed digest in hex notation"}, {"digest_create", OPT_DIGEST_CREATE, '-', "Create a CMS \"DigestedData\" object"}, {"digest_verify", OPT_DIGEST_VERIFY, '-', @@ -174,7 +176,10 @@ const OPTIONS cms_options[] = { OPT_SECTION("Signing"), {"md", OPT_MD, 's', "Digest algorithm to use"}, {"signer", OPT_SIGNER, 's', "Signer certificate input file"}, - {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"certfile", OPT_CERTFILE, '<', + "Extra signer and intermediate CA certificates to include when signing"}, + {OPT_MORE_STR, 0, 0, + "or to use as preferred signer certs and for chain building when verifying"}, {"cades", OPT_CADES, '-', "Include signingCertificate attribute (CAdES-BES)"}, {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, @@ -182,6 +187,8 @@ const OPTIONS cms_options[] = { "Don't include signer's certificate when signing"}, {"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"}, {"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"}, + {"no_signing_time", OPT_NO_SIGNING_TIME, '-', + "Omit the signing time attribute"}, {"receipt_request_all", OPT_RR_ALL, '-', "When signing, create a receipt request for all recipients"}, {"receipt_request_first", OPT_RR_FIRST, '-', @@ -293,6 +300,9 @@ int cms_main(int argc, char **argv) const char *CAfile = NULL, *CApath = NULL, *CAstore = NULL; char *certsoutfile = NULL, *digestname = NULL, *wrapname = NULL; int noCAfile = 0, noCApath = 0, noCAstore = 0; + char *digesthex = NULL; + unsigned char *digestbin = NULL; + long digestlen = 0; char *infile = NULL, *outfile = NULL, *rctfile = NULL; char *passinarg = NULL, *passin = NULL, *signerfile = NULL; char *originatorfile = NULL, *recipfile = NULL, *ciphername = NULL; @@ -314,6 +324,7 @@ int cms_main(int argc, char **argv) if (encerts == NULL || vpm == NULL) goto end; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, cms_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -366,6 +377,9 @@ int cms_main(int argc, char **argv) case OPT_DIGEST_CREATE: operation = SMIME_DIGEST_CREATE; break; + case OPT_DIGEST: + digesthex = opt_arg(); + break; case OPT_DIGEST_VERIFY: operation = SMIME_DIGEST_VERIFY; break; @@ -418,6 +432,9 @@ int cms_main(int argc, char **argv) case OPT_NOSMIMECAP: flags |= CMS_NOSMIMECAP; break; + case OPT_NO_SIGNING_TIME: + flags |= CMS_NO_SIGNING_TIME; + break; case OPT_BINARY: flags |= CMS_BINARY; break; @@ -705,17 +722,14 @@ int cms_main(int argc, char **argv) if (!opt_md(digestname, &sign_md)) goto end; } - if (ciphername != NULL) { - if (!opt_cipher_any(ciphername, &cipher)) - goto end; - } + if (!opt_cipher_any(ciphername, &cipher)) + goto end; if (wrapname != NULL) { if (!opt_cipher_any(wrapname, &wrap_cipher)) goto end; } /* Remaining args are files to process. */ - argc = opt_num_rest(); argv = opt_rest(); if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) { @@ -822,15 +836,8 @@ int cms_main(int argc, char **argv) } if (operation == SMIME_ENCRYPT) { - if (!cipher) { -#ifndef OPENSSL_NO_DES - cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); -#else - BIO_printf(bio_err, "No cipher selected\n"); - goto end; -#endif - } - + if (!cipher) + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); if (secret_key && !secret_keyid) { BIO_printf(bio_err, "No secret key id\n"); goto end; @@ -894,10 +901,31 @@ int cms_main(int argc, char **argv) goto end; } - in = bio_open_default(infile, 'r', - binary_files ? FORMAT_BINARY : informat); - if (in == NULL) - goto end; + if (digesthex != NULL) { + if (operation != SMIME_SIGN) { + BIO_printf(bio_err, + "Cannot use -digest for non-signing operation\n"); + goto end; + } + if (infile != NULL + || (flags & CMS_DETACHED) == 0 + || (flags & CMS_STREAM) != 0) { + BIO_printf(bio_err, + "Cannot use -digest when -in, -nodetach or streaming is used\n"); + goto end; + } + digestbin = OPENSSL_hexstr2buf(digesthex, &digestlen); + if (digestbin == NULL) { + BIO_printf(bio_err, + "Invalid hex value after -digest\n"); + goto end; + } + } else { + in = bio_open_default(infile, 'r', + binary_files ? FORMAT_BINARY : informat); + if (in == NULL) + goto end; + } if (operation & SMIME_IP) { cms = load_content_info(informat, in, flags, &indata, "SMIME"); @@ -919,7 +947,7 @@ int cms_main(int argc, char **argv) ret = 5; goto end; } - sk_X509_pop_free(allcerts, X509_free); + OSSL_STACK_OF_X509_free(allcerts); } } @@ -983,7 +1011,7 @@ int cms_main(int argc, char **argv) goto end; pctx = CMS_RecipientInfo_get0_pkey_ctx(ri); - if (kparam != NULL) { + if (pctx != NULL && kparam != NULL) { if (!cms_set_pkey_param(pctx, kparam->param)) goto end; } @@ -998,7 +1026,8 @@ int cms_main(int argc, char **argv) && wrap_cipher != NULL) { EVP_CIPHER_CTX *wctx; wctx = CMS_RecipientInfo_kari_get0_ctx(ri); - EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL); + if (EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL) != 1) + goto end; } } @@ -1053,12 +1082,12 @@ int cms_main(int argc, char **argv) } else if (operation & SMIME_SIGNERS) { int i; /* - * If detached data content we enable streaming if S/MIME output - * format. + * If detached data content and not signing pre-computed digest, we + * enable streaming if S/MIME output format. */ if (operation == SMIME_SIGN) { - if (flags & CMS_DETACHED) { + if ((flags & CMS_DETACHED) != 0 && digestbin == NULL) { if (outformat == FORMAT_SMIME) flags |= CMS_STREAM; } @@ -1119,7 +1148,12 @@ int cms_main(int argc, char **argv) key = NULL; } /* If not streaming or resigning finalize structure */ - if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) { + if (operation == SMIME_SIGN && digestbin != NULL + && (flags & CMS_STREAM) == 0) { + /* Use pre-computed digest instead of content */ + if (!CMS_final_digest(cms, digestbin, digestlen, NULL, flags)) + goto end; + } else if (operation == SMIME_SIGN && (flags & CMS_STREAM) == 0) { if (!CMS_final(cms, in, NULL, flags)) goto end; } @@ -1254,8 +1288,8 @@ int cms_main(int argc, char **argv) end: if (ret) ERR_print_errors(bio_err); - sk_X509_pop_free(encerts, X509_free); - sk_X509_pop_free(other, X509_free); + OSSL_STACK_OF_X509_free(encerts); + OSSL_STACK_OF_X509_free(other); X509_VERIFY_PARAM_free(vpm); sk_OPENSSL_STRING_free(sksigners); sk_OPENSSL_STRING_free(skkeys); @@ -1289,6 +1323,7 @@ int cms_main(int argc, char **argv) BIO_free(in); BIO_free(indata); BIO_free_all(out); + OPENSSL_free(digestbin); OPENSSL_free(passin); NCONF_free(conf); return ret; diff --git a/apps/crl.c b/apps/crl.c index 2158a107e551..afb59178fda6 100644 --- a/apps/crl.c +++ b/apps/crl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -98,6 +98,7 @@ int crl_main(int argc, char **argv) int hash_old = 0; #endif + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, crl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -209,14 +210,11 @@ int crl_main(int argc, char **argv) } /* No remaining args. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; - if (digestname != NULL) { - if (!opt_md(digestname, &digest)) - goto opthelp; - } + if (!opt_md(digestname, &digest)) + goto opthelp; x = load_crl(infile, informat, 1, "CRL"); if (x == NULL) goto end; @@ -250,9 +248,10 @@ int crl_main(int argc, char **argv) EVP_PKEY_free(pkey); if (i < 0) goto end; - if (i == 0) + if (i == 0) { BIO_printf(bio_err, "verify failure\n"); - else + goto end; + } else BIO_printf(bio_err, "verify OK\n"); } diff --git a/apps/crl2pkcs7.c b/apps/crl2pkcs7.c index fe59e654270d..f661393907e7 100644 --- a/apps/crl2pkcs7.c +++ b/apps/crl2pkcs7.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -104,8 +104,7 @@ int crl2pkcs7_main(int argc, char **argv) } /* No remaining args. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!nocrl) { @@ -139,7 +138,9 @@ int crl2pkcs7_main(int argc, char **argv) if ((crl_stack = sk_X509_CRL_new_null()) == NULL) goto end; p7s->crl = crl_stack; - sk_X509_CRL_push(crl_stack, crl); + + if (!sk_X509_CRL_push(crl_stack, crl)) + goto end; crl = NULL; /* now part of p7 for OPENSSL_freeing */ } @@ -217,7 +218,10 @@ static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile) while (sk_X509_INFO_num(sk)) { xi = sk_X509_INFO_shift(sk); if (xi->x509 != NULL) { - sk_X509_push(stack, xi->x509); + if (!sk_X509_push(stack, xi->x509)) { + X509_INFO_free(xi); + goto end; + } xi->x509 = NULL; count++; } diff --git a/apps/demoSRP/srp_verifier.txt b/apps/demoSRP/srp_verifier.txt index c2d5c6033608..a59b46413775 100644 --- a/apps/demoSRP/srp_verifier.txt +++ b/apps/demoSRP/srp_verifier.txt @@ -1,6 +1,6 @@ # This is a file that will be filled by the openssl srp routine. # You can initialize the file with additional groups, these are -# records starting with a I followed by the g and N values and the id. +# records starting with an 'I' followed by the 'g' and 'N' values and the ID. # The exact values ... you have to dig this out from the source of srp.c # or srp_vfy.c -# The last value of an I is used as the default group for new users. +# The last value of an 'I' is used as the default group for new users. diff --git a/apps/dgst.c b/apps/dgst.c index 51383bec26ca..0fb1f45200a0 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -24,6 +24,9 @@ #undef BUFSIZE #define BUFSIZE 1024*8 +static int do_fp_oneshot_sign(BIO *out, EVP_MD_CTX *ctx, BIO *in, int sep, int binout, + EVP_PKEY *key, unsigned char *sigin, int siglen, + const char *sig_name, const char *file); 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, @@ -93,7 +96,7 @@ const OPTIONS dgst_options[] = { int dgst_main(int argc, char **argv) { - BIO *in = NULL, *inp, *bmd = NULL, *out = NULL; + BIO *in = NULL, *inp = NULL, *bmd = NULL, *out = NULL; ENGINE *e = NULL, *impl = NULL; EVP_PKEY *sigkey = NULL; STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL; @@ -111,12 +114,15 @@ int dgst_main(int argc, char **argv) unsigned char *buf = NULL, *sigbuf = NULL; int engine_impl = 0; struct doall_dgst_digests dec; + EVP_MD_CTX *signctx = NULL; + int oneshot_sign = 0; buf = app_malloc(BUFSIZE, "I/O buffer"); md = (EVP_MD *)EVP_get_digestbyname(argv[0]); if (md != NULL) digestname = argv[0]; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, dgst_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -277,8 +283,6 @@ int dgst_main(int argc, char **argv) } if (keyfile != NULL) { - int type; - if (want_pub) sigkey = load_pubkey(keyfile, keyform, 0, NULL, e, "public key"); else @@ -289,14 +293,16 @@ int dgst_main(int argc, char **argv) */ 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; + { + char def_md[80]; + + if (EVP_PKEY_get_default_digest_name(sigkey, def_md, + sizeof(def_md)) == 2 + && strcmp(def_md, "UNDEF") == 0) + oneshot_sign = 1; + signctx = EVP_MD_CTX_new(); + if (signctx == NULL) + goto end; } } @@ -341,7 +347,9 @@ int dgst_main(int argc, char **argv) EVP_PKEY_CTX *pctx = NULL; int res; - if (BIO_get_md_ctx(bmd, &mctx) <= 0) { + if (oneshot_sign) { + mctx = signctx; + } else if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); goto end; } @@ -378,6 +386,11 @@ int dgst_main(int argc, char **argv) /* we use md as a filter, reading from 'in' */ else { EVP_MD_CTX *mctx = NULL; + + if (oneshot_sign) { + BIO_printf(bio_err, "Oneshot algorithms don't use a digest\n"); + goto end; + } if (BIO_get_md_ctx(bmd, &mctx) <= 0) { BIO_printf(bio_err, "Error getting context\n"); goto end; @@ -406,19 +419,20 @@ int dgst_main(int argc, char **argv) goto end; } } - inp = BIO_push(bmd, in); + if (!oneshot_sign) { + inp = BIO_push(bmd, in); - if (md == NULL) { - EVP_MD_CTX *tctx; + if (md == NULL) { + EVP_MD_CTX *tctx; - BIO_get_md_ctx(bmd, &tctx); - md = EVP_MD_CTX_get1_md(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 (md != NULL) - md_name = EVP_MD_get0_name(md); - if (xoflen > 0) { - if (!(EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF)) { + if (!EVP_MD_xof(md)) { BIO_printf(bio_err, "Length can only be specified for XOF\n"); goto end; } @@ -435,8 +449,12 @@ int dgst_main(int argc, char **argv) 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"); + if (oneshot_sign) + ret = do_fp_oneshot_sign(out, signctx, in, separator, out_bin, + sigkey, sigbuf, siglen, NULL, "stdin"); + else + ret = do_fp(out, buf, inp, separator, out_bin, xoflen, + sigkey, sigbuf, siglen, NULL, md_name, "stdin"); } else { const char *sig_name = NULL; @@ -451,9 +469,16 @@ int dgst_main(int argc, char **argv) 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; + if (oneshot_sign) { + if (do_fp_oneshot_sign(out, signctx, in, separator, out_bin, + sigkey, sigbuf, siglen, sig_name, + argv[i])) + ret = EXIT_FAILURE; + } 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); } @@ -467,6 +492,7 @@ int dgst_main(int argc, char **argv) BIO_free_all(out); EVP_MD_free(md); EVP_PKEY_free(sigkey); + EVP_MD_CTX_free(signctx); sk_OPENSSL_STRING_free(sigopts); sk_OPENSSL_STRING_free(macopts); OPENSSL_free(sigbuf); @@ -515,7 +541,7 @@ static void show_digests(const OBJ_NAME *name, void *arg) * in the '*sum' checksum programs. This aims to preserve backward * compatibility. */ -static const char *newline_escape_filename(const char *file, int * backslash) +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; @@ -528,7 +554,7 @@ static const char *newline_escape_filename(const char *file, int * backslash) file_cpy = app_malloc(mem_len, file); i = 0; - while(e < length) { + while (e < length) { const char c = file[e]; if (c == '\n') { file_cpy[i++] = '\\'; @@ -543,6 +569,54 @@ static const char *newline_escape_filename(const char *file, int * backslash) return (const char*)file_cpy; } +static void print_out(BIO *out, unsigned char *buf, size_t len, + int sep, int binout, + const char *sig_name, const char *md_name, const char *file) +{ + int i, backslash = 0; + + 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"); + } +} + +static void print_verify_result(BIO *out, int i) +{ + if (i > 0) + BIO_printf(out, "Verified OK\n"); + else if (i == 0) + BIO_printf(out, "Verification failure\n"); + else + BIO_printf(bio_err, "Error verifying data\n"); +} int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen, EVP_PKEY *key, unsigned char *sigin, int siglen, @@ -550,7 +624,7 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen const char *file) { size_t len = BUFSIZE; - int i, backslash = 0, ret = EXIT_FAILURE; + int i, ret = EXIT_FAILURE; unsigned char *allocated_buf = NULL; while (BIO_pending(bp) || !BIO_eof(bp)) { @@ -566,16 +640,9 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen 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; + print_verify_result(out, i); + if (i > 0) + ret = EXIT_SUCCESS; goto end; } if (key != NULL) { @@ -616,39 +683,7 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen 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"); - } - + print_out(out, buf, len, sep, binout, sig_name, md_name, file); ret = EXIT_SUCCESS; end: if (allocated_buf != NULL) @@ -656,3 +691,55 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen return ret; } + +/* + * Some new algorithms only support one shot operations. + * For these we need to buffer all input and then do the sign on the + * total buffered input. These algorithms set a NULL digest name which is + * then used inside EVP_DigestVerify() and EVP_DigestSign(). + */ +static int do_fp_oneshot_sign(BIO *out, EVP_MD_CTX *ctx, BIO *in, int sep, int binout, + EVP_PKEY *key, unsigned char *sigin, int siglen, + const char *sig_name, const char *file) +{ + int res, ret = EXIT_FAILURE; + size_t len = 0; + int buflen = 0; + int maxlen = 16 * 1024 * 1024; + uint8_t *buf = NULL, *sig = NULL; + + buflen = bio_to_mem(&buf, maxlen, in); + if (buflen <= 0) { + BIO_printf(bio_err, "Read error in %s\n", file); + return ret; + } + if (sigin != NULL) { + res = EVP_DigestVerify(ctx, sigin, siglen, buf, buflen); + print_verify_result(out, res); + if (res > 0) + ret = EXIT_SUCCESS; + goto end; + } + if (key != NULL) { + if (EVP_DigestSign(ctx, NULL, &len, buf, buflen) != 1) { + BIO_printf(bio_err, "Error getting maximum length of signed data\n"); + goto end; + } + sig = app_malloc(len, "Signature buffer"); + if (EVP_DigestSign(ctx, sig, &len, buf, buflen) != 1) { + BIO_printf(bio_err, "Error signing data\n"); + goto end; + } + print_out(out, sig, len, sep, binout, sig_name, NULL, file); + ret = EXIT_SUCCESS; + } else { + BIO_printf(bio_err, "key must be set for one-shot algorithms\n"); + goto end; + } + + end: + OPENSSL_free(sig); + OPENSSL_clear_free(buf, buflen); + + return ret; +} diff --git a/apps/dhparam.c b/apps/dhparam.c index 2a54dca9d8b5..600b7ed2b5bc 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -31,13 +31,14 @@ #define DEFBITS 2048 static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh); -static int gendh_cb(EVP_PKEY_CTX *ctx); + +static int verbose = 1; typedef enum OPTION_choice { OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT, - OPT_DSAPARAM, OPT_2, OPT_3, OPT_5, + OPT_DSAPARAM, OPT_2, OPT_3, OPT_5, OPT_VERBOSE, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -67,6 +68,8 @@ const OPTIONS dhparam_options[] = { {"2", OPT_2, '-', "Generate parameters using 2 as the generator value"}, {"3", OPT_3, '-', "Generate parameters using 3 as the generator value"}, {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"}, + {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"quiet", OPT_QUIET, '-', "Terse output"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -138,6 +141,12 @@ int dhparam_main(int argc, char **argv) case OPT_NOOUT: noout = 1; break; + case OPT_VERBOSE: + verbose = 1; + break; + case OPT_QUIET: + verbose = 0; + break; case OPT_R_CASES: if (!opt_rand(o)) goto end; @@ -155,7 +164,7 @@ int dhparam_main(int argc, char **argv) if (argc == 1) { if (!opt_int(argv[0], &num) || num <= 0) goto opthelp; - } else if (argc != 0) { + } else if (!opt_check_rest_arg(NULL)) { goto opthelp; } if (!app_RAND_load()) @@ -170,10 +179,6 @@ int dhparam_main(int argc, char **argv) goto end; } - out = bio_open_default(outfile, 'w', outformat); - if (out == NULL) - goto end; - /* DH parameters */ if (num && !g) g = 2; @@ -192,11 +197,13 @@ int dhparam_main(int argc, char **argv) alg); goto end; } - EVP_PKEY_CTX_set_cb(ctx, gendh_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); - BIO_printf(bio_err, - "Generating %s parameters, %d bit long %sprime\n", - alg, num, dsaparam ? "" : "safe "); + if (verbose) { + EVP_PKEY_CTX_set_cb(ctx, progress_cb); + BIO_printf(bio_err, + "Generating %s parameters, %d bit long %sprime\n", + alg, num, dsaparam ? "" : "safe "); + } if (EVP_PKEY_paramgen_init(ctx) <= 0) { BIO_printf(bio_err, @@ -274,7 +281,7 @@ int dhparam_main(int argc, char **argv) * because, unlike PEM, there is no header to declare what * the contents of the DER file are. The decoders just try * and guess. Unfortunately with DHX key types they may guess - * wrong and think we have a DSA keytype. Therefore we try + * wrong and think we have a DSA keytype. Therefore, we try * both DH and DHX sequentially. */ keytype = "DHX"; @@ -311,6 +318,10 @@ int dhparam_main(int argc, char **argv) } } + out = bio_open_default(outfile, 'w', outformat); + if (out == NULL) + goto end; + if (text) EVP_PKEY_print_params(out, pkey, 4, NULL); @@ -356,7 +367,7 @@ int dhparam_main(int argc, char **argv) } /* - * Historically we had the low level call DSA_dup_DH() to do this. + * Historically we had the low-level call DSA_dup_DH() to do this. * That is now deprecated with no replacement. Since we still need to do this * for backwards compatibility reasons, we do it "manually". */ @@ -405,14 +416,3 @@ static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh) return pkey; } -static int gendh_cb(EVP_PKEY_CTX *ctx) -{ - int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - static const char symbols[] = ".+*\n"; - char c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; -} diff --git a/apps/dsa.c b/apps/dsa.c index 51c02843539f..9ba8c252dafe 100644 --- a/apps/dsa.c +++ b/apps/dsa.c @@ -1,5 +1,5 @@ /* - * 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 @@ -92,6 +92,7 @@ int dsa_main(int argc, char **argv) int selection = 0; OSSL_ENCODER_CTX *ectx = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, dsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -161,17 +162,12 @@ int dsa_main(int argc, char **argv) } /* No extra args. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &enc)) - goto end; - } - private = pubin || pubout ? 0 : 1; - if (text && !pubin) - private = 1; + if (!opt_cipher(ciphername, &enc)) + goto end; + private = !pubin && (!pubout || text); if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); diff --git a/apps/dsaparam.c b/apps/dsaparam.c index ca91beb5b893..99fc3ee7b804 100644 --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -11,7 +11,6 @@ #include #include -#include "apps.h" #include #include #include "apps.h" @@ -25,17 +24,15 @@ static int verbose = 0; -static int gendsa_cb(EVP_PKEY_CTX *ctx); - typedef enum OPTION_choice { OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, - OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE, + OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS dsaparam_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits]\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] [numbits] [numqbits]\n"}, OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, @@ -53,13 +50,15 @@ const OPTIONS dsaparam_options[] = { {"text", OPT_TEXT, '-', "Print as text"}, {"noout", OPT_NOOUT, '-', "No output"}, {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"quiet", OPT_QUIET, '-', "Terse output"}, {"genkey", OPT_GENKEY, '-', "Generate a DSA key"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, OPT_PARAMETERS(), - {"numbits", 0, 0, "Number of bits if generating parameters (optional)"}, + {"numbits", 0, 0, "Number of bits if generating parameters or key (optional)"}, + {"numqbits", 0, 0, "Number of bits in the subprime parameter q if generating parameters or key (optional)"}, {NULL} }; @@ -69,7 +68,7 @@ int dsaparam_main(int argc, char **argv) BIO *out = NULL; EVP_PKEY *params = NULL, *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; - int numbits = -1, num = 0, genkey = 0; + int numbits = -1, numqbits = -1, num = 0, genkey = 0; int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, noout = 0; int ret = 1, i, text = 0, private = 0; char *infile = NULL, *outfile = NULL, *prog; @@ -124,16 +123,24 @@ int dsaparam_main(int argc, char **argv) case OPT_VERBOSE: verbose = 1; break; + case OPT_QUIET: + verbose = 0; + break; } } - /* Optional arg is bitsize. */ + /* Optional args are bitsize and q bitsize. */ argc = opt_num_rest(); argv = opt_rest(); - if (argc == 1) { + if (argc == 2) { if (!opt_int(argv[0], &num) || num < 0) goto opthelp; - } else if (argc != 0) { + if (!opt_int(argv[1], &numqbits) || numqbits < 0) + goto opthelp; + } else if (argc == 1) { + if (!opt_int(argv[0], &num) || num < 0) + goto opthelp; + } else if (!opt_check_rest_arg(NULL)) { goto opthelp; } if (!app_RAND_load()) @@ -143,10 +150,6 @@ int dsaparam_main(int argc, char **argv) numbits = num; private = genkey ? 1 : 0; - out = bio_open_owner(outfile, outformat, private); - if (out == NULL) - goto end; - ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DSA", app_get0_propq()); if (ctx == NULL) { BIO_printf(bio_err, @@ -160,9 +163,9 @@ int dsaparam_main(int argc, char **argv) " Your key size is %d! Larger key size may behave not as expected.\n", OPENSSL_DSA_MAX_MODULUS_BITS, numbits); - EVP_PKEY_CTX_set_cb(ctx, gendsa_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); if (verbose) { + EVP_PKEY_CTX_set_cb(ctx, progress_cb); BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); BIO_printf(bio_err, "This could take some time\n"); @@ -177,6 +180,13 @@ int dsaparam_main(int argc, char **argv) "Error, DSA key generation setting bit length failed\n"); goto end; } + if (numqbits > 0) { + if (EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, numqbits) <= 0) { + BIO_printf(bio_err, + "Error, DSA key generation setting subprime bit length failed\n"); + goto end; + } + } params = app_paramgen(ctx, "DSA"); } else { params = load_keyparams(infile, informat, 1, "DSA", "DSA parameters"); @@ -186,6 +196,10 @@ int dsaparam_main(int argc, char **argv) goto end; } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + if (text) { EVP_PKEY_print_params(out, params, 0, NULL); } @@ -237,22 +251,3 @@ int dsaparam_main(int argc, char **argv) release_engine(e); return ret; } - -static int gendsa_cb(EVP_PKEY_CTX *ctx) -{ - static const char symbols[] = ".+*\n"; - int p; - char c; - BIO *b; - - if (!verbose) - return 1; - - b = EVP_PKEY_CTX_get_app_data(ctx); - p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - c = (p >= 0 && (size_t)p < sizeof(symbols) - 1) ? symbols[p] : '?'; - - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; -} diff --git a/apps/ec.c b/apps/ec.c index e2dd6f2b48f3..677876ccc90e 100644 --- a/apps/ec.c +++ b/apps/ec.c @@ -1,5 +1,5 @@ /* - * 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 @@ -80,6 +80,7 @@ int ec_main(int argc, char **argv) char *point_format = NULL; int no_public = 0; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, ec_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -157,17 +158,12 @@ int ec_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &enc)) - goto opthelp; - } - private = param_out || pubin || pubout ? 0 : 1; - if (text && !pubin) - private = 1; + if (!opt_cipher(ciphername, &enc)) + goto opthelp; + private = !pubin && (text || (!param_out && !pubout)); if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); diff --git a/apps/ecparam.c b/apps/ecparam.c index 9e9ad136837b..f0879dfb11a9 100644 --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -67,13 +67,11 @@ const OPTIONS ecparam_options[] = { static int list_builtin_curves(BIO *out) { - int ret = 0; EC_builtin_curve *curves = NULL; size_t n, crv_len = EC_get_builtin_curves(NULL, 0); curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves"); - if (!EC_get_builtin_curves(curves, crv_len)) - goto end; + EC_get_builtin_curves(curves, crv_len); for (n = 0; n < crv_len; n++) { const char *comment = curves[n].comment; @@ -87,10 +85,8 @@ static int list_builtin_curves(BIO *out) BIO_printf(out, " %-10s: ", sname); BIO_printf(out, "%s\n", comment); } - ret = 1; -end: OPENSSL_free(curves); - return ret; + return 1; } int ecparam_main(int argc, char **argv) @@ -186,25 +182,24 @@ int ecparam_main(int argc, char **argv) } /* No extra args. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) goto end; - private = genkey ? 1 : 0; - - out = bio_open_owner(outfile, outformat, private); - if (out == NULL) - goto end; - if (list_curves) { + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + if (list_builtin_curves(out)) ret = 0; goto end; } + private = genkey ? 1 : 0; + if (curve_name != NULL) { OSSL_PARAM params[4]; OSSL_PARAM *p = params; @@ -243,9 +238,17 @@ int ecparam_main(int argc, char **argv) goto end; } } else { - params_key = load_keyparams(infile, informat, 1, "EC", "EC parameters"); - if (params_key == NULL || !EVP_PKEY_is_a(params_key, "EC")) + params_key = load_keyparams_suppress(infile, informat, 1, "EC", + "EC parameters", 1); + if (params_key == NULL) + params_key = load_keyparams_suppress(infile, informat, 1, "SM2", + "SM2 parameters", 1); + + if (params_key == NULL) { + BIO_printf(bio_err, "Unable to load parameters from %s\n", infile); goto end; + } + if (point_format && !EVP_PKEY_set_utf8_string_param( params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, @@ -269,8 +272,12 @@ int ecparam_main(int argc, char **argv) goto end; } + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + if (text - && !EVP_PKEY_print_params(out, params_key, 0, NULL)) { + && EVP_PKEY_print_params(out, params_key, 0, NULL) <= 0) { BIO_printf(bio_err, "unable to print params\n"); goto end; } diff --git a/apps/enc.c b/apps/enc.c index c275046cf57a..3f45ba15e576 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -49,7 +49,8 @@ typedef enum OPTION_choice { 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 + OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM, + OPT_SKEYOPT, OPT_SKEYMGMT } OPTION_CHOICE; const OPTIONS enc_options[] = { @@ -100,9 +101,13 @@ const OPTIONS enc_options[] = { {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 + {"saltlen", OPT_SALTLEN, 'p', "Specify the PBKDF2 salt length (in bytes)"}, + {OPT_MORE_STR, 0, 0, "Default: 16"}, +#ifndef OPENSSL_NO_ZLIB {"z", OPT_Z, '-', "Compress or decompress encrypted data using zlib"}, #endif + {"skeyopt", OPT_SKEYOPT, 's', "Key options as opt:value for opaque symmetric key handling"}, + {"skeymgmt", OPT_SKEYMGMT, 's', "Symmetric key management name for opaque symmetric key handling"}, {"", OPT_CIPHER, '-', "Any supported cipher"}, OPT_R_OPTIONS, @@ -132,26 +137,47 @@ int enc_main(int argc, char **argv) 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 rawkey_set = 0; + unsigned char *buff = NULL, salt[EVP_MAX_IV_LENGTH]; + int saltlen = 0; int pbkdf2 = 0; int iter = 0; long n; + int streamable = 1; + int wrap = 0; struct doall_enc_ciphers dec; -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB int do_zlib = 0; BIO *bzl = NULL; #endif + int do_brotli = 0; + BIO *bbrot = NULL; + int do_zstd = 0; + BIO *bzstd = NULL; + STACK_OF(OPENSSL_STRING) *skeyopts = NULL; + const char *skeymgmt = NULL; + EVP_SKEY *skey = NULL; + EVP_SKEYMGMT *mgmt = NULL; /* first check the command name */ if (strcmp(argv[0], "base64") == 0) base64 = 1; -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB else if (strcmp(argv[0], "zlib") == 0) do_zlib = 1; +#endif +#ifndef OPENSSL_NO_BROTLI + else if (strcmp(argv[0], "brotli") == 0) + do_brotli = 1; +#endif +#ifndef OPENSSL_NO_ZSTD + else if (strcmp(argv[0], "zstd") == 0) + do_zstd = 1; #endif else if (strcmp(argv[0], "enc") != 0) ciphername = argv[0]; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, enc_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -219,7 +245,7 @@ int enc_main(int argc, char **argv) base64 = 1; break; case OPT_Z: -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB do_zlib = 1; #endif break; @@ -278,6 +304,12 @@ int enc_main(int argc, char **argv) iter = opt_int_arg(); pbkdf2 = 1; break; + case OPT_SALTLEN: + if (!opt_int(opt_arg(), &saltlen)) + goto opthelp; + if (saltlen > (int)sizeof(salt)) + saltlen = (int)sizeof(salt); + break; case OPT_PBKDF2: pbkdf2 = 1; if (iter == 0) /* do not overwrite a chosen value */ @@ -286,6 +318,17 @@ int enc_main(int argc, char **argv) case OPT_NONE: cipher = NULL; break; + case OPT_SKEYOPT: + if ((skeyopts == NULL && + (skeyopts = sk_OPENSSL_STRING_new_null()) == NULL) || + sk_OPENSSL_STRING_push(skeyopts, opt_arg()) == 0) { + BIO_printf(bio_err, "%s: out of memory\n", prog); + goto end; + } + break; + case OPT_SKEYMGMT: + skeymgmt = opt_arg(); + break; case OPT_R_CASES: if (!opt_rand(o)) goto end; @@ -298,16 +341,19 @@ int enc_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) goto end; + if (saltlen == 0 || pbkdf2 == 0) + saltlen = PKCS5_SALT_LEN; /* Get the cipher name, either from progname (if set) or flag. */ - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &cipher)) - goto opthelp; + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; + if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_WRAP_MODE)) { + wrap = 1; + streamable = 0; } if (digestname != NULL) { if (!opt_md(digestname, &dgst)) @@ -325,20 +371,30 @@ int enc_main(int argc, char **argv) if (verbose) BIO_printf(bio_err, "bufsize=%d\n", bsize); -#ifdef ZLIB - if (!do_zlib) +#ifndef OPENSSL_NO_ZLIB + if (do_zlib) + base64 = 0; #endif - if (base64) { - if (enc) - outformat = FORMAT_BASE64; - else - informat = FORMAT_BASE64; - } + if (do_brotli) + base64 = 0; + if (do_zstd) + base64 = 0; + + 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) { + if (!streamable && printkey != 2) { /* if just print key and exit, it's ok */ + BIO_printf(bio_err, "Unstreamable cipher mode\n"); + goto end; + } in = dup_bio_in(informat); } else { in = bio_open_default(infile, 'r', informat); @@ -354,7 +410,7 @@ int enc_main(int argc, char **argv) str = pass; } - if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) { + if ((str == NULL) && (cipher != NULL) && (hkey == NULL) && (skeyopts == NULL)) { if (1) { #ifndef OPENSSL_NO_UI_CONSOLE for (;;) { @@ -399,7 +455,8 @@ int enc_main(int argc, char **argv) rbio = in; wbio = out; -#ifdef ZLIB +#ifndef OPENSSL_NO_COMP +# ifndef OPENSSL_NO_ZLIB if (do_zlib) { if ((bzl = BIO_new(BIO_f_zlib())) == NULL) goto end; @@ -412,6 +469,33 @@ int enc_main(int argc, char **argv) else rbio = BIO_push(bzl, rbio); } +# endif + + if (do_brotli) { + if ((bbrot = BIO_new(BIO_f_brotli())) == NULL) + goto end; + if (debug) { + BIO_set_callback_ex(bbrot, BIO_debug_callback_ex); + BIO_set_callback_arg(bbrot, (char *)bio_err); + } + if (enc) + wbio = BIO_push(bbrot, wbio); + else + rbio = BIO_push(bbrot, rbio); + } + + if (do_zstd) { + if ((bzstd = BIO_new(BIO_f_zstd())) == NULL) + goto end; + if (debug) { + BIO_set_callback_ex(bzstd, BIO_debug_callback_ex); + BIO_set_callback_arg(bzstd, (char *)bio_err); + } + if (enc) + wbio = BIO_push(bzstd, wbio); + else + rbio = BIO_push(bzstd, rbio); + } #endif if (base64) { @@ -442,13 +526,13 @@ int enc_main(int argc, char **argv) if (nosalt) { sptr = NULL; } else { - if (hsalt != NULL && !set_hex(hsalt, salt, sizeof(salt))) { + if (hsalt != NULL && !set_hex(hsalt, salt, saltlen)) { BIO_printf(bio_err, "invalid hex salt value\n"); goto end; } if (enc) { /* encryption */ if (hsalt == NULL) { - if (RAND_bytes(salt, sizeof(salt)) <= 0) { + if (RAND_bytes(salt, saltlen) <= 0) { BIO_printf(bio_err, "RAND_bytes failed\n"); goto end; } @@ -461,7 +545,7 @@ int enc_main(int argc, char **argv) sizeof(magic) - 1) != sizeof(magic) - 1 || BIO_write(wbio, (char *)salt, - sizeof(salt)) != sizeof(salt))) { + saltlen) != saltlen)) { BIO_printf(bio_err, "error writing output file\n"); goto end; } @@ -474,7 +558,7 @@ int enc_main(int argc, char **argv) } if (memcmp(mbuf, magic, sizeof(mbuf)) == 0) { /* file IS salted */ if (BIO_read(rbio, salt, - sizeof(salt)) != sizeof(salt)) { + saltlen) != saltlen) { BIO_printf(bio_err, "error reading input file\n"); goto end; } @@ -496,7 +580,8 @@ int enc_main(int argc, char **argv) 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); + int islen = (sptr != NULL ? saltlen : 0); + if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen, iter, dgst, iklen+ivlen, tmpkeyiv)) { BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n"); @@ -505,6 +590,7 @@ int enc_main(int argc, char **argv) /* split and move data back to global buffer */ memcpy(key, tmpkeyiv, iklen); memcpy(iv, tmpkeyiv+iklen, ivlen); + rawkey_set = 1; } else { BIO_printf(bio_err, "*** WARNING : " "deprecated key derivation used.\n" @@ -515,6 +601,7 @@ int enc_main(int argc, char **argv) BIO_printf(bio_err, "EVP_BytesToKey failed\n"); goto end; } + rawkey_set = 1; } /* * zero the complete buffer or the string passed from the command @@ -527,6 +614,7 @@ int enc_main(int argc, char **argv) } 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)) { @@ -535,7 +623,8 @@ int enc_main(int argc, char **argv) } } if ((hiv == NULL) && (str == NULL) - && EVP_CIPHER_get_iv_length(cipher) != 0) { + && EVP_CIPHER_get_iv_length(cipher) != 0 + && wrap == 0) { /* * No IV was explicitly set and no IV was generated. * Hence the IV is undefined, making correct decryption impossible. @@ -550,6 +639,16 @@ int enc_main(int argc, char **argv) } /* wiping secret data as we no longer need it */ cleanse(hkey); + rawkey_set = 1; + } + + /* + * At this moment we know whether we trying to use raw bytes as the key + * or an opaque symmetric key. We do not allow both options simultaneously. + */ + if (rawkey_set > 0 && skeyopts != NULL) { + BIO_printf(bio_err, "Either a raw key or the 'skeyopt' args must be used.\n"); + goto end; } if ((benc = BIO_new(BIO_f_cipher())) == NULL) @@ -562,23 +661,54 @@ int enc_main(int argc, char **argv) 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 (wrap == 1) + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + if (rawkey_set) { + if (!EVP_CipherInit_ex(ctx, cipher, e, key, + (hiv == NULL && wrap == 1 ? NULL : iv), enc)) { + BIO_printf(bio_err, "Error setting cipher %s\n", + EVP_CIPHER_get0_name(cipher)); + ERR_print_errors(bio_err); + goto end; + } + } else { + OSSL_PARAM *params = NULL; + + mgmt = EVP_SKEYMGMT_fetch(app_get0_libctx(), + skeymgmt != NULL ? skeymgmt : EVP_CIPHER_name(cipher), + app_get0_propq()); + if (mgmt == NULL) + goto end; + + params = app_params_new_from_opts(skeyopts, + EVP_SKEYMGMT_get0_imp_settable_params(mgmt)); + if (params == NULL) + goto end; + + skey = EVP_SKEY_import(app_get0_libctx(), EVP_SKEYMGMT_get0_name(mgmt), + app_get0_propq(), OSSL_SKEYMGMT_SELECT_ALL, params); + OSSL_PARAM_free(params); + if (skey == NULL) { + BIO_printf(bio_err, "Error creating opaque key object for skeymgmt %s\n", + skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher)); + ERR_print_errors(bio_err); + goto end; + } + + if (!EVP_CipherInit_SKEY(ctx, cipher, skey, + (hiv == NULL && wrap == 1 ? NULL : iv), + EVP_CIPHER_get_iv_length(cipher), enc, NULL)) { + BIO_printf(bio_err, "Error setting an opaque key for 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); @@ -587,7 +717,7 @@ int enc_main(int argc, char **argv) if (printkey) { if (!nosalt) { printf("salt="); - for (i = 0; i < (int)sizeof(salt); i++) + for (i = 0; i < (int)saltlen; i++) printf("%02X", salt[i]); printf("\n"); } @@ -618,10 +748,16 @@ int enc_main(int argc, char **argv) inl = BIO_read(rbio, (char *)buff, bsize); if (inl <= 0) break; + if (!streamable && !BIO_eof(rbio)) { /* do not output data */ + BIO_printf(bio_err, "Unstreamable cipher mode\n"); + goto end; + } if (BIO_write(wbio, (char *)buff, inl) != inl) { BIO_printf(bio_err, "error writing output file\n"); goto end; } + if (!streamable) + break; } if (!BIO_flush(wbio)) { if (enc) @@ -638,6 +774,9 @@ int enc_main(int argc, char **argv) } end: ERR_print_errors(bio_err); + sk_OPENSSL_STRING_free(skeyopts); + EVP_SKEYMGMT_free(mgmt); + EVP_SKEY_free(skey); OPENSSL_free(strbuf); OPENSSL_free(buff); BIO_free(in); @@ -646,9 +785,11 @@ int enc_main(int argc, char **argv) BIO_free(b64); EVP_MD_free(dgst); EVP_CIPHER_free(cipher); -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB BIO_free(bzl); #endif + BIO_free(bbrot); + BIO_free(bzstd); release_engine(e); OPENSSL_free(pass); return ret; diff --git a/apps/engine.c b/apps/engine.c index c83bdfc150c3..edd787514882 100644 --- a/apps/engine.c +++ b/apps/engine.c @@ -251,7 +251,7 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds, cmd = sk_OPENSSL_STRING_value(cmds, loop); res = 1; /* assume success */ /* Check if this command has no ":arg" */ - if ((arg = strstr(cmd, ":")) == NULL) { + if ((arg = strchr(cmd, ':')) == NULL) { if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0)) res = 0; } else { @@ -316,7 +316,8 @@ int engine_main(int argc, char **argv) * names, and then setup to parse the rest of the line as flags. */ prog = argv[0]; while ((argv1 = argv[1]) != NULL && *argv1 != '-') { - sk_OPENSSL_CSTRING_push(engines, argv1); + if (!sk_OPENSSL_CSTRING_push(engines, argv1)) + goto end; argc--; argv++; } @@ -347,7 +348,7 @@ int engine_main(int argc, char **argv) break; case OPT_TT: test_avail_noise++; - /* fall thru */ + /* fall through */ case OPT_T: test_avail++; break; @@ -372,12 +373,14 @@ int engine_main(int argc, char **argv) BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; } - sk_OPENSSL_CSTRING_push(engines, *argv); + if (!sk_OPENSSL_CSTRING_push(engines, *argv)) + goto end; } if (sk_OPENSSL_CSTRING_num(engines) == 0) { for (e = ENGINE_get_first(); e != NULL; e = ENGINE_get_next(e)) { - sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e)); + if (!sk_OPENSSL_CSTRING_push(engines, ENGINE_get_id(e))) + goto end; } } @@ -407,6 +410,9 @@ int engine_main(int argc, char **argv) if (ENGINE_get_RSA(e) != NULL && !append_buf(&cap_buf, &cap_size, "RSA")) goto end; + if (ENGINE_get_EC(e) != NULL + && !append_buf(&cap_buf, &cap_size, "EC")) + goto end; if (ENGINE_get_DSA(e) != NULL && !append_buf(&cap_buf, &cap_size, "DSA")) goto end; diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c index d0efdf7643bd..0daa55a1b8ae 100644 --- a/apps/fipsinstall.c +++ b/apps/fipsinstall.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,6 @@ * https://www.openssl.org/source/license.html */ -#include #include #include #include @@ -34,38 +33,116 @@ static int quiet = 0; typedef enum OPTION_choice { OPT_COMMON, - OPT_IN, OPT_OUT, OPT_MODULE, + OPT_IN, OPT_OUT, OPT_MODULE, OPT_PEDANTIC, OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY, OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG, OPT_NO_CONDITIONAL_ERRORS, OPT_NO_SECURITY_CHECKS, - OPT_SELF_TEST_ONLOAD + OPT_TLS_PRF_EMS_CHECK, OPT_NO_SHORT_MAC, + OPT_DISALLOW_PKCS15_PADDING, OPT_RSA_PSS_SALTLEN_CHECK, + OPT_DISALLOW_SIGNATURE_X931_PADDING, + OPT_HMAC_KEY_CHECK, OPT_KMAC_KEY_CHECK, + OPT_DISALLOW_DRGB_TRUNC_DIGEST, + OPT_SIGNATURE_DIGEST_CHECK, + OPT_HKDF_DIGEST_CHECK, + OPT_TLS13_KDF_DIGEST_CHECK, + OPT_TLS1_PRF_DIGEST_CHECK, + OPT_SSHKDF_DIGEST_CHECK, + OPT_SSKDF_DIGEST_CHECK, + OPT_X963KDF_DIGEST_CHECK, + OPT_DISALLOW_DSA_SIGN, + OPT_DISALLOW_TDES_ENCRYPT, + OPT_HKDF_KEY_CHECK, + OPT_KBKDF_KEY_CHECK, + OPT_TLS13_KDF_KEY_CHECK, + OPT_TLS1_PRF_KEY_CHECK, + OPT_SSHKDF_KEY_CHECK, + OPT_SSKDF_KEY_CHECK, + OPT_X963KDF_KEY_CHECK, + OPT_X942KDF_KEY_CHECK, + OPT_NO_PBKDF2_LOWER_BOUND_CHECK, + OPT_ECDH_COFACTOR_CHECK, + OPT_SELF_TEST_ONLOAD, OPT_SELF_TEST_ONINSTALL } OPTION_CHOICE; const OPTIONS fipsinstall_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"pedantic", OPT_PEDANTIC, '-', "Set options for strict FIPS compliance"}, {"verify", OPT_VERIFY, '-', - "Verify a config file instead of generating one"}, + "Verify a config file instead of generating one"}, {"module", OPT_MODULE, '<', "File name of the provider module"}, {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"}, {"section_name", OPT_SECTION_NAME, 's', "FIPS Provider config section name (optional)"}, - {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-', - "Disable the ability of the fips module to enter an error state if" - " any conditional self tests fail"}, + {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-', + "Disable the ability of the fips module to enter an error state if" + " any conditional self tests fail"}, {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-', "Disable the run-time FIPS security checks in the module"}, {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-', "Forces self tests to always run on module load"}, + {"self_test_oninstall", OPT_SELF_TEST_ONINSTALL, '-', + "Forces self tests to run once on module installation"}, + {"ems_check", OPT_TLS_PRF_EMS_CHECK, '-', + "Enable the run-time FIPS check for EMS during TLS1_PRF"}, + {"no_short_mac", OPT_NO_SHORT_MAC, '-', "Disallow short MAC output"}, + {"no_drbg_truncated_digests", OPT_DISALLOW_DRGB_TRUNC_DIGEST, '-', + "Disallow truncated digests with Hash and HMAC DRBGs"}, + {"signature_digest_check", OPT_SIGNATURE_DIGEST_CHECK, '-', + "Enable checking for approved digests for signatures"}, + {"hmac_key_check", OPT_HMAC_KEY_CHECK, '-', "Enable key check for HMAC"}, + {"kmac_key_check", OPT_KMAC_KEY_CHECK, '-', "Enable key check for KMAC"}, + {"hkdf_digest_check", OPT_HKDF_DIGEST_CHECK, '-', + "Enable digest check for HKDF"}, + {"tls13_kdf_digest_check", OPT_TLS13_KDF_DIGEST_CHECK, '-', + "Enable digest check for TLS13-KDF"}, + {"tls1_prf_digest_check", OPT_TLS1_PRF_DIGEST_CHECK, '-', + "Enable digest check for TLS1-PRF"}, + {"sshkdf_digest_check", OPT_SSHKDF_DIGEST_CHECK, '-', + "Enable digest check for SSHKDF"}, + {"sskdf_digest_check", OPT_SSKDF_DIGEST_CHECK, '-', + "Enable digest check for SSKDF"}, + {"x963kdf_digest_check", OPT_X963KDF_DIGEST_CHECK, '-', + "Enable digest check for X963KDF"}, + {"dsa_sign_disabled", OPT_DISALLOW_DSA_SIGN, '-', + "Disallow DSA signing"}, + {"tdes_encrypt_disabled", OPT_DISALLOW_TDES_ENCRYPT, '-', + "Disallow Triple-DES encryption"}, + {"rsa_pkcs15_padding_disabled", OPT_DISALLOW_PKCS15_PADDING, '-', + "Disallow PKCS#1 version 1.5 padding for RSA encryption"}, + {"rsa_pss_saltlen_check", OPT_RSA_PSS_SALTLEN_CHECK, '-', + "Enable salt length check for RSA-PSS signature operations"}, + {"rsa_sign_x931_disabled", OPT_DISALLOW_SIGNATURE_X931_PADDING, '-', + "Disallow X931 Padding for RSA signing"}, + {"hkdf_key_check", OPT_HKDF_KEY_CHECK, '-', + "Enable key check for HKDF"}, + {"kbkdf_key_check", OPT_KBKDF_KEY_CHECK, '-', + "Enable key check for KBKDF"}, + {"tls13_kdf_key_check", OPT_TLS13_KDF_KEY_CHECK, '-', + "Enable key check for TLS13-KDF"}, + {"tls1_prf_key_check", OPT_TLS1_PRF_KEY_CHECK, '-', + "Enable key check for TLS1-PRF"}, + {"sshkdf_key_check", OPT_SSHKDF_KEY_CHECK, '-', + "Enable key check for SSHKDF"}, + {"sskdf_key_check", OPT_SSKDF_KEY_CHECK, '-', + "Enable key check for SSKDF"}, + {"x963kdf_key_check", OPT_X963KDF_KEY_CHECK, '-', + "Enable key check for X963KDF"}, + {"x942kdf_key_check", OPT_X942KDF_KEY_CHECK, '-', + "Enable key check for X942KDF"}, + {"no_pbkdf2_lower_bound_check", OPT_NO_PBKDF2_LOWER_BOUND_CHECK, '-', + "Disable lower bound check for PBKDF2"}, + {"ecdh_cofactor_check", OPT_ECDH_COFACTOR_CHECK, '-', + "Enable Cofactor check for ECDH"}, OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input config file, used when verifying"}, OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output config file, used when generating"}, {"mac_name", OPT_MAC_NAME, 's', "MAC name"}, - {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form. " - "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, + {"macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form."}, + {OPT_MORE_STR, 0, 0, "See 'PARAMETER NAMES' in the EVP_MAC_ docs"}, {"noout", OPT_NO_LOG, '-', "Disable logging of self test events"}, {"corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description"}, {"corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type"}, @@ -74,6 +151,116 @@ const OPTIONS fipsinstall_options[] = { {NULL} }; +typedef struct { + unsigned int self_test_onload : 1; + unsigned int conditional_errors : 1; + unsigned int security_checks : 1; + unsigned int hmac_key_check : 1; + unsigned int kmac_key_check : 1; + unsigned int tls_prf_ems_check : 1; + unsigned int no_short_mac : 1; + unsigned int drgb_no_trunc_dgst : 1; + unsigned int signature_digest_check : 1; + unsigned int hkdf_digest_check : 1; + unsigned int tls13_kdf_digest_check : 1; + unsigned int tls1_prf_digest_check : 1; + unsigned int sshkdf_digest_check : 1; + unsigned int sskdf_digest_check : 1; + unsigned int x963kdf_digest_check : 1; + unsigned int dsa_sign_disabled : 1; + unsigned int tdes_encrypt_disabled : 1; + unsigned int rsa_pkcs15_padding_disabled : 1; + unsigned int rsa_pss_saltlen_check : 1; + unsigned int sign_x931_padding_disabled : 1; + unsigned int hkdf_key_check : 1; + unsigned int kbkdf_key_check : 1; + unsigned int tls13_kdf_key_check : 1; + unsigned int tls1_prf_key_check : 1; + unsigned int sshkdf_key_check : 1; + unsigned int sskdf_key_check : 1; + unsigned int x963kdf_key_check : 1; + unsigned int x942kdf_key_check : 1; + unsigned int pbkdf2_lower_bound_check : 1; + unsigned int ecdh_cofactor_check : 1; +} FIPS_OPTS; + +/* Pedantic FIPS compliance */ +static const FIPS_OPTS pedantic_opts = { + 1, /* self_test_onload */ + 1, /* conditional_errors */ + 1, /* security_checks */ + 1, /* hmac_key_check */ + 1, /* kmac_key_check */ + 1, /* tls_prf_ems_check */ + 1, /* no_short_mac */ + 1, /* drgb_no_trunc_dgst */ + 1, /* signature_digest_check */ + 1, /* hkdf_digest_check */ + 1, /* tls13_kdf_digest_check */ + 1, /* tls1_prf_digest_check */ + 1, /* sshkdf_digest_check */ + 1, /* sskdf_digest_check */ + 1, /* x963kdf_digest_check */ + 1, /* dsa_sign_disabled */ + 1, /* tdes_encrypt_disabled */ + 1, /* rsa_pkcs15_padding_disabled */ + 1, /* rsa_pss_saltlen_check */ + 1, /* sign_x931_padding_disabled */ + 1, /* hkdf_key_check */ + 1, /* kbkdf_key_check */ + 1, /* tls13_kdf_key_check */ + 1, /* tls1_prf_key_check */ + 1, /* sshkdf_key_check */ + 1, /* sskdf_key_check */ + 1, /* x963kdf_key_check */ + 1, /* x942kdf_key_check */ + 1, /* pbkdf2_lower_bound_check */ + 1, /* ecdh_cofactor_check */ +}; + +/* Default FIPS settings for backward compatibility */ +static FIPS_OPTS fips_opts = { + 1, /* self_test_onload */ + 1, /* conditional_errors */ + 1, /* security_checks */ + 0, /* hmac_key_check */ + 0, /* kmac_key_check */ + 0, /* tls_prf_ems_check */ + 0, /* no_short_mac */ + 0, /* drgb_no_trunc_dgst */ + 0, /* signature_digest_check */ + 0, /* hkdf_digest_check */ + 0, /* tls13_kdf_digest_check */ + 0, /* tls1_prf_digest_check */ + 0, /* sshkdf_digest_check */ + 0, /* sskdf_digest_check */ + 0, /* x963kdf_digest_check */ + 0, /* dsa_sign_disabled */ + 0, /* tdes_encrypt_disabled */ + 0, /* rsa_pkcs15_padding_disabled */ + 0, /* rsa_pss_saltlen_check */ + 0, /* sign_x931_padding_disabled */ + 0, /* hkdf_key_check */ + 0, /* kbkdf_key_check */ + 0, /* tls13_kdf_key_check */ + 0, /* tls1_prf_key_check */ + 0, /* sshkdf_key_check */ + 0, /* sskdf_key_check */ + 0, /* x963kdf_key_check */ + 0, /* x942kdf_key_check */ + 1, /* pbkdf2_lower_bound_check */ + 0, /* ecdh_cofactor_check */ +}; + +static int check_non_pedantic_fips(int pedantic, const char *name) +{ + if (pedantic) { + BIO_printf(bio_err, "Cannot specify -%s after -pedantic\n", name); + return 0; + } + return 1; +} + static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in, unsigned char *out, size_t *out_len) { @@ -97,16 +284,47 @@ err: return ret; } -static int load_fips_prov_and_run_self_test(const char *prov_name) +static int load_fips_prov_and_run_self_test(const char *prov_name, + int *is_fips_140_2_prov) { int ret = 0; OSSL_PROVIDER *prov = NULL; + OSSL_PARAM params[4], *p = params; + char *name = "", *vers = "", *build = ""; prov = OSSL_PROVIDER_load(NULL, prov_name); if (prov == NULL) { BIO_printf(bio_err, "Failed to load FIPS module\n"); goto end; } + if (!quiet) { + *p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME, + &name, sizeof(name)); + *p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, + &vers, sizeof(vers)); + *p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO, + &build, sizeof(build)); + *p = OSSL_PARAM_construct_end(); + if (!OSSL_PROVIDER_get_params(prov, params)) { + BIO_printf(bio_err, "Failed to query FIPS module parameters\n"); + goto end; + } + if (OSSL_PARAM_modified(params)) + BIO_printf(bio_err, "\t%-10s\t%s\n", "name:", name); + if (OSSL_PARAM_modified(params + 1)) + BIO_printf(bio_err, "\t%-10s\t%s\n", "version:", vers); + if (OSSL_PARAM_modified(params + 2)) + BIO_printf(bio_err, "\t%-10s\t%s\n", "build:", build); + } else { + *p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, + &vers, sizeof(vers)); + *p = OSSL_PARAM_construct_end(); + if (!OSSL_PROVIDER_get_params(prov, params)) { + BIO_printf(bio_err, "Failed to query FIPS module parameters\n"); + goto end; + } + } + *is_fips_140_2_prov = (strncmp("3.0.", vers, 4) == 0); ret = 1; end: OSSL_PROVIDER_unload(prov); @@ -147,8 +365,7 @@ static int write_config_header(BIO *out, const char *prov_name, static int write_config_fips_section(BIO *out, const char *section, unsigned char *module_mac, size_t module_mac_len, - int conditional_errors, - int security_checks, + const FIPS_OPTS *opts, unsigned char *install_mac, size_t install_mac_len) { @@ -159,19 +376,84 @@ static int write_config_fips_section(BIO *out, const char *section, || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, VERSION_VAL) <= 0 || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS, - conditional_errors ? "1" : "0") <= 0 - || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS, - security_checks ? "1" : "0") <= 0 + opts->conditional_errors ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SECURITY_CHECKS, + opts->security_checks ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HMAC_KEY_CHECK, + opts->hmac_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_KMAC_KEY_CHECK, + opts->kmac_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK, + opts->tls_prf_ems_check ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_NO_SHORT_MAC, + opts->no_short_mac ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST, + opts->drgb_no_trunc_dgst ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SIGNATURE_DIGEST_CHECK, + opts->signature_digest_check ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HKDF_DIGEST_CHECK, + opts->hkdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_TLS13_KDF_DIGEST_CHECK, + opts->tls13_kdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_TLS1_PRF_DIGEST_CHECK, + opts->tls1_prf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_SSHKDF_DIGEST_CHECK, + opts->sshkdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSKDF_DIGEST_CHECK, + opts->sskdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_X963KDF_DIGEST_CHECK, + opts->x963kdf_digest_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_DSA_SIGN_DISABLED, + opts->dsa_sign_disabled ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED, + opts->tdes_encrypt_disabled ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_RSA_PKCS15_PAD_DISABLED, + opts->rsa_pkcs15_padding_disabled ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_RSA_PSS_SALTLEN_CHECK, + opts->rsa_pss_saltlen_check ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_RSA_SIGN_X931_PAD_DISABLED, + opts->sign_x931_padding_disabled ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HKDF_KEY_CHECK, + opts->hkdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_KBKDF_KEY_CHECK, + opts->kbkdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_TLS13_KDF_KEY_CHECK, + opts->tls13_kdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TLS1_PRF_KEY_CHECK, + opts->tls1_prf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSHKDF_KEY_CHECK, + opts->sshkdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSKDF_KEY_CHECK, + opts->sskdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X963KDF_KEY_CHECK, + opts->x963kdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X942KDF_KEY_CHECK, + opts->x942kdf_key_check ? "1": "0") <= 0 + || BIO_printf(out, "%s = %s\n", + OSSL_PROV_PARAM_PBKDF2_LOWER_BOUND_CHECK, + opts->pbkdf2_lower_bound_check ? "1" : "0") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_ECDH_COFACTOR_CHECK, + opts->ecdh_cofactor_check ? "1": "0") <= 0 || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, module_mac_len)) goto end; - if (install_mac != NULL && install_mac_len > 0) { + if (install_mac != NULL + && install_mac_len > 0 + && opts->self_test_onload == 0) { if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac, install_mac_len) || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS, INSTALL_STATUS_VAL) <= 0) - goto end; + goto end; } ret = 1; end: @@ -182,21 +464,18 @@ static CONF *generate_config_and_load(const char *prov_name, const char *section, unsigned char *module_mac, size_t module_mac_len, - int conditional_errors, - int security_checks) + const FIPS_OPTS *opts) { BIO *mem_bio = NULL; CONF *conf = NULL; mem_bio = BIO_new(BIO_s_mem()); - if (mem_bio == NULL) + if (mem_bio == NULL) return 0; if (!write_config_header(mem_bio, prov_name, section) - || !write_config_fips_section(mem_bio, section, - module_mac, module_mac_len, - conditional_errors, - security_checks, - NULL, 0)) + || !write_config_fips_section(mem_bio, section, + module_mac, module_mac_len, + opts, NULL, 0)) goto end; conf = app_load_config_bio(mem_bio, NULL); @@ -291,8 +570,8 @@ end: int fipsinstall_main(int argc, char **argv) { - int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 0; - int enable_conditional_errors = 1, enable_security_checks = 1; + int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, pedantic = 0; + int is_fips_140_2_prov = 0, set_selftest_onload_option = 0; const char *section_name = "fips_sect"; const char *mac_name = "HMAC"; const char *prov_name = "fips"; @@ -319,7 +598,7 @@ int fipsinstall_main(int argc, char **argv) switch (o) { case OPT_EOF: case OPT_ERR: -opthelp: + opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto cleanup; case OPT_HELP: @@ -332,11 +611,102 @@ opthelp: case OPT_OUT: out_fname = opt_arg(); break; + case OPT_PEDANTIC: + fips_opts = pedantic_opts; + pedantic = 1; + break; case OPT_NO_CONDITIONAL_ERRORS: - enable_conditional_errors = 0; + if (!check_non_pedantic_fips(pedantic, "no_conditional_errors")) + goto end; + fips_opts.conditional_errors = 0; break; case OPT_NO_SECURITY_CHECKS: - enable_security_checks = 0; + if (!check_non_pedantic_fips(pedantic, "no_security_checks")) + goto end; + fips_opts.security_checks = 0; + break; + case OPT_HMAC_KEY_CHECK: + fips_opts.hmac_key_check = 1; + break; + case OPT_KMAC_KEY_CHECK: + fips_opts.kmac_key_check = 1; + break; + case OPT_TLS_PRF_EMS_CHECK: + fips_opts.tls_prf_ems_check = 1; + break; + case OPT_NO_SHORT_MAC: + fips_opts.no_short_mac = 1; + break; + case OPT_DISALLOW_DRGB_TRUNC_DIGEST: + fips_opts.drgb_no_trunc_dgst = 1; + break; + case OPT_SIGNATURE_DIGEST_CHECK: + fips_opts.signature_digest_check = 1; + break; + case OPT_HKDF_DIGEST_CHECK: + fips_opts.hkdf_digest_check = 1; + break; + case OPT_TLS13_KDF_DIGEST_CHECK: + fips_opts.tls13_kdf_digest_check = 1; + break; + case OPT_TLS1_PRF_DIGEST_CHECK: + fips_opts.tls1_prf_digest_check = 1; + break; + case OPT_SSHKDF_DIGEST_CHECK: + fips_opts.sshkdf_digest_check = 1; + break; + case OPT_SSKDF_DIGEST_CHECK: + fips_opts.sskdf_digest_check = 1; + break; + case OPT_X963KDF_DIGEST_CHECK: + fips_opts.x963kdf_digest_check = 1; + break; + case OPT_DISALLOW_DSA_SIGN: + fips_opts.dsa_sign_disabled = 1; + break; + case OPT_DISALLOW_TDES_ENCRYPT: + fips_opts.tdes_encrypt_disabled = 1; + break; + case OPT_RSA_PSS_SALTLEN_CHECK: + fips_opts.rsa_pss_saltlen_check = 1; + break; + case OPT_DISALLOW_SIGNATURE_X931_PADDING: + fips_opts.sign_x931_padding_disabled = 1; + break; + case OPT_DISALLOW_PKCS15_PADDING: + fips_opts.rsa_pkcs15_padding_disabled = 1; + break; + case OPT_HKDF_KEY_CHECK: + fips_opts.hkdf_key_check = 1; + break; + case OPT_KBKDF_KEY_CHECK: + fips_opts.kbkdf_key_check = 1; + break; + case OPT_TLS13_KDF_KEY_CHECK: + fips_opts.tls13_kdf_key_check = 1; + break; + case OPT_TLS1_PRF_KEY_CHECK: + fips_opts.tls1_prf_key_check = 1; + break; + case OPT_SSHKDF_KEY_CHECK: + fips_opts.sshkdf_key_check = 1; + break; + case OPT_SSKDF_KEY_CHECK: + fips_opts.sskdf_key_check = 1; + break; + case OPT_X963KDF_KEY_CHECK: + fips_opts.x963kdf_key_check = 1; + break; + case OPT_X942KDF_KEY_CHECK: + fips_opts.x942kdf_key_check = 1; + break; + case OPT_NO_PBKDF2_LOWER_BOUND_CHECK: + if (!check_non_pedantic_fips(pedantic, "no_pbkdf2_lower_bound_check")) + goto end; + fips_opts.pbkdf2_lower_bound_check = 0; + break; + case OPT_ECDH_COFACTOR_CHECK: + fips_opts.ecdh_cofactor_check = 1; break; case OPT_QUIET: quiet = 1; @@ -368,32 +738,43 @@ opthelp: case OPT_MACOPT: if (!sk_OPENSSL_STRING_push(opts, opt_arg())) goto opthelp; - if (strncmp(opt_arg(), "hexkey:", 7) == 0) + if (HAS_PREFIX(opt_arg(), "hexkey:")) gotkey = 1; - else if (strncmp(opt_arg(), "digest:", 7) == 0) + else if (HAS_PREFIX(opt_arg(), "digest:")) gotdigest = 1; break; case OPT_VERIFY: verify = 1; break; case OPT_SELF_TEST_ONLOAD: - self_test_onload = 1; + set_selftest_onload_option = 1; + fips_opts.self_test_onload = 1; + break; + case OPT_SELF_TEST_ONINSTALL: + if (!check_non_pedantic_fips(pedantic, "self_test_oninstall")) + goto end; + set_selftest_onload_option = 1; + fips_opts.self_test_onload = 0; break; } } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0 || (verify && in_fname == NULL)) + if (!opt_check_rest_arg(NULL)) goto opthelp; + if (verify && in_fname == NULL) { + BIO_printf(bio_err, "Missing -in option for -verify\n"); + goto opthelp; + } if (parent_config != NULL) { /* Test that a parent config can load the module */ if (verify_module_load(parent_config)) { ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1; - if (!quiet) + if (!quiet) { BIO_printf(bio_err, "FIPS provider is %s\n", - ret == 0 ? "available" : " not available"); + ret == 0 ? "available" : "not available"); + } } goto end; } @@ -470,36 +851,43 @@ opthelp: if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len)) goto end; - if (self_test_onload == 0) { - mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL, - strlen(INSTALL_STATUS_VAL)); - if (mem_bio == NULL) { - BIO_printf(bio_err, "Unable to create memory BIO\n"); - goto end; - } - if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len)) - goto end; - } else { - install_mac_len = 0; + /* Calculate the MAC for the indicator status - it may not be used */ + mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL, + strlen(INSTALL_STATUS_VAL)); + if (mem_bio == NULL) { + BIO_printf(bio_err, "Unable to create memory BIO\n"); + goto end; } + if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len)) + goto end; if (verify) { + if (fips_opts.self_test_onload == 1) + install_mac_len = 0; if (!verify_config(in_fname, section_name, module_mac, module_mac_len, install_mac, install_mac_len)) goto end; if (!quiet) BIO_printf(bio_err, "VERIFY PASSED\n"); } else { - conf = generate_config_and_load(prov_name, section_name, module_mac, - module_mac_len, - enable_conditional_errors, - enable_security_checks); + module_mac_len, &fips_opts); if (conf == NULL) goto end; - if (!load_fips_prov_and_run_self_test(prov_name)) + if (!load_fips_prov_and_run_self_test(prov_name, &is_fips_140_2_prov)) goto end; + /* + * In OpenSSL 3.1 the code was changed so that the status indicator is + * not written out by default since this is a FIPS 140-3 requirement. + * For backwards compatibility - if the detected FIPS provider is 3.0.X + * (Which was a FIPS 140-2 validation), then the indicator status will + * be written to the config file unless 'self_test_onload' is set on the + * command line. + */ + if (set_selftest_onload_option == 0 && is_fips_140_2_prov) + fips_opts.self_test_onload = 0; + fout = out_fname == NULL ? dup_bio_out(FORMAT_TEXT) : bio_open_default(out_fname, 'w', FORMAT_TEXT); @@ -507,10 +895,9 @@ opthelp: BIO_printf(bio_err, "Failed to open file\n"); goto end; } + if (!write_config_fips_section(fout, section_name, - module_mac, module_mac_len, - enable_conditional_errors, - enable_security_checks, + module_mac, module_mac_len, &fips_opts, install_mac, install_mac_len)) goto end; if (!quiet) diff --git a/apps/gendsa.c b/apps/gendsa.c index 8aefca65566c..a655c6ea02b2 100644 --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -24,7 +24,7 @@ typedef enum OPTION_choice { OPT_COMMON, - OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE, + OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -44,6 +44,7 @@ const OPTIONS gendsa_options[] = { OPT_PROV_OPTIONS, {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"quiet", OPT_QUIET, '-', "Terse output"}, OPT_PARAMETERS(), {"dsaparam-file", 0, 0, "File containing DSA parameters"}, @@ -62,6 +63,7 @@ int gendsa_main(int argc, char **argv) OPTION_CHOICE o; int ret = 1, private = 0, verbose = 0, nbits; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, gendsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -97,23 +99,23 @@ int gendsa_main(int argc, char **argv) case OPT_VERBOSE: verbose = 1; break; + case OPT_QUIET: + verbose = 0; + break; } } /* One argument, the params file. */ - argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 1) + if (!opt_check_rest_arg("params file")) goto opthelp; + argv = opt_rest(); dsaparams = argv[0]; if (!app_RAND_load()) goto end; - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &enc)) - goto end; - } + if (!opt_cipher(ciphername, &enc)) + goto end; private = 1; if (!app_passwd(NULL, passoutarg, NULL, &passout)) { diff --git a/apps/genpkey.c b/apps/genpkey.c index 705e5c76b47d..eaca1e0dea63 100644 --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,18 +15,16 @@ #include #include -static int quiet; +static int verbose = 1; static int init_keygen_file(EVP_PKEY_CTX **pctx, const char *file, ENGINE *e, OSSL_LIB_CTX *libctx, const char *propq); -static int genpkey_cb(EVP_PKEY_CTX *ctx); - typedef enum OPTION_choice { OPT_COMMON, OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE, OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER, - OPT_QUIET, OPT_CONFIG, - OPT_PROV_ENUM + OPT_VERBOSE, OPT_QUIET, OPT_CONFIG, OPT_OUTPUBKEY, + OPT_PROV_ENUM, OPT_R_ENUM } OPTION_CHOICE; const OPTIONS genpkey_options[] = { @@ -37,20 +35,23 @@ const OPTIONS genpkey_options[] = { #endif {"paramfile", OPT_PARAMFILE, '<', "Parameters file"}, {"algorithm", OPT_ALGORITHM, 's', "The public key algorithm"}, + {"verbose", OPT_VERBOSE, '-', "Output status while generating keys"}, {"quiet", OPT_QUIET, '-', "Do not output status while generating keys"}, {"pkeyopt", OPT_PKEYOPT, 's', "Set the public key algorithm option as opt:value"}, OPT_CONFIG_OPTION, OPT_SECTION("Output"), - {"out", OPT_OUT, '>', "Output file"}, + {"out", OPT_OUT, '>', "Output (private key) file"}, + {"outpubkey", OPT_OUTPUBKEY, '>', "Output public key file"}, {"outform", OPT_OUTFORM, 'F', "output format (DER or PEM)"}, {"pass", OPT_PASS, 's', "Output file pass phrase source"}, {"genparam", OPT_GENPARAM, '-', "Generate parameters, not key"}, - {"text", OPT_TEXT, '-', "Print the in text"}, + {"text", OPT_TEXT, '-', "Print the private key in text"}, {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"}, OPT_PROV_OPTIONS, + OPT_R_OPTIONS, /* This is deliberately last. */ {OPT_HELP_STR, 1, 1, @@ -58,14 +59,59 @@ const OPTIONS genpkey_options[] = { {NULL} }; +static const char *param_datatype_2name(unsigned int type, int *ishex) +{ + *ishex = 0; + + switch (type) { + case OSSL_PARAM_INTEGER: return "int"; + case OSSL_PARAM_UNSIGNED_INTEGER: return "uint"; + case OSSL_PARAM_REAL: return "float"; + case OSSL_PARAM_OCTET_STRING: *ishex = 1; return "string"; + case OSSL_PARAM_UTF8_STRING: return "string"; + default: + return NULL; + } +} + +static void show_gen_pkeyopt(const char *algname, OSSL_LIB_CTX *libctx, const char *propq) +{ + EVP_PKEY_CTX *ctx = NULL; + const OSSL_PARAM *params; + int i, ishex = 0; + + if (algname == NULL) + return; + ctx = EVP_PKEY_CTX_new_from_name(libctx, algname, propq); + if (ctx == NULL) + return; + + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto cleanup; + params = EVP_PKEY_CTX_settable_params(ctx); + if (params == NULL) + goto cleanup; + + BIO_printf(bio_err, "\nThe possible -pkeyopt arguments are:\n"); + for (i = 0; params[i].key != NULL; ++i) { + const char *name = param_datatype_2name(params[i].data_type, &ishex); + + if (name != NULL) + BIO_printf(bio_err, " %s%s:%s\n", ishex ? "hex" : "", params[i].key, name); + } +cleanup: + EVP_PKEY_CTX_free(ctx); +} + int genpkey_main(int argc, char **argv) { CONF *conf = NULL; - BIO *in = NULL, *out = NULL; + BIO *mem_out = NULL, *mem_outpubkey = NULL; ENGINE *e = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; char *outfile = NULL, *passarg = NULL, *pass = NULL, *prog, *p; + char *outpubkeyfile = NULL; const char *ciphername = NULL, *paramfile = NULL, *algname = NULL; EVP_CIPHER *cipher = NULL; OPTION_CHOICE o; @@ -74,6 +120,7 @@ int genpkey_main(int argc, char **argv) OSSL_LIB_CTX *libctx = app_get0_libctx(); STACK_OF(OPENSSL_STRING) *keyopt = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, genpkey_options); keyopt = sk_OPENSSL_STRING_new_null(); if (keyopt == NULL) @@ -88,6 +135,7 @@ int genpkey_main(int argc, char **argv) case OPT_HELP: ret = 0; opt_help(genpkey_options); + show_gen_pkeyopt(algname, libctx, app_get0_propq()); goto end; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) @@ -96,6 +144,9 @@ int genpkey_main(int argc, char **argv) case OPT_OUT: outfile = opt_arg(); break; + case OPT_OUTPUBKEY: + outpubkeyfile = opt_arg(); + break; case OPT_PASS: passarg = opt_arg(); break; @@ -115,7 +166,10 @@ int genpkey_main(int argc, char **argv) goto end; break; case OPT_QUIET: - quiet = 1; + verbose = 0; + break; + case OPT_VERBOSE: + verbose = 1; break; case OPT_GENPARAM: do_param = 1; @@ -135,14 +189,20 @@ int genpkey_main(int argc, char **argv) if (!opt_provider(o)) goto end; break; + case OPT_R_CASES: + if (!opt_rand(o)) + goto end; + break; } } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; + if (!app_RAND_load()) + goto end; + /* Fetch cipher, etc. */ if (paramfile != NULL) { if (!init_keygen_file(&ctx, paramfile, e, libctx, app_get0_propq())) @@ -163,9 +223,12 @@ int genpkey_main(int argc, char **argv) goto end; } } - if (ciphername != NULL) - if (!opt_cipher(ciphername, &cipher) || do_param == 1) - goto opthelp; + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; + if (ciphername != NULL && do_param == 1) { + BIO_printf(bio_err, "Cannot use cipher with -genparam option\n"); + goto opthelp; + } private = do_param ? 0 : 1; @@ -174,11 +237,20 @@ int genpkey_main(int argc, char **argv) goto end; } - out = bio_open_owner(outfile, outformat, private); - if (out == NULL) + mem_out = BIO_new(BIO_s_mem()); + if (mem_out == NULL) goto end; + BIO_set_mem_eof_return(mem_out, 0); - EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); + if (outpubkeyfile != NULL) { + mem_outpubkey = BIO_new(BIO_s_mem()); + if (mem_outpubkey == NULL) + goto end; + BIO_set_mem_eof_return(mem_outpubkey, 0); + } + + if (verbose) + EVP_PKEY_CTX_set_cb(ctx, progress_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); pkey = do_param ? app_paramgen(ctx, algname) @@ -187,13 +259,17 @@ int genpkey_main(int argc, char **argv) goto end; if (do_param) { - rv = PEM_write_bio_Parameters(out, pkey); + rv = PEM_write_bio_Parameters(mem_out, pkey); } else if (outformat == FORMAT_PEM) { assert(private); - rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass); + rv = PEM_write_bio_PrivateKey(mem_out, pkey, cipher, NULL, 0, NULL, pass); + if (rv > 0 && mem_outpubkey != NULL) + rv = PEM_write_bio_PUBKEY(mem_outpubkey, pkey); } else if (outformat == FORMAT_ASN1) { assert(private); - rv = i2d_PrivateKey_bio(out, pkey); + rv = i2d_PrivateKey_bio(mem_out, pkey); + if (rv > 0 && mem_outpubkey != NULL) + rv = i2d_PUBKEY_bio(mem_outpubkey, pkey); } else { BIO_printf(bio_err, "Bad format specified for key\n"); goto end; @@ -202,15 +278,15 @@ int genpkey_main(int argc, char **argv) ret = 0; if (rv <= 0) { - BIO_puts(bio_err, "Error writing key\n"); + BIO_puts(bio_err, "Error writing key(s)\n"); ret = 1; } if (text) { if (do_param) - rv = EVP_PKEY_print_params(out, pkey, 0, NULL); + rv = EVP_PKEY_print_params(mem_out, pkey, 0, NULL); else - rv = EVP_PKEY_print_private(out, pkey, 0, NULL); + rv = EVP_PKEY_print_private(mem_out, pkey, 0, NULL); if (rv <= 0) { BIO_puts(bio_err, "Error printing key\n"); @@ -220,13 +296,25 @@ int genpkey_main(int argc, char **argv) end: sk_OPENSSL_STRING_free(keyopt); - if (ret != 0) + if (ret != 0) { ERR_print_errors(bio_err); + } else { + if (mem_outpubkey != NULL) { + rv = mem_bio_to_file(mem_outpubkey, outpubkeyfile, outformat, private); + if (!rv) + BIO_printf(bio_err, "Error writing to outpubkey: '%s'. Error: %s\n", outpubkeyfile, strerror(errno)); + } + if (mem_out != NULL) { + rv = mem_bio_to_file(mem_out, outfile, outformat, private); + if (!rv) + BIO_printf(bio_err, "Error writing to outfile: '%s'. Error: %s\n", outpubkeyfile, strerror(errno)); + } + } EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); EVP_CIPHER_free(cipher); - BIO_free_all(out); - BIO_free(in); + BIO_free_all(mem_out); + BIO_free_all(mem_outpubkey); release_engine(e); OPENSSL_free(pass); NCONF_free(conf); @@ -318,27 +406,3 @@ int init_gen_str(EVP_PKEY_CTX **pctx, } -static int genpkey_cb(EVP_PKEY_CTX *ctx) -{ - char c = '*'; - BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - - if (quiet) - return 1; - - switch (EVP_PKEY_CTX_get_keygen_info(ctx, 0)) { - case 0: - c = '.'; - break; - case 1: - c = '+'; - break; - case 3: - c = '\n'; - break; - } - - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; -} diff --git a/apps/genrsa.c b/apps/genrsa.c index 6a683517a15f..54d025e24c2c 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -29,15 +29,13 @@ static int verbose = 0; -static int genrsa_cb(EVP_PKEY_CTX *ctx); - typedef enum OPTION_choice { OPT_COMMON, #ifndef OPENSSL_NO_DEPRECATED_3_0 OPT_3, #endif OPT_F4, OPT_ENGINE, - OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE, + OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM, OPT_TRADITIONAL } OPTION_CHOICE; @@ -62,6 +60,7 @@ const OPTIONS genrsa_options[] = { {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"}, {"primes", OPT_PRIMES, 'p', "Specify number of primes"}, {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"quiet", OPT_QUIET, '-', "Terse output"}, {"traditional", OPT_TRADITIONAL, '-', "Use traditional format for private keys"}, {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"}, @@ -93,6 +92,7 @@ int genrsa_main(int argc, char **argv) if (bn == NULL || cb == NULL) goto end; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, genrsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -139,6 +139,9 @@ opthelp: case OPT_VERBOSE: verbose = 1; break; + case OPT_QUIET: + verbose = 0; + break; case OPT_TRADITIONAL: traditional = 1; break; @@ -157,8 +160,7 @@ opthelp: "Warning: It is not recommended to use more than %d bit for RSA keys.\n" " Your key size is %d! Larger key size may behave not as expected.\n", OPENSSL_RSA_MAX_MODULUS_BITS, num); - } else if (argc > 0) { - BIO_printf(bio_err, "Extra arguments given.\n"); + } else if (!opt_check_rest_arg(NULL)) { goto opthelp; } @@ -166,10 +168,8 @@ opthelp: goto end; private = 1; - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &enc)) - goto end; - } + if (!opt_cipher(ciphername, &enc)) + goto end; if (!app_passwd(NULL, passoutarg, NULL, &passout)) { BIO_printf(bio_err, "Error getting password\n"); goto end; @@ -183,7 +183,8 @@ opthelp: app_get0_propq())) goto end; - EVP_PKEY_CTX_set_cb(ctx, genrsa_cb); + if (verbose) + EVP_PKEY_CTX_set_cb(ctx, progress_cb); EVP_PKEY_CTX_set_app_data(ctx, bio_err); if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, num) <= 0) { @@ -248,24 +249,3 @@ opthelp: return ret; } -static int genrsa_cb(EVP_PKEY_CTX *ctx) -{ - char c = '*'; - BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - - if (!verbose) - return 1; - - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; -} diff --git a/apps/include/apps.h b/apps/include/apps.h index baacd0025d68..ceebfde72786 100644 --- a/apps/include/apps.h +++ b/apps/include/apps.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,10 +10,8 @@ #ifndef OSSL_APPS_H # define OSSL_APPS_H -# include "e_os.h" /* struct timeval for DTLS */ +# include "internal/common.h" /* for HAS_PREFIX */ # include "internal/nelem.h" -# include "internal/sockets.h" /* for openssl_fdset() */ -# include "internal/cryptlib.h" /* ossl_assert() */ # include # include @@ -65,9 +63,13 @@ BIO *dup_bio_err(int format); BIO *bio_open_owner(const char *filename, int format, int private); BIO *bio_open_default(const char *filename, char mode, int format); BIO *bio_open_default_quiet(const char *filename, char mode, int format); +int mem_bio_to_file(BIO *in, const char *filename, int format, int private); +char *app_conf_try_string(const CONF *cnf, const char *group, const char *name); +int app_conf_try_number(const CONF *conf, const char *group, const char *name, + long *result); CONF *app_load_config_bio(BIO *in, const char *filename); -#define app_load_config(filename) app_load_config_internal(filename, 0) -#define app_load_config_quiet(filename) app_load_config_internal(filename, 1) +# define app_load_config(filename) app_load_config_internal(filename, 0) +# define app_load_config_quiet(filename) app_load_config_internal(filename, 1) CONF *app_load_config_internal(const char *filename, int quiet); CONF *app_load_config_verbose(const char *filename, int verbose); int app_load_modules(const CONF *config); @@ -79,8 +81,12 @@ int has_stdin_waiting(void); # endif void corrupt_signature(const ASN1_STRING *signature); + +/* Helpers for setting X509v3 certificate fields notBefore and notAfter */ +int check_cert_time_string(const char *time, const char *desc); int set_cert_times(X509 *x, const char *startdate, const char *enddate, - int days); + int days, int strict_compare_times); + int set_crl_lastupdate(X509_CRL *crl, const char *lastupdate); int set_crl_nextupdate(X509_CRL *crl, const char *nextupdate, long days, long hours, long secs); @@ -94,10 +100,13 @@ typedef struct args_st { /* We need both wrap and the "real" function because libcrypto uses both. */ int wrap_password_callback(char *buf, int bufsiz, int verify, void *cb_data); +/* progress callback for dsaparam, dhparam, req, genpkey, etc. */ +int progress_cb(EVP_PKEY_CTX *ctx); + int chopup_args(ARGS *arg, char *buf); void dump_cert_text(BIO *out, X509 *x); void print_name(BIO *out, const char *title, const X509_NAME *nm); -void print_bignum_var(BIO *, const BIGNUM *, const char*, +void print_bignum_var(BIO *, const BIGNUM *, const char *, int, unsigned char *); void print_array(BIO *, const char *, int, const unsigned char *); int set_nameopt(const char *arg); @@ -111,15 +120,18 @@ char *get_passwd(const char *pass, const char *desc); int app_passwd(const char *arg1, const char *arg2, char **pass1, char **pass2); int add_oid_section(CONF *conf); X509_REQ *load_csr(const char *file, int format, const char *desc); +X509_REQ *load_csr_autofmt(const char *infile, int format, + STACK_OF(OPENSSL_STRING) *vfyopts, const char *desc); X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, const char *pass, const char *desc); -#define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc) +# define load_cert(uri, format, desc) load_cert_pass(uri, format, 1, NULL, desc) X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, const char *desc); void cleanse(char *str); void clear_free(char *str); EVP_PKEY *load_key(const char *uri, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *desc); +/* first try reading public key, on failure resort to loading private key */ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *desc); EVP_PKEY *load_keyparams(const char *uri, int format, int maybe_stdin, @@ -141,15 +153,11 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs, int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, const char *pass, const char *desc); int load_key_certs_crls(const char *uri, int format, int maybe_stdin, - const char *pass, const char *desc, + const char *pass, const char *desc, int quiet, EVP_PKEY **ppkey, EVP_PKEY **ppubkey, EVP_PKEY **pparams, X509 **pcert, STACK_OF(X509) **pcerts, X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls); -int load_key_cert_crl(const char *uri, int format, int maybe_stdin, - const char *pass, const char *desc, - EVP_PKEY **ppkey, EVP_PKEY **ppubkey, - X509 **pcert, X509_CRL **pcrl); X509_STORE *setup_verify(const char *CAfile, int noCAfile, const char *CApath, int noCApath, const char *CAstore, int noCAstore); @@ -195,10 +203,9 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, # define DB_type 0 # define DB_exp_date 1 # define DB_rev_date 2 -# define DB_serial 3 /* index - unique */ +# define DB_serial 3 /* index - unique */ # define DB_file 4 -# define DB_name 5 /* index - unique when active and not - * disabled */ +# define DB_name 5 /* index - unique when active and not disabled */ # define DB_NUMBER 6 # define DB_TYPE_REV 'R' /* Revoked */ @@ -218,6 +225,8 @@ typedef struct ca_db_st { # endif } CA_DB; +extern int do_updatedb(CA_DB *db, time_t *now); + void app_bail_out(char *fmt, ...); void *app_malloc(size_t sz, const char *what); @@ -237,8 +246,8 @@ int rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix); void free_index(CA_DB *db); # define index_name_cmp_noconst(a, b) \ - index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ - (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) + index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ + (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); int parse_yesno(const char *str, int def); @@ -252,7 +261,8 @@ int x509_req_ctrl_string(X509_REQ *x, const char *value); int init_gen_str(EVP_PKEY_CTX **pctx, const char *algname, ENGINE *e, int do_param, OSSL_LIB_CTX *libctx, const char *propq); -int do_X509_sign(X509 *x, EVP_PKEY *pkey, const char *md, +int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey); +int do_X509_sign(X509 *x, int force_v1, EVP_PKEY *pkey, const char *md, STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx); int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts); int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const char *md, @@ -264,12 +274,11 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md, extern char *psk_key; - unsigned char *next_protos_parse(size_t *outlen, const char *in); -void print_cert_checks(BIO *bio, X509 *x, - const char *checkhost, - const char *checkemail, const char *checkip); +int check_cert_attributes(BIO *bio, X509 *x, + const char *checkhost, const char *checkemail, + const char *checkip, int print); void store_setup_crl_download(X509_STORE *st); @@ -303,16 +312,16 @@ ASN1_VALUE *app_http_post_asn1(const char *host, const char *port, # define EXT_COPY_ADD 1 # define EXT_COPY_ALL 2 -# define NETSCAPE_CERT_HDR "certificate" +# define NETSCAPE_CERT_HDR "certificate" -# define APP_PASS_LEN 1024 +# define APP_PASS_LEN 1024 /* * IETF RFC 5280 says serial number must be <= 20 bytes. Use 159 bits * so that the first bit will never be one, so that the DER encoding * rules won't force a leading octet. */ -# define SERIAL_RAND_BITS 159 +# define SERIAL_RAND_BITS 159 int app_isdir(const char *); int app_access(const char *, int flag); diff --git a/apps/include/cmp_mock_srv.h b/apps/include/cmp_mock_srv.h index 18c141c563c4..00f3b8f1cbca 100644 --- a/apps/include/cmp_mock_srv.h +++ b/apps/include/cmp_mock_srv.h @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 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 @@ -20,11 +20,17 @@ 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_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); +int ossl_cmp_mock_srv_set1_keyOut(OSSL_CMP_SRV_CTX *srv_ctx, EVP_PKEY *pkey); +int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx, X509_CRL *crl); 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_set1_newWithNew(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); +int ossl_cmp_mock_srv_set1_newWithOld(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); +int ossl_cmp_mock_srv_set1_oldWithNew(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert); 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_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype); diff --git a/apps/include/engine_loader.h b/apps/include/engine_loader.h index fa80fc96567c..30fdb9e55120 100644 --- a/apps/include/engine_loader.h +++ b/apps/include/engine_loader.h @@ -13,7 +13,7 @@ /* this is a private URI scheme */ # define ENGINE_SCHEME "org.openssl.engine" -# define ENGINE_SCHEME_COLON (ENGINE_SCHEME ":") +# define ENGINE_SCHEME_COLON ENGINE_SCHEME ":" int setup_engine_loader(void); void destroy_engine_loader(void); diff --git a/apps/include/function.h b/apps/include/function.h index 14e8dd388670..e796ff4045ad 100644 --- a/apps/include/function.h +++ b/apps/include/function.h @@ -29,7 +29,7 @@ typedef struct function_st { const char *deprecated_version; } FUNCTION; -DEFINE_LHASH_OF(FUNCTION); +DEFINE_LHASH_OF_EX(FUNCTION); /* Structure to hold the number of columns to be displayed and the * field width used to display them. diff --git a/apps/include/http_server.h b/apps/include/http_server.h index 8c339660a65e..4811e6be4013 100644 --- a/apps/include/http_server.h +++ b/apps/include/http_server.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,6 +11,7 @@ # define OSSL_HTTP_SERVER_H # include "apps.h" +# include "log.h" # ifndef HAVE_FORK # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) @@ -31,37 +32,19 @@ # define HTTP_DAEMON # include # include -# include # include # define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */ -# else -# undef LOG_DEBUG -# undef LOG_INFO -# undef LOG_WARNING -# undef LOG_ERR -# define LOG_DEBUG 7 -# define LOG_INFO 6 -# define LOG_WARNING 4 -# define LOG_ERR 3 # endif -/*- - * Log a message to syslog if multi-threaded HTTP_DAEMON, else to bio_err - * prog: the name of the current app - * level: the severity of the message, e.g., LOG_ERR - * fmt: message with potential extra parameters like with printf() - * returns nothing - */ -void log_message(const char *prog, int level, const char *fmt, ...); - # ifndef OPENSSL_NO_SOCK /*- - * Initialize an HTTP server by setting up its listening BIO + * Initialize an HTTP server, setting up its listening BIO * prog: the name of the current app * port: the port to listen on + * verbosity: the level of verbosity to use, or -1 for default: LOG_INFO * returns a BIO for accepting requests, NULL on error */ -BIO *http_server_init_bio(const char *prog, const char *port); +BIO *http_server_init(const char *prog, const char *port, int verbosity); /*- * Accept an ASN.1-formatted HTTP request @@ -72,7 +55,6 @@ BIO *http_server_init_bio(const char *prog, const char *port); * acbio: the listening bio (typically as returned by http_server_init_bio()) * found_keep_alive: for returning flag if client requests persistent connection * prog: the name of the current app, for diagnostics only - * port: the local port listening to, for diagnostics only * accept_get: whether to accept GET requests (in addition to POST requests) * timeout: connection timeout (in seconds), or 0 for none/infinite * returns 0 in case caller should retry, then *preq == *ppath == *pcbio == NULL @@ -86,36 +68,38 @@ BIO *http_server_init_bio(const char *prog, const char *port); int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, char **ppath, BIO **pcbio, BIO *acbio, int *found_keep_alive, - const char *prog, const char *port, - int accept_get, int timeout); + const char *prog, int accept_get, int timeout); /*- * Send an ASN.1-formatted HTTP response + * prog: the name of the current app, for diagnostics only * cbio: destination BIO (typically as returned by http_server_get_asn1_req()) * note: cbio should not do an encoding that changes the output length - * keep_alive: grant persistent connnection + * keep_alive: grant persistent connection * content_type: string identifying the type of the response * it: the response ASN.1 type * resp: the response to send * returns 1 on success, 0 on failure */ -int http_server_send_asn1_resp(BIO *cbio, int keep_alive, +int http_server_send_asn1_resp(const char *prog, BIO *cbio, int keep_alive, const char *content_type, const ASN1_ITEM *it, const ASN1_VALUE *resp); /*- * Send a trivial HTTP response, typically to report an error or OK + * prog: the name of the current app, for diagnostics only * cbio: destination BIO (typically as returned by http_server_get_asn1_req()) * status: the status code to send * reason: the corresponding human-readable string * returns 1 on success, 0 on failure */ -int http_server_send_status(BIO *cbio, int status, const char *reason); +int http_server_send_status(const char *prog, BIO *cbio, + int status, const char *reason); # endif # ifdef HTTP_DAEMON -extern int multi; +extern int n_responders; extern int acfd; void socket_timeout(int signum); diff --git a/apps/include/opt.h b/apps/include/opt.h index 4f83a0ed53c9..d8d75182802d 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -157,13 +157,18 @@ OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \ OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_CLIENTRENEG, \ OPT_S_LEGACYCONN, \ - OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \ + OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, \ + OPT_S_ALLOW_NO_DHE_KEX, OPT_S_PREFER_NO_DHE_KEX, \ OPT_S_PRIORITIZE_CHACHA, \ OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \ OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \ OPT_S_RECORD_PADDING, OPT_S_DEBUGBROKE, OPT_S_COMP, \ OPT_S_MINPROTO, OPT_S_MAXPROTO, \ - OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S_NO_ETM, OPT_S__LAST + OPT_S_NO_RENEGOTIATION, OPT_S_NO_MIDDLEBOX, OPT_S_NO_ETM, \ + OPT_S_NO_EMS, \ + OPT_S_NO_TX_CERT_COMP, \ + OPT_S_NO_RX_CERT_COMP, \ + OPT_S__LAST # define OPT_S_OPTIONS \ OPT_SECTION("TLS/SSL"), \ @@ -175,6 +180,8 @@ {"bugs", OPT_S_BUGS, '-', "Turn on SSL bug compatibility"}, \ {"no_comp", OPT_S_NO_COMP, '-', "Disable SSL/TLS compression (default)" }, \ {"comp", OPT_S_COMP, '-', "Use SSL/TLS-level compression" }, \ + {"no_tx_cert_comp", OPT_S_NO_TX_CERT_COMP, '-', "Disable sending TLSv1.3 compressed certificates" }, \ + {"no_rx_cert_comp", OPT_S_NO_RX_CERT_COMP, '-', "Disable receiving TLSv1.3 compressed certificates" }, \ {"no_ticket", OPT_S_NOTICKET, '-', \ "Disable use of TLS session tickets"}, \ {"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \ @@ -192,6 +199,8 @@ "Disallow initial connection to servers that don't support RI"}, \ {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \ "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \ + {"prefer_no_dhe_kex", OPT_S_PREFER_NO_DHE_KEX, '-', \ + "In TLSv1.3 prefer non-(ec)dhe over (ec)dhe-based key exchange on resumption"}, \ {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \ "Prioritize ChaCha ciphers when preferred by clients"}, \ {"strict", OPT_S_STRICT, '-', \ @@ -218,7 +227,9 @@ {"no_middlebox", OPT_S_NO_MIDDLEBOX, '-', \ "Disable TLSv1.3 middlebox compat mode" }, \ {"no_etm", OPT_S_NO_ETM, '-', \ - "Disable Encrypt-then-Mac extension"} + "Disable Encrypt-then-Mac extension"}, \ + {"no_ems", OPT_S_NO_EMS, '-', \ + "Disable Extended master secret extension"} # define OPT_S_CASES \ OPT_S__FIRST: case OPT_S__LAST: break; \ @@ -230,6 +241,8 @@ case OPT_S_BUGS: \ case OPT_S_NO_COMP: \ case OPT_S_COMP: \ + case OPT_S_NO_TX_CERT_COMP: \ + case OPT_S_NO_RX_CERT_COMP: \ case OPT_S_NOTICKET: \ case OPT_S_SERVERPREF: \ case OPT_S_LEGACYRENEG: \ @@ -238,6 +251,7 @@ case OPT_S_ONRESUMP: \ case OPT_S_NOLEGACYCONN: \ case OPT_S_ALLOW_NO_DHE_KEX: \ + case OPT_S_PREFER_NO_DHE_KEX: \ case OPT_S_PRIORITIZE_CHACHA: \ case OPT_S_STRICT: \ case OPT_S_SIGALGS: \ @@ -253,7 +267,8 @@ case OPT_S_MAXPROTO: \ case OPT_S_DEBUGBROKE: \ case OPT_S_NO_MIDDLEBOX: \ - case OPT_S_NO_ETM + case OPT_S_NO_ETM: \ + case OPT_S_NO_EMS #define IS_NO_PROT_FLAG(o) \ (o == OPT_S_NOSSL3 || o == OPT_S_NOTLS1 || o == OPT_S_NOTLS1_1 \ @@ -280,6 +295,7 @@ # define OPT_PROV_ENUM \ OPT_PROV__FIRST=1600, \ OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, OPT_PROV_PROPQUERY, \ + OPT_PROV_PARAM, \ OPT_PROV__LAST # define OPT_CONFIG_OPTION \ @@ -289,12 +305,14 @@ OPT_SECTION("Provider"), \ { "provider-path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path (must be before 'provider' argument if required)" }, \ { "provider", OPT_PROV_PROVIDER, 's', "Provider to load (can be specified multiple times)" }, \ + { "provparam", OPT_PROV_PARAM, 's', "Set a provider key-value parameter" }, \ { "propquery", OPT_PROV_PROPQUERY, 's', "Property query used when fetching algorithms" } # define OPT_PROV_CASES \ OPT_PROV__FIRST: case OPT_PROV__LAST: break; \ case OPT_PROV_PROVIDER: \ case OPT_PROV_PROVIDER_PATH: \ + case OPT_PROV_PARAM: \ case OPT_PROV_PROPQUERY /* @@ -308,11 +326,28 @@ extern const char OPT_PARAM_STR[]; typedef struct options_st { const char *name; int retval; - /* - * value type: - no value (also the value zero), n number, p positive - * number, u unsigned, l long, s string, < input file, > output file, - * f any format, F der/pem format, E der/pem/engine format identifier. - * l, n and u include zero; p does not. + /*- + * value type: + * + * '-' no value (also the value zero) + * 'n' number (type 'int') + * 'p' positive number (type 'int') + * 'u' unsigned number (type 'unsigned long') + * 'l' number (type 'unsigned long') + * 'M' number (type 'intmax_t') + * 'U' unsigned number (type 'uintmax_t') + * 's' string + * '<' input file + * '>' output file + * '/' directory + * 'f' any format [OPT_FMT_ANY] + * 'F' der/pem format [OPT_FMT_PEMDER] + * 'A' any ASN1, der/pem/b64 format [OPT_FMT_ASN1] + * 'E' der/pem/engine format [OPT_FMT_PDE] + * 'c' pem/der/smime format [OPT_FMT_PDS] + * + * The 'l', 'n' and 'u' value types include the values zero, + * the 'p' value type does not. */ int valtype; const char *helpstr; @@ -332,46 +367,54 @@ typedef struct string_int_pair_st { } OPT_PAIR, STRINT_PAIR; /* Flags to pass into opt_format; see FORMAT_xxx, below. */ -# define OPT_FMT_PEMDER (1L << 1) -# define OPT_FMT_PKCS12 (1L << 2) -# define OPT_FMT_SMIME (1L << 3) -# define OPT_FMT_ENGINE (1L << 4) -# define OPT_FMT_MSBLOB (1L << 5) -/* (1L << 6) was OPT_FMT_NETSCAPE, but wasn't used */ -# define OPT_FMT_NSS (1L << 7) -# define OPT_FMT_TEXT (1L << 8) -# define OPT_FMT_HTTP (1L << 9) -# define OPT_FMT_PVK (1L << 10) +# define OPT_FMT_PEM (1L << 1) +# define OPT_FMT_DER (1L << 2) +# define OPT_FMT_B64 (1L << 3) +# define OPT_FMT_PKCS12 (1L << 4) +# define OPT_FMT_SMIME (1L << 5) +# define OPT_FMT_ENGINE (1L << 6) +# define OPT_FMT_MSBLOB (1L << 7) +# define OPT_FMT_NSS (1L << 8) +# define OPT_FMT_TEXT (1L << 9) +# define OPT_FMT_HTTP (1L << 10) +# define OPT_FMT_PVK (1L << 11) + +# define OPT_FMT_PEMDER (OPT_FMT_PEM | OPT_FMT_DER) +# define OPT_FMT_ASN1 (OPT_FMT_PEM | OPT_FMT_DER | OPT_FMT_B64) # define OPT_FMT_PDE (OPT_FMT_PEMDER | OPT_FMT_ENGINE) # define OPT_FMT_PDS (OPT_FMT_PEMDER | OPT_FMT_SMIME) # define OPT_FMT_ANY ( \ - OPT_FMT_PEMDER | OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ - OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ - OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) + OPT_FMT_PEM | OPT_FMT_DER | OPT_FMT_B64 | \ + OPT_FMT_PKCS12 | OPT_FMT_SMIME | \ + OPT_FMT_ENGINE | OPT_FMT_MSBLOB | OPT_FMT_NSS | \ + OPT_FMT_TEXT | OPT_FMT_HTTP | OPT_FMT_PVK) /* Divide options into sections when displaying usage */ #define OPT_SECTION(sec) { OPT_SECTION_STR, 1, '-', sec " options:\n" } #define OPT_PARAMETERS() { OPT_PARAM_STR, 1, '-', "Parameters:\n" } const char *opt_path_end(const char *filename); -char *opt_init(int ac, char **av, const OPTIONS * o); +char *opt_init(int ac, char **av, const OPTIONS *o); char *opt_progname(const char *argv0); char *opt_appname(const char *argv0); char *opt_getprog(void); -void opt_help(const OPTIONS * list); +void opt_help(const OPTIONS *list); void opt_begin(void); int opt_next(void); char *opt_flag(void); char *opt_arg(void); char *opt_unknown(void); +void reset_unknown(void); int opt_cipher(const char *name, EVP_CIPHER **cipherp); int opt_cipher_any(const char *name, EVP_CIPHER **cipherp); int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp); +int opt_check_md(const char *name); int opt_md(const char *name, EVP_MD **mdp); int opt_md_silent(const char *name, EVP_MD **mdp); int opt_int(const char *arg, int *result); +void opt_set_unknown_name(const char *name); int opt_int_arg(void); int opt_long(const char *arg, long *result); int opt_ulong(const char *arg, unsigned long *result); @@ -383,7 +426,7 @@ int opt_format(const char *s, unsigned long flags, int *result); void print_format_error(int format, unsigned long flags); int opt_printf_stderr(const char *fmt, ...); int opt_string(const char *name, const char **options); -int opt_pair(const char *arg, const OPT_PAIR * pairs, int *result); +int opt_pair(const char *arg, const OPT_PAIR *pairs, int *result); int opt_verify(int i, X509_VERIFY_PARAM *vpm); int opt_rand(int i); @@ -392,6 +435,7 @@ int opt_provider_option_given(void); char **opt_rest(void); int opt_num_rest(void); +int opt_check_rest_arg(const char *expected); /* Returns non-zero if legacy paths are still available */ int opt_legacy_okay(void); diff --git a/apps/include/platform.h b/apps/include/platform.h index 491559df3152..62fc99c5fd7a 100644 --- a/apps/include/platform.h +++ b/apps/include/platform.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,7 +16,7 @@ /* * VMS C only for now, implemented in vms_decc_init.c * If other C compilers forget to terminate argv with NULL, this function - * can be re-used. + * can be reused. */ char **copy_argv(int *argc, char *argv[]); # endif diff --git a/apps/include/s_apps.h b/apps/include/s_apps.h index d610df40be3f..33c3b6278c82 100644 --- a/apps/include/s_apps.h +++ b/apps/include/s_apps.h @@ -1,5 +1,5 @@ /* - * 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 @@ -15,12 +15,16 @@ #define PORT "4433" #define PROTOCOL "tcp" +#define SSL_VERSION_ALLOWS_RENEGOTIATION(s) \ + (SSL_is_dtls(s) || (SSL_version(s) < TLS1_3_VERSION)) + typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context); +void get_sock_info_address(int asock, char **hostname, char **service); int report_server_accept(BIO *out, int asock, int with_address, int with_pid); int do_server(int *accept_sock, const char *host, const char *port, int family, int type, int protocol, do_server_cb cb, - unsigned char *context, int naccept, BIO *bio_s_out); - + unsigned char *context, int naccept, BIO *bio_s_out, + int tfo); int verify_callback(int ok, X509_STORE_CTX *ctx); int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); @@ -32,7 +36,8 @@ int ssl_print_groups(BIO *out, SSL *s, int noshared); int ssl_print_tmp_key(BIO *out, SSL *s); int init_client(int *sock, const char *host, const char *port, const char *bindhost, const char *bindport, - int family, int type, int protocol); + int family, int type, int protocol, int tfo, int doconn, + BIO_ADDR **ba_ret); int should_retry(int i); void do_ssl_shutdown(SSL *ssl); @@ -79,6 +84,7 @@ int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath, void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose); int set_keylog_file(SSL_CTX *ctx, const char *keylog_file); void print_ca_names(BIO *bio, SSL *s); +void ssl_print_secure_renegotiation_notes(BIO *bio, SSL *s); #ifndef OPENSSL_NO_SRP /* The client side SRP context that we pass to all SRP related callbacks */ diff --git a/apps/info.c b/apps/info.c index c68603652f21..5a469eed9695 100644 --- a/apps/info.c +++ b/apps/info.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,7 +14,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_CONFIGDIR, OPT_ENGINESDIR, OPT_MODULESDIR, OPT_DSOEXT, OPT_DIRNAMESEP, - OPT_LISTSEP, OPT_SEEDS, OPT_CPUSETTINGS + OPT_LISTSEP, OPT_SEEDS, OPT_CPUSETTINGS, OPT_WINDOWSCONTEXT } OPTION_CHOICE; const OPTIONS info_options[] = { @@ -32,6 +32,7 @@ const OPTIONS info_options[] = { {"listsep", OPT_LISTSEP, '-', "List separator character"}, {"seeds", OPT_SEEDS, '-', "Seed sources"}, {"cpusettings", OPT_CPUSETTINGS, '-', "CPU settings info"}, + {"windowscontext", OPT_WINDOWSCONTEXT, '-', "Windows install context"}, {NULL} }; @@ -40,6 +41,7 @@ int info_main(int argc, char **argv) int ret = 1, dirty = 0, type = 0; char *prog; OPTION_CHOICE o; + const char *typedata; prog = opt_init(argc, argv, info_options); while ((o = opt_next()) != OPT_EOF) { @@ -84,9 +86,13 @@ opthelp: type = OPENSSL_INFO_CPU_SETTINGS; dirty++; break; + case OPT_WINDOWSCONTEXT: + type = OPENSSL_INFO_WINDOWS_CONTEXT; + dirty++; + break; } } - if (opt_num_rest() != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (dirty > 1) { BIO_printf(bio_err, "%s: Only one item allowed\n", prog); @@ -97,7 +103,8 @@ opthelp: goto opthelp; } - BIO_printf(bio_out, "%s\n", OPENSSL_info(type)); + typedata = OPENSSL_info(type); + BIO_printf(bio_out, "%s\n", typedata == NULL ? "Undefined" : typedata); ret = 0; end: return ret; diff --git a/apps/lib/app_libctx.c b/apps/lib/app_libctx.c index 4b9ec40e8527..2f68cb0a75ea 100644 --- a/apps/lib/app_libctx.c +++ b/apps/lib/app_libctx.c @@ -36,7 +36,7 @@ OSSL_LIB_CTX *app_create_libctx(void) */ if (app_libctx == NULL) { if (!app_provider_load(NULL, "null")) { - opt_printf_stderr( "Failed to create null provider\n"); + opt_printf_stderr("Failed to create null provider\n"); return NULL; } app_libctx = OSSL_LIB_CTX_new(); diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c index 63f78ae07d80..6db1d4b0b50c 100644 --- a/apps/lib/app_provider.c +++ b/apps/lib/app_provider.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,6 +8,7 @@ */ #include "apps.h" +#include #include #include #include @@ -65,6 +66,78 @@ static int opt_provider_path(const char *path) return OSSL_PROVIDER_set_default_search_path(app_get0_libctx(), path); } +struct prov_param_st { + char *name; + char *key; + char *val; + int found; +}; + +static int set_prov_param(OSSL_PROVIDER *prov, void *vp) +{ + struct prov_param_st *p = (struct prov_param_st *)vp; + + if (p->name != NULL && strcmp(OSSL_PROVIDER_get0_name(prov), p->name) != 0) + return 1; + p->found = 1; + return OSSL_PROVIDER_add_conf_parameter(prov, p->key, p->val); +} + +static int opt_provider_param(const char *arg) +{ + struct prov_param_st p; + char *copy, *tmp; + int ret = 0; + + if ((copy = OPENSSL_strdup(arg)) == NULL + || (p.val = strchr(copy, '=')) == NULL) { + opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n", + opt_getprog(), arg); + goto end; + } + + /* Drop whitespace on both sides of the '=' sign */ + *(tmp = p.val++) = '\0'; + while (tmp > copy && isspace(_UC(*--tmp))) + *tmp = '\0'; + while (isspace(_UC(*p.val))) + ++p.val; + + /* + * Split the key on ':', to get the optional provider, empty or missing + * means all. + */ + if ((p.key = strchr(copy, ':')) != NULL) { + *p.key++ = '\0'; + p.name = *copy != '\0' ? copy : NULL; + } else { + p.name = NULL; + p.key = copy; + } + + /* The key must not be empty */ + if (*p.key == '\0') { + opt_printf_stderr("%s: malformed '-provparam' option value: '%s'\n", + opt_getprog(), arg); + goto end; + } + + p.found = 0; + ret = OSSL_PROVIDER_do_all(app_get0_libctx(), set_prov_param, (void *)&p); + if (ret == 0) { + opt_printf_stderr("%s: Error setting provider '%s' parameter '%s'\n", + opt_getprog(), p.name, p.key); + } else if (p.found == 0) { + opt_printf_stderr("%s: No provider named '%s' is loaded\n", + opt_getprog(), p.name); + ret = 0; + } + + end: + OPENSSL_free(copy); + return ret; +} + int opt_provider(int opt) { const int given = provider_option_given; @@ -78,6 +151,8 @@ int opt_provider(int opt) return app_provider_load(app_get0_libctx(), opt_arg()); case OPT_PROV_PROVIDER_PATH: return opt_provider_path(opt_arg()); + case OPT_PROV_PARAM: + return opt_provider_param(opt_arg()); case OPT_PROV_PROPQUERY: return app_set_propq(opt_arg()); } diff --git a/apps/lib/app_rand.c b/apps/lib/app_rand.c index 713792ead40a..64d0f9b30910 100644 --- a/apps/lib/app_rand.c +++ b/apps/lib/app_rand.c @@ -1,5 +1,5 @@ /* - * 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 @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" /* LIST_SEPARATOR_CHAR */ #include "apps.h" #include #include @@ -18,12 +19,10 @@ static STACK_OF(OPENSSL_STRING) *randfiles; void app_RAND_load_conf(CONF *c, const char *section) { - const char *randfile = NCONF_get_string(c, section, "RANDFILE"); + const char *randfile = app_conf_try_string(c, section, "RANDFILE"); - if (randfile == NULL) { - ERR_clear_error(); + if (randfile == NULL) return; - } if (RAND_load_file(randfile, -1) < 0) { BIO_printf(bio_err, "Can't load %s into RNG\n", randfile); ERR_print_errors(bio_err); @@ -43,7 +42,7 @@ static int loadfiles(char *name) char *p; int last, ret = 1; - for ( ; ; ) { + for (;;) { last = 0; for (p = name; *p != '\0' && *p != LIST_SEPARATOR_CHAR; p++) continue; diff --git a/apps/lib/apps.c b/apps/lib/apps.c index a632b0cff2bf..d4e72307de58 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,14 +44,16 @@ #include #include #include -#include #include #include "s_apps.h" #include "apps.h" +#include "internal/sockets.h" /* for openssl_fdset() */ +#include "internal/e_os.h" + #ifdef _WIN32 static int WIN32_rename(const char *from, const char *to); -# define rename(from,to) WIN32_rename((from),(to)) +# define rename(from, to) WIN32_rename((from), (to)) #endif #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) @@ -76,18 +78,9 @@ typedef struct { } NAME_EX_TBL; static int set_table_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl); + 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); - + const NAME_EX_TBL *in_tbl); int app_init(long mesgwin); int chopup_args(ARGS *arg, char *buf) @@ -111,6 +104,7 @@ int chopup_args(ARGS *arg, char *buf) /* 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) @@ -197,7 +191,12 @@ int set_nameopt(const char *arg) unsigned long get_nameopt(void) { - return (nmflag_set) ? nmflag : XN_FLAG_ONELINE; + return + nmflag_set ? nmflag : XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN + | ASN1_STRFLGS_ESC_CTRL + | ASN1_STRFLGS_UTF8_CONVERT + | ASN1_STRFLGS_DUMP_UNKNOWN + | ASN1_STRFLGS_DUMP_DER; } void dump_cert_text(BIO *out, X509 *x) @@ -211,7 +210,6 @@ 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) @@ -227,7 +225,8 @@ char *get_passwd(const char *pass, const char *desc) "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); + BIO_printf(bio_err, + "Out of memory getting password for %s\n", desc); } return result; } @@ -260,21 +259,21 @@ static char *app_get_pass(const char *arg, int keepbio) 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 (CHECK_AND_SKIP_PREFIX(arg, "pass:")) + return OPENSSL_strdup(arg); + if (CHECK_AND_SKIP_PREFIX(arg, "env:")) { + tmp = getenv(arg); if (tmp == NULL) { - BIO_printf(bio_err, "No environment variable %s\n", arg + 4); + BIO_printf(bio_err, "No environment variable %s\n", arg); return NULL; } return OPENSSL_strdup(tmp); } if (!keepbio || pwdbio == NULL) { - if (strncmp(arg, "file:", 5) == 0) { - pwdbio = BIO_new_file(arg + 5, "r"); + if (CHECK_AND_SKIP_PREFIX(arg, "file:")) { + pwdbio = BIO_new_file(arg, "r"); if (pwdbio == NULL) { - BIO_printf(bio_err, "Can't open file %s\n", arg + 5); + BIO_printf(bio_err, "Can't open file %s\n", arg); return NULL; } #if !defined(_WIN32) @@ -286,13 +285,14 @@ static char *app_get_pass(const char *arg, int keepbio) * on real Windows descriptors, such as those obtained * with CreateFile. */ - } else if (strncmp(arg, "fd:", 3) == 0) { + } else if (CHECK_AND_SKIP_PREFIX(arg, "fd:")) { BIO *btmp; - i = atoi(arg + 3); + + i = atoi(arg); 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); + BIO_printf(bio_err, "Can't access file descriptor %s\n", arg); return NULL; } /* @@ -343,6 +343,33 @@ static char *app_get_pass(const char *arg, int keepbio) return OPENSSL_strdup(tpass); } +char *app_conf_try_string(const CONF *conf, const char *group, const char *name) +{ + char *res; + + ERR_set_mark(); + res = NCONF_get_string(conf, group, name); + if (res == NULL) + ERR_pop_to_mark(); + else + ERR_clear_last_mark(); + return res; +} + +int app_conf_try_number(const CONF *conf, const char *group, const char *name, + long *result) +{ + int ok; + + ERR_set_mark(); + ok = NCONF_get_number(conf, group, name, result); + if (!ok) + ERR_pop_to_mark(); + else + ERR_clear_last_mark(); + return ok; +} + CONF *app_load_config_bio(BIO *in, const char *filename) { long errorline = -1; @@ -423,10 +450,8 @@ int add_oid_section(CONF *conf) CONF_VALUE *cnf; int i; - if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) { - ERR_clear_error(); + if ((p = app_conf_try_string(conf, NULL, "oid_section")) == NULL) return 1; - } if ((sktmp = NCONF_get_section(conf, p)) == NULL) { BIO_printf(bio_err, "problem loading oid section %s\n", p); return 0; @@ -457,10 +482,8 @@ CONF *app_load_config_modules(const char *configfile) 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) +#define IS_HTTP(uri) ((uri) != NULL && HAS_PREFIX(uri, OSSL_HTTP_PREFIX)) +#define IS_HTTPS(uri) ((uri) != NULL && HAS_PREFIX(uri, OSSL_HTTPS_PREFIX)) X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, const char *pass, const char *desc) @@ -469,16 +492,17 @@ X509 *load_cert_pass(const char *uri, int format, int maybe_stdin, if (desc == NULL) desc = "certificate"; - if (IS_HTTPS(uri)) + if (IS_HTTPS(uri)) { BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); - else if (IS_HTTP(uri)) + } 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, + if (cert == NULL) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri); + } + } else { + (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0, 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; } @@ -490,20 +514,22 @@ X509_CRL *load_crl(const char *uri, int format, int maybe_stdin, if (desc == NULL) desc = "CRL"; - if (IS_HTTPS(uri)) + if (IS_HTTPS(uri)) { BIO_printf(bio_err, "Loading %s over HTTPS is unsupported\n", desc); - else if (IS_HTTP(uri)) + } 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, + if (crl == NULL) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri); + } + } else { + (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, 0, 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; } +/* Could be simplified if OSSL_STORE supported CSRs, see FR #15725 */ X509_REQ *load_csr(const char *file, int format, const char *desc) { X509_REQ *req = NULL; @@ -511,8 +537,6 @@ X509_REQ *load_csr(const char *file, int format, const char *desc) if (format == FORMAT_UNDEF) format = FORMAT_PEM; - if (desc == NULL) - desc = "CSR"; in = bio_open_default(file, 'r', format); if (in == NULL) goto end; @@ -526,13 +550,50 @@ X509_REQ *load_csr(const char *file, int format, const char *desc) end: if (req == NULL) { - BIO_printf(bio_err, "Unable to load %s\n", desc); ERR_print_errors(bio_err); + if (desc != NULL) + BIO_printf(bio_err, "Unable to load %s\n", desc); } BIO_free(in); return req; } +/* Better extend OSSL_STORE to support CSRs, see FR #15725 */ +X509_REQ *load_csr_autofmt(const char *infile, int format, + STACK_OF(OPENSSL_STRING) *vfyopts, const char *desc) +{ + X509_REQ *csr; + + if (format != FORMAT_UNDEF) { + csr = load_csr(infile, format, desc); + } else { /* try PEM, then DER */ + BIO *bio_bak = bio_err; + + bio_err = NULL; /* do not show errors on more than one try */ + csr = load_csr(infile, FORMAT_PEM, NULL /* desc */); + bio_err = bio_bak; + if (csr == NULL) { + ERR_clear_error(); + csr = load_csr(infile, FORMAT_ASN1, NULL /* desc */); + } + if (csr == NULL) { + BIO_printf(bio_err, "error: unable to load %s from file '%s'\n", + desc, infile); + } + } + if (csr != NULL) { + EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr); + int ret = do_X509_REQ_verify(csr, pkey, vfyopts); + + if (pkey == NULL || ret < 0) + BIO_puts(bio_err, "Warning: error while verifying CSR self-signature\n"); + else if (ret == 0) + BIO_puts(bio_err, "Warning: CSR self-signature does not match the contents\n"); + return csr; + } + return csr; +} + void cleanse(char *str) { if (str != NULL) @@ -554,16 +615,16 @@ EVP_PKEY *load_key(const char *uri, int format, int may_stdin, if (desc == NULL) desc = "private key"; - if (format == FORMAT_ENGINE) { + if (format == FORMAT_ENGINE) uri = allocated_uri = make_engine_uri(e, uri, desc); - } - (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, + (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, 0, &pkey, NULL, NULL, NULL, NULL, NULL, NULL); OPENSSL_free(allocated_uri); return pkey; } +/* first try reading public key, on failure resort to loading private key */ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, const char *pass, ENGINE *e, const char *desc) { @@ -573,35 +634,33 @@ EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin, if (desc == NULL) desc = "public key"; - if (format == FORMAT_ENGINE) { + if (format == FORMAT_ENGINE) uri = allocated_uri = make_engine_uri(e, uri, desc); - } - (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, + (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 1, NULL, &pkey, NULL, NULL, NULL, NULL, NULL); - + if (pkey == NULL) + (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0, + &pkey, NULL, 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) + 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, ¶ms, NULL, NULL, NULL, - NULL, suppress_decode_errors); + (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, + suppress_decode_errors, + NULL, NULL, ¶ms, NULL, NULL, NULL, NULL); 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); - } + ERR_print_errors(bio_err); + BIO_printf(bio_err, + "Unable to load %s from %s (unexpected parameters type)\n", + desc, uri); EVP_PKEY_free(params); params = NULL; } @@ -689,15 +748,16 @@ int load_cert_certs(const char *uri, int ret = 0; char *pass_string; - if (exclude_http && (OPENSSL_strncasecmp(uri, "http://", 7) == 0 - || OPENSSL_strncasecmp(uri, "https://", 8) == 0)) { + if (desc == NULL) + desc = pcerts == NULL ? "certificate" : "certificates"; + if (exclude_http && (HAS_CASE_PREFIX(uri, "http://") + || HAS_CASE_PREFIX(uri, "https://"))) { 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); + ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, 0, + NULL, NULL, NULL, pcert, pcerts, NULL, NULL); clear_free(pass_string); if (ret) { @@ -707,7 +767,7 @@ int load_cert_certs(const char *uri, warn_certs(uri, *pcerts, 1, vpm); } else { if (pcerts != NULL) { - sk_X509_pop_free(*pcerts, X509_free); + OSSL_STACK_OF_X509_free(*pcerts); *pcerts = NULL; } } @@ -733,7 +793,7 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass, 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); + OSSL_STACK_OF_X509_free(certs); certs = NULL; files = next; } @@ -742,8 +802,8 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass, oom: BIO_printf(bio_err, "out of memory\n"); err: - sk_X509_pop_free(certs, X509_free); - sk_X509_pop_free(result, X509_free); + OSSL_STACK_OF_X509_free(certs); + OSSL_STACK_OF_X509_free(result); return NULL; } @@ -784,7 +844,7 @@ X509_STORE *load_certstore(char *input, const char *pass, const char *desc, return NULL; } ok = (store = sk_X509_to_store(store, certs)) != NULL; - sk_X509_pop_free(certs, X509_free); + OSSL_STACK_OF_X509_free(certs); certs = NULL; if (!ok) return NULL; @@ -800,13 +860,15 @@ X509_STORE *load_certstore(char *input, const char *pass, const char *desc, 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); + int ret, was_NULL = *certs == NULL; + + if (desc == NULL) + desc = "certificates"; + ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc, 0, + NULL, NULL, NULL, NULL, certs, NULL, NULL); if (!ret && was_NULL) { - sk_X509_pop_free(*certs, X509_free); + OSSL_STACK_OF_X509_free(*certs); *certs = NULL; } return ret; @@ -819,10 +881,12 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs, 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); + int ret, was_NULL = *crls == NULL; + + if (desc == NULL) + desc = "CRLs"; + ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, 0, + NULL, NULL, NULL, NULL, NULL, NULL, crls); if (!ret && was_NULL) { sk_X509_CRL_pop_free(*crls, X509_CRL_free); @@ -833,20 +897,38 @@ int load_crls(const char *uri, STACK_OF(X509_CRL) **crls, static const char *format2string(int format) { - switch(format) { + switch (format) { case FORMAT_PEM: return "PEM"; case FORMAT_ASN1: return "DER"; + case FORMAT_PVK: + return "PVK"; + case FORMAT_MSBLOB: + return "MSBLOB"; } 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)) +/* Set type expectation, but set to 0 if objects of multiple types expected. */ +#define SET_EXPECT(val) \ + (expect = expect < 0 ? (val) : (expect == (val) ? (val) : 0)) +#define SET_EXPECT1(pvar, val) \ + if ((pvar) != NULL) { \ + *(pvar) = NULL; \ + SET_EXPECT(val); \ + } +/* Provide (error msg) text for some of the credential types to be loaded. */ +#define FAIL_NAME \ + (ppkey != NULL ? "private key" : ppubkey != NULL ? "public key" : \ + pparams != NULL ? "key parameters" : \ + pcert != NULL ? "certificate" : pcerts != NULL ? "certificates" : \ + pcrl != NULL ? "CRL" : pcrls != NULL ? "CRLs" : NULL) /* * 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. + * Reads from stdin if 'uri' is NULL and 'maybe_stdin' is nonzero. + * 'format' parameter may be FORMAT_PEM, FORMAT_ASN1, or 0 for no hint. + * desc may contain more detail on the credential(s) to be loaded for error msg * 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 @@ -857,94 +939,88 @@ static const char *format2string(int format) * 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) +int load_key_certs_crls(const char *uri, int format, int maybe_stdin, + const char *pass, const char *desc, int quiet, + EVP_PKEY **ppkey, EVP_PKEY **ppubkey, + EVP_PKEY **pparams, + X509 **pcert, STACK_OF(X509) **pcerts, + X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls) { 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; + int ncerts = 0, ncrls = 0, expect = -1; + const char *failed = FAIL_NAME; 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); + /* 'failed' describes type of credential to load for potential error msg */ + if (failed == NULL) { + if (!quiet) + BIO_printf(bio_err, "Internal error: nothing was requested to load from %s\n", + uri != NULL ? uri : ""); + return 0; } + /* suppress any extraneous errors left over from failed parse attempts */ + ERR_set_mark(); + + SET_EXPECT1(ppkey, OSSL_STORE_INFO_PKEY); + SET_EXPECT1(ppubkey, OSSL_STORE_INFO_PUBKEY); + SET_EXPECT1(pparams, OSSL_STORE_INFO_PARAMS); + SET_EXPECT1(pcert, OSSL_STORE_INFO_CERT); + /* + * Up to here, the follwing holds. + * If just one of the ppkey, ppubkey, pparams, and pcert function parameters + * is nonzero, expect > 0 indicates which type of credential is expected. + * If expect == 0, more than one of them is nonzero (multiple types expected). + */ + if (pcerts != NULL) { if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) { - BIO_printf(bio_err, "Out of memory loading"); + if (!quiet) + 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); + /* + * Adapt the 'expect' variable: + * set to OSSL_STORE_INFO_CERT if no other type is expected so far, + * otherwise set to 0 (indicating that multiple types are expected). + */ + SET_EXPECT(OSSL_STORE_INFO_CERT); } + SET_EXPECT1(pcrl, 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"); + if (!quiet) + 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 : ""); - return 0; + /* + * Adapt the 'expect' variable: + * set to OSSL_STORE_INFO_CRL if no other type is expected so far, + * otherwise set to 0 (indicating that multiple types are expected). + */ + SET_EXPECT(OSSL_STORE_INFO_CRL); } 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; + 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\n"); + if (!quiet) + BIO_printf(bio_err, "No filename or uri specified for loading\n"); goto end; } uri = ""; @@ -961,16 +1037,23 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, params, NULL, NULL); } if (ctx == NULL) { - BIO_printf(bio_err, "Could not open file or uri for loading"); + if (!quiet) + BIO_printf(bio_err, "Could not open file or uri for loading"); goto end; } + /* expect == 0 means here multiple types of credentials are to be loaded */ if (expect > 0 && !OSSL_STORE_expect(ctx, expect)) { - BIO_printf(bio_err, "Internal error trying to load"); + if (!quiet) + BIO_printf(bio_err, "Internal error trying to load"); goto end; } failed = NULL; - while (cnt_expectations > 0 && !OSSL_STORE_eof(ctx)) { + /* from here, failed != NULL only if actually an error has been detected */ + + while ((ppkey != NULL || ppubkey != NULL || pparams != NULL + || pcert != NULL || pcerts != NULL || pcrl != NULL || pcrls != NULL) + && !OSSL_STORE_eof(ctx)) { OSSL_STORE_INFO *info = OSSL_STORE_load(ctx); int type, ok = 1; @@ -988,91 +1071,85 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, type = OSSL_STORE_INFO_get_type(info); switch (type) { case OSSL_STORE_INFO_PKEY: - if (ppkey != NULL && *ppkey == NULL) { + if (ppkey != NULL) { ok = (*ppkey = OSSL_STORE_INFO_get1_PKEY(info)) != NULL; - cnt_expectations -= ok; + if (ok) + ppkey = NULL; + break; } /* * 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; + /* fall through */ case OSSL_STORE_INFO_PUBKEY: - if (ppubkey != NULL && *ppubkey == NULL) { - ok = ((*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL); - cnt_expectations -= ok; + if (ppubkey != NULL) { + ok = (*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL; + if (ok) + ppubkey = NULL; } break; case OSSL_STORE_INFO_PARAMS: - if (pparams != NULL && *pparams == NULL) { - ok = ((*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL); - cnt_expectations -= ok; + if (pparams != NULL) { + ok = (*pparams = OSSL_STORE_INFO_get1_PARAMS(info)) != NULL; + if (ok) + pparams = NULL; } break; case OSSL_STORE_INFO_CERT: - if (pcert != NULL && *pcert == NULL) { + if (pcert != NULL) { ok = (*pcert = OSSL_STORE_INFO_get1_CERT(info)) != NULL; - cnt_expectations -= ok; - } - else if (pcerts != NULL) + if (ok) + pcert = NULL; + } 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) { + if (pcrl != NULL) { ok = (*pcrl = OSSL_STORE_INFO_get1_CRL(info)) != NULL; - cnt_expectations -= ok; - } - else if (pcrls != NULL) + if (ok) + pcrl = NULL; + } else if (pcrls != NULL) { ok = sk_X509_CRL_push(*pcrls, OSSL_STORE_INFO_get1_CRL(info)); + } ncrls += ok; break; default: - /* skip any other type */ + /* skip any other type; ok stays == 1 */ break; } OSSL_STORE_INFO_free(info); if (!ok) { - failed = info == NULL ? NULL : OSSL_STORE_INFO_type_string(type); - BIO_printf(bio_err, "Error reading"); + failed = OSSL_STORE_INFO_type_string(type); + if (!quiet) + 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"); - } + /* see if any of the requested types of credentials was not found */ + if (failed == NULL) { + if (ncerts > 0) + pcerts = NULL; + if (ncrls > 0) + pcrls = NULL; + failed = FAIL_NAME; + if (failed != NULL && !quiet) + BIO_printf(bio_err, "Could not find"); } - if (!suppress_decode_errors && failed != NULL) { + + if (failed != NULL && !quiet) { + unsigned long err = ERR_peek_last_error(); + + /* continue the error message with the type of credential affected */ if (desc != NULL && strstr(desc, failed) != NULL) { BIO_printf(bio_err, " %s", desc); } else { @@ -1082,39 +1159,31 @@ int load_key_certs_crls_suppress(const char *uri, int format, int maybe_stdin, } if (uri != NULL) BIO_printf(bio_err, " from %s", uri); + if (ERR_SYSTEM_ERROR(err)) { + /* provide more readable diagnostic output */ + BIO_printf(bio_err, ": %s", strerror(ERR_GET_REASON(err))); + ERR_pop_to_mark(); + ERR_set_mark(); + } BIO_printf(bio_err, "\n"); ERR_print_errors(bio_err); } - if (suppress_decode_errors || failed == NULL) - /* clear any spurious errors */ - ERR_clear_error(); + if (quiet || failed == NULL) + /* clear any suppressed or spurious errors */ + ERR_pop_to_mark(); + else + ERR_clear_last_mark(); 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 X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +#define X509V3_EXT_DEFAULT 0 /* Return error for unknown exts */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) /* Print error for unknown exts */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) /* ASN1 parse unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) /* BIO_dump unknown extensions */ #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ - X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) + X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) int set_cert_ex(unsigned long *flags, const char *arg) { @@ -1245,11 +1314,12 @@ int copy_extensions(X509 *x, X509_REQ *req, int copy_type) } static int set_multi_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl) + 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); @@ -1263,12 +1333,12 @@ static int set_multi_opts(unsigned long *flags, const char *arg, } static int set_table_opts(unsigned long *flags, const char *arg, - const NAME_EX_TBL * in_tbl) + const NAME_EX_TBL *in_tbl) { char c; const NAME_EX_TBL *ptbl; - c = arg[0]; + c = arg[0]; if (c == '-') { c = 0; arg++; @@ -1341,7 +1411,7 @@ void print_bignum_var(BIO *out, const BIGNUM *in, const char *var, BIO_printf(out, "\n };\n"); } -void print_array(BIO *out, const char* title, int len, const unsigned char* d) +void print_array(BIO *out, const char *title, int len, const unsigned char *d) { int i; @@ -1375,9 +1445,13 @@ X509_STORE *setup_verify(const char *CAfile, int noCAfile, 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; + libctx, propq) <= 0) { + ERR_clear_error(); + if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_ASN1, + 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, @@ -1514,8 +1588,8 @@ BIGNUM *load_serial(const char *serialfile, int *exists, int create, return ret; } -int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, - ASN1_INTEGER **retai) +int save_serial(const char *serialfile, const char *suffix, + const BIGNUM *serial, ASN1_INTEGER **retai) { char buf[1][BSIZE]; BIO *out = NULL; @@ -1532,13 +1606,13 @@ int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial goto err; } - if (suffix == NULL) + if (suffix == NULL) { OPENSSL_strlcpy(buf[0], serialfile, BSIZE); - else { + } else { #ifndef OPENSSL_SYS_VMS - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, suffix); #else - j = BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, suffix); #endif } out = BIO_new_file(buf[0], "w"); @@ -1580,11 +1654,11 @@ int rotate_serial(const char *serialfile, const char *new_suffix, 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); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s.%s", serialfile, new_suffix); + 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); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", serialfile, new_suffix); + BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", serialfile, old_suffix); #endif if (rename(serialfile, buf[1]) < 0 && errno != ENOENT #ifdef ENOTDIR @@ -1673,21 +1747,20 @@ CA_DB *load_index(const char *dbfile, DB_ATTR *db_attr) tmpdb = NULL; if (db_attr) retdb->attributes = *db_attr; - else { + else retdb->attributes.unique_subject = 1; - } - if (dbattr_conf) { - char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); - if (p) { + if (dbattr_conf != NULL) { + char *p = app_conf_try_string(dbattr_conf, NULL, "unique_subject"); + + if (p != NULL) retdb->attributes.unique_subject = parse_yesno(p, 1); - } else { - ERR_clear_error(); - } - } retdb->dbfname = OPENSSL_strdup(dbfile); + if (retdb->dbfname == NULL) + goto err; + #ifndef OPENSSL_NO_POSIX_IO retdb->dbst = dbst; #endif @@ -1740,13 +1813,13 @@ int save_index(const char *dbfile, const char *suffix, CA_DB *db) 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); + BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr", dbfile); + BIO_snprintf(buf[1], sizeof(buf[1]), "%s.attr.%s", dbfile, suffix); + 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); + BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr", dbfile); + BIO_snprintf(buf[1], sizeof(buf[1]), "%s-attr-%s", dbfile, suffix); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, suffix); #endif out = BIO_new_file(buf[0], "w"); if (out == NULL) { @@ -1790,17 +1863,17 @@ int rotate_index(const char *dbfile, const char *new_suffix, 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); + BIO_snprintf(buf[4], sizeof(buf[4]), "%s.attr", dbfile); + BIO_snprintf(buf[3], sizeof(buf[3]), "%s.attr.%s", dbfile, old_suffix); + BIO_snprintf(buf[2], sizeof(buf[2]), "%s.attr.%s", dbfile, new_suffix); + BIO_snprintf(buf[1], sizeof(buf[1]), "%s.%s", dbfile, old_suffix); + 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); + BIO_snprintf(buf[4], sizeof(buf[4]), "%s-attr", dbfile); + BIO_snprintf(buf[3], sizeof(buf[3]), "%s-attr-%s", dbfile, old_suffix); + BIO_snprintf(buf[2], sizeof(buf[2]), "%s-attr-%s", dbfile, new_suffix); + BIO_snprintf(buf[1], sizeof(buf[1]), "%s-%s", dbfile, old_suffix); + BIO_snprintf(buf[0], sizeof(buf[0]), "%s-%s", dbfile, new_suffix); #endif if (rename(dbfile, buf[1]) < 0 && errno != ENOENT #ifdef ENOTDIR @@ -1911,6 +1984,7 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti, unsigned char *valstr; int nid; int ismulti = nextismulti; + nextismulti = 0; /* Collect the type */ @@ -1970,7 +2044,7 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti, ERR_print_errors(bio_err); BIO_printf(bio_err, "%s: Error adding %s name attribute \"/%s=%s\"\n", - opt_getprog(), desc, typestr ,valstr); + opt_getprog(), desc, typestr, valstr); goto err; } } @@ -2068,6 +2142,7 @@ 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); @@ -2119,7 +2194,7 @@ unsigned char *next_protos_parse(size_t *outlen, const char *in) OPENSSL_free(out); return NULL; } - out[start-skipped] = (unsigned char)(i - start); + out[start - skipped] = (unsigned char)(i - start); start = i + 1; } else { out[i + 1 - skipped] = in[i]; @@ -2135,29 +2210,43 @@ unsigned char *next_protos_parse(size_t *outlen, const char *in) return out; } -void print_cert_checks(BIO *bio, X509 *x, - const char *checkhost, - const char *checkemail, const char *checkip) +int check_cert_attributes(BIO *bio, X509 *x, const char *checkhost, + const char *checkemail, const char *checkip, + int print) { + int valid_host = 0; + int valid_mail = 0; + int valid_ip = 0; + int ret = 1; + 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"); + return 0; + + if (checkhost != NULL) { + valid_host = X509_check_host(x, checkhost, 0, 0, NULL); + if (print) + BIO_printf(bio, "Hostname %s does%s match certificate\n", + checkhost, valid_host == 1 ? "" : " NOT"); + ret = ret && valid_host > 0; } - if (checkemail) { - BIO_printf(bio, "Email %s does%s match certificate\n", - checkemail, X509_check_email(x, checkemail, 0, 0) - ? "" : " NOT"); + if (checkemail != NULL) { + valid_mail = X509_check_email(x, checkemail, 0, 0); + if (print) + BIO_printf(bio, "Email %s does%s match certificate\n", + checkemail, valid_mail ? "" : " NOT"); + ret = ret && valid_mail > 0; } - if (checkip) { - BIO_printf(bio, "IP %s does%s match certificate\n", - checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT"); + if (checkip != NULL) { + valid_ip = X509_check_ip_asc(x, checkip, 0); + if (print) + BIO_printf(bio, "IP %s does%s match certificate\n", + checkip, valid_ip ? "" : " NOT"); + ret = ret && valid_ip > 0; } + + return ret; } static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts) @@ -2169,6 +2258,7 @@ static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts) 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); @@ -2188,6 +2278,7 @@ static int do_x509_init(X509 *x, STACK_OF(OPENSSL_STRING) *opts) 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); @@ -2207,6 +2298,7 @@ static int do_x509_req_init(X509_REQ *x, STACK_OF(OPENSSL_STRING) *opts) 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); @@ -2253,50 +2345,57 @@ static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx, 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" */ + ASN1_OCTET_STRING *encoded = X509_EXTENSION_get_data(found_ext); + int disabled = ASN1_STRING_length(encoded) <= 2; /* indicating "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 { + } else { rv = !add_default || X509_add_ext(cert, new_ext, -1); } X509_EXTENSION_free(new_ext); return rv; } +int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey) +{ + int match; + + ERR_set_mark(); + match = X509_check_private_key(cert, pkey); + ERR_pop_to_mark(); + return match; +} + /* 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, +int do_X509_sign(X509 *cert, int force_v1, 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 (!force_v1) { if (!X509_set_version(cert, X509_VERSION_3)) goto end; /* - * Add default SKID before such that default AKID can make use of it + * Add default SKID before AKID such that 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(); + self_sign = cert_matches_key(cert, pkey); if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier", "keyid, issuer", !self_sign)) goto end; } + /* May add further measures for ensuring RFC 5280 compliance, see #19805 */ if (mctx != NULL && do_sign_init(mctx, pkey, md, sigopts) > 0) rv = (X509_sign_ctx(cert, mctx) > 0); @@ -2356,8 +2455,7 @@ int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey, int rv = 0; if (do_x509_req_init(x, vfyopts) > 0) - rv = X509_REQ_verify_ex(x, pkey, - app_get0_libctx(), app_get0_propq()); + rv = X509_REQ_verify_ex(x, pkey, app_get0_libctx(), app_get0_propq()); else rv = -1; return rv; @@ -2371,6 +2469,7 @@ static const char *get_dp_url(DIST_POINT *dp) GENERAL_NAME *gen; int i, gtype; ASN1_STRING *uri; + if (!dp->distpoint || dp->distpoint->type != 0) return NULL; gens = dp->distpoint->name.fullname; @@ -2396,8 +2495,10 @@ 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"); @@ -2425,18 +2526,24 @@ static STACK_OF(X509_CRL) *crls_http_cb(const X509_STORE_CTX *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); + + if (crl == NULL || !sk_X509_CRL_push(crls, crl)) + goto error; + /* 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); + + if (crl != NULL && !sk_X509_CRL_push(crls, crl)) + goto error; + return crls; + +error: + X509_CRL_free(crl); + sk_X509_CRL_free(crls); + return NULL; } void store_setup_crl_download(X509_STORE *st) @@ -2444,7 +2551,7 @@ void store_setup_crl_download(X509_STORE *st) X509_STORE_set_lookup_crls_cb(st, crls_http_cb); } -#ifndef OPENSSL_NO_SOCK +#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP) static const char *tls_error_hint(void) { unsigned long err = ERR_peek_error(); @@ -2452,7 +2559,7 @@ static const char *tls_error_hint(void) if (ERR_GET_LIB(err) != ERR_LIB_SSL) err = ERR_peek_last_error(); if (ERR_GET_LIB(err) != ERR_LIB_SSL) - return NULL; + return NULL; /* likely no TLS error */ switch (ERR_GET_REASON(err)) { case SSL_R_WRONG_VERSION_NUMBER: @@ -2465,11 +2572,29 @@ static const char *tls_error_hint(void) 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; + default: + return NULL; /* no hint available for TLS error */ } } +static BIO *http_tls_shutdown(BIO *bio) +{ + if (bio != NULL) { + BIO *cbio; + const char *hint = tls_error_hint(); + + if (hint != NULL) + BIO_printf(bio_err, "%s\n", hint); + (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; +} + /* HTTP callback function that supports TLS connection also via HTTPS proxy */ BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail) { @@ -2494,7 +2619,7 @@ BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail) || (sbio = BIO_new(BIO_f_ssl())) == NULL) { return NULL; } - if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) { + if ((ssl = SSL_new(ssl_ctx)) == NULL) { BIO_free(sbio); return NULL; } @@ -2506,24 +2631,8 @@ BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail) 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; - } + } else { /* disconnect from TLS */ + bio = http_tls_shutdown(bio); } return bio; } @@ -2648,18 +2757,18 @@ static int WIN32_rename(const char *from, const char *to) 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 !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 !defined(_WIN32_WCE) || _WIN32_WCE >= 101 if (!MultiByteToWideChar(CP_ACP, 0, to, tlen, (WCHAR *)tto, tlen)) # endif for (i = 0; i < tlen; i++) @@ -2697,6 +2806,7 @@ double app_tminterval(int stop, int usertime) double ret = 0; static ULARGE_INTEGER tmstart; static int warning = 1; + int use_GetSystemTime = 1; # ifdef _WIN32_WINNT static HANDLE proc = NULL; @@ -2710,10 +2820,12 @@ double app_tminterval(int stop, int usertime) if (usertime && proc != (HANDLE) - 1) { FILETIME junk; + GetProcessTimes(proc, &junk, &junk, &junk, &now); - } else + use_GetSystemTime = 0; + } # endif - { + if (use_GetSystemTime) { SYSTEMTIME systime; if (usertime && warning) { @@ -2793,6 +2905,7 @@ double app_tminterval(int stop, int usertime) tmstart = now; } else { long int tck = sysconf(_SC_CLK_TCK); + ret = (now - tmstart) / (double)tck; } @@ -2825,7 +2938,7 @@ double app_tminterval(int stop, int usertime) } #endif -int app_access(const char* name, int flag) +int app_access(const char *name, int flag) { #ifdef _WIN32 return _access(name, flag); @@ -2846,7 +2959,7 @@ static int stdin_sock = -1; static void close_stdin_sock(void) { - TerminalSocket (TERM_SOCK_DELETE, &stdin_sock); + TerminalSocket(TERM_SOCK_DELETE, &stdin_sock); } int fileno_stdin(void) @@ -2874,6 +2987,7 @@ int fileno_stdout(void) int raw_read_stdin(void *buf, int siz) { DWORD n; + if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), buf, siz, &n, NULL)) return n; else @@ -2887,11 +3001,6 @@ 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 -# endif -# endif int raw_read_stdin(void *buf, int siz) { return read(fileno_stdin(), buf, siz); @@ -2902,27 +3011,19 @@ int raw_read_stdin(void *buf, int siz) 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 -# endif -# endif -int raw_write_stdout(const void *buf,int siz) +#elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) \ + && defined(_SPT_MODEL_) +int raw_write_stdout(const void *buf, int siz) { - return write(fileno(stdout),(void*)buf,siz); + return write(fileno(stdout), (void *)buf, siz); } #else -# if defined(__TANDEM) -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif -# endif int raw_write_stdout(const void *buf, int siz) { return write(fileno_stdout(), buf, siz); @@ -2969,6 +3070,7 @@ 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); @@ -3057,7 +3159,8 @@ BIO *bio_open_owner(const char *filename, int format, int private) } # ifdef OPENSSL_SYS_VMS - /* VMS doesn't have O_BINARY, it just doesn't make sense. But, + /* + * 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. @@ -3139,6 +3242,32 @@ BIO *bio_open_default_quiet(const char *filename, char mode, int format) return bio_open_default_(filename, mode, format, 1); } +int mem_bio_to_file(BIO *in, const char *filename, int format, int private) +{ + int rv = 0, ret = 0; + BIO *out = NULL; + BUF_MEM *mem_buffer = NULL; + + rv = BIO_get_mem_ptr(in, &mem_buffer); + if (rv <= 0) { + BIO_puts(bio_err, "Error reading mem buffer\n"); + goto end; + } + out = bio_open_owner(filename, format, private); + if (out == NULL) + goto end; + rv = BIO_write(out, mem_buffer->data, mem_buffer->length); + if (rv < 0 || (size_t)rv != mem_buffer->length) + BIO_printf(bio_err, "Error writing to output file: '%s'\n", filename); + else + ret = 1; +end: + if (!ret) + ERR_print_errors(bio_err); + BIO_free_all(out); + return ret; +} + void wait_for_async(SSL *s) { /* On Windows select only works for sockets, so we simply don't wait */ @@ -3201,27 +3330,59 @@ int has_stdin_waiting(void) /* Corrupt a signature by modifying final byte */ void corrupt_signature(const ASN1_STRING *signature) { - unsigned char *s = signature->data; - s[signature->length - 1] ^= 0x1; + unsigned char *s = signature->data; + + s[signature->length - 1] ^= 0x1; +} + +int check_cert_time_string(const char *time, const char *desc) +{ + if (time == NULL || strcmp(time, "today") == 0 + || ASN1_TIME_set_string_X509(NULL, time)) + return 1; + BIO_printf(bio_err, + "%s is invalid, it should be \"today\" or have format [CC]YYMMDDHHMMSSZ\n", + desc); + return 0; } int set_cert_times(X509 *x, const char *startdate, const char *enddate, - int days) + int days, int strict_compare_times) { + if (!check_cert_time_string(startdate, "start date")) + return 0; + if (!check_cert_time_string(enddate, "end date")) + return 0; if (startdate == NULL || strcmp(startdate, "today") == 0) { - if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) + if (X509_gmtime_adj(X509_getm_notBefore(x), 0) == NULL) { + BIO_printf(bio_err, "Error setting notBefore certificate field\n"); return 0; + } } else { - if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) + if (!ASN1_TIME_set_string_X509(X509_getm_notBefore(x), startdate)) { + BIO_printf(bio_err, "Error setting notBefore certificate field\n"); return 0; + } + } + if (enddate != NULL && strcmp(enddate, "today") == 0) { + enddate = NULL; + days = 0; } if (enddate == NULL) { - if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) - == NULL) + if (X509_time_adj_ex(X509_getm_notAfter(x), days, 0, NULL) == NULL) { + BIO_printf(bio_err, "Error setting notAfter certificate field\n"); return 0; + } } else if (!ASN1_TIME_set_string_X509(X509_getm_notAfter(x), enddate)) { + BIO_printf(bio_err, "Error setting notAfter certificate field\n"); return 0; } + if (ASN1_TIME_compare(X509_get0_notAfter(x), X509_get0_notBefore(x)) < 0) { + BIO_printf(bio_err, "%s: end date before start date\n", + strict_compare_times ? "Error" : "Warning"); + if (strict_compare_times) + return 0; + } return 1; } @@ -3284,18 +3445,6 @@ void make_uppercase(char *string) 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) { @@ -3390,6 +3539,7 @@ 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. diff --git a/apps/lib/build.info b/apps/lib/build.info index 923ef5d92b83..f0df60873401 100644 --- a/apps/lib/build.info +++ b/apps/lib/build.info @@ -8,9 +8,9 @@ IF[{- $config{target} =~ /^vms-/ -}] ENDIF # Source for libapps -$LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \ +$LIBAPPSSRC=apps.c apps_ui.c log.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \ columns.c app_params.c names.c app_provider.c app_x509.c http_server.c \ - engine.c engine_loader.c app_libctx.c + engine.c engine_loader.c app_libctx.c apps_opt_printf.c IF[{- !$disabled{apps} -}] LIBS{noinst}=../libapps.a diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index 637bd1d0b7a4..73ab1eb5600e 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 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 @@ -16,30 +16,35 @@ #include /* the context for the CMP mock server */ -typedef struct -{ +typedef struct { + X509 *refCert; /* cert to expect for oldCertID in kur/rr msg */ X509 *certOut; /* certificate to be returned in cp/ip/kup msg */ + EVP_PKEY *keyOut; /* Private key to be returned for central keygen */ + X509_CRL *crlOut; /* CRL to be returned in genp for crls */ 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 */ + STACK_OF(X509) *caPubsOut; /* used in caPubs of ip and in caCerts of genp */ + X509 *newWithNew; /* to return in newWithNew of rootKeyUpdate */ + X509 *newWithOld; /* to return in newWithOld of rootKeyUpdate */ + X509 *oldWithNew; /* to return in oldWithNew of rootKeyUpdate */ OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */ int sendError; /* send error response on given request type */ - OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ + OSSL_CMP_MSG *req; /* original request message during 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->refCert); 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); + OSSL_STACK_OF_X509_free(ctx->chainOut); + OSSL_STACK_OF_X509_free(ctx->caPubsOut); + OSSL_CMP_MSG_free(ctx->req); OPENSSL_free(ctx); } @@ -62,7 +67,28 @@ static mock_srv_ctx *mock_srv_ctx_new(void) return NULL; } -int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) +#define DEFINE_OSSL_SET1_CERT(FIELD) \ + int ossl_cmp_mock_srv_set1_##FIELD(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->FIELD); \ + ctx->FIELD = cert; \ + return 1; \ + } \ + return 0; \ + } + +DEFINE_OSSL_SET1_CERT(refCert) +DEFINE_OSSL_SET1_CERT(certOut) + +int ossl_cmp_mock_srv_set1_keyOut(OSSL_CMP_SRV_CTX *srv_ctx, EVP_PKEY *pkey) { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); @@ -70,12 +96,27 @@ int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert) 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; + if (pkey != NULL && !EVP_PKEY_up_ref(pkey)) + return 0; + EVP_PKEY_free(ctx->keyOut); + ctx->keyOut = pkey; + return 1; +} + +int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx, + X509_CRL *crl) +{ + 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; } - return 0; + if (crl != NULL && !X509_CRL_up_ref(crl)) + return 0; + X509_CRL_free(ctx->crlOut); + ctx->crlOut = crl; + return 1; } int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, @@ -90,7 +131,7 @@ int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, } if (chain != NULL && (chain_copy = X509_chain_up_ref(chain)) == NULL) return 0; - sk_X509_pop_free(ctx->chainOut, X509_free); + OSSL_STACK_OF_X509_free(ctx->chainOut); ctx->chainOut = chain_copy; return 1; } @@ -107,11 +148,15 @@ int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, } if (caPubs != NULL && (caPubs_copy = X509_chain_up_ref(caPubs)) == NULL) return 0; - sk_X509_pop_free(ctx->caPubsOut, X509_free); + OSSL_STACK_OF_X509_free(ctx->caPubsOut); ctx->caPubsOut = caPubs_copy; return 1; } +DEFINE_OSSL_SET1_CERT(newWithNew) +DEFINE_OSSL_SET1_CERT(newWithOld) +DEFINE_OSSL_SET1_CERT(oldWithNew) + int ossl_cmp_mock_srv_set_statusInfo(OSSL_CMP_SRV_CTX *srv_ctx, int status, int fail_info, const char *text) { @@ -170,6 +215,70 @@ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) return 1; } +/* determine whether to delay response to (non-polling) request */ +static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + int req_type = OSSL_CMP_MSG_get_bodytype(req); + + if (ctx == NULL || req == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return -1; + } + + /* + * For ir/cr/p10cr/kur delayed delivery is handled separately in + * process_cert_request + */ + if (req_type == OSSL_CMP_IR + || req_type == OSSL_CMP_CR + || req_type == OSSL_CMP_P10CR + || req_type == OSSL_CMP_KUR + /* Client may use error to abort the ongoing polling */ + || req_type == OSSL_CMP_ERROR) + return 0; + + if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { + /* start polling */ + if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL) + return -1; + return 1; + } + return 0; +} + +/* check for matching reference cert components, as far as given */ +static int refcert_cmp(const X509 *refcert, + const X509_NAME *issuer, const ASN1_INTEGER *serial) +{ + const X509_NAME *ref_issuer; + const ASN1_INTEGER *ref_serial; + + if (refcert == NULL) + return 1; + ref_issuer = X509_get_issuer_name(refcert); + ref_serial = X509_get0_serialNumber(refcert); + return (ref_issuer == NULL || X509_NAME_cmp(issuer, ref_issuer) == 0) + && (ref_serial == NULL || ASN1_INTEGER_cmp(serial, ref_serial) == 0); +} + +/* reset the state that belongs to a transaction */ +static int clean_transaction(OSSL_CMP_SRV_CTX *srv_ctx, + ossl_unused const ASN1_OCTET_STRING *id) +{ + 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->curr_pollCount = 0; + OSSL_CMP_MSG_free(ctx->req); + ctx->req = NULL; + return 1; +} + static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *cert_req, ossl_unused int certReqId, @@ -180,15 +289,17 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, STACK_OF(X509) **caPubs) { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + int bodytype, central_keygen; OSSL_CMP_PKISI *si = NULL; + EVP_PKEY *keyOut = 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 == 1 - || ctx->sendError == OSSL_CMP_MSG_get_bodytype(cert_req)) { + bodytype = OSSL_CMP_MSG_get_bodytype(cert_req); + if (ctx->sendError == 1 || ctx->sendError == bodytype) { ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return NULL; } @@ -199,12 +310,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, 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) + if ((ctx->req = OSSL_CMP_MSG_dup(cert_req)) == NULL) return NULL; return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); } @@ -212,24 +318,54 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, /* 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) { + /* accept cert profile for cr messages only with the configured name */ + if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_CR) { + STACK_OF(OSSL_CMP_ITAV) *itavs = + OSSL_CMP_HDR_get0_geninfo_ITAVs(OSSL_CMP_MSG_get0_header(cert_req)); + int i; + + for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) { + OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_value(itavs, i); + ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(itav); + STACK_OF(ASN1_UTF8STRING) *strs; + ASN1_UTF8STRING *str; + const char *data; + + if (OBJ_obj2nid(obj) == NID_id_it_certProfile) { + if (!OSSL_CMP_ITAV_get0_certProfile(itav, &strs)) + return NULL; + if (sk_ASN1_UTF8STRING_num(strs) < 1) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + str = sk_ASN1_UTF8STRING_value(strs, 0); + if (str == NULL + || (data = + (const char *)ASN1_STRING_get0_data(str)) == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + if (strcmp(data, "profile1") != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + break; + } + } + } + + /* accept cert update request only for the reference cert, if given */ + if (bodytype == OSSL_CMP_KUR + && crm != NULL /* thus not p10cr */ && ctx->refCert != 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) { + if (!refcert_cmp(ctx->refCert, + OSSL_CRMF_CERTID_get0_issuer(cid), + OSSL_CRMF_CERTID_get0_serialNumber(cid))) { ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_CERTID); return NULL; } @@ -237,11 +373,29 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, if (ctx->certOut != NULL && (*certOut = X509_dup(ctx->certOut)) == NULL) + /* Should return a cert produced from request template, see FR #16054 */ goto err; + + central_keygen = OSSL_CRMF_MSG_centralkeygen_requested(crm, p10cr); + if (central_keygen < 0) + goto err; + if (central_keygen == 1 + && (ctx->keyOut == NULL + || (keyOut = EVP_PKEY_dup(ctx->keyOut)) == NULL + || !OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx), + 1 /* priv */, keyOut))) { + EVP_PKEY_free(keyOut); + goto err; + } + /* + * Note that this uses newPkey to return the private key + * and does not check whether the 'popo' field is absent. + */ + if (ctx->chainOut != NULL && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL) goto err; - if (ctx->caPubsOut != NULL + if (ctx->caPubsOut != NULL /* OSSL_CMP_PKIBODY_IP not visible here */ && (*caPubs = X509_chain_up_ref(ctx->caPubsOut)) == NULL) goto err; if (ctx->statusOut != NULL @@ -252,9 +406,9 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, err: X509_free(*certOut); *certOut = NULL; - sk_X509_pop_free(*chainOut, X509_free); + OSSL_STACK_OF_X509_free(*chainOut); *chainOut = NULL; - sk_X509_pop_free(*caPubs, X509_free); + OSSL_STACK_OF_X509_free(*caPubs); *caPubs = NULL; return NULL; } @@ -270,20 +424,16 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return NULL; } - if (ctx->certOut == NULL || ctx->sendError == 1 + if (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) { + /* allow any RR derived from CSR which does not include issuer and serial */ + if ((issuer != NULL || serial != NULL) + /* accept revocation only for the reference cert, if given */ + && !refcert_cmp(ctx->refCert, issuer, serial)) { ERR_raise_data(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED, "wrong certificate to revoke"); return NULL; @@ -291,6 +441,136 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, return OSSL_CMP_PKISI_dup(ctx->statusOut); } +/* return -1 for error, 0 for no update available */ +static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList, + const X509_CRL *crl) +{ + OSSL_CMP_CRLSTATUS *crlstatus; + DIST_POINT_NAME *dpn = NULL; + GENERAL_NAMES *issuer = NULL; + ASN1_TIME *thisupd = NULL; + + if (sk_OSSL_CMP_CRLSTATUS_num(crlStatusList) != 1) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST); + return -1; + } + if (crl == NULL) + return 0; + + crlstatus = sk_OSSL_CMP_CRLSTATUS_value(crlStatusList, 0); + if (!OSSL_CMP_CRLSTATUS_get0(crlstatus, &dpn, &issuer, &thisupd)) + return -1; + + if (issuer != NULL) { + GENERAL_NAME *gn = sk_GENERAL_NAME_value(issuer, 0); + + if (gn != NULL && gn->type == GEN_DIRNAME) { + X509_NAME *gen_name = gn->d.dirn; + + if (X509_NAME_cmp(gen_name, X509_CRL_get_issuer(crl)) != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER); + return -1; + } + } else { + ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED); + return -1; /* error according to RFC 9483 section 4.3.4 */ + } + } + + return thisupd == NULL + || ASN1_TIME_compare(thisupd, X509_CRL_get0_lastUpdate(crl)) < 0; +} + +static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid, + const OSSL_CMP_ITAV *req) +{ + OSSL_CMP_ITAV *rsp = NULL; + + switch (req_nid) { + case NID_id_it_caCerts: + rsp = OSSL_CMP_ITAV_new_caCerts(ctx->caPubsOut); + break; + case NID_id_it_rootCaCert: + { + X509 *rootcacert = NULL; + + if (!OSSL_CMP_ITAV_get0_rootCaCert(req, &rootcacert)) + return NULL; + + if (rootcacert != NULL + && X509_NAME_cmp(X509_get_subject_name(rootcacert), + X509_get_subject_name(ctx->newWithNew)) != 0) + /* The subjects do not match */ + rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(NULL, NULL, NULL); + else + rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx->newWithNew, + ctx->newWithOld, + ctx->oldWithNew); + } + break; + case NID_id_it_crlStatusList: + { + STACK_OF(OSSL_CMP_CRLSTATUS) *crlstatuslist = NULL; + int res = 0; + + if (!OSSL_CMP_ITAV_get0_crlStatusList(req, &crlstatuslist)) + return NULL; + + res = check_client_crl(crlstatuslist, ctx->crlOut); + if (res < 0) + rsp = NULL; + else + rsp = OSSL_CMP_ITAV_new_crls(res == 0 ? NULL : ctx->crlOut); + } + break; + case NID_id_it_certReqTemplate: + { + OSSL_CRMF_CERTTEMPLATE *reqtemp; + OSSL_CMP_ATAVS *keyspec = NULL; + X509_ALGOR *keyalg = NULL; + OSSL_CMP_ATAV *rsakeylen, *eckeyalg; + int ok = 0; + + if ((reqtemp = OSSL_CRMF_CERTTEMPLATE_new()) == NULL) + return NULL; + + if (!OSSL_CRMF_CERTTEMPLATE_fill(reqtemp, NULL, NULL, + X509_get_issuer_name(ctx->refCert), + NULL)) + goto crt_err; + + if ((keyalg = X509_ALGOR_new()) == NULL) + goto crt_err; + + (void)X509_ALGOR_set0(keyalg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), + V_ASN1_UNDEF, NULL); /* cannot fail */ + + eckeyalg = OSSL_CMP_ATAV_new_algId(keyalg); + rsakeylen = OSSL_CMP_ATAV_new_rsaKeyLen(4096); + ok = OSSL_CMP_ATAV_push1(&keyspec, eckeyalg) + && OSSL_CMP_ATAV_push1(&keyspec, rsakeylen); + OSSL_CMP_ATAV_free(eckeyalg); + OSSL_CMP_ATAV_free(rsakeylen); + X509_ALGOR_free(keyalg); + + if (!ok) + goto crt_err; + + rsp = OSSL_CMP_ITAV_new0_certReqTemplate(reqtemp, keyspec); + return rsp; + + crt_err: + OSSL_CRMF_CERTTEMPLATE_free(reqtemp); + OSSL_CMP_ATAVS_free(keyspec); + return NULL; + } + break; + default: + rsp = OSSL_CMP_ITAV_dup(req); + } + return rsp; +} + static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *genm, const STACK_OF(OSSL_CMP_ITAV) *in, @@ -308,6 +588,18 @@ static int process_genm(OSSL_CMP_SRV_CTX *srv_ctx, ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } + if (sk_OSSL_CMP_ITAV_num(in) == 1) { + OSSL_CMP_ITAV *req = sk_OSSL_CMP_ITAV_value(in, 0), *rsp; + ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(req); + + if ((*out = sk_OSSL_CMP_ITAV_new_reserve(NULL, 1)) == NULL) + return 0; + rsp = process_genm_itav(ctx, OBJ_obj2nid(obj), req); + if (rsp != NULL && sk_OSSL_CMP_ITAV_push(*out, rsp)) + return 1; + sk_OSSL_CMP_ITAV_free(*out); + return 0; + } *out = sk_OSSL_CMP_ITAV_deep_copy(in, OSSL_CMP_ITAV_dup, OSSL_CMP_ITAV_free); @@ -351,10 +643,9 @@ static void process_error(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *error, 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, "\""); + ASN1_STRING_print_ex(bio_err, + sk_ASN1_UTF8STRING_value(errorDetails, i), + ASN1_STRFLGS_ESC_QUOTE); } BIO_printf(bio_err, "\n"); } @@ -391,38 +682,38 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return 1; } +/* return 0 on failure, 1 on success, setting *req or otherwise *check_after */ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *pollReq, ossl_unused int certReqId, - OSSL_CMP_MSG **certReq, int64_t *check_after) + OSSL_CMP_MSG **req, int64_t *check_after) { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + if (req != NULL) + *req = NULL; if (ctx == NULL || pollReq == NULL - || certReq == NULL || check_after == NULL) { + || req == NULL || check_after == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } + 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); + if (ctx->req == NULL) { /* not currently in polling mode */ + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ); return 0; } if (++ctx->curr_pollCount >= ctx->pollCount) { /* end polling */ - *certReq = ctx->certReq; - ctx->certReq = NULL; + *req = ctx->req; + ctx->req = NULL; *check_after = 0; } else { - *certReq = NULL; *check_after = ctx->checkAfterTime; } return 1; @@ -436,7 +727,9 @@ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) 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)) + process_certConf, process_pollReq) + && OSSL_CMP_SRV_CTX_init_trans(srv_ctx, + delayed_delivery, clean_transaction)) return srv_ctx; mock_srv_ctx_free(ctx); diff --git a/apps/lib/engine_loader.c b/apps/lib/engine_loader.c index 42775a89f361..e0f26f614afe 100644 --- a/apps/lib/engine_loader.c +++ b/apps/lib/engine_loader.c @@ -14,6 +14,7 @@ */ #define OPENSSL_SUPPRESS_DEPRECATED +#include "internal/e_os.h" #include "apps.h" #ifndef OPENSSL_NO_ENGINE @@ -71,10 +72,8 @@ static OSSL_STORE_LOADER_CTX *engine_open(const OSSL_STORE_LOADER *loader, char *keyid = NULL; OSSL_STORE_LOADER_CTX *ctx = NULL; - if (OPENSSL_strncasecmp(p, ENGINE_SCHEME_COLON, sizeof(ENGINE_SCHEME_COLON) - 1) - != 0) + if (!CHECK_AND_SKIP_CASE_PREFIX(p, ENGINE_SCHEME_COLON)) return NULL; - p += sizeof(ENGINE_SCHEME_COLON) - 1; /* Look for engine ID */ q = strchr(p, ':'); diff --git a/apps/lib/http_server.c b/apps/lib/http_server.c index 33ae886d4a1c..8136228b32d0 100644 --- a/apps/lib/http_server.c +++ b/apps/lib/http_server.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,71 +17,36 @@ # define _POSIX_C_SOURCE 2 #endif -#include #include +#include "internal/e_os.h" #include "http_server.h" -#include "internal/sockets.h" +#include "internal/sockets.h" /* for openssl_fdset() */ + #include +#include #include #include "s_apps.h" - -#if defined(__TANDEM) -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif -#endif - -static int verbosity = LOG_INFO; +#include "log.h" #define HTTP_PREFIX "HTTP/" #define HTTP_VERSION_PATT "1." /* allow 1.x */ #define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT #define HTTP_1_0 HTTP_PREFIX_VERSION"0" /* "HTTP/1.0" */ +#define HTTP_VERSION_STR " "HTTP_PREFIX_VERSION + +#define log_HTTP(prog, level, text) \ + trace_log_message(OSSL_TRACE_CATEGORY_HTTP, prog, level, "%s", text) +#define log_HTTP1(prog, level, fmt, arg) \ + trace_log_message(OSSL_TRACE_CATEGORY_HTTP, prog, level, fmt, arg) +#define log_HTTP2(prog, level, fmt, arg1, arg2) \ + trace_log_message(OSSL_TRACE_CATEGORY_HTTP, prog, level, fmt, arg1, arg2) +#define log_HTTP3(prog, level, fmt, a1, a2, a3) \ + trace_log_message(OSSL_TRACE_CATEGORY_HTTP, prog, level, fmt, a1, a2, a3) #ifdef HTTP_DAEMON +int n_responders = 0; /* run multiple responder processes, set by ocsp.c */ +int acfd = (int)INVALID_SOCKET; -int multi = 0; /* run multiple responder processes */ -int acfd = (int) INVALID_SOCKET; - -static int print_syslog(const char *str, size_t len, void *levPtr) -{ - int level = *(int *)levPtr; - int ilen = len > MAXERRLEN ? MAXERRLEN : len; - - syslog(level, "%.*s", ilen, str); - - return ilen; -} -#endif - -void log_message(const char *prog, int level, const char *fmt, ...) -{ - va_list ap; - - if (verbosity < level) - return; - - va_start(ap, fmt); -#ifdef HTTP_DAEMON - if (multi) { - char buf[1024]; - - if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) - syslog(level, "%s", buf); - if (level <= LOG_ERR) - ERR_print_errors_cb(print_syslog, &level); - } else -#endif - { - BIO_printf(bio_err, "%s: ", prog); - BIO_vprintf(bio_err, fmt, ap); - BIO_printf(bio_err, "\n"); - (void)BIO_flush(bio_err); - } - va_end(ap); -} - -#ifdef HTTP_DAEMON void socket_timeout(int signum) { if (acfd != (int)INVALID_SOCKET) @@ -92,11 +57,11 @@ static void killall(int ret, pid_t *kidpids) { int i; - for (i = 0; i < multi; ++i) + for (i = 0; i < n_responders; ++i) if (kidpids[i] != 0) (void)kill(kidpids[i], SIGTERM); OPENSSL_free(kidpids); - ossl_sleep(1000); + OSSL_sleep(1000); exit(ret); } @@ -122,12 +87,13 @@ void spawn_loop(const char *prog) openlog(prog, LOG_PID, LOG_DAEMON); if (setpgid(0, 0)) { - syslog(LOG_ERR, "fatal: error detaching from parent process group: %s", - strerror(errno)); + log_HTTP1(prog, LOG_CRIT, + "error detaching from parent process group: %s", + strerror(errno)); exit(1); } - kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array"); - for (i = 0; i < multi; ++i) + kidpids = app_malloc(n_responders * sizeof(*kidpids), "child PID array"); + for (i = 0; i < n_responders; ++i) kidpids[i] = 0; signal(SIGINT, noteterm); @@ -140,7 +106,7 @@ void spawn_loop(const char *prog) * Wait for a child to replace when we're at the limit. * Slow down if a child exited abnormally or waitpid() < 0 */ - while (termsig == 0 && procs >= multi) { + while (termsig == 0 && procs >= n_responders) { if ((fpid = waitpid(-1, &status, 0)) > 0) { for (i = 0; i < procs; ++i) { if (kidpids[i] == fpid) { @@ -149,28 +115,34 @@ void spawn_loop(const char *prog) break; } } - if (i >= multi) { - syslog(LOG_ERR, "fatal: internal error: " - "no matching child slot for pid: %ld", - (long) fpid); + if (i >= n_responders) { + log_HTTP1(prog, LOG_CRIT, + "internal error: no matching child slot for pid: %ld", + (long)fpid); killall(1, kidpids); } if (status != 0) { - if (WIFEXITED(status)) - syslog(LOG_WARNING, "child process: %ld, exit status: %d", - (long)fpid, WEXITSTATUS(status)); - else if (WIFSIGNALED(status)) - syslog(LOG_WARNING, "child process: %ld, term signal %d%s", - (long)fpid, WTERMSIG(status), + if (WIFEXITED(status)) { + log_HTTP2(prog, LOG_WARNING, + "child process: %ld, exit status: %d", + (long)fpid, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + char *dumped = ""; + # ifdef WCOREDUMP - WCOREDUMP(status) ? " (core dumped)" : + if (WCOREDUMP(status)) + dumped = " (core dumped)"; # endif - ""); - ossl_sleep(1000); + log_HTTP3(prog, LOG_WARNING, + "child process: %ld, term signal %d%s", + (long)fpid, WTERMSIG(status), dumped); + } + OSSL_sleep(1000); } break; } else if (errno != EINTR) { - syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno)); + log_HTTP1(prog, LOG_CRIT, + "waitpid() failed: %s", strerror(errno)); killall(1, kidpids); } } @@ -180,7 +152,7 @@ void spawn_loop(const char *prog) switch (fpid = fork()) { case -1: /* error */ /* System critically low on memory, pause and try again later */ - ossl_sleep(30000); + OSSL_sleep(30000); break; case 0: /* child */ OPENSSL_free(kidpids); @@ -189,20 +161,21 @@ void spawn_loop(const char *prog) if (termsig) _exit(0); if (RAND_poll() <= 0) { - syslog(LOG_ERR, "fatal: RAND_poll() failed"); + log_HTTP(prog, LOG_CRIT, "RAND_poll() failed"); _exit(1); } return; default: /* parent */ - for (i = 0; i < multi; ++i) { + for (i = 0; i < n_responders; ++i) { if (kidpids[i] == 0) { kidpids[i] = fpid; procs++; break; } } - if (i >= multi) { - syslog(LOG_ERR, "fatal: internal error: no free child slots"); + if (i >= n_responders) { + log_HTTP(prog, LOG_CRIT, + "internal error: no free child slots"); killall(1, kidpids); } break; @@ -210,19 +183,22 @@ void spawn_loop(const char *prog) } /* The loop above can only break on termsig */ - syslog(LOG_INFO, "terminating on signal: %d", termsig); + log_HTTP1(prog, LOG_INFO, "terminating on signal: %d", termsig); killall(0, kidpids); } #endif #ifndef OPENSSL_NO_SOCK -BIO *http_server_init_bio(const char *prog, const char *port) +BIO *http_server_init(const char *prog, const char *port, int verb) { BIO *acbio = NULL, *bufbio; int asock; + int port_num; char name[40]; - snprintf(name, sizeof(name), "[::]:%s", port); /* port may be "0" */ + BIO_snprintf(name, sizeof(name), "*:%s", port); /* port may be "0" */ + if (verb >= 0 && !log_set_verbosity(prog, verb)) + return NULL; bufbio = BIO_new(BIO_f_buffer()); if (bufbio == NULL) goto err; @@ -231,27 +207,29 @@ BIO *http_server_init_bio(const char *prog, const char *port) || BIO_set_accept_ip_family(acbio, BIO_FAMILY_IPANY) <= 0 /* IPv4/6 */ || BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) <= 0 || BIO_set_accept_name(acbio, name) <= 0) { - log_message(prog, LOG_ERR, "Error setting up accept BIO"); + log_HTTP(prog, LOG_ERR, "error setting up accept BIO"); goto err; } BIO_set_accept_bios(acbio, bufbio); bufbio = NULL; if (BIO_do_accept(acbio) <= 0) { - log_message(prog, LOG_ERR, "Error starting accept"); + log_HTTP1(prog, LOG_ERR, "error setting accept on port %s", port); goto err; } /* Report back what address and port are used */ BIO_get_fd(acbio, &asock); - if (!report_server_accept(bio_out, asock, 1, 1)) { - log_message(prog, LOG_ERR, "Error printing ACCEPT string"); + port_num = report_server_accept(bio_out, asock, 1, 1); + if (port_num == 0) { + log_HTTP(prog, LOG_ERR, "error printing ACCEPT string"); goto err; } return acbio; err: + ERR_print_errors(bio_err); BIO_free_all(acbio); BIO_free(bufbio); return NULL; @@ -286,8 +264,7 @@ static int urldecode(char *p) int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, char **ppath, BIO **pcbio, BIO *acbio, int *found_keep_alive, - const char *prog, const char *port, - int accept_get, int timeout) + const char *prog, int accept_get, int timeout) { BIO *cbio = *pcbio, *getbio = NULL, *b64 = NULL; int len; @@ -301,18 +278,27 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, *ppath = NULL; if (cbio == NULL) { - log_message(prog, LOG_DEBUG, - "Awaiting new connection on port %s...", port); + char *port; + + get_sock_info_address(BIO_get_fd(acbio, NULL), NULL, &port); + if (port == NULL) { + log_HTTP(prog, LOG_ERR, "cannot get port listening on"); + goto fatal; + } + log_HTTP1(prog, LOG_DEBUG, + "awaiting new connection on port %s ...", port); + OPENSSL_free(port); + if (BIO_do_accept(acbio) <= 0) /* Connection loss before accept() is routine, ignore silently */ return ret; *pcbio = cbio = BIO_pop(acbio); } else { - log_message(prog, LOG_DEBUG, "Awaiting next request..."); + log_HTTP(prog, LOG_DEBUG, "awaiting next request ..."); } if (cbio == NULL) { - /* Cannot call http_server_send_status(cbio, ...) */ + /* Cannot call http_server_send_status(..., cbio, ...) */ ret = -1; goto out; } @@ -330,31 +316,39 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, return ret; ret = 1; if (len < 0) { - log_message(prog, LOG_WARNING, "Request line read error"); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP(prog, LOG_WARNING, "request line read error"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } - if ((end = strchr(reqbuf, '\r')) != NULL + + if (((end = strchr(reqbuf, '\r')) != NULL && end[1] == '\n') || (end = strchr(reqbuf, '\n')) != NULL) *end = '\0'; - log_message(prog, LOG_INFO, "Received request, 1st line: %s", reqbuf); + if (log_get_verbosity() < LOG_TRACE) + trace_log_message(-1, prog, LOG_INFO, + "received request, 1st line: %s", reqbuf); + log_HTTP(prog, LOG_TRACE, "received request header:"); + log_HTTP1(prog, LOG_TRACE, "%s", reqbuf); + if (end == NULL) { + log_HTTP(prog, LOG_WARNING, + "cannot parse HTTP header: missing end of line"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); + goto out; + } - meth = reqbuf; - url = meth + 3; - if ((accept_get && strncmp(meth, "GET ", 4) == 0) - || (url++, strncmp(meth, "POST ", 5) == 0)) { - static const char http_version_str[] = " "HTTP_PREFIX_VERSION; - static const size_t http_version_str_len = sizeof(http_version_str) - 1; + url = meth = reqbuf; + if ((accept_get && CHECK_AND_SKIP_PREFIX(url, "GET ")) + || CHECK_AND_SKIP_PREFIX(url, "POST ")) { /* Expecting (GET|POST) {sp} /URL {sp} HTTP/1.x */ - *(url++) = '\0'; + url[-1] = '\0'; while (*url == ' ') url++; if (*url != '/') { - log_message(prog, LOG_WARNING, - "Invalid %s -- URL does not begin with '/': %s", - meth, url); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP2(prog, LOG_WARNING, + "invalid %s -- URL does not begin with '/': %s", + meth, url); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } url++; @@ -363,17 +357,17 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, for (end = url; *end != '\0'; end++) if (*end == ' ') break; - if (strncmp(end, http_version_str, http_version_str_len) != 0) { - log_message(prog, LOG_WARNING, - "Invalid %s -- bad HTTP/version string: %s", - meth, end + 1); - (void)http_server_send_status(cbio, 400, "Bad Request"); + if (!HAS_PREFIX(end, HTTP_VERSION_STR)) { + log_HTTP2(prog, LOG_WARNING, + "invalid %s -- bad HTTP/version string: %s", + meth, end + 1); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } *end = '\0'; /* above HTTP 1.0, connection persistence is the default */ if (found_keep_alive != NULL) - *found_keep_alive = end[http_version_str_len] > '0'; + *found_keep_alive = end[sizeof(HTTP_VERSION_STR) - 1] > '0'; /*- * Skip "GET / HTTP..." requests often used by load-balancers. @@ -381,34 +375,32 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, * the leading slash, so in case 'GET / ' it is now an empty string. */ if (strlen(meth) == 3 && url[0] == '\0') { - (void)http_server_send_status(cbio, 200, "OK"); + (void)http_server_send_status(prog, cbio, 200, "OK"); goto out; } len = urldecode(url); if (len < 0) { - log_message(prog, LOG_WARNING, - "Invalid %s request -- bad URL encoding: %s", - meth, url); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP2(prog, LOG_WARNING, + "invalid %s request -- bad URL encoding: %s", meth, url); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } if (strlen(meth) == 3) { /* GET */ if ((getbio = BIO_new_mem_buf(url, len)) == NULL || (b64 = BIO_new(BIO_f_base64())) == NULL) { - log_message(prog, LOG_ERR, - "Could not allocate base64 bio with size = %d", - len); + log_HTTP1(prog, LOG_ERR, + "could not allocate base64 bio with size = %d", len); goto fatal; } BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); getbio = BIO_push(b64, getbio); } } else { - log_message(prog, LOG_WARNING, - "HTTP request does not begin with %sPOST: %s", - accept_get ? "GET or " : "", reqbuf); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP2(prog, LOG_WARNING, + "HTTP request does not begin with %sPOST: %s", + accept_get ? "GET or " : "", reqbuf); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } @@ -421,40 +413,41 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, /* Read and skip past the headers. */ for (;;) { - char *key, *value, *line_end = NULL; + char *key, *value; len = BIO_gets(cbio, inbuf, sizeof(inbuf)); if (len <= 0) { - log_message(prog, LOG_WARNING, "Error reading HTTP header"); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP(prog, LOG_WARNING, "error reading HTTP header"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } - if (inbuf[0] == '\r' || inbuf[0] == '\n') + if (((end = strchr(inbuf, '\r')) != NULL && end[1] == '\n') + || (end = strchr(inbuf, '\n')) != NULL) + *end = '\0'; + log_HTTP1(prog, LOG_TRACE, "%s", *inbuf == '\0' ? + " " /* workaround for "" getting ignored */ : inbuf); + if (end == NULL) { + log_HTTP(prog, LOG_WARNING, + "error parsing HTTP header: missing end of line"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); + goto out; + } + + if (inbuf[0] == '\0') break; key = inbuf; value = strchr(key, ':'); if (value == NULL) { - log_message(prog, LOG_WARNING, - "Error parsing HTTP header: missing ':'"); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP(prog, LOG_WARNING, + "error parsing HTTP header: missing ':'"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); goto out; } *(value++) = '\0'; while (*value == ' ') value++; - line_end = strchr(value, '\r'); - if (line_end == NULL) { - line_end = strchr(value, '\n'); - if (line_end == NULL) { - log_message(prog, LOG_WARNING, - "Error parsing HTTP header: missing end of line"); - (void)http_server_send_status(cbio, 400, "Bad Request"); - goto out; - } - } - *line_end = '\0'; /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */ if (found_keep_alive != NULL && OPENSSL_strcasecmp(key, "Connection") == 0) { @@ -474,12 +467,12 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, /* Try to read and parse request */ req = ASN1_item_d2i_bio(it, getbio != NULL ? getbio : cbio, NULL); if (req == NULL) { - log_message(prog, LOG_WARNING, - "Error parsing DER-encoded request content"); - (void)http_server_send_status(cbio, 400, "Bad Request"); + log_HTTP(prog, LOG_WARNING, + "error parsing DER-encoded request content"); + (void)http_server_send_status(prog, cbio, 400, "Bad Request"); } else if (ppath != NULL && (*ppath = OPENSSL_strdup(url)) == NULL) { - log_message(prog, LOG_ERR, - "Out of memory allocating %zu bytes", strlen(url) + 1); + log_HTTP1(prog, LOG_ERR, + "out of memory allocating %zu bytes", strlen(url) + 1); ASN1_item_free(req, it); goto fatal; } @@ -496,7 +489,7 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, return ret; fatal: - (void)http_server_send_status(cbio, 500, "Internal Server Error"); + (void)http_server_send_status(prog, cbio, 500, "Internal Server Error"); if (ppath != NULL) { OPENSSL_free(*ppath); *ppath = NULL; @@ -508,28 +501,46 @@ int http_server_get_asn1_req(const ASN1_ITEM *it, ASN1_VALUE **preq, } /* assumes that cbio does not do an encoding that changes the output length */ -int http_server_send_asn1_resp(BIO *cbio, int keep_alive, +int http_server_send_asn1_resp(const char *prog, BIO *cbio, int keep_alive, const char *content_type, const ASN1_ITEM *it, const ASN1_VALUE *resp) { - int ret = BIO_printf(cbio, HTTP_1_0" 200 OK\r\n%s" - "Content-type: %s\r\n" - "Content-Length: %d\r\n\r\n", - keep_alive ? "Connection: keep-alive\r\n" : "", - content_type, - ASN1_item_i2d(resp, NULL, it)) > 0 - && ASN1_item_i2d_bio(it, cbio, resp) > 0; + char buf[200], *p; + int ret = BIO_snprintf(buf, sizeof(buf), HTTP_1_0" 200 OK\r\n%s" + "Content-type: %s\r\n" + "Content-Length: %d\r\n", + keep_alive ? "Connection: keep-alive\r\n" : "", + content_type, + ASN1_item_i2d(resp, NULL, it)); + + if (ret < 0 || (size_t)ret >= sizeof(buf)) + return 0; + if (log_get_verbosity() < LOG_TRACE && (p = strchr(buf, '\r')) != NULL) + trace_log_message(-1, prog, LOG_INFO, + "sending response, 1st line: %.*s", (int)(p - buf), + buf); + log_HTTP1(prog, LOG_TRACE, "sending response header:\n%s", buf); + + ret = BIO_printf(cbio, "%s\r\n", buf) > 0 + && ASN1_item_i2d_bio(it, cbio, resp) > 0; (void)BIO_flush(cbio); return ret; } -int http_server_send_status(BIO *cbio, int status, const char *reason) +int http_server_send_status(const char *prog, BIO *cbio, + int status, const char *reason) { - int ret = BIO_printf(cbio, HTTP_1_0" %d %s\r\n\r\n", - /* This implicitly cancels keep-alive */ - status, reason) > 0; + char buf[200]; + int ret = BIO_snprintf(buf, sizeof(buf), HTTP_1_0" %d %s\r\n\r\n", + /* This implicitly cancels keep-alive */ + status, reason); + if (ret < 0 || (size_t)ret >= sizeof(buf)) + return 0; + log_HTTP1(prog, LOG_TRACE, "sending response header:\n%s", buf); + + ret = BIO_printf(cbio, "%s\r\n", buf) > 0; (void)BIO_flush(cbio); return ret; } diff --git a/apps/lib/names.c b/apps/lib/names.c index 4788ae84b915..8825dfa3d895 100644 --- a/apps/lib/names.c +++ b/apps/lib/names.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ #include #include #include "names.h" -#include "openssl/crypto.h" +#include "internal/e_os.h" int name_cmp(const char * const *a, const char * const *b) { @@ -22,7 +22,8 @@ void collect_names(const char *name, void *vdata) { STACK_OF(OPENSSL_CSTRING) *names = vdata; - sk_OPENSSL_CSTRING_push(names, name); + /* A failure to push cannot be handled so we ignore the result. */ + (void)sk_OPENSSL_CSTRING_push(names, name); } void print_names(BIO *out, STACK_OF(OPENSSL_CSTRING) *names) diff --git a/apps/lib/opt.c b/apps/lib/opt.c index 88db9ad6947b..0018c268c0b4 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -41,6 +41,7 @@ static int opt_index; static char *arg; static char *flag; static char *dunno; +static const char *unknown_name; static const OPTIONS *unknown; static const OPTIONS *opts; static char prog[40]; @@ -166,7 +167,6 @@ char *opt_init(int ac, char **av, const OPTIONS *o) opt_begin(); opts = o; unknown = NULL; - /* Make sure prog name is set for usage output */ (void)opt_progname(argv[0]); @@ -194,7 +194,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o) case 0: case '-': case '.': case '/': case '<': case '>': case 'E': case 'F': case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': - case 'u': case 'c': case ':': case 'N': + case 'u': case 'c': case ':': case 'N': case 'A': break; default: OPENSSL_assert(0); @@ -215,6 +215,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o) } #endif if (o->name[0] == '\0') { + OPENSSL_assert(unknown_name != NULL); OPENSSL_assert(unknown == NULL); unknown = o; OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-'); @@ -224,7 +225,9 @@ char *opt_init(int ac, char **av, const OPTIONS *o) } static OPT_PAIR formats[] = { - {"PEM/DER", OPT_FMT_PEMDER}, + {"pem", OPT_FMT_PEM}, + {"der", OPT_FMT_DER}, + {"b64", OPT_FMT_B64}, {"pkcs12", OPT_FMT_PKCS12}, {"smime", OPT_FMT_SMIME}, {"engine", OPT_FMT_ENGINE}, @@ -236,21 +239,22 @@ static OPT_PAIR formats[] = { {NULL} }; +void opt_set_unknown_name(const char *name) +{ + unknown_name = name; +} + /* Print an error message about a failed format parse. */ static int opt_format_error(const char *s, unsigned long flags) { OPT_PAIR *ap; - if (flags == OPT_FMT_PEMDER) { - opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n", - prog, s); - } else { - opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n", - prog, s); - for (ap = formats; ap->name; ap++) - if (flags & ap->retval) - opt_printf_stderr(" %s\n", ap->name); - } + opt_printf_stderr("%s: Bad format \"%s\"; must be one of: ", prog, s); + for (ap = formats; ap->name; ap++) + if (flags & ap->retval) + opt_printf_stderr(" %s", ap->name); + opt_printf_stderr("\n"); + return 0; } @@ -261,9 +265,21 @@ int opt_format(const char *s, unsigned long flags, int *result) default: opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s); return 0; + case 'B': + case 'b': + if (s[1] == '\0' + || strcmp(s, "B64") == 0 || strcmp(s, "b64") == 0 + || strcmp(s, "BASE64") == 0 || strcmp(s, "base64") == 0 ) { + if ((flags & OPT_FMT_B64) == 0) + return opt_format_error(s, flags); + *result = FORMAT_BASE64; + } else { + return 0; + } + break; case 'D': case 'd': - if ((flags & OPT_FMT_PEMDER) == 0) + if ((flags & OPT_FMT_DER) == 0) return opt_format_error(s, flags); *result = FORMAT_ASN1; break; @@ -313,7 +329,7 @@ int opt_format(const char *s, unsigned long flags, int *result) case 'P': case 'p': if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { - if ((flags & OPT_FMT_PEMDER) == 0) + if ((flags & OPT_FMT_PEM) == 0) return opt_format_error(s, flags); *result = FORMAT_PEM; } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { @@ -399,8 +415,10 @@ int opt_cipher_any(const char *name, EVP_CIPHER **cipherp) { int ret; + if (name == NULL) + return 1; if ((ret = opt_cipher_silent(name, cipherp)) == 0) - opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); + opt_printf_stderr("%s: Unknown option or cipher: %s\n", prog, name); return ret; } @@ -410,6 +428,8 @@ int opt_cipher(const char *name, EVP_CIPHER **cipherp) unsigned long int flags; EVP_CIPHER *c = NULL; + if (name == NULL) + return 1; if (opt_cipher_any(name, &c)) { mode = EVP_CIPHER_get_mode(c); flags = EVP_CIPHER_get_flags(c); @@ -454,12 +474,22 @@ int opt_md(const char *name, EVP_MD **mdp) { int ret; + if (name == NULL) + return 1; if ((ret = opt_md_silent(name, mdp)) == 0) - opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog, - name != NULL ? name : "\"\""); + opt_printf_stderr("%s: Unknown option or message digest: %s\n", + prog, name); return ret; } +int opt_check_md(const char *name) +{ + if (opt_md(name, NULL)) + return 1; + ERR_clear_error(); + return 0; +} + /* Look through a list of name/value pairs. */ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) { @@ -961,11 +991,14 @@ int opt_next(void) case 'E': case 'F': case 'f': + case 'A': + case 'a': if (opt_format(arg, o->valtype == 'c' ? OPT_FMT_PDS : o->valtype == 'E' ? OPT_FMT_PDE : - o->valtype == 'F' ? OPT_FMT_PEMDER - : OPT_FMT_ANY, &ival)) + o->valtype == 'F' ? OPT_FMT_PEMDER : + o->valtype == 'A' ? OPT_FMT_ASN1 : + OPT_FMT_ANY, &ival)) break; opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n", prog, arg, o->name); @@ -976,6 +1009,11 @@ int opt_next(void) return o->retval; } if (unknown != NULL) { + if (dunno != NULL) { + opt_printf_stderr("%s: Multiple %s or unknown options: -%s and -%s\n", + prog, unknown_name, dunno, p); + return -1; + } dunno = p; return unknown->retval; } @@ -1001,6 +1039,12 @@ char *opt_unknown(void) return dunno; } +/* Reset the unknown option; needed by ocsp to allow multiple digest options. */ +void reset_unknown(void) +{ + dunno = NULL; +} + /* Return the rest of the arguments after parsing flags. */ char **opt_rest(void) { @@ -1018,6 +1062,31 @@ int opt_num_rest(void) return i; } +int opt_check_rest_arg(const char *expected) +{ + char *opt = *opt_rest(); + + if (opt == NULL || *opt == '\0') { + if (expected == NULL) + return 1; + opt_printf_stderr("%s: Missing argument: %s\n", prog, expected); + return 0; + } + if (expected != NULL) { + opt = argv[opt_index + 1]; + if (opt == NULL || *opt == '\0') + return 1; + opt_printf_stderr("%s: Extra argument after %s: \"%s\"\n", prog, expected, opt); + return 0; + } + if (opt_unknown() == NULL) + opt_printf_stderr("%s: Extra option: \"%s\"\n", prog, opt); + else + opt_printf_stderr("%s: Extra (unknown) options: \"%s\" \"%s\"\n", + prog, opt_unknown(), opt); + return 0; +} + /* Return a string describing the parameter type. */ static const char *valtype2param(const OPTIONS *o) { @@ -1063,55 +1132,60 @@ static void opt_print(const OPTIONS *o, int doingparams, int width) { const char* help; char start[80 + 1]; - char *p; + int linelen, printlen; - help = o->helpstr ? o->helpstr : "(No additional info)"; - if (o->name == OPT_HELP_STR) { - opt_printf_stderr(help, prog); - return; - } - if (o->name == OPT_SECTION_STR) { - opt_printf_stderr("\n"); - opt_printf_stderr(help, prog); - return; - } - if (o->name == OPT_PARAM_STR) { - opt_printf_stderr("\nParameters:\n"); - return; - } + /* Avoid OOB if width is beyond the buffer size of start */ + if (width >= (int)sizeof(start)) + width = (int)sizeof(start) - 1; - /* Pad out prefix */ - memset(start, ' ', sizeof(start) - 1); - start[sizeof(start) - 1] = '\0'; + help = o->helpstr ? o->helpstr : "(No additional info)"; + if (o->name == OPT_HELP_STR) { + opt_printf_stderr(help, prog); + return; + } else if (o->name == OPT_SECTION_STR) { + opt_printf_stderr("\n"); + opt_printf_stderr(help, prog); + return; + } else if (o->name == OPT_PARAM_STR) { + opt_printf_stderr("\nParameters:\n"); + return; + } - if (o->name == OPT_MORE_STR) { - /* Continuation of previous line; pad and print. */ - start[width] = '\0'; - opt_printf_stderr("%s %s\n", start, help); - return; - } + /* Pad out prefix */ + memset(start, ' ', sizeof(start) - 1); + start[sizeof(start) - 1] = '\0'; - /* Build up the "-flag [param]" part. */ - p = start; - *p++ = ' '; - if (!doingparams) - *p++ = '-'; - if (o->name[0]) - p += strlen(strcpy(p, o->name)); - else - *p++ = '*'; - if (o->valtype != '-') { - *p++ = ' '; - p += strlen(strcpy(p, valtype2param(o))); - } - *p = ' '; - if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { - *p = '\0'; - opt_printf_stderr("%s\n", start); - memset(start, ' ', sizeof(start)); - } + if (o->name == OPT_MORE_STR) { + /* Continuation of previous line; pad and print. */ start[width] = '\0'; opt_printf_stderr("%s %s\n", start, help); + return; + } + + /* Build up the "-flag [param]" part. */ + linelen = 0; + + printlen = opt_printf_stderr(" %s", !doingparams ? "-" : ""); + linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH; + + printlen = opt_printf_stderr("%s" , o->name[0] ? o->name : "*"); + linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH; + + if (o->valtype != '-') { + printlen = opt_printf_stderr(" %s" , valtype2param(o)); + linelen += (printlen > 0) ? printlen : MAX_OPT_HELP_WIDTH; + } + + if (linelen >= MAX_OPT_HELP_WIDTH || linelen > width) { + opt_printf_stderr("%s", "\n"); + memset(start, ' ', sizeof(start)); + linelen = 0; + } + + width -= linelen; + + start[width] = '\0'; + opt_printf_stderr("%s %s\n", start, help); } void opt_help(const OPTIONS *list) @@ -1119,7 +1193,6 @@ void opt_help(const OPTIONS *list) const OPTIONS *o; int i, sawparams = 0, width = 5; int standard_prolog; - char start[80 + 1]; /* Starts with its own help message? */ standard_prolog = list[0].name != OPT_HELP_STR; @@ -1128,14 +1201,18 @@ void opt_help(const OPTIONS *list) for (o = list; o->name; o++) { if (o->name == OPT_MORE_STR) continue; + i = 2 + (int)strlen(o->name); if (o->valtype != '-') i += 1 + strlen(valtype2param(o)); - if (i < MAX_OPT_HELP_WIDTH && i > width) + + if (i > width) width = i; - OPENSSL_assert(i < (int)sizeof(start)); } + if (width > MAX_OPT_HELP_WIDTH) + width = MAX_OPT_HELP_WIDTH; + if (standard_prolog) { opt_printf_stderr("Usage: %s [options]\n", prog); if (list[0].name != OPT_SECTION_STR) diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c index 9f33c24c4e35..9641e369e621 100644 --- a/apps/lib/s_cb.c +++ b/apps/lib/s_cb.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,10 @@ * https://www.openssl.org/source/license.html */ -/* callback functions used by s_client, s_server, and s_time */ +/* + * callback functions used by s_client, s_server, and s_time, + * as well as other common logic for those apps + */ #include #include #include /* for memcpy() and strcmp() */ @@ -255,7 +258,8 @@ static const char *get_sigtype(int nid) return "gost2012_512"; default: - return NULL; + /* Try to output provider-registered sig alg name */ + return OBJ_nid2sn(nid); } } @@ -324,6 +328,7 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared) int ssl_print_sigalgs(BIO *out, SSL *s) { + const char *name; int nid; if (!SSL_is_server(s)) @@ -332,7 +337,9 @@ int ssl_print_sigalgs(BIO *out, SSL *s) do_print_sigalgs(out, s, 1); if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef) BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid)); - if (SSL_get_peer_signature_type_nid(s, &nid)) + if (SSL_get0_peer_signature_name(s, &name)) + BIO_printf(out, "Peer signature type: %s\n", name); + else if (SSL_get_peer_signature_type_nid(s, &nid)) BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid)); return 1; } @@ -412,16 +419,28 @@ int ssl_print_groups(BIO *out, SSL *s, int noshared) int ssl_print_tmp_key(BIO *out, SSL *s) { + const char *keyname; EVP_PKEY *key; - if (!SSL_get_peer_tmp_key(s, &key)) + if (!SSL_get_peer_tmp_key(s, &key)) { + if (SSL_version(s) == TLS1_3_VERSION) + BIO_printf(out, "Negotiated TLS1.3 group: %s\n", + SSL_group_to_name(s, SSL_get_negotiated_group(s))); return 1; - BIO_puts(out, "Server Temp Key: "); + } + + BIO_puts(out, "Peer Temp Key: "); switch (EVP_PKEY_get_id(key)) { case EVP_PKEY_RSA: BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_get_bits(key)); break; + case EVP_PKEY_KEYMGMT: + if ((keyname = EVP_PKEY_get0_type_name(key)) == NULL) + keyname = "?"; + BIO_printf(out, "%s\n", keyname); + break; + case EVP_PKEY_DH: BIO_printf(out, "DH, %d bits\n", EVP_PKEY_get_bits(key)); break; @@ -450,12 +469,15 @@ long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len, int argi, long argl, int ret, size_t *processed) { BIO *out; + BIO_MMSG_CB_ARGS *mmsgargs; + size_t i; out = (BIO *)BIO_get_callback_arg(bio); if (out == NULL) return ret; - if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { + switch (cmd) { + case (BIO_CB_READ | BIO_CB_RETURN): if (ret > 0 && processed != NULL) { BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n", (void *)bio, (void *)argp, len, *processed, *processed); @@ -464,7 +486,9 @@ long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len, BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n", (void *)bio, (void *)argp, len, ret); } - } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { + break; + + case (BIO_CB_WRITE | BIO_CB_RETURN): if (ret > 0 && processed != NULL) { BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n", (void *)bio, (void *)argp, len, *processed, *processed); @@ -473,6 +497,51 @@ long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len, BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n", (void *)bio, (void *)argp, len, ret); } + break; + + case (BIO_CB_RECVMMSG | BIO_CB_RETURN): + mmsgargs = (BIO_MMSG_CB_ARGS *)argp; + if (ret > 0) { + for (i = 0; i < *(mmsgargs->msgs_processed); i++) { + BIO_MSG *msg = (BIO_MSG *)((char *)mmsgargs->msg + + (i * mmsgargs->stride)); + + BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n", + (void *)bio, (void *)msg->data, msg->data_len, + msg->data_len, msg->data_len); + BIO_dump(out, msg->data, msg->data_len); + } + } else if (mmsgargs->num_msg > 0) { + BIO_MSG *msg = mmsgargs->msg; + + BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n", + (void *)bio, (void *)msg->data, msg->data_len, ret); + } + break; + + case (BIO_CB_SENDMMSG | BIO_CB_RETURN): + mmsgargs = (BIO_MMSG_CB_ARGS *)argp; + if (ret > 0) { + for (i = 0; i < *(mmsgargs->msgs_processed); i++) { + BIO_MSG *msg = (BIO_MSG *)((char *)mmsgargs->msg + + (i * mmsgargs->stride)); + + BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n", + (void *)bio, (void *)msg->data, msg->data_len, + msg->data_len, msg->data_len); + BIO_dump(out, msg->data, msg->data_len); + } + } else if (mmsgargs->num_msg > 0) { + BIO_MSG *msg = mmsgargs->msg; + + BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n", + (void *)bio, (void *)msg->data, msg->data_len, ret); + } + break; + + default: + /* do nothing */ + break; } return ret; } @@ -576,6 +645,7 @@ static STRINT_PAIR handshakes[] = { {", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS}, {", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA}, {", KeyUpdate", SSL3_MT_KEY_UPDATE}, + {", CompressedCertificate", SSL3_MT_COMPRESSED_CERTIFICATE}, #ifndef OPENSSL_NO_NEXTPROTONEG {", NextProto", SSL3_MT_NEXT_PROTO}, #endif @@ -688,6 +758,8 @@ static const STRINT_PAIR tlsext_types[] = { {"session ticket", TLSEXT_TYPE_session_ticket}, {"renegotiation info", TLSEXT_TYPE_renegotiate}, {"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp}, + {"client cert type", TLSEXT_TYPE_client_cert_type}, + {"server cert type", TLSEXT_TYPE_server_cert_type}, {"TLS padding", TLSEXT_TYPE_padding}, #ifdef TLSEXT_TYPE_next_proto_neg {"next protocol", TLSEXT_TYPE_next_proto_neg}, @@ -702,6 +774,7 @@ static const STRINT_PAIR tlsext_types[] = { #ifdef TLSEXT_TYPE_extended_master_secret {"extended master secret", TLSEXT_TYPE_extended_master_secret}, #endif + {"compress certificate", TLSEXT_TYPE_compress_certificate}, {"key share", TLSEXT_TYPE_key_share}, {"supported versions", TLSEXT_TYPE_supported_versions}, {"psk", TLSEXT_TYPE_psk}, @@ -1016,7 +1089,7 @@ void ssl_excert_free(SSL_EXCERT *exc) while (exc) { X509_free(exc->cert); EVP_PKEY_free(exc->key); - sk_X509_pop_free(exc->chain, X509_free); + OSSL_STACK_OF_X509_free(exc->chain); curr = exc; exc = exc->next; OPENSSL_free(curr); @@ -1186,7 +1259,7 @@ static char *hexencode(const unsigned char *data, size_t len) void print_verify_detail(SSL *s, BIO *bio) { int mdpth; - EVP_PKEY *mspki; + EVP_PKEY *mspki = NULL; long verify_err = SSL_get_verify_result(s); if (verify_err == X509_V_OK) { @@ -1221,52 +1294,56 @@ void print_verify_detail(SSL *s, BIO *bio) hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE); else hexdata = hexencode(data, dlen); - BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n", + BIO_printf(bio, "DANE TLSA %d %d %d %s%s ", usage, selector, mtype, - (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata, - (mspki != NULL) ? "signed the certificate" : - mdpth ? "matched TA certificate" : "matched EE certificate", - mdpth); + (dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata); + if (SSL_get0_peer_rpk(s) == NULL) + BIO_printf(bio, "%s certificate at depth %d\n", + (mspki != NULL) ? "signed the peer" : + mdpth ? "matched the TA" : "matched the EE", mdpth); + else + BIO_printf(bio, "matched the peer raw public key\n"); OPENSSL_free(hexdata); } } void print_ssl_summary(SSL *s) { + const char *sigalg; const SSL_CIPHER *c; - X509 *peer; + X509 *peer = SSL_get0_peer_certificate(s); + EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s); + int nid; BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s)); print_raw_cipherlist(s); c = SSL_get_current_cipher(s); BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); do_print_sigalgs(bio_err, s, 0); - peer = SSL_get0_peer_certificate(s); if (peer != NULL) { - int nid; - BIO_puts(bio_err, "Peer certificate: "); X509_NAME_print_ex(bio_err, X509_get_subject_name(peer), 0, get_nameopt()); BIO_puts(bio_err, "\n"); if (SSL_get_peer_signature_nid(s, &nid)) BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid)); - if (SSL_get_peer_signature_type_nid(s, &nid)) - BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid)); + if (SSL_get0_peer_signature_name(s, &sigalg)) + BIO_printf(bio_err, "Signature type: %s\n", sigalg); + print_verify_detail(s, bio_err); + } else if (peer_rpk != NULL) { + BIO_printf(bio_err, "Peer used raw public key\n"); + if (SSL_get0_peer_signature_name(s, &sigalg)) + BIO_printf(bio_err, "Signature type: %s\n", sigalg); print_verify_detail(s, bio_err); } else { - BIO_puts(bio_err, "No peer certificate\n"); + BIO_puts(bio_err, "No peer certificate or raw public key\n"); } #ifndef OPENSSL_NO_EC ssl_print_point_formats(bio_err, s); if (SSL_is_server(s)) ssl_print_groups(bio_err, s, 1); - else - ssl_print_tmp_key(bio_err, s); -#else - if (!SSL_is_server(s)) - ssl_print_tmp_key(bio_err, s); #endif + ssl_print_tmp_key(bio_err, s); } int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, @@ -1584,9 +1661,31 @@ void print_ca_names(BIO *bio, SSL *s) return; } - BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs); + BIO_printf(bio, "---\nAcceptable %s certificate CA names\n", cs); for (i = 0; i < sk_X509_NAME_num(sk); i++) { X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt()); BIO_write(bio, "\n", 1); } } + +void ssl_print_secure_renegotiation_notes(BIO *bio, SSL *s) +{ + if (SSL_VERSION_ALLOWS_RENEGOTIATION(s)) { + BIO_printf(bio, "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); + } else { + BIO_printf(bio, "This TLS version forbids renegotiation.\n"); + } +} + +int progress_cb(EVP_PKEY_CTX *ctx) +{ + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + static const char symbols[] = ".+*\n"; + char c = (p >= 0 && (size_t)p <= sizeof(symbols) - 1) ? symbols[p] : '?'; + + BIO_write(b, &c, 1); + (void)BIO_flush(b); + return 1; +} diff --git a/apps/lib/s_socket.c b/apps/lib/s_socket.c index 8c6020d01692..f61b1b5c8268 100644 --- a/apps/lib/s_socket.c +++ b/apps/lib/s_socket.c @@ -37,15 +37,10 @@ typedef unsigned int u_int; #ifndef OPENSSL_NO_SOCK +# include "internal/e_os.h" # include "apps.h" # include "s_apps.h" -# include "internal/sockets.h" - -# if defined(__TANDEM) -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif -# endif +# include "internal/sockets.h" /* for openssl_fdset() */ # include # include @@ -56,7 +51,7 @@ BIO_ADDR *ourpeer = NULL; /* * init_client - helper routine to set up socket communication * @sock: pointer to storage of resulting socket. - * @host: the host name or path (for AF_UNIX) to connect to. + * @host: the hostname or path (for AF_UNIX) to connect to. * @port: the port to connect to (ignored for AF_UNIX). * @bindhost: source host or path (for AF_UNIX). * @bindport: source port (ignored for AF_UNIX). @@ -64,6 +59,9 @@ BIO_ADDR *ourpeer = NULL; * AF_UNSPEC * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any) + * @tfo: flag to enable TCP Fast Open + * @doconn: whether we should call BIO_connect() on the socket + * @ba_ret: BIO_ADDR for the remote peer, to be freed by caller * * This will create a socket and use it to connect to a host:port, or if * family == AF_UNIX, to the path found in host. @@ -76,7 +74,8 @@ BIO_ADDR *ourpeer = NULL; */ int init_client(int *sock, const char *host, const char *port, const char *bindhost, const char *bindport, - int family, int type, int protocol) + int family, int type, int protocol, int tfo, int doconn, + BIO_ADDR **ba_ret) { BIO_ADDRINFO *res = NULL; BIO_ADDRINFO *bindaddr = NULL; @@ -84,6 +83,7 @@ int init_client(int *sock, const char *host, const char *port, const BIO_ADDRINFO *bi = NULL; int found = 0; int ret; + int options = 0; if (BIO_sock_init() != 1) return 0; @@ -160,14 +160,22 @@ int init_client(int *sock, const char *host, const char *port, BIO_free(tmpbio); } #endif + if (BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP) { + options |= BIO_SOCK_NODELAY; + if (tfo) + options |= BIO_SOCK_TFO; + } - if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), - BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) { + if (doconn && !BIO_connect(*sock, BIO_ADDRINFO_address(ai), options)) { BIO_closesocket(*sock); *sock = INVALID_SOCKET; continue; } + /* Save the address */ + if (tfo || !doconn) + *ba_ret = BIO_ADDR_dup(BIO_ADDRINFO_address(ai)); + /* Success, don't try any more addresses */ break; } @@ -188,6 +196,13 @@ int init_client(int *sock, const char *host, const char *port, } ERR_print_errors(bio_err); } else { + char *hostname = NULL; + + hostname = BIO_ADDR_hostname_string(BIO_ADDRINFO_address(ai), 1); + if (hostname != NULL) { + BIO_printf(bio_err, "Connecting to %s\n", hostname); + OPENSSL_free(hostname); + } /* Remove any stale errors from previous connection attempts */ ERR_clear_error(); ret = 1; @@ -200,6 +215,25 @@ out: return ret; } +void get_sock_info_address(int asock, char **hostname, char **service) +{ + union BIO_sock_info_u info; + + if (hostname != NULL) + *hostname = NULL; + if (service != NULL) + *service = NULL; + + if ((info.addr = BIO_ADDR_new()) != NULL + && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info)) { + if (hostname != NULL) + *hostname = BIO_ADDR_hostname_string(info.addr, 1); + if (service != NULL) + *service = BIO_ADDR_service_string(info.addr, 1); + } + BIO_ADDR_free(info.addr); +} + int report_server_accept(BIO *out, int asock, int with_address, int with_pid) { int success = 1; @@ -207,30 +241,24 @@ int report_server_accept(BIO *out, int asock, int with_address, int with_pid) if (BIO_printf(out, "ACCEPT") <= 0) return 0; if (with_address) { - union BIO_sock_info_u info; - char *hostname = NULL; - char *service = NULL; + char *hostname, *service; - if ((info.addr = BIO_ADDR_new()) != NULL - && BIO_sock_info(asock, BIO_SOCK_INFO_ADDRESS, &info) - && (hostname = BIO_ADDR_hostname_string(info.addr, 1)) != NULL - && (service = BIO_ADDR_service_string(info.addr, 1)) != NULL) { + get_sock_info_address(asock, &hostname, &service); + success = hostname != NULL && service != NULL; + if (success) success = BIO_printf(out, strchr(hostname, ':') == NULL ? /* IPv4 */ " %s:%s" : /* IPv6 */ " [%s]:%s", hostname, service) > 0; - } else { + else (void)BIO_printf(out, "unknown:error\n"); - success = 0; - } OPENSSL_free(hostname); OPENSSL_free(service); - BIO_ADDR_free(info.addr); } if (with_pid) - success = success && BIO_printf(out, " PID=%d", getpid()) > 0; - success = success && BIO_printf(out, "\n") > 0; + success *= BIO_printf(out, " PID=%d", getpid()) > 0; + success *= BIO_printf(out, "\n") > 0; (void)BIO_flush(out); return success; @@ -239,7 +267,7 @@ int report_server_accept(BIO *out, int asock, int with_address, int with_pid) /* * do_server - helper routine to perform a server operation * @accept_sock: pointer to storage of resulting socket. - * @host: the host name or path (for AF_UNIX) to connect to. + * @host: the hostname or path (for AF_UNIX) to connect to. * @port: the port to connect to (ignored for AF_UNIX). * @family: desired socket family, may be AF_INET, AF_INET6, AF_UNIX or * AF_UNSPEC @@ -258,7 +286,8 @@ int report_server_accept(BIO *out, int asock, int with_address, int with_pid) */ int do_server(int *accept_sock, const char *host, const char *port, int family, int type, int protocol, do_server_cb cb, - unsigned char *context, int naccept, BIO *bio_s_out) + unsigned char *context, int naccept, BIO *bio_s_out, + int tfo) { int asock = 0; int sock; @@ -292,6 +321,8 @@ int do_server(int *accept_sock, const char *host, const char *port, sock_protocol = BIO_ADDRINFO_protocol(res); sock_address = BIO_ADDRINFO_address(res); next = BIO_ADDRINFO_next(res); + if (tfo && sock_type == SOCK_STREAM) + sock_options |= BIO_SOCK_TFO; #ifdef AF_INET6 if (sock_family == AF_INET6) sock_options |= BIO_SOCK_V6_ONLY; diff --git a/apps/lib/tlssrp_depr.c b/apps/lib/tlssrp_depr.c index 91c19b096e9a..413f1f3538ce 100644 --- a/apps/lib/tlssrp_depr.c +++ b/apps/lib/tlssrp_depr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 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 @@ -87,7 +87,7 @@ static int ssl_srp_verify_param_cb(SSL *s, void *arg) "SRP param N and g are not known params, going to check deeper.\n"); /* - * The srp_moregroups is a real debugging feature. Implementors + * The srp_moregroups is a real debugging feature. Implementers * should rather add the value to the known ones. The minimal size * has already been tested. */ @@ -178,7 +178,7 @@ static int ssl_srp_server_param_cb(SSL *s, int *ad, void *arg) goto err; } BIO_printf(bio_err, - "SRP parameters set: username = \"%s\" info=\"%s\" \n", + "SRP parameters set: username = \"%s\" info=\"%s\"\n", p->login, p->user->info); ret = SSL_ERROR_NONE; @@ -199,7 +199,7 @@ int set_up_srp_verifier_file(SSL_CTX *ctx, srpsrvparm *srp_callback_parm, srp_callback_parm->login = NULL; if (srp_callback_parm->vb == NULL) { - BIO_printf(bio_err, "Failed to initialize SRP verifier file \n"); + BIO_printf(bio_err, "Failed to initialize SRP verifier file\n"); return 0; } if ((ret = diff --git a/apps/lib/vms_term_sock.c b/apps/lib/vms_term_sock.c index 1a413376b20b..219a978966c7 100644 --- a/apps/lib/vms_term_sock.c +++ b/apps/lib/vms_term_sock.c @@ -120,7 +120,7 @@ typedef struct _SocketPairTimeoutBlock { } SPTB; # ifdef TERM_SOCK_TEST - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ @@ -160,7 +160,7 @@ int main (int argc, char *argv[], char *envp[]) } # endif - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ @@ -275,7 +275,7 @@ int TerminalSocket (int FunctionCode, int *ReturnSocket) return TERM_SOCK_SUCCESS; } - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ @@ -441,7 +441,7 @@ static int CreateSocketPair (int SocketFamily, sin.sin_port = LocalHostPort ; status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin)); - if (status < 0 ) { + if (status < 0) { LogMessage ("CreateSocketPair: connect () - %d", errno); sys$cantim (&sptb, 0); sys$cancel (TcpAcceptChan); @@ -485,7 +485,7 @@ static int CreateSocketPair (int SocketFamily, return (0) ; } - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ @@ -499,7 +499,7 @@ static void SocketPairTimeoutAst (int astparm) return; } - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ @@ -538,7 +538,7 @@ static int TerminalDeviceAst (int astparm) return status; } - + /*----------------------------------------------------------------------------*/ /* */ /*----------------------------------------------------------------------------*/ diff --git a/apps/list.c b/apps/list.c index 7d3136a8a161..5219773fcf04 100644 --- a/apps/list.c +++ b/apps/list.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,6 +10,8 @@ /* We need to use some deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED +#include "internal/e_os.h" + #include #include #include @@ -21,6 +23,9 @@ #include #include #include +#include +#include +#include #include "apps.h" #include "app_params.h" #include "progs.h" @@ -53,6 +58,7 @@ IS_FETCHABLE(mac, EVP_MAC) IS_FETCHABLE(kdf, EVP_KDF) IS_FETCHABLE(rand, EVP_RAND) IS_FETCHABLE(keymgmt, EVP_KEYMGMT) +IS_FETCHABLE(skeymgmt, EVP_SKEYMGMT) IS_FETCHABLE(signature, EVP_SIGNATURE) IS_FETCHABLE(kem, EVP_KEM) IS_FETCHABLE(asym_cipher, EVP_ASYM_CIPHER) @@ -71,7 +77,7 @@ static void legacy_cipher_fn(const EVP_CIPHER *c, { if (select_name != NULL && (c == NULL - || OPENSSL_strcasecmp(select_name, EVP_CIPHER_get0_name(c)) != 0)) + || OPENSSL_strcasecmp(select_name, EVP_CIPHER_get0_name(c)) != 0)) return; if (c != NULL) { BIO_printf(arg, " %s\n", EVP_CIPHER_get0_name(c)); @@ -98,11 +104,12 @@ static void collect_ciphers(EVP_CIPHER *cipher, void *stack) STACK_OF(EVP_CIPHER) *cipher_stack = stack; if (is_cipher_fetchable(cipher) - && sk_EVP_CIPHER_push(cipher_stack, cipher) > 0) - EVP_CIPHER_up_ref(cipher); + && EVP_CIPHER_up_ref(cipher) + && sk_EVP_CIPHER_push(cipher_stack, cipher) <= 0) + EVP_CIPHER_free(cipher); /* up-ref successful but push to stack failed */ } -static void list_ciphers(void) +static void list_ciphers(const char *prefix) { STACK_OF(EVP_CIPHER) *ciphers = sk_EVP_CIPHER_new(cipher_cmp); int i; @@ -113,12 +120,12 @@ static void list_ciphers(void) } #ifndef OPENSSL_NO_DEPRECATED_3_0 if (include_legacy()) { - BIO_printf(bio_out, "Legacy:\n"); + BIO_printf(bio_out, "%sLegacy:\n", prefix); EVP_CIPHER_do_all_sorted(legacy_cipher_fn, bio_out); } #endif - BIO_printf(bio_out, "Provided:\n"); + BIO_printf(bio_out, "%sProvided:\n", prefix); EVP_CIPHER_do_all_provided(app_get0_libctx(), collect_ciphers, ciphers); sk_EVP_CIPHER_sort(ciphers); for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) { @@ -182,11 +189,12 @@ static void collect_digests(EVP_MD *digest, void *stack) STACK_OF(EVP_MD) *digest_stack = stack; if (is_digest_fetchable(digest) - && sk_EVP_MD_push(digest_stack, digest) > 0) - EVP_MD_up_ref(digest); + && EVP_MD_up_ref(digest) + && sk_EVP_MD_push(digest_stack, digest) <= 0) + EVP_MD_free(digest); /* up-ref successful but push to stack failed */ } -static void list_digests(void) +static void list_digests(const char *prefix) { STACK_OF(EVP_MD) *digests = sk_EVP_MD_new(md_cmp); int i; @@ -197,12 +205,12 @@ static void list_digests(void) } #ifndef OPENSSL_NO_DEPRECATED_3_0 if (include_legacy()) { - BIO_printf(bio_out, "Legacy:\n"); + BIO_printf(bio_out, "%sLegacy:\n", prefix); EVP_MD_do_all_sorted(legacy_md_fn, bio_out); } #endif - BIO_printf(bio_out, "Provided:\n"); + BIO_printf(bio_out, "%sProvided:\n", prefix); EVP_MD_do_all_provided(app_get0_libctx(), collect_digests, digests); sk_EVP_MD_sort(digests); for (i = 0; i < sk_EVP_MD_num(digests); i++) { @@ -314,8 +322,9 @@ static void collect_kdfs(EVP_KDF *kdf, void *stack) STACK_OF(EVP_KDF) *kdf_stack = stack; if (is_kdf_fetchable(kdf) - && sk_EVP_KDF_push(kdf_stack, kdf) > 0) - EVP_KDF_up_ref(kdf); + && EVP_KDF_up_ref(kdf) + && sk_EVP_KDF_push(kdf_stack, kdf) <= 0) + EVP_KDF_free(kdf); /* up-ref successful but push to stack failed */ } static void list_kdfs(void) @@ -384,8 +393,9 @@ static void collect_rands(EVP_RAND *rand, void *stack) STACK_OF(EVP_RAND) *rand_stack = stack; if (is_rand_fetchable(rand) - && sk_EVP_RAND_push(rand_stack, rand) > 0) - EVP_RAND_up_ref(rand); + && EVP_RAND_up_ref(rand) + && sk_EVP_RAND_push(rand_stack, rand) <= 0) + EVP_RAND_free(rand); /* up-ref successful but push to stack failed */ } static void list_random_generators(void) @@ -510,8 +520,9 @@ static void collect_encoders(OSSL_ENCODER *encoder, void *stack) STACK_OF(OSSL_ENCODER) *encoder_stack = stack; if (is_encoder_fetchable(encoder) - && sk_OSSL_ENCODER_push(encoder_stack, encoder) > 0) - OSSL_ENCODER_up_ref(encoder); + && OSSL_ENCODER_up_ref(encoder) + && sk_OSSL_ENCODER_push(encoder_stack, encoder) <= 0) + OSSL_ENCODER_free(encoder); /* up-ref successful but push to stack failed */ } static void list_encoders(void) @@ -575,8 +586,9 @@ static void collect_decoders(OSSL_DECODER *decoder, void *stack) STACK_OF(OSSL_DECODER) *decoder_stack = stack; if (is_decoder_fetchable(decoder) - && sk_OSSL_DECODER_push(decoder_stack, decoder) > 0) - OSSL_DECODER_up_ref(decoder); + && OSSL_DECODER_up_ref(decoder) + && sk_OSSL_DECODER_push(decoder_stack, decoder) <= 0) + OSSL_DECODER_free(decoder); /* up-ref successful but push to stack failed */ } static void list_decoders(void) @@ -637,8 +649,9 @@ static void collect_keymanagers(EVP_KEYMGMT *km, void *stack) STACK_OF(EVP_KEYMGMT) *km_stack = stack; if (is_keymgmt_fetchable(km) - && sk_EVP_KEYMGMT_push(km_stack, km) > 0) - EVP_KEYMGMT_up_ref(km); + && EVP_KEYMGMT_up_ref(km) + && sk_EVP_KEYMGMT_push(km_stack, km) <= 0) + EVP_KEYMGMT_free(km); /* up-ref successful but push to stack failed */ } static void list_keymanagers(void) @@ -687,6 +700,61 @@ static void list_keymanagers(void) sk_EVP_KEYMGMT_pop_free(km_stack, EVP_KEYMGMT_free); } +DEFINE_STACK_OF(EVP_SKEYMGMT) +static int skeymanager_cmp(const EVP_SKEYMGMT * const *a, + const EVP_SKEYMGMT * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(*b))); +} + +static void collect_skeymanagers(EVP_SKEYMGMT *km, void *stack) +{ + STACK_OF(EVP_SKEYMGMT) *km_stack = stack; + + if (is_skeymgmt_fetchable(km) + && sk_EVP_SKEYMGMT_push(km_stack, km) > 0) + EVP_SKEYMGMT_up_ref(km); +} + +static void list_skeymanagers(void) +{ + int i; + STACK_OF(EVP_SKEYMGMT) *km_stack = sk_EVP_SKEYMGMT_new(skeymanager_cmp); + + EVP_SKEYMGMT_do_all_provided(app_get0_libctx(), collect_skeymanagers, + km_stack); + sk_EVP_SKEYMGMT_sort(km_stack); + + for (i = 0; i < sk_EVP_SKEYMGMT_num(km_stack); i++) { + EVP_SKEYMGMT *k = sk_EVP_SKEYMGMT_value(km_stack, i); + STACK_OF(OPENSSL_CSTRING) *names = NULL; + + if (select_name != NULL && !EVP_SKEYMGMT_is_a(k, select_name)) + continue; + + names = sk_OPENSSL_CSTRING_new(name_cmp); + if (names != NULL && EVP_SKEYMGMT_names_do_all(k, collect_names, names)) { + const char *desc = EVP_SKEYMGMT_get0_description(k); + + BIO_printf(bio_out, " Name: "); + if (desc != NULL) + BIO_printf(bio_out, "%s", desc); + else + BIO_printf(bio_out, "%s", sk_OPENSSL_CSTRING_value(names, 0)); + BIO_printf(bio_out, "\n"); + BIO_printf(bio_out, " Type: Provider Algorithm\n"); + BIO_printf(bio_out, " IDs: "); + print_names(bio_out, names); + BIO_printf(bio_out, " @ %s\n", + OSSL_PROVIDER_get0_name(EVP_SKEYMGMT_get0_provider(k))); + + } + sk_OPENSSL_CSTRING_free(names); + } + sk_EVP_SKEYMGMT_pop_free(km_stack, EVP_SKEYMGMT_free); +} + DEFINE_STACK_OF(EVP_SIGNATURE) static int signature_cmp(const EVP_SIGNATURE * const *a, const EVP_SIGNATURE * const *b) @@ -700,8 +768,9 @@ static void collect_signatures(EVP_SIGNATURE *sig, void *stack) STACK_OF(EVP_SIGNATURE) *sig_stack = stack; if (is_signature_fetchable(sig) - && sk_EVP_SIGNATURE_push(sig_stack, sig) > 0) - EVP_SIGNATURE_up_ref(sig); + && EVP_SIGNATURE_up_ref(sig) + && sk_EVP_SIGNATURE_push(sig_stack, sig) <= 0) + EVP_SIGNATURE_free(sig); /* up-ref successful but push to stack failed */ } static void list_signatures(void) @@ -747,6 +816,90 @@ static void list_signatures(void) BIO_printf(bio_out, " -\n"); } +static int list_provider_tls_sigalgs(const OSSL_PARAM params[], void *data) +{ + const OSSL_PARAM *p; + + /* Get registered IANA name */ + p = OSSL_PARAM_locate_const(params, OSSL_CAPABILITY_TLS_SIGALG_IANA_NAME); + if (p != NULL && p->data_type == OSSL_PARAM_UTF8_STRING) { + if (*((int *)data) > 0) + BIO_printf(bio_out, ":"); + BIO_printf(bio_out, "%s", (char *)(p->data)); + /* mark presence of a provider-based sigalg */ + *((int *)data) = 2; + } + /* As built-in providers don't have this capability, never error */ + return 1; +} + +static int list_tls_sigalg_caps(OSSL_PROVIDER *provider, void *cbdata) +{ + OSSL_PROVIDER_get_capabilities(provider, "TLS-SIGALG", + list_provider_tls_sigalgs, + cbdata); + /* As built-in providers don't have this capability, never error */ + return 1; +} + +#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) +static void list_tls_groups(int version, int all) +{ + SSL_CTX *ctx = NULL; + STACK_OF(OPENSSL_CSTRING) *groups; + size_t i, num; + + if ((groups = sk_OPENSSL_CSTRING_new_null()) == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + return; + } + if ((ctx = SSL_CTX_new(TLS_method())) == NULL) { + BIO_printf(bio_err, "ERROR: Memory allocation\n"); + goto err; + } + if (!SSL_CTX_set_min_proto_version(ctx, version) + || !SSL_CTX_set_max_proto_version(ctx, version)) { + BIO_printf(bio_err, "ERROR: setting TLS protocol version\n"); + goto err; + } + if (!SSL_CTX_get0_implemented_groups(ctx, all, groups)) { + BIO_printf(bio_err, "ERROR: getting implemented TLS group list\n"); + goto err; + } + num = sk_OPENSSL_CSTRING_num(groups); + for (i = 0; i < num; ++i) { + BIO_printf(bio_out, "%s%c", sk_OPENSSL_CSTRING_value(groups, i), + (i < num - 1) ? ':' : '\n'); + } + err: + SSL_CTX_free(ctx); + sk_OPENSSL_CSTRING_free(groups); + return; +} +#endif + +static void list_tls_signatures(void) +{ + int tls_sigalg_listed = 0; + char *builtin_sigalgs = SSL_get1_builtin_sigalgs(app_get0_libctx()); + + if (builtin_sigalgs != NULL) { + if (builtin_sigalgs[0] != 0) { + BIO_printf(bio_out, "%s", builtin_sigalgs); + tls_sigalg_listed = 1; + } + OPENSSL_free(builtin_sigalgs); + } + + if (!OSSL_PROVIDER_do_all(NULL, list_tls_sigalg_caps, &tls_sigalg_listed)) + BIO_printf(bio_err, + "ERROR: could not list all provider signature algorithms\n"); + if (tls_sigalg_listed < 2) + BIO_printf(bio_out, + "\nNo TLS sig algs registered by currently active providers"); + BIO_printf(bio_out, "\n"); +} + DEFINE_STACK_OF(EVP_KEM) static int kem_cmp(const EVP_KEM * const *a, const EVP_KEM * const *b) @@ -760,8 +913,9 @@ static void collect_kem(EVP_KEM *kem, void *stack) STACK_OF(EVP_KEM) *kem_stack = stack; if (is_kem_fetchable(kem) - && sk_EVP_KEM_push(kem_stack, kem) > 0) - EVP_KEM_up_ref(kem); + && EVP_KEM_up_ref(kem) + && sk_EVP_KEM_push(kem_stack, kem) <= 0) + EVP_KEM_free(kem); /* up-ref successful but push to stack failed */ } static void list_kems(void) @@ -819,8 +973,9 @@ static void collect_asymciph(EVP_ASYM_CIPHER *asym_cipher, void *stack) STACK_OF(EVP_ASYM_CIPHER) *asym_cipher_stack = stack; if (is_asym_cipher_fetchable(asym_cipher) - && sk_EVP_ASYM_CIPHER_push(asym_cipher_stack, asym_cipher) > 0) - EVP_ASYM_CIPHER_up_ref(asym_cipher); + && EVP_ASYM_CIPHER_up_ref(asym_cipher) + && sk_EVP_ASYM_CIPHER_push(asym_cipher_stack, asym_cipher) <= 0) + EVP_ASYM_CIPHER_free(asym_cipher); /* up-ref successful but push to stack failed */ } static void list_asymciphers(void) @@ -881,8 +1036,9 @@ static void collect_kex(EVP_KEYEXCH *kex, void *stack) STACK_OF(EVP_KEYEXCH) *kex_stack = stack; if (is_keyexch_fetchable(kex) - && sk_EVP_KEYEXCH_push(kex_stack, kex) > 0) - EVP_KEYEXCH_up_ref(kex); + && EVP_KEYEXCH_up_ref(kex) + && sk_EVP_KEYEXCH_push(kex_stack, kex) <= 0) + EVP_KEYEXCH_free(kex); /* up-ref successful but push to stack failed */ } static void list_keyexchanges(void) @@ -1161,8 +1317,9 @@ static void collect_store_loaders(OSSL_STORE_LOADER *store, void *stack) { STACK_OF(OSSL_STORE_LOADER) *store_stack = stack; - if (sk_OSSL_STORE_LOADER_push(store_stack, store) > 0) - OSSL_STORE_LOADER_up_ref(store); + if (OSSL_STORE_LOADER_up_ref(store) + && sk_OSSL_STORE_LOADER_push(store_stack, store) <= 0) + OSSL_STORE_LOADER_free(store); /* up-ref successful but push to stack failed */ } static void list_store_loaders(void) @@ -1209,6 +1366,7 @@ static int provider_cmp(const OSSL_PROVIDER * const *a, static int collect_providers(OSSL_PROVIDER *provider, void *stack) { STACK_OF(OSSL_PROVIDER) *provider_stack = stack; + /* * If OK - result is the index of inserted data * Error - result is -1 or 0 @@ -1297,6 +1455,9 @@ static void list_engines(void) static void list_disabled(void) { BIO_puts(bio_out, "Disabled algorithms:\n"); +#ifdef OPENSSL_NO_ARGON2 + BIO_puts(bio_out, "ARGON2\n"); +#endif #ifdef OPENSSL_NO_ARIA BIO_puts(bio_out, "ARIA\n"); #endif @@ -1345,6 +1506,9 @@ static void list_disabled(void) #ifdef OPENSSL_NO_EC BIO_puts(bio_out, "EC\n"); #endif +#ifdef OPENSSL_NO_ECX + BIO_puts(bio_out, "ECX\n"); +#endif #ifdef OPENSSL_NO_EC2M BIO_puts(bio_out, "EC2M\n"); #endif @@ -1432,25 +1596,43 @@ static void list_disabled(void) #ifdef OPENSSL_NO_WHIRLPOOL BIO_puts(bio_out, "WHIRLPOOL\n"); #endif -#ifndef ZLIB +#ifdef OPENSSL_NO_ZLIB BIO_puts(bio_out, "ZLIB\n"); #endif +#ifdef OPENSSL_NO_BROTLI + BIO_puts(bio_out, "BROTLI\n"); +#endif +#ifdef OPENSSL_NO_ZSTD + BIO_puts(bio_out, "ZSTD\n"); +#endif } /* Unified enum for help and list commands. */ typedef enum HELPLIST_CHOICE { OPT_COMMON, OPT_ONE, OPT_VERBOSE, + OPT_ALL_ARGORITHMS, OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS, OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS, OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_DISABLED, OPT_KDF_ALGORITHMS, OPT_RANDOM_INSTANCES, OPT_RANDOM_GENERATORS, OPT_ENCODERS, OPT_DECODERS, OPT_KEYMANAGERS, OPT_KEYEXCHANGE_ALGORITHMS, - OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS, - OPT_STORE_LOADERS, OPT_PROVIDER_INFO, - OPT_OBJECTS, OPT_SELECT_NAME, + OPT_SKEYMANAGERS, + OPT_KEM_ALGORITHMS, OPT_SIGNATURE_ALGORITHMS, + OPT_TLS_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS, + OPT_STORE_LOADERS, OPT_PROVIDER_INFO, OPT_OBJECTS, + OPT_SELECT_NAME, +#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + OPT_ALL_TLS_GROUPS, OPT_TLS_GROUPS, +# if !defined(OPENSSL_NO_TLS1_2) + OPT_TLS1_2, +# endif +# if !defined(OPENSSL_NO_TLS1_3) + OPT_TLS1_3, +# endif +#endif #ifndef OPENSSL_NO_DEPRECATED_3_0 - OPT_ENGINES, + OPT_ENGINES, #endif OPT_PROV_ENUM } HELPLIST_CHOICE; @@ -1466,6 +1648,7 @@ const OPTIONS list_options[] = { {"select", OPT_SELECT_NAME, 's', "Select a single algorithm"}, {"commands", OPT_COMMANDS, '-', "List of standard commands"}, {"standard-commands", OPT_COMMANDS, '-', "List of standard commands"}, + {"all-algorithms", OPT_ALL_ARGORITHMS, '-', "List of all algorithms"}, #ifndef OPENSSL_NO_DEPRECATED_3_0 {"digest-commands", OPT_DIGEST_COMMANDS, '-', "List of message digest commands (deprecated)"}, @@ -1481,20 +1664,23 @@ const OPTIONS list_options[] = { {"mac-algorithms", OPT_MAC_ALGORITHMS, '-', "List of message authentication code algorithms"}, #ifndef OPENSSL_NO_DEPRECATED_3_0 - {"cipher-commands", OPT_CIPHER_COMMANDS, '-', - "List of cipher commands (deprecated)"}, + {"cipher-commands", OPT_CIPHER_COMMANDS, '-', + "List of cipher commands (deprecated)"}, #endif {"cipher-algorithms", OPT_CIPHER_ALGORITHMS, '-', "List of symmetric cipher algorithms"}, {"encoders", OPT_ENCODERS, '-', "List of encoding methods" }, {"decoders", OPT_DECODERS, '-', "List of decoding methods" }, {"key-managers", OPT_KEYMANAGERS, '-', "List of key managers" }, + {"skey-managers", OPT_SKEYMANAGERS, '-', "List of symmetric key managers" }, {"key-exchange-algorithms", OPT_KEYEXCHANGE_ALGORITHMS, '-', "List of key exchange algorithms" }, {"kem-algorithms", OPT_KEM_ALGORITHMS, '-', "List of key encapsulation mechanism algorithms" }, {"signature-algorithms", OPT_SIGNATURE_ALGORITHMS, '-', "List of signature algorithms" }, + {"tls-signature-algorithms", OPT_TLS_SIGNATURE_ALGORITHMS, '-', + "List of TLS signature algorithms" }, {"asymcipher-algorithms", OPT_ASYM_CIPHER_ALGORITHMS, '-', "List of asymmetric cipher algorithms" }, {"public-key-algorithms", OPT_PK_ALGORITHMS, '-', @@ -1503,6 +1689,20 @@ const OPTIONS list_options[] = { "List of public key methods"}, {"store-loaders", OPT_STORE_LOADERS, '-', "List of store loaders"}, +#if !defined(OPENSSL_NO_TLS1_2) || !defined(OPENSSL_NO_TLS1_3) + {"tls-groups", OPT_TLS_GROUPS, '-', + "List implemented TLS key exchange 'groups'" }, + {"all-tls-groups", OPT_ALL_TLS_GROUPS, '-', + "List implemented TLS key exchange 'groups' and all aliases" }, +# ifndef OPENSSL_NO_TLS1_2 + {"tls1_2", OPT_TLS1_2, '-', + "When listing 'groups', list those compatible with TLS1.2"}, +# endif +# ifndef OPENSSL_NO_TLS1_3 + {"tls1_3", OPT_TLS1_3, '-', + "When listing 'groups', list those compatible with TLS1.3"}, +# endif +#endif {"providers", OPT_PROVIDER_INFO, '-', "List of provider information"}, #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -1524,8 +1724,18 @@ int list_main(int argc, char **argv) char *prog; HELPLIST_CHOICE o; int one = 0, done = 0; + int print_newline = 0; +#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + int all_tls_groups = 0; +# if !defined(OPENSSL_NO_TLS1_3) + unsigned int tls_version = TLS1_3_VERSION; +# else + unsigned int tls_version = TLS1_2_VERSION; +# endif +#endif struct { unsigned int commands:1; + unsigned int all_algorithms:1; unsigned int random_instances:1; unsigned int random_generators:1; unsigned int digest_commands:1; @@ -1537,9 +1747,12 @@ int list_main(int argc, char **argv) unsigned int encoder_algorithms:1; unsigned int decoder_algorithms:1; unsigned int keymanager_algorithms:1; + unsigned int skeymanager_algorithms:1; unsigned int signature_algorithms:1; + unsigned int tls_signature_algorithms:1; unsigned int keyexchange_algorithms:1; unsigned int kem_algorithms:1; + unsigned int tls_groups:1; unsigned int asym_cipher_algorithms:1; unsigned int pk_algorithms:1; unsigned int pk_method:1; @@ -1569,6 +1782,9 @@ opthelp: case OPT_ONE: one = 1; break; + case OPT_ALL_ARGORITHMS: + todo.all_algorithms = 1; + break; case OPT_COMMANDS: todo.commands = 1; break; @@ -1605,15 +1821,40 @@ opthelp: case OPT_KEYMANAGERS: todo.keymanager_algorithms = 1; break; + case OPT_SKEYMANAGERS: + todo.skeymanager_algorithms = 1; + break; case OPT_SIGNATURE_ALGORITHMS: todo.signature_algorithms = 1; break; + case OPT_TLS_SIGNATURE_ALGORITHMS: + todo.tls_signature_algorithms = 1; + break; case OPT_KEYEXCHANGE_ALGORITHMS: todo.keyexchange_algorithms = 1; break; case OPT_KEM_ALGORITHMS: todo.kem_algorithms = 1; break; +#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + case OPT_TLS_GROUPS: + todo.tls_groups = 1; + break; + case OPT_ALL_TLS_GROUPS: + all_tls_groups = 1; + todo.tls_groups = 1; + break; +# if !defined(OPENSSL_NO_TLS1_2) + case OPT_TLS1_2: + tls_version = TLS1_2_VERSION; + break; +# endif +# if !defined(OPENSSL_NO_TLS1_3) + case OPT_TLS1_3: + tls_version = TLS1_3_VERSION; + break; +# endif +#endif case OPT_ASYM_CIPHER_ALGORITHMS: todo.asym_cipher_algorithms = 1; break; @@ -1658,57 +1899,105 @@ opthelp: } /* No extra arguments. */ - if (opt_num_rest() != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; +#define MAYBE_ADD_NL(cmd) \ + do { \ + if (print_newline++) { \ + BIO_printf(bio_out, "\n"); \ + } \ + cmd; \ + } while (0) + if (todo.commands) - list_type(FT_general, one); - if (todo.random_instances) - list_random_instances(); - if (todo.random_generators) - list_random_generators(); - if (todo.digest_commands) - list_type(FT_md, one); - if (todo.digest_algorithms) - list_digests(); - if (todo.kdf_algorithms) + MAYBE_ADD_NL(list_type(FT_general, one)); + if (todo.all_algorithms) { + MAYBE_ADD_NL({}); + + BIO_printf(bio_out, "Digests:\n"); + list_digests(" "); + BIO_printf(bio_out, "\nSymmetric Ciphers:\n"); + list_ciphers(" "); + BIO_printf(bio_out, "\n"); list_kdfs(); - if (todo.mac_algorithms) + BIO_printf(bio_out, "\n"); list_macs(); - if (todo.cipher_commands) - list_type(FT_cipher, one); - if (todo.cipher_algorithms) - list_ciphers(); - if (todo.encoder_algorithms) - list_encoders(); - if (todo.decoder_algorithms) - list_decoders(); - if (todo.keymanager_algorithms) - list_keymanagers(); - if (todo.signature_algorithms) - list_signatures(); - if (todo.asym_cipher_algorithms) + + BIO_printf(bio_out, "\nProvided Asymmetric Encryption:\n"); list_asymciphers(); - if (todo.keyexchange_algorithms) + BIO_printf(bio_out, "\nProvided Key Exchange:\n"); list_keyexchanges(); - if (todo.kem_algorithms) + BIO_printf(bio_out, "\nProvided Signatures:\n"); + list_signatures(); + BIO_printf(bio_out, "\nProvided Key encapsulation:\n"); list_kems(); - if (todo.pk_algorithms) - list_pkey(); - if (todo.pk_method) - list_pkey_meth(); - if (todo.store_loaders) + BIO_printf(bio_out, "\nProvided Key managers:\n"); + list_keymanagers(); + + BIO_printf(bio_out, "\n"); + list_encoders(); + BIO_printf(bio_out, "\n"); + list_decoders(); + BIO_printf(bio_out, "\n"); list_store_loaders(); + } + if (todo.random_instances) + MAYBE_ADD_NL(list_random_instances()); + if (todo.random_generators) + MAYBE_ADD_NL(list_random_generators()); + if (todo.digest_commands) + MAYBE_ADD_NL(list_type(FT_md, one)); + if (todo.digest_algorithms) + MAYBE_ADD_NL(list_digests("")); + if (todo.kdf_algorithms) + MAYBE_ADD_NL(list_kdfs()); + if (todo.mac_algorithms) + MAYBE_ADD_NL(list_macs()); + if (todo.cipher_commands) + MAYBE_ADD_NL(list_type(FT_cipher, one)); + if (todo.cipher_algorithms) + MAYBE_ADD_NL(list_ciphers("")); + if (todo.encoder_algorithms) + MAYBE_ADD_NL(list_encoders()); + if (todo.decoder_algorithms) + MAYBE_ADD_NL(list_decoders()); + if (todo.keymanager_algorithms) + MAYBE_ADD_NL(list_keymanagers()); + if (todo.skeymanager_algorithms) + MAYBE_ADD_NL(list_skeymanagers()); + if (todo.signature_algorithms) + MAYBE_ADD_NL(list_signatures()); + if (todo.tls_signature_algorithms) + MAYBE_ADD_NL(list_tls_signatures()); + if (todo.asym_cipher_algorithms) + MAYBE_ADD_NL(list_asymciphers()); + if (todo.keyexchange_algorithms) + MAYBE_ADD_NL(list_keyexchanges()); + if (todo.kem_algorithms) + MAYBE_ADD_NL(list_kems()); +#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) + if (todo.tls_groups) + MAYBE_ADD_NL(list_tls_groups(tls_version, all_tls_groups)); +#endif + if (todo.pk_algorithms) + MAYBE_ADD_NL(list_pkey()); + if (todo.pk_method) + MAYBE_ADD_NL(list_pkey_meth()); + if (todo.store_loaders) + MAYBE_ADD_NL(list_store_loaders()); if (todo.provider_info) - list_provider_info(); + MAYBE_ADD_NL(list_provider_info()); #ifndef OPENSSL_NO_DEPRECATED_3_0 if (todo.engines) - list_engines(); + MAYBE_ADD_NL(list_engines()); #endif if (todo.disabled) - list_disabled(); + MAYBE_ADD_NL(list_disabled()); if (todo.objects) - list_objects(); + MAYBE_ADD_NL(list_objects()); + +#undef MAYBE_ADD_NL if (!done) goto opthelp; diff --git a/apps/mac.c b/apps/mac.c index a9b6a265f49a..0a07b2ea4332 100644 --- a/apps/mac.c +++ b/apps/mac.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -137,10 +137,9 @@ opthelp: } /* One argument, the MAC name. */ - argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 1) + if (!opt_check_rest_arg("MAC name")) goto opthelp; + argv = opt_rest(); mac = EVP_MAC_fetch(app_get0_libctx(), argv[0], app_get0_propq()); if (mac == NULL) { @@ -218,7 +217,7 @@ opthelp: for (i = 0; i < (int)len; ++i) BIO_printf(out, "%02X", buf[i]); if (outfile == NULL) - BIO_printf(out,"\n"); + BIO_printf(out, "\n"); } ret = 0; diff --git a/apps/nseq.c b/apps/nseq.c index d5524370f26c..e66b58d95705 100644 --- a/apps/nseq.c +++ b/apps/nseq.c @@ -73,8 +73,7 @@ int nseq_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; in = bio_open_default(infile, 'r', FORMAT_PEM); diff --git a/apps/ocsp.c b/apps/ocsp.c index fb3105da5526..79b76a2ca747 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ #ifdef OPENSSL_SYS_VMS /* So fd_set and friends get properly defined on OpenVMS */ -# define _XOPEN_SOURCE_EXTENDED 1 +# define _XOPEN_SOURCE_EXTENDED #endif #include @@ -33,12 +33,6 @@ #include #include -#if defined(__TANDEM) -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif -#endif - #if defined(OPENSSL_SYS_VXWORKS) /* not supported */ int setpgid(pid_t pid, pid_t pgid) @@ -76,7 +70,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, - const char *port, int timeout); + int timeout); static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp); static char *prog; @@ -136,7 +130,7 @@ const OPTIONS ocsp_options[] = { "Don't include any certificates in signed request"}, {"badsig", OPT_BADSIG, '-', "Corrupt last byte of loaded OCSP response signature (for test)"}, - {"CA", OPT_CA, '<', "CA certificate"}, + {"CA", OPT_CA, '<', "CA certificates"}, {"nmin", OPT_NMIN, 'p', "Number of minutes before next update"}, {"nrequest", OPT_REQUEST, 'p', "Number of requests to accept (default unlimited)"}, @@ -196,8 +190,10 @@ const OPTIONS ocsp_options[] = { {"VAfile", OPT_VAFILE, '<', "Validator certificates file"}, {"verify_other", OPT_VERIFY_OTHER, '<', "Additional certificates to search for signer"}, - {"cert", OPT_CERT, '<', "Certificate to check"}, - {"serial", OPT_SERIAL, 's', "Serial number to check"}, + {"cert", OPT_CERT, '<', + "Certificate to check; may be given multiple times"}, + {"serial", OPT_SERIAL, 's', + "Serial number to check; may be given multiple times"}, {"validity_period", OPT_VALIDITY_PERIOD, 'u', "Maximum validity discrepancy in seconds"}, {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"}, @@ -228,7 +224,7 @@ int ocsp_main(int argc, char **argv) STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; STACK_OF(X509) *issuers = NULL; X509 *issuer = NULL, *cert = NULL; - STACK_OF(X509) *rca_cert = NULL; + STACK_OF(X509) *rca_certs = NULL; EVP_MD *resp_certid_md = NULL; X509 *signer = NULL, *rsigner = NULL; X509_STORE *store = NULL; @@ -261,6 +257,7 @@ int ocsp_main(int argc, char **argv) || (vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, ocsp_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -436,6 +433,7 @@ int ocsp_main(int argc, char **argv) goto end; break; case OPT_CERT: + reset_unknown(); X509_free(cert); cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate"); if (cert == NULL) @@ -449,6 +447,7 @@ int ocsp_main(int argc, char **argv) trailing_md = 0; break; case OPT_SERIAL: + reset_unknown(); if (cert_id_md == NULL) cert_id_md = (EVP_MD *)EVP_sha1(); if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids)) @@ -524,7 +523,7 @@ int ocsp_main(int argc, char **argv) break; case OPT_MULTI: #ifdef HTTP_DAEMON - multi = atoi(opt_arg()); + n_responders = atoi(opt_arg()); #endif break; case OPT_PROV_CASES: @@ -535,8 +534,7 @@ int ocsp_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (trailing_md) { @@ -555,10 +553,6 @@ int ocsp_main(int argc, char **argv) && respin == NULL && !(port != NULL && ridx_filename != NULL)) goto opthelp; - out = bio_open_default(outfile, 'w', FORMAT_TEXT); - if (out == NULL) - goto end; - if (req == NULL && (add_nonce != 2)) add_nonce = 0; @@ -576,7 +570,7 @@ int ocsp_main(int argc, char **argv) if (req == NULL && port != NULL) { #ifndef OPENSSL_NO_SOCK - acbio = http_server_init_bio(prog, port); + acbio = http_server_init(prog, port, -1); if (acbio == NULL) goto end; #else @@ -593,7 +587,7 @@ int ocsp_main(int argc, char **argv) BIO_printf(bio_err, "Error loading responder certificate\n"); goto end; } - if (!load_certs(rca_filename, 0, &rca_cert, NULL, "CA certificates")) + if (!load_certs(rca_filename, 0, &rca_certs, NULL, "CA certificates")) goto end; if (rcertfile != NULL) { if (!load_certs(rcertfile, 0, &rother, NULL, @@ -611,7 +605,7 @@ int ocsp_main(int argc, char **argv) } if (ridx_filename != NULL - && (rkey == NULL || rsigner == NULL || rca_cert == NULL)) { + && (rkey == NULL || rsigner == NULL || rca_certs == NULL)) { BIO_printf(bio_err, "Responder mode requires certificate, key, and CA.\n"); goto end; @@ -629,14 +623,15 @@ int ocsp_main(int argc, char **argv) } #ifdef HTTP_DAEMON - if (multi && acbio != NULL) + if (n_responders != 0 && acbio != NULL) spawn_loop(prog); if (acbio != NULL && req_timeout > 0) signal(SIGALRM, socket_timeout); #endif if (acbio != NULL) - log_message(prog, LOG_INFO, "waiting for OCSP client connections..."); + trace_log_message(-1, prog, + LOG_INFO, "waiting for OCSP client connections..."); redo_accept: @@ -650,14 +645,15 @@ redo_accept: rdb = newrdb; } else { free_index(newrdb); - log_message(prog, LOG_ERR, "error reloading updated index: %s", - ridx_filename); + trace_log_message(-1, prog, + LOG_ERR, "error reloading updated index: %s", + ridx_filename); } } #endif req = NULL; - res = do_responder(&req, &cbio, acbio, port, req_timeout); + res = do_responder(&req, &cbio, acbio, req_timeout); if (res == 0) goto redo_accept; @@ -709,6 +705,10 @@ redo_accept: } } + out = bio_open_default(outfile, 'w', FORMAT_TEXT); + if (out == NULL) + goto end; + if (req_text && req != NULL) OCSP_REQUEST_print(out, req, 0); @@ -721,7 +721,7 @@ redo_accept: } if (rdb != NULL) { - make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey, + make_ocsp_response(bio_err, &resp, req, rdb, rca_certs, rsigner, rkey, rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig, resp_certid_md); if (resp == NULL) @@ -858,9 +858,9 @@ redo_accept: EVP_MD_free(rsign_md); EVP_MD_free(resp_certid_md); X509_free(cert); - sk_X509_pop_free(issuers, X509_free); + OSSL_STACK_OF_X509_free(issuers); X509_free(rsigner); - sk_X509_pop_free(rca_cert, X509_free); + OSSL_STACK_OF_X509_free(rca_certs); free_index(rdb); BIO_free_all(cbio); BIO_free_all(acbio); @@ -870,8 +870,8 @@ redo_accept: OCSP_BASICRESP_free(bs); sk_OPENSSL_STRING_free(reqnames); sk_OCSP_CERTID_free(ids); - sk_X509_pop_free(sign_other, X509_free); - sk_X509_pop_free(verify_other, X509_free); + OSSL_STACK_OF_X509_free(sign_other); + OSSL_STACK_OF_X509_free(verify_other); sk_CONF_VALUE_pop_free(headers, X509V3_conf_free); OPENSSL_free(thost); OPENSSL_free(tport); @@ -1049,6 +1049,10 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req } bs = OCSP_BASICRESP_new(); + if (bs == NULL) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, bs); + goto end; + } thisupd = X509_gmtime_adj(NULL, 0); if (ndays != -1) nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL); @@ -1139,7 +1143,7 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req OCSP_copy_nonce(bs, req); mctx = EVP_MD_CTX_new(); - if ( mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) { + if (mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) { *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); goto end; } @@ -1197,13 +1201,13 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser) } static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, - const char *port, int timeout) + int timeout) { #ifndef OPENSSL_NO_SOCK return http_server_get_asn1_req(ASN1_ITEM_rptr(OCSP_REQUEST), (ASN1_VALUE **)preq, NULL, pcbio, acbio, NULL /* found_keep_alive */, - prog, port, 1 /* accept_get */, timeout); + prog, 1 /* accept_get */, timeout); #else BIO_printf(bio_err, "Error getting OCSP request - sockets not supported\n"); @@ -1215,7 +1219,7 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, static int send_ocsp_response(BIO *cbio, const OCSP_RESPONSE *resp) { #ifndef OPENSSL_NO_SOCK - return http_server_send_asn1_resp(cbio, + return http_server_send_asn1_resp(prog, cbio, 0 /* no keep-alive */, "application/ocsp-response", ASN1_ITEM_rptr(OCSP_RESPONSE), diff --git a/apps/openssl-vms.cnf b/apps/openssl-vms.cnf index ac858d670d18..768291e4ee87 100644 --- a/apps/openssl-vms.cnf +++ b/apps/openssl-vms.cnf @@ -13,7 +13,7 @@ # defined. HOME = . - # Use this in order to automatically load providers. +# Use this in order to automatically load providers. openssl_conf = openssl_init # Comment out the next line to ignore configuration errors @@ -92,7 +92,7 @@ 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 +private_key = $dir.private]cakey.pem # The private key x509_extensions = usr_cert # The extensions to add to the cert @@ -330,8 +330,8 @@ 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) +ess_cert_id_alg = sha256 # algorithm to compute certificate + # identifier (optional, default: sha256) [insta] # CMP using Insta Demo CA # Message transfer @@ -342,8 +342,8 @@ 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 +ignore_keyusage = 1 # quirk needed to accept Insta CA cert not including digitalsignature +unprotected_errors = 1 # quirk needed to accept negative responses possibly not protected extracertsout = insta.extracerts.pem # Client authentication diff --git a/apps/openssl.c b/apps/openssl.c index a3056c799f85..cbd3476b32b6 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -1,5 +1,5 @@ /* - * 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 @@ -7,9 +7,11 @@ * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" + #include -#include #include +#include "internal/common.h" #include #include #include @@ -157,8 +159,6 @@ static void tracedata_free(tracedata *data) OPENSSL_free(data); } -static STACK_OF(tracedata) *trace_data_stack; - static void cleanup_trace(void) { sk_tracedata_pop_free(trace_data_stack, tracedata_free); @@ -232,6 +232,7 @@ static void setup_trace(const char *str) #endif /* OPENSSL_NO_TRACE */ static char *help_argv[] = { "help", NULL }; +static char *version_argv[] = { "version", NULL }; int main(int argc, char *argv[]) { @@ -241,6 +242,7 @@ int main(int argc, char *argv[]) const char *fname; ARGS arg; int global_help = 0; + int global_version = 0; int ret = 0; arg.argv = NULL; @@ -285,17 +287,26 @@ int main(int argc, char *argv[]) global_help = argc > 1 && (strcmp(argv[1], "-help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--h") == 0); + global_version = argc > 1 + && (strcmp(argv[1], "-version") == 0 || strcmp(argv[1], "--version") == 0 + || strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--v") == 0); + argc--; argv++; - opt_appname(argc == 1 || global_help ? "help" : argv[0]); + opt_appname(argc == 1 || global_help ? "help" : global_version ? "version" : argv[0]); } else { argv[0] = pname; } - /* If there's a command, run with that, otherwise "help". */ - ret = argc == 0 || global_help - ? do_cmd(prog, 1, help_argv) - : do_cmd(prog, argc, argv); + /* + * If there's no command, assume "help". If there's an override for help + * or version run those, otherwise run the command given. + */ + ret = (argc == 0) || global_help + ? do_cmd(prog, 1, help_argv) + : global_version + ? do_cmd(prog, 1, version_argv) + : do_cmd(prog, argc, argv); end: OPENSSL_free(default_config_file); @@ -326,7 +337,6 @@ const OPTIONS help_options[] = { {NULL} }; - int help_main(int argc, char **argv) { FUNCTION *fp; @@ -357,7 +367,7 @@ int help_main(int argc, char **argv) new_argv[2] = NULL; return do_cmd(prog_init(), 2, new_argv); } - if (opt_num_rest() != 0) { + if (!opt_check_rest_arg(NULL)) { BIO_printf(bio_err, "Usage: %s\n", prog); return 1; } @@ -417,12 +427,12 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) warn_deprecated(fp); return fp->func(argc, argv); } - if ((strncmp(argv[0], "no-", 3)) == 0) { + f.name = argv[0]; + if (CHECK_AND_SKIP_PREFIX(f.name, "no-")) { /* * User is asking if foo is unsupported, by trying to "run" the * no-foo command. Strange. */ - f.name = argv[0] + 3; if (lh_FUNCTION_retrieve(prog, &f) == NULL) { BIO_printf(bio_out, "%s\n", argv[0]); return 0; @@ -436,12 +446,12 @@ static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]) return 1; } -static int function_cmp(const FUNCTION * a, const FUNCTION * b) +static int function_cmp(const FUNCTION *a, const FUNCTION *b) { return strncmp(a->name, b->name, 8); } -static unsigned long function_hash(const FUNCTION * a) +static unsigned long function_hash(const FUNCTION *a) { return OPENSSL_LH_strhash(a->name); } diff --git a/apps/openssl.cnf b/apps/openssl.cnf index 12bc40896ef2..abace0ea7f1c 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -13,7 +13,7 @@ # defined. HOME = . - # Use this in order to automatically load providers. +# Use this in order to automatically load providers. openssl_conf = openssl_init # Comment out the next line to ignore configuration errors @@ -92,7 +92,7 @@ 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 +private_key = $dir/private/cakey.pem # The private key x509_extensions = usr_cert # The extensions to add to the cert @@ -330,8 +330,8 @@ 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) +ess_cert_id_alg = sha256 # algorithm to compute certificate + # identifier (optional, default: sha256) [insta] # CMP using Insta Demo CA # Message transfer @@ -342,8 +342,8 @@ 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 +ignore_keyusage = 1 # quirk needed to accept Insta CA cert not including digitalsignature +unprotected_errors = 1 # quirk needed to accept negative responses possibly not protected extracertsout = insta.extracerts.pem # Client authentication diff --git a/apps/passwd.c b/apps/passwd.c index 31d8bdd87cb6..8b233538d87b 100644 --- a/apps/passwd.c +++ b/apps/passwd.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -369,8 +369,7 @@ static char *md5crypt(const char *passwd, const char *magic, const char *salt) if (magic_len > 0) salt_out += 2 + magic_len; - if (salt_len > 8) - goto err; + assert(salt_len <= 8); md = EVP_MD_CTX_new(); if (md == NULL @@ -602,7 +601,7 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt) OPENSSL_strlcat(out_buf, ascii_salt, sizeof(out_buf)); /* assert "$5$rounds=999999999$......salt......" */ - if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len ) + if (strlen(out_buf) > 3 + 17 * rounds_custom + salt_len) goto err; md = EVP_MD_CTX_new(); @@ -707,15 +706,14 @@ static char *shacrypt(const char *passwd, const char *magic, const char *salt) cp = out_buf + strlen(out_buf); *cp++ = ascii_dollar[0]; -# define b64_from_24bit(B2, B1, B0, N) \ +# define b64_from_24bit(B2, B1, B0, N) \ do { \ unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ int i = (N); \ - while (i-- > 0) \ - { \ - *cp++ = cov_2char[w & 0x3f]; \ - w >>= 6; \ - } \ + while (i-- > 0) { \ + *cp++ = cov_2char[w & 0x3f]; \ + w >>= 6; \ + } \ } while (0) switch (magic[0]) { diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 5146699f1672..9964faf21aae 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -14,12 +14,14 @@ #include #include "apps.h" #include "progs.h" +#include #include #include #include #include #include #include +#include #define NOKEYS 0x1 #define NOCERTS 0x2 @@ -53,6 +55,7 @@ void hex_prin(BIO *out, unsigned char *buf, int len); static int alg_print(const X509_ALGOR *alg); int cert_load(BIO *in, STACK_OF(X509) *sk); static int set_pbe(int *ppbe, const char *str); +static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg); typedef enum OPTION_choice { OPT_COMMON, @@ -61,13 +64,13 @@ typedef enum OPTION_choice { #ifndef OPENSSL_NO_DES OPT_DESCERT, #endif - OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, + OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER, OPT_MACSALTLEN, OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE, OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS, OPT_NAME, OPT_CSP, OPT_CANAME, OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE, - OPT_R_ENUM, OPT_PROV_ENUM, + OPT_R_ENUM, OPT_PROV_ENUM, OPT_JDKTRUST, OPT_PBMAC1_PBKDF2, OPT_PBMAC1_PBKDF2_MD, #ifndef OPENSSL_NO_DES OPT_LEGACY_ALG #endif @@ -144,33 +147,39 @@ const OPTIONS pkcs12_options[] = { #endif {"macalg", OPT_MACALG, 's', "Digest algorithm to use in MAC (default SHA256)"}, + {"pbmac1_pbkdf2", OPT_PBMAC1_PBKDF2, '-', "Use PBMAC1 with PBKDF2 instead of MAC"}, + {"pbmac1_pbkdf2_md", OPT_PBMAC1_PBKDF2_MD, 's', "Digest to use for PBMAC1 KDF (default SHA256)"}, {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"}, {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"}, {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"}, {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"}, + {"macsaltlen", OPT_MACSALTLEN, 'p', "Specify the salt len for MAC"}, {"nomac", OPT_NOMAC, '-', "Don't generate MAC"}, + {"jdktrust", OPT_JDKTRUST, 's', "Mark certificate in PKCS#12 store as trusted for JDK compatibility"}, {NULL} }; int pkcs12_main(int argc, char **argv) { char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL; - char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL; + char *untrusted = NULL, *ciphername = NULL, *enc_name = NULL; char *passcertsarg = NULL, *passcerts = NULL; char *name = NULL, *csp_name = NULL; char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = ""; int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0; + char *jdktrust = NULL; #ifndef OPENSSL_NO_DES int use_legacy = 0; #endif /* use library defaults for the iter, maciter, cert, and key PBE */ - int iter = 0, maciter = 0; + int iter = 0, maciter = 0, pbmac1_pbkdf2 = 0; + int macsaltlen = PKCS12_SALT_LEN; int cert_pbe = NID_undef; int key_pbe = NID_undef; int ret = 1, macver = 1, add_lmk = 0, private = 0; int noprompt = 0; char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; - char *passin = NULL, *passout = NULL, *macalg = NULL; + char *passin = NULL, *passout = NULL, *macalg = NULL, *pbmac1_pbkdf2_md = NULL; char *cpass = NULL, *mpass = NULL, *badpass = NULL; const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog; int noCApath = 0, noCAfile = 0, noCAstore = 0; @@ -182,6 +191,7 @@ int pkcs12_main(int argc, char **argv) EVP_CIPHER *enc = (EVP_CIPHER *)default_enc; OPTION_CHOICE o; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, pkcs12_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -215,6 +225,11 @@ int pkcs12_main(int argc, char **argv) case OPT_NOOUT: options |= (NOKEYS | NOCERTS); break; + case OPT_JDKTRUST: + jdktrust = opt_arg(); + /* Adding jdk trust implies nokeys */ + options |= NOKEYS; + break; case OPT_INFO: options |= INFO; break; @@ -238,16 +253,15 @@ int pkcs12_main(int argc, char **argv) case OPT_NODES: case OPT_NOENC: /* - * |enc_flag| stores the name of the option used so it + * |enc_name| stores the name of the option used so it * can be printed if an error message is output. */ - enc_flag = opt_flag() + 1; + enc_name = opt_flag() + 1; enc = NULL; ciphername = NULL; break; case OPT_CIPHER: - ciphername = opt_unknown(); - enc_flag = opt_unknown(); + enc_name = ciphername = opt_unknown(); break; case OPT_ITER: maciter = iter = opt_int_arg(); @@ -261,6 +275,9 @@ int pkcs12_main(int argc, char **argv) case OPT_NOMACITER: maciter = 1; break; + case OPT_MACSALTLEN: + macsaltlen = opt_int_arg(); + break; case OPT_NOMAC: cert_pbe = -1; maciter = -1; @@ -268,6 +285,12 @@ int pkcs12_main(int argc, char **argv) case OPT_MACALG: macalg = opt_arg(); break; + case OPT_PBMAC1_PBKDF2: + pbmac1_pbkdf2 = 1; + break; + case OPT_PBMAC1_PBKDF2_MD: + pbmac1_pbkdf2_md = opt_arg(); + break; case OPT_CERTPBE: if (!set_pbe(&cert_pbe, opt_arg())) goto opthelp; @@ -357,17 +380,14 @@ int pkcs12_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) goto end; - if (ciphername != NULL) { - if (!opt_cipher_any(ciphername, &enc)) - goto opthelp; - } + if (!opt_cipher_any(ciphername, &enc)) + goto opthelp; if (export_pkcs12) { if ((options & INFO) != 0) WARN_EXPORT("info"); @@ -379,7 +399,7 @@ int pkcs12_main(int argc, char **argv) WARN_EXPORT("cacerts"); if (enc != default_enc) BIO_printf(bio_err, - "Warning: output encryption option -%s ignored with -export\n", enc_flag); + "Warning: output encryption option -%s ignored with -export\n", enc_name); } else { if (keyname != NULL) WARN_NO_EXPORT("inkey"); @@ -427,6 +447,8 @@ int pkcs12_main(int argc, char **argv) WARN_NO_EXPORT("nomaciter"); if (cert_pbe == -1 && maciter == -1) WARN_NO_EXPORT("nomac"); + if (macsaltlen != PKCS12_SALT_LEN) + WARN_NO_EXPORT("macsaltlen"); } #ifndef OPENSSL_NO_DES if (use_legacy) { @@ -521,6 +543,7 @@ int pkcs12_main(int argc, char **argv) EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; + ASN1_OBJECT *obj = NULL; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n"); @@ -556,7 +579,7 @@ int pkcs12_main(int argc, char **argv) /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); - if (X509_check_private_key(x, key)) { + if (cert_matches_key(x, key)) { ee_cert = x; /* Zero keyid and alias */ X509_keyid_set1(ee_cert, NULL, 0); @@ -614,7 +637,7 @@ int pkcs12_main(int argc, char **argv) /* Add the remaining certs (except for duplicates) */ add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP); - sk_X509_pop_free(chain2, X509_free); + OSSL_STACK_OF_X509_free(chain2); if (!add_certs) goto export_end; } else { @@ -665,9 +688,14 @@ int pkcs12_main(int argc, char **argv) if (!twopass) OPENSSL_strlcpy(macpass, pass, sizeof(macpass)); - p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs, - key_pbe, cert_pbe, iter, -1, keytype, - app_get0_libctx(), app_get0_propq()); + if (jdktrust != NULL) { + obj = OBJ_txt2obj(jdktrust, 0); + } + + p12 = PKCS12_create_ex2(cpass, name, key, ee_cert, certs, + key_pbe, cert_pbe, iter, -1, keytype, + app_get0_libctx(), app_get0_propq(), + jdk_trust, (void*)obj); if (p12 == NULL) { BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n", @@ -680,13 +708,23 @@ int pkcs12_main(int argc, char **argv) goto opthelp; } - if (maciter != -1) - if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) { - BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n"); - BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n"); - goto export_end; + if (maciter != -1) { + if (pbmac1_pbkdf2 == 1) { + if (!PKCS12_set_pbmac1_pbkdf2(p12, mpass, -1, NULL, + macsaltlen, maciter, + macmd, pbmac1_pbkdf2_md)) { + BIO_printf(bio_err, "Error creating PBMAC1\n"); + goto export_end; + } + } else { + if (!PKCS12_set_mac(p12, mpass, -1, NULL, macsaltlen, maciter, macmd)) { + BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n"); + BIO_printf(bio_err, + "Use -nomac or -pbmac1_pbkdf2 if PKCS12KDF support not available\n"); + goto export_end; + } } - + } assert(private); out = bio_open_owner(outfile, FORMAT_PKCS12, private); @@ -701,10 +739,10 @@ int pkcs12_main(int argc, char **argv) EVP_PKEY_free(key); EVP_MD_free(macmd); - sk_X509_pop_free(certs, X509_free); - sk_X509_pop_free(untrusted_certs, X509_free); + OSSL_STACK_OF_X509_free(certs); + OSSL_STACK_OF_X509_free(untrusted_certs); X509_free(ee_cert); - + ASN1_OBJECT_free(obj); ERR_print_errors(bio_err); goto end; @@ -755,23 +793,64 @@ int pkcs12_main(int argc, char **argv) X509_ALGOR_get0(&macobj, NULL, NULL, macalgid); BIO_puts(bio_err, "MAC: "); i2a_ASN1_OBJECT(bio_err, macobj); - BIO_printf(bio_err, ", Iteration %ld\n", - tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L); - BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n", - tmac != NULL ? ASN1_STRING_length(tmac) : 0L, - tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); - } - if (macver) { - EVP_KDF *pkcs12kdf; + if (OBJ_obj2nid(macobj) == NID_pbmac1) { + PBKDF2PARAM *pbkdf2_param = PBMAC1_get1_pbkdf2_param(macalgid); - pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF", - app_get0_propq()); - if (pkcs12kdf == NULL) { - BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n"); - BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n"); - goto end; + if (pbkdf2_param == NULL) { + BIO_printf(bio_err, ", Unsupported KDF or params for PBMAC1\n"); + } else { + const ASN1_OBJECT *prfobj; + int prfnid; + + BIO_printf(bio_err, " using PBKDF2, Iteration %ld\n", + ASN1_INTEGER_get(pbkdf2_param->iter)); + BIO_printf(bio_err, "Key length: %ld, Salt length: %d\n", + ASN1_INTEGER_get(pbkdf2_param->keylength), + ASN1_STRING_length(pbkdf2_param->salt->value.octet_string)); + if (pbkdf2_param->prf == NULL) { + prfnid = NID_hmacWithSHA1; + } else { + X509_ALGOR_get0(&prfobj, NULL, NULL, pbkdf2_param->prf); + prfnid = OBJ_obj2nid(prfobj); + } + BIO_printf(bio_err, "PBKDF2 PRF: %s\n", OBJ_nid2sn(prfnid)); + } + PBKDF2PARAM_free(pbkdf2_param); + } else { + BIO_printf(bio_err, ", Iteration %ld\n", + tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L); + BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n", + tmac != NULL ? ASN1_STRING_length(tmac) : 0L, + tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L); } - EVP_KDF_free(pkcs12kdf); + } + + if (macver) { + const X509_ALGOR *macalgid; + const ASN1_OBJECT *macobj; + + PKCS12_get0_mac(NULL, &macalgid, NULL, NULL, p12); + + if (macalgid == NULL) { + BIO_printf(bio_err, "Warning: MAC is absent!\n"); + goto dump; + } + + X509_ALGOR_get0(&macobj, NULL, NULL, macalgid); + + if (OBJ_obj2nid(macobj) != NID_pbmac1) { + EVP_KDF *pkcs12kdf; + + pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF", + app_get0_propq()); + if (pkcs12kdf == NULL) { + BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n"); + BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n"); + goto end; + } + EVP_KDF_free(pkcs12kdf); + } + /* If we enter empty password try no password first */ if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ @@ -836,12 +915,36 @@ int pkcs12_main(int argc, char **argv) return ret; } +static int jdk_trust(PKCS12_SAFEBAG *bag, void *cbarg) +{ + STACK_OF(X509_ATTRIBUTE) *attrs = NULL; + X509_ATTRIBUTE *attr = NULL; + + /* Nothing to do */ + if (cbarg == NULL) + return 1; + + /* Get the current attrs */ + attrs = (STACK_OF(X509_ATTRIBUTE)*)PKCS12_SAFEBAG_get0_attrs(bag); + + /* Create a new attr for the JDK Trusted Usage and add it */ + attr = X509_ATTRIBUTE_create(NID_oracle_jdk_trustedkeyusage, V_ASN1_OBJECT, (ASN1_OBJECT*)cbarg); + + /* Add the new attr, if attrs is NULL, it'll be initialised */ + X509at_add1_attr(&attrs, attr); + + /* Set the bag attrs */ + PKCS12_SAFEBAG_set0_attrs(bag, attrs); + + X509_ATTRIBUTE_free(attr); + return 1; +} + int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, int passlen, int options, char *pempass, const EVP_CIPHER *enc) { STACK_OF(PKCS7) *asafes = NULL; - STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid; int ret = 0; PKCS7 *p7; @@ -849,6 +952,8 @@ int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) return 0; for (i = 0; i < sk_PKCS7_num(asafes); i++) { + STACK_OF(PKCS12_SAFEBAG) *bags; + p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { @@ -868,7 +973,7 @@ int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, } else { continue; } - if (!bags) + if (bags == NULL) goto err; if (!dump_certs_pkeys_bags(out, bags, pass, passlen, options, pempass, enc)) { @@ -876,7 +981,6 @@ int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass, goto err; } sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); - bags = NULL; } ret = 1; @@ -1139,6 +1243,8 @@ int cert_load(BIO *in, STACK_OF(X509) *sk) void print_attribute(BIO *out, const ASN1_TYPE *av) { char *value; + const char *ln; + char objbuf[80]; switch (av->type) { case V_ASN1_BMPSTRING: @@ -1165,6 +1271,15 @@ void print_attribute(BIO *out, const ASN1_TYPE *av) BIO_printf(out, "\n"); break; + case V_ASN1_OBJECT: + ln = OBJ_nid2ln(OBJ_obj2nid(av->value.object)); + if (!ln) + ln = ""; + OBJ_obj2txt(objbuf, sizeof(objbuf), av->value.object, 1); + BIO_printf(out, "%s (%s)", ln, objbuf); + BIO_printf(out, "\n"); + break; + default: BIO_printf(out, "\n", av->type); break; @@ -1202,8 +1317,7 @@ int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, } if (X509_ATTRIBUTE_count(attr)) { - for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) - { + for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) { av = X509_ATTRIBUTE_get0_type(attr, j); print_attribute(out, av); } diff --git a/apps/pkcs7.c b/apps/pkcs7.c index ba11e8151ae9..57cb517b178f 100644 --- a/apps/pkcs7.c +++ b/apps/pkcs7.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,8 +23,8 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT, - OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE, - OPT_PROV_ENUM + OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_QUIET, + OPT_ENGINE, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS pkcs7_options[] = { @@ -46,6 +46,8 @@ const OPTIONS pkcs7_options[] = { {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"}, {"print_certs", OPT_PRINT_CERTS, '-', "Print_certs print any certs or crl in the input"}, + {"quiet", OPT_QUIET, '-', + "When used with -print_certs, it produces a cleaner output"}, OPT_PROV_OPTIONS, {NULL} @@ -58,7 +60,7 @@ int pkcs7_main(int argc, char **argv) BIO *in = NULL, *out = NULL; int informat = FORMAT_PEM, outformat = FORMAT_PEM; char *infile = NULL, *outfile = NULL, *prog; - int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; + int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, quiet = 0, ret = 1; OPTION_CHOICE o; OSSL_LIB_CTX *libctx = app_get0_libctx(); @@ -100,6 +102,9 @@ int pkcs7_main(int argc, char **argv) case OPT_PRINT_CERTS: print_certs = 1; break; + case OPT_QUIET: + quiet = 1; + break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; @@ -111,8 +116,7 @@ int pkcs7_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; in = bio_open_default(infile, 'r', informat); @@ -172,7 +176,7 @@ int pkcs7_main(int argc, char **argv) x = sk_X509_value(certs, i); if (text) X509_print(out, x); - else + else if (!quiet) dump_cert_text(out, x); if (!noout) diff --git a/apps/pkcs8.c b/apps/pkcs8.c index 6b09b909eb7a..22978afb9093 100644 --- a/apps/pkcs8.c +++ b/apps/pkcs8.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -17,6 +17,9 @@ #include #include +#define STR(a) XSTR(a) +#define XSTR(a) #a + typedef enum OPTION_choice { OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT, @@ -26,6 +29,7 @@ typedef enum OPTION_choice { #endif OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT, OPT_TRADITIONAL, + OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -53,7 +57,8 @@ const OPTIONS pkcs8_options[] = { {"traditional", OPT_TRADITIONAL, '-', "use traditional format private key"}, {"iter", OPT_ITER, 'p', "Specify the iteration count"}, {"noiter", OPT_NOITER, '-', "Use 1 as iteration count"}, - + {"saltlen", OPT_SALTLEN, 'p', "Specify the salt length (in bytes)"}, + {OPT_MORE_STR, 0, 0, "Default: 8 (For PBE1) or 16 (for PBE2)"}, #ifndef OPENSSL_NO_SCRYPT OPT_SECTION("Scrypt"), {"scrypt", OPT_SCRYPT, '-', "Use scrypt algorithm"}, @@ -88,6 +93,7 @@ int pkcs8_main(int argc, char **argv) #ifndef OPENSSL_NO_SCRYPT long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; #endif + int saltlen = 0; /* A value of zero chooses the default */ prog = opt_init(argc, argv, pkcs8_options); while ((o = opt_next()) != OPT_EOF) { @@ -189,12 +195,15 @@ int pkcs8_main(int argc, char **argv) goto opthelp; break; #endif + case OPT_SALTLEN: + if (!opt_int(opt_arg(), &saltlen)) + goto opthelp; + break; } } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; private = 1; @@ -218,9 +227,6 @@ int pkcs8_main(int argc, char **argv) informat == FORMAT_UNDEF ? FORMAT_PEM : informat); if (in == NULL) goto end; - out = bio_open_owner(outfile, outformat, private); - if (out == NULL) - goto end; if (topk8) { pkey = load_key(infile, informat, 1, passin, e, "key"); @@ -231,6 +237,8 @@ int pkcs8_main(int argc, char **argv) ERR_print_errors(bio_err); goto end; } + if ((out = bio_open_owner(outfile, outformat, private)) == NULL) + goto end; if (nocrypt) { assert(private); if (outformat == FORMAT_PEM) { @@ -246,14 +254,14 @@ int pkcs8_main(int argc, char **argv) if (cipher) { #ifndef OPENSSL_NO_SCRYPT if (scrypt_N && scrypt_r && scrypt_p) - pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, 0, NULL, + pbe = PKCS5_pbe2_set_scrypt(cipher, NULL, saltlen, NULL, scrypt_N, scrypt_r, scrypt_p); else #endif - pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, 0, NULL, + pbe = PKCS5_pbe2_set_iv(cipher, iter, NULL, saltlen, NULL, pbe_nid); } else { - pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, 0); + pbe = PKCS5_pbe_set(pbe_nid, iter, NULL, saltlen); } if (pbe == NULL) { BIO_printf(bio_err, "Error setting PBE algorithm\n"); @@ -352,6 +360,9 @@ int pkcs8_main(int argc, char **argv) } assert(private); + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; if (outformat == FORMAT_PEM) { if (traditional) PEM_write_bio_PrivateKey_traditional(out, pkey, NULL, NULL, 0, diff --git a/apps/pkey.c b/apps/pkey.c index 196678533c1d..ab0c95c2acd6 100644 --- a/apps/pkey.c +++ b/apps/pkey.c @@ -83,6 +83,7 @@ int pkey_main(int argc, char **argv) char *point_format = NULL; #endif + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, pkey_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -171,8 +172,7 @@ int pkey_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (text && text_pub) @@ -190,10 +190,8 @@ int pkey_main(int argc, char **argv) private = (!noout && !pubout) || (text && !text_pub); - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &cipher)) - goto opthelp; - } + if (!opt_cipher(ciphername, &cipher)) + goto opthelp; if (cipher == NULL) { if (passoutarg != NULL) BIO_printf(bio_err, @@ -210,10 +208,6 @@ int pkey_main(int argc, char **argv) goto end; } - out = bio_open_owner(outfile, outformat, private); - if (out == NULL) - goto end; - if (pubin) pkey = load_pubkey(infile, informat, 1, passin, e, "Public Key"); else @@ -221,6 +215,10 @@ int pkey_main(int argc, char **argv) if (pkey == NULL) goto end; + out = bio_open_owner(outfile, outformat, private); + if (out == NULL) + goto end; + #ifndef OPENSSL_NO_EC if (asn1_encoding != NULL || point_format != NULL) { OSSL_PARAM params[3], *p = params; diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c index b02882ccc296..fd8de0e02fe9 100644 --- a/apps/pkeyparam.c +++ b/apps/pkeyparam.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -91,16 +91,12 @@ int pkeyparam_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; in = bio_open_default(infile, 'r', FORMAT_PEM); if (in == NULL) goto end; - out = bio_open_default(outfile, 'w', FORMAT_PEM); - if (out == NULL) - goto end; pkey = PEM_read_bio_Parameters_ex(in, NULL, app_get0_libctx(), app_get0_propq()); if (pkey == NULL) { @@ -108,6 +104,9 @@ int pkeyparam_main(int argc, char **argv) ERR_print_errors(bio_err); goto end; } + out = bio_open_default(outfile, 'w', FORMAT_PEM); + if (out == NULL) + goto end; if (check) { if (e == NULL) diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c index 5e5047137632..2d3fd6314476 100644 --- a/apps/pkeyutl.c +++ b/apps/pkeyutl.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,25 +20,40 @@ #define KEY_PUBKEY 2 #define KEY_CERT 3 +static EVP_PKEY *get_pkey(const char *kdfalg, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e); static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, - const char *keyfile, int keyform, int key_type, - char *passinarg, int pkey_op, ENGINE *e, - const int impl, int rawin, EVP_PKEY **ppkey, + int pkey_op, ENGINE *e, + const int engine_impl, int rawin, + EVP_PKEY *pkey /* ownership is passed to ctx */, EVP_MD_CTX *mctx, const char *digestname, - OSSL_LIB_CTX *libctx, const char *propq); + const char *kemop, OSSL_LIB_CTX *libctx, const char *propq); static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, ENGINE *e); static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, unsigned char *out, size_t *poutlen, - const unsigned char *in, size_t inlen); + const unsigned char *in, size_t inlen, + unsigned char *secret, size_t *psecretlen); static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, EVP_PKEY *pkey, BIO *in, int filesize, unsigned char *sig, int siglen, unsigned char **out, size_t *poutlen); +static int only_nomd(EVP_PKEY *pkey) +{ +#define MADE_UP_MAX_MD_NAME_LEN 100 + char defname[MADE_UP_MAX_MD_NAME_LEN]; + int deftype; + + deftype = EVP_PKEY_get_default_digest_name(pkey, defname, sizeof(defname)); + return deftype == 2 /* Mandatory */ + && strcmp(defname, "UNDEF") == 0; +} + typedef enum OPTION_choice { OPT_COMMON, OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, @@ -47,6 +62,7 @@ typedef enum OPTION_choice { OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF, OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM, + OPT_DECAP, OPT_ENCAP, OPT_SECOUT, OPT_KEMOP, OPT_CONFIG, OPT_RAWIN, OPT_DIGEST } OPTION_CHOICE; @@ -63,14 +79,15 @@ const OPTIONS pkeyutl_options[] = { {"verify", OPT_VERIFY, '-', "Verify with public key"}, {"encrypt", OPT_ENCRYPT, '-', "Encrypt input data with public key"}, {"decrypt", OPT_DECRYPT, '-', "Decrypt input data with private key"}, - {"derive", OPT_DERIVE, '-', "Derive shared secret"}, + {"derive", OPT_DERIVE, '-', "Derive shared secret from own and peer (EC)DH keys"}, + {"decap", OPT_DECAP, '-', "Decapsulate shared secret"}, + {"encap", OPT_ENCAP, '-', "Encapsulate shared secret"}, OPT_CONFIG_OPTION, OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file - default stdin"}, - {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"}, - {"pubin", OPT_PUBIN, '-', "Input is a public key"}, - {"inkey", OPT_INKEY, 's', "Input private key file"}, + {"inkey", OPT_INKEY, 's', "Input key, by default private key"}, + {"pubin", OPT_PUBIN, '-', "Input key is a public key"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"peerkey", OPT_PEERKEY, 's', "Peer key file used in key derivation"}, {"peerform", OPT_PEERFORM, 'E', "Peer key format (DER/PEM/P12/ENGINE)"}, @@ -81,20 +98,24 @@ const OPTIONS pkeyutl_options[] = { OPT_SECTION("Output"), {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"secret", OPT_SECOUT, '>', "File to store secret on encapsulation"}, {"asn1parse", OPT_ASN1PARSE, '-', "parse the output as ASN.1 data to check its DER encoding and print errors"}, {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"}, {"verifyrecover", OPT_VERIFYRECOVER, '-', "Verify RSA signature, recovering original signature input data"}, - OPT_SECTION("Signing/Derivation"), + OPT_SECTION("Signing/Derivation/Encapsulation"), + {"rawin", OPT_RAWIN, '-', + "Indicate that the signature/verification input data is not yet hashed"}, {"digest", OPT_DIGEST, 's', - "Specify the digest algorithm when signing the raw input data"}, + "The digest algorithm to use for signing/verifying raw input data. Implies -rawin"}, {"pkeyopt", OPT_PKEYOPT, 's', "Public key options as opt:value"}, {"pkeyopt_passin", OPT_PKEYOPT_PASSIN, 's', "Public key option that is read as a passphrase argument opt:passphrase"}, {"kdf", OPT_KDF, 's', "Use KDF algorithm"}, {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"}, + {"kemop", OPT_KEMOP, 's', "KEM operation specific to the key algorithm"}, OPT_R_OPTIONS, OPT_PROV_OPTIONS, @@ -104,23 +125,23 @@ const OPTIONS pkeyutl_options[] = { int pkeyutl_main(int argc, char **argv) { CONF *conf = NULL; - BIO *in = NULL, *out = NULL; + BIO *in = NULL, *out = NULL, *secout = NULL; ENGINE *e = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *pkey = NULL; - char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; + char *infile = NULL, *outfile = NULL, *secoutfile = NULL, *sigfile = NULL, *passinarg = NULL; char hexdump = 0, asn1parse = 0, rev = 0, *prog; - unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL, *secret = NULL; OPTION_CHOICE o; int buf_inlen = 0, siglen = -1; int keyform = FORMAT_UNDEF, peerform = FORMAT_UNDEF; int keysize = -1, pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY; int engine_impl = 0; int ret = 1, rv = -1; - size_t buf_outlen; + size_t buf_outlen = 0, secretlen = 0; const char *inkey = NULL; const char *peerkey = NULL; - const char *kdfalg = NULL, *digestname = NULL; + const char *kdfalg = NULL, *digestname = NULL, *kemop = NULL; int kdflen = 0; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; STACK_OF(OPENSSL_STRING) *pkeyopts_passin = NULL; @@ -148,6 +169,9 @@ int pkeyutl_main(int argc, char **argv) case OPT_OUT: outfile = opt_arg(); break; + case OPT_SECOUT: + secoutfile = opt_arg(); + break; case OPT_SIGFILE: sigfile = opt_arg(); break; @@ -217,6 +241,16 @@ int pkeyutl_main(int argc, char **argv) case OPT_DERIVE: pkey_op = EVP_PKEY_OP_DERIVE; break; + case OPT_DECAP: + pkey_op = EVP_PKEY_OP_DECAPSULATE; + break; + case OPT_ENCAP: + key_type = KEY_PUBKEY; + pkey_op = EVP_PKEY_OP_ENCAPSULATE; + break; + case OPT_KEMOP: + kemop = opt_arg(); + break; case OPT_KDF: pkey_op = EVP_PKEY_OP_DERIVE; key_type = KEY_NONE; @@ -254,32 +288,14 @@ int pkeyutl_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) goto end; - if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) { - BIO_printf(bio_err, - "%s: -rawin can only be used with -sign or -verify\n", - prog); - goto opthelp; - } - - if (digestname != NULL && !rawin) { - BIO_printf(bio_err, - "%s: -digest can only be used with -rawin\n", - prog); - goto opthelp; - } - - if (rawin && rev) { - BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", - prog); - goto opthelp; - } + if (digestname != NULL) + rawin = 1; if (kdfalg != NULL) { if (kdflen == 0) { @@ -293,7 +309,45 @@ int pkeyutl_main(int argc, char **argv) goto opthelp; } else if (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE) { BIO_printf(bio_err, - "%s: no peer key given (-peerkey parameter).\n", prog); + "%s: -peerkey option not allowed without -derive.\n", prog); + goto opthelp; + } else if (peerkey == NULL && pkey_op == EVP_PKEY_OP_DERIVE) { + BIO_printf(bio_err, + "%s: missing -peerkey option for -derive operation.\n", prog); + goto opthelp; + } + + pkey = get_pkey(kdfalg, inkey, keyform, key_type, passinarg, pkey_op, e); + if (key_type != KEY_NONE && pkey == NULL) { + BIO_printf(bio_err, "%s: Error loading key\n", prog); + goto end; + } + + if (pkey_op == EVP_PKEY_OP_VERIFYRECOVER && !EVP_PKEY_is_a(pkey, "RSA")) { + BIO_printf(bio_err, "%s: -verifyrecover can be used only with RSA\n", prog); + goto end; + } + + if (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY) { + if (only_nomd(pkey)) { + if (digestname != NULL) { + const char *alg = EVP_PKEY_get0_type_name(pkey); + + BIO_printf(bio_err, + "%s: -digest (prehash) is not supported with %s\n", + prog, alg != NULL ? alg : "(unknown key type)"); + goto end; + } + rawin = 1; + } + } else if (digestname != NULL || rawin) { + BIO_printf(bio_err, + "%s: -digest and -rawin can only be used with -sign or -verify\n", prog); + goto opthelp; + } + + if (rawin && rev) { + BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", prog); goto opthelp; } @@ -303,9 +357,8 @@ int pkeyutl_main(int argc, char **argv) goto end; } } - ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, - passinarg, pkey_op, e, engine_impl, rawin, &pkey, - mctx, digestname, libctx, app_get0_propq()); + ctx = init_ctx(kdfalg, &keysize, pkey_op, e, engine_impl, rawin, pkey, + mctx, digestname, kemop, libctx, app_get0_propq()); if (ctx == NULL) { BIO_printf(bio_err, "%s: Error initializing context\n", prog); goto end; @@ -358,8 +411,10 @@ int pkeyutl_main(int argc, char **argv) goto end; } } else { - /* Get password as a passin argument: First split option name - * and passphrase argument into two strings */ + /* + * Get password as a passin argument: First split option name + * and passphrase argument into two strings + */ *passin = 0; passin++; if (app_passwd(passin, NULL, &passwd, NULL) == 0) { @@ -389,7 +444,7 @@ int pkeyutl_main(int argc, char **argv) goto end; } - if (pkey_op != EVP_PKEY_OP_DERIVE) { + if (pkey_op != EVP_PKEY_OP_DERIVE && pkey_op != EVP_PKEY_OP_ENCAPSULATE) { in = bio_open_default(infile, 'r', FORMAT_BINARY); if (infile != NULL) { struct stat st; @@ -400,9 +455,33 @@ int pkeyutl_main(int argc, char **argv) if (in == NULL) goto end; } - out = bio_open_default(outfile, 'w', FORMAT_BINARY); - if (out == NULL) - goto end; + if (pkey_op == EVP_PKEY_OP_DECAPSULATE && outfile != NULL) { + if (secoutfile != NULL) { + BIO_printf(bio_err, "%s: Decapsulation produces only a shared " + "secret and no output. The '-out' option " + "is not applicable.\n", prog); + goto end; + } + if ((out = bio_open_owner(outfile, 'w', FORMAT_BINARY)) == NULL) + goto end; + } else { + out = bio_open_default(outfile, 'w', FORMAT_BINARY); + if (out == NULL) + goto end; + } + + if (pkey_op == EVP_PKEY_OP_ENCAPSULATE + || pkey_op == EVP_PKEY_OP_DECAPSULATE) { + if (secoutfile == NULL && pkey_op == EVP_PKEY_OP_ENCAPSULATE) { + BIO_printf(bio_err, "KEM-based shared-secret derivation requires " + "the '-secret ' option\n"); + goto end; + } + /* For backwards compatibility, default decap secrets to the output */ + if (secoutfile != NULL + && (secout = bio_open_owner(secoutfile, 'w', FORMAT_BINARY)) == NULL) + goto end; + } if (sigfile != NULL) { BIO *sigbio = BIO_new_file(sigfile, "rb"); @@ -431,6 +510,7 @@ int pkeyutl_main(int argc, char **argv) size_t i; unsigned char ctmp; size_t l = (size_t)buf_inlen; + for (i = 0; i < l / 2; i++) { ctmp = buf_in[i]; buf_in[i] = buf_in[l - 1 - i]; @@ -441,12 +521,13 @@ int pkeyutl_main(int argc, char **argv) /* Sanity check the input if the input is not raw */ if (!rawin - && buf_inlen > EVP_MAX_MD_SIZE - && (pkey_op == EVP_PKEY_OP_SIGN - || pkey_op == EVP_PKEY_OP_VERIFY)) { - BIO_printf(bio_err, - "Error: The input data looks too long to be a hash\n"); - goto end; + && (pkey_op == EVP_PKEY_OP_SIGN || pkey_op == EVP_PKEY_OP_VERIFY)) { + if (buf_inlen > EVP_MAX_MD_SIZE) { + BIO_printf(bio_err, + "Error: The non-raw input data length %d is too long - max supported hashed size is %d\n", + buf_inlen, EVP_MAX_MD_SIZE); + goto end; + } } if (pkey_op == EVP_PKEY_OP_VERIFY) { @@ -475,13 +556,19 @@ int pkeyutl_main(int argc, char **argv) rv = 1; } else { rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, - buf_in, (size_t)buf_inlen); + buf_in, (size_t)buf_inlen, NULL, (size_t *)&secretlen); } - if (rv > 0 && buf_outlen != 0) { - buf_out = app_malloc(buf_outlen, "buffer output"); + if (rv > 0 + && (secretlen > 0 || (pkey_op != EVP_PKEY_OP_ENCAPSULATE + && pkey_op != EVP_PKEY_OP_DECAPSULATE)) + && (buf_outlen > 0 || pkey_op == EVP_PKEY_OP_DECAPSULATE)) { + if (buf_outlen > 0) + buf_out = app_malloc(buf_outlen, "buffer output"); + if (secretlen > 0) + secret = app_malloc(secretlen, "secret output"); rv = do_keyop(ctx, pkey_op, buf_out, (size_t *)&buf_outlen, - buf_in, (size_t)buf_inlen); + buf_in, (size_t)buf_inlen, secret, (size_t *)&secretlen); } } if (rv <= 0) { @@ -502,48 +589,48 @@ int pkeyutl_main(int argc, char **argv) } else { BIO_write(out, buf_out, buf_outlen); } + /* Backwards compatible decap output fallback */ + if (secretlen > 0) + BIO_write(secout ? secout : out, secret, secretlen); end: if (ret != 0) ERR_print_errors(bio_err); EVP_MD_CTX_free(mctx); EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); EVP_MD_free(md); release_engine(e); BIO_free(in); BIO_free_all(out); + BIO_free_all(secout); OPENSSL_free(buf_in); OPENSSL_free(buf_out); OPENSSL_free(sig); + OPENSSL_free(secret); sk_OPENSSL_STRING_free(pkeyopts); sk_OPENSSL_STRING_free(pkeyopts_passin); NCONF_free(conf); return ret; } -static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, - const char *keyfile, int keyform, int key_type, - char *passinarg, int pkey_op, ENGINE *e, - const int engine_impl, int rawin, - EVP_PKEY **ppkey, EVP_MD_CTX *mctx, const char *digestname, - OSSL_LIB_CTX *libctx, const char *propq) +static EVP_PKEY *get_pkey(const char *kdfalg, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e) { EVP_PKEY *pkey = NULL; - EVP_PKEY_CTX *ctx = NULL; - ENGINE *impl = NULL; char *passin = NULL; - int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); - goto end; + return NULL; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); - goto end; + return NULL; } switch (key_type) { case KEY_PRIVKEY: @@ -566,6 +653,20 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, break; } + OPENSSL_free(passin); + return pkey; +} + +static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + int pkey_op, ENGINE *e, + const int engine_impl, int rawin, + EVP_PKEY *pkey /* ownership is passed to ctx */, + EVP_MD_CTX *mctx, const char *digestname, + const char *kemop, OSSL_LIB_CTX *libctx, const char *propq) +{ + EVP_PKEY_CTX *ctx = NULL; + ENGINE *impl = NULL; + int rv = -1; #ifndef OPENSSL_NO_ENGINE if (engine_impl) @@ -580,7 +681,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, if (kdfnid == NID_undef) { BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", kdfalg); - goto end; + return NULL; } } if (impl != NULL) @@ -589,20 +690,17 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, ctx = EVP_PKEY_CTX_new_from_name(libctx, kdfalg, propq); } else { if (pkey == NULL) - goto end; + return NULL; *pkeysize = EVP_PKEY_get_size(pkey); if (impl != NULL) ctx = EVP_PKEY_CTX_new(pkey, impl); else ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq); - if (ppkey != NULL) - *ppkey = pkey; - EVP_PKEY_free(pkey); } if (ctx == NULL) - goto end; + return NULL; if (rawin) { EVP_MD_CTX_set_pkey_ctx(mctx, ctx); @@ -644,6 +742,18 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; + + case EVP_PKEY_OP_ENCAPSULATE: + rv = EVP_PKEY_encapsulate_init(ctx, NULL); + if (rv > 0 && kemop != NULL) + rv = EVP_PKEY_CTX_set_kem_op(ctx, kemop); + break; + + case EVP_PKEY_OP_DECAPSULATE: + rv = EVP_PKEY_decapsulate_init(ctx, NULL); + if (rv > 0 && kemop != NULL) + rv = EVP_PKEY_CTX_set_kem_op(ctx, kemop); + break; } } @@ -652,18 +762,16 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, ctx = NULL; } - end: - OPENSSL_free(passin); return ctx; - } static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, ENGINE *e) { + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); EVP_PKEY *peer = NULL; ENGINE *engine = NULL; - int ret; + int ret = 1; if (peerform == FORMAT_ENGINE) engine = e; @@ -672,8 +780,14 @@ static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, BIO_printf(bio_err, "Error reading peer key %s\n", file); return 0; } - - ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0; + if (strcmp(EVP_PKEY_get0_type_name(peer), EVP_PKEY_get0_type_name(pkey)) != 0) { + BIO_printf(bio_err, + "Type of peer public key: %s does not match type of private key: %s\n", + EVP_PKEY_get0_type_name(peer), EVP_PKEY_get0_type_name(pkey)); + ret = 0; + } else { + ret = EVP_PKEY_derive_set_peer(ctx, peer) > 0; + } EVP_PKEY_free(peer); return ret; @@ -681,9 +795,11 @@ static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, unsigned char *out, size_t *poutlen, - const unsigned char *in, size_t inlen) + const unsigned char *in, size_t inlen, + unsigned char *secret, size_t *pseclen) { int rv = 0; + switch (pkey_op) { case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); @@ -705,6 +821,14 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, rv = EVP_PKEY_derive(ctx, out, poutlen); break; + case EVP_PKEY_OP_ENCAPSULATE: + rv = EVP_PKEY_encapsulate(ctx, out, poutlen, secret, pseclen); + break; + + case EVP_PKEY_OP_DECAPSULATE: + rv = EVP_PKEY_decapsulate(ctx, secret, pseclen, in, inlen); + break; + } return rv; } @@ -722,15 +846,14 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, int buf_len = 0; /* Some algorithms only support oneshot digests */ - if (EVP_PKEY_get_id(pkey) == EVP_PKEY_ED25519 - || EVP_PKEY_get_id(pkey) == EVP_PKEY_ED448) { + if (only_nomd(pkey)) { if (filesize < 0) { BIO_printf(bio_err, "Error: unable to determine file size for oneshot operation\n"); goto end; } mbuf = app_malloc(filesize, "oneshot sign/verify buffer"); - switch(pkey_op) { + switch (pkey_op) { case EVP_PKEY_OP_VERIFY: buf_len = BIO_read(in, mbuf, filesize); if (buf_len != filesize) { @@ -755,7 +878,7 @@ static int do_raw_keyop(int pkey_op, EVP_MD_CTX *mctx, goto end; } - switch(pkey_op) { + switch (pkey_op) { case EVP_PKEY_OP_VERIFY: for (;;) { buf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); diff --git a/apps/prime.c b/apps/prime.c index e269493d5cd7..23b7e462fc20 100644 --- a/apps/prime.c +++ b/apps/prime.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,23 @@ typedef enum OPTION_choice { OPT_PROV_ENUM } OPTION_CHOICE; +static int check_num(const char *s, const int is_hex) +{ + int i; + /* + * It would make sense to use ossl_isxdigit and ossl_isdigit here, + * but ossl_ctype_check is a local symbol in libcrypto.so. + */ + if (is_hex) { + for (i = 0; ('0' <= s[i] && s[i] <= '9') + || ('A' <= s[i] && s[i] <= 'F') + || ('a' <= s[i] && s[i] <= 'f'); i++); + } else { + for (i = 0; '0' <= s[i] && s[i] <= '9'; i++); + } + return s[i] == 0; +} + const OPTIONS prime_options[] = { {OPT_HELP_STR, 1, '-', "Usage: %s [options] [number...]\n"}, @@ -83,12 +100,12 @@ opthelp: } /* Optional arguments are numbers to check. */ + if (generate && !opt_check_rest_arg(NULL)) + goto opthelp; argc = opt_num_rest(); argv = opt_rest(); - if (generate) { - if (argc != 0) - goto opthelp; - } else if (argc == 0) { + if (!generate && argc == 0) { + BIO_printf(bio_err, "Missing number (s) to check\n"); goto opthelp; } @@ -117,12 +134,10 @@ opthelp: OPENSSL_free(s); } else { for ( ; *argv; argv++) { - int r; + int r = check_num(argv[0], hex); - if (hex) - r = BN_hex2bn(&bn, argv[0]); - else - r = BN_dec2bn(&bn, argv[0]); + if (r) + r = hex ? BN_hex2bn(&bn, argv[0]) : BN_dec2bn(&bn, argv[0]); if (!r) { BIO_printf(bio_err, "Failed to process value (%s)\n", argv[0]); @@ -130,10 +145,14 @@ opthelp: } BN_print(bio_out, bn); + r = BN_check_prime(bn, NULL, NULL); + if (r < 0) { + BIO_printf(bio_err, "Error checking prime\n"); + goto end; + } BIO_printf(bio_out, " (%s) %s prime\n", argv[0], - BN_check_prime(bn, NULL, NULL) - ? "is" : "is not"); + r == 1 ? "is" : "is not"); } } diff --git a/apps/progs.pl b/apps/progs.pl index 29f9be13ca08..4a1e4be47c69 100644 --- a/apps/progs.pl +++ b/apps/progs.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# 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 @@ -104,7 +104,7 @@ EOF # The format of this table is: # [0] = alternative command to use instead # [1] = deprecented in this version -# [2] = preprocessor conditional for exclusing irrespective of deprecation +# [2] = preprocessor conditional for excluding irrespective of deprecation # rsa => [ "pkey", "3_0", "rsa" ], # genrsa => [ "genpkey", "3_0", "rsa" ], rsautl => [ "pkeyutl", "3_0", "rsa" ], @@ -188,7 +188,7 @@ EOF "camellia-128-cbc", "camellia-128-ecb", "camellia-192-cbc", "camellia-192-ecb", "camellia-256-cbc", "camellia-256-ecb", - "base64", "zlib", + "base64", "zlib", "brotli", "zstd", "des", "des3", "desx", "idea", "seed", "rc4", "rc4-40", "rc2", "bf", "cast", "rc5", "des-ecb", "des-ede", "des-ede3", @@ -205,9 +205,7 @@ EOF ) { my $str = " {FT_cipher, \"$cmd\", enc_main, enc_options, NULL},\n"; (my $algo = $cmd) =~ s/-.*//g; - if ($cmd eq "zlib") { - print "#ifdef ZLIB\n${str}#endif\n"; - } elsif (grep { $algo eq $_ } @disablables) { + if (grep { $algo eq $_ } @disablables) { print "#ifndef OPENSSL_NO_" . uc($algo) . "\n${str}#endif\n"; } elsif (my $disabler = $cipher_disabler{$algo}) { print "#ifndef OPENSSL_NO_" . uc($disabler) . "\n${str}#endif\n"; diff --git a/apps/rand.c b/apps/rand.c index cbf495d5bc53..b123a151ea74 100644 --- a/apps/rand.c +++ b/apps/rand.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -25,7 +25,7 @@ typedef enum OPTION_choice { } OPTION_CHOICE; const OPTIONS rand_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"}, + {OPT_HELP_STR, 1, '-', "Usage: %s [options] num[K|M|G|T]\n"}, OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, @@ -52,7 +52,11 @@ int rand_main(int argc, char **argv) BIO *out = NULL; char *outfile = NULL, *prog; OPTION_CHOICE o; - int format = FORMAT_BINARY, i, num = -1, r, ret = 1; + int format = FORMAT_BINARY, r, i, ret = 1; + size_t buflen = (1 << 16); /* max rand chunk size is 2^16 bytes */ + long num = -1; + uint64_t scaled_num = 0; + uint8_t *buf = NULL; prog = opt_init(argc, argv, rand_options); while ((o = opt_next()) != OPT_EOF) { @@ -93,9 +97,86 @@ int rand_main(int argc, char **argv) argc = opt_num_rest(); argv = opt_rest(); if (argc == 1) { - if (!opt_int(argv[0], &num) || num <= 0) + int factoridx = 0; + int shift = 0; + + /* + * special case for requesting the max allowed + * number of random bytes to be generated + */ + if (!strcmp(argv[0], "max")) { + /* + * 2^61 bytes is the limit of random output + * per drbg instantiation + */ + scaled_num = UINT64_MAX >> 3; + } else { + /* + * iterate over the value and check to see if there are + * any non-numerical chars + * A non digit suffix indicates we need to shift the + * number of requested bytes by a factor of: + * K = 1024^1 (1 << (10 * 1)) + * M = 1024^2 (1 << (10 * 2)) + * G = 1024^3 (1 << (10 * 3)) + * T = 1024^4 (1 << (10 * 4)) + * which can be achieved by bit-shifting the number + */ + while (argv[0][factoridx]) { + if (!isdigit((int)(argv[0][factoridx]))) { + switch(argv[0][factoridx]) { + case 'K': + shift = 10; + break; + case 'M': + shift = 20; + break; + case 'G': + shift = 30; + break; + case 'T': + shift = 40; + break; + default: + BIO_printf(bio_err, "Invalid size suffix %s\n", + &argv[0][factoridx]); + goto opthelp; + } + break; + } + factoridx++; + } + + if (shift != 0 && strlen(&argv[0][factoridx]) != 1) { + BIO_printf(bio_err, "Invalid size suffix %s\n", + &argv[0][factoridx]); + goto opthelp; + } + } + /* Remove the suffix from the arg so that opt_long works */ + if (shift != 0) + argv[0][factoridx] = '\0'; + + if ((scaled_num == 0) && (!opt_long(argv[0], &num) || num <= 0)) goto opthelp; - } else if (argc != 0) { + + if (shift != 0) { + /* check for overflow */ + if ((UINT64_MAX >> shift) < (size_t)num) { + BIO_printf(bio_err, "%lu bytes with suffix overflows\n", + num); + goto opthelp; + } + scaled_num = num << shift; + if (scaled_num > (UINT64_MAX >> 3)) { + BIO_printf(bio_err, "Request exceeds max allowed output\n"); + goto opthelp; + } + } else { + if (scaled_num == 0) + scaled_num = num; + } + } else if (!opt_check_rest_arg(NULL)) { goto opthelp; } @@ -113,13 +194,11 @@ int rand_main(int argc, char **argv) out = BIO_push(b64, out); } - while (num > 0) { - unsigned char buf[4096]; + buf = app_malloc(buflen, "buffer for output file"); + while (scaled_num > 0) { int chunk; - chunk = num; - if (chunk > (int)sizeof(buf)) - chunk = sizeof(buf); + chunk = scaled_num > buflen ? (int)buflen : (int)scaled_num; r = RAND_bytes(buf, chunk); if (r <= 0) goto end; @@ -131,7 +210,7 @@ int rand_main(int argc, char **argv) if (BIO_printf(out, "%02x", buf[i]) != 2) goto end; } - num -= chunk; + scaled_num -= chunk; } if (format == FORMAT_TEXT) BIO_puts(out, "\n"); @@ -143,6 +222,7 @@ int rand_main(int argc, char **argv) end: if (ret != 0) ERR_print_errors(bio_err); + OPENSSL_free(buf); release_engine(e); BIO_free_all(out); return ret; diff --git a/apps/rehash.c b/apps/rehash.c index 6e0ca3642c40..e6b12d36fb6f 100644 --- a/apps/rehash.c +++ b/apps/rehash.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2013-2014 Timo Teräs * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -8,6 +8,7 @@ * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" /* LIST_SEPARATOR_CHAR */ #include "apps.h" #include "progs.h" @@ -140,7 +141,7 @@ static int add_entry(enum Type type, unsigned int hash, const char *filename, } for (ep = bp->first_entry; ep; ep = ep->next) { - if (digest && memcmp(digest, ep->digest, evpmdsize) == 0) { + if (digest && memcmp(digest, ep->digest, (size_t)evpmdsize) == 0) { BIO_printf(bio_err, "%s: warning: skipping duplicate %s in %s\n", opt_getprog(), @@ -183,7 +184,7 @@ static int add_entry(enum Type type, unsigned int hash, const char *filename, if (need_symlink && !ep->need_symlink) { ep->need_symlink = 1; bp->num_needed++; - memcpy(ep->digest, digest, evpmdsize); + memcpy(ep->digest, digest, (size_t)evpmdsize); } return 0; } @@ -209,11 +210,11 @@ static int handle_symlink(const char *filename, const char *fullpath) } 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) + for (type = OSSL_NELEM(suffixes) - 1; type > 0; type--) + if (OPENSSL_strncasecmp(&filename[i], + suffixes[type], strlen(suffixes[type])) == 0) break; - } + i += strlen(suffixes[type]); id = strtoul(&filename[i], &endptr, 10); @@ -266,7 +267,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h) if (sk_X509_INFO_num(inf) != 1) { BIO_printf(bio_err, - "%s: warning: skipping %s," + "%s: warning: skipping %s, " "it does not contain exactly one certificate or CRL\n", opt_getprog(), filename); /* This is not an error. */ @@ -553,6 +554,9 @@ int rehash_main(int argc, char **argv) evpmd = EVP_sha1(); evpmdsize = EVP_MD_get_size(evpmd); + if (evpmdsize <= 0 || evpmdsize > EVP_MAX_MD_SIZE) + goto end; + if (*argv != NULL) { while (*argv != NULL) errs += do_dir(*argv++, h); diff --git a/apps/req.c b/apps/req.c index 2fc53d4bfcfa..c5627ffda542 100644 --- a/apps/req.c +++ b/apps/req.c @@ -30,6 +30,7 @@ #ifndef OPENSSL_NO_DSA # include #endif +#include "internal/e_os.h" /* For isatty() */ #define BITS "default_bits" #define KEYFILE "default_keyfile" @@ -43,7 +44,7 @@ #define DEFAULT_KEY_LENGTH 2048 #define MIN_KEY_LENGTH 512 -#define DEFAULT_DAYS 30 /* default cert validity period in days */ +#define DEFAULT_DAYS 30 /* default certificate validity period in days */ #define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */ #define EXT_COPY_UNSET -1 @@ -62,7 +63,6 @@ static int add_attribute_object(X509_REQ *req, char *text, const char *def, static int add_DN_object(X509_NAME *n, char *text, const char *def, char *value, int nid, int n_min, int n_max, unsigned long chtype, int mval); -static int genpkey_cb(EVP_PKEY_CTX *ctx); static int build_data(char *text, const char *def, char *value, int n_min, int n_max, char *buf, const int buf_size, const char *desc1, const char *desc2); @@ -81,30 +81,33 @@ static int batch = 0; typedef enum OPTION_choice { OPT_COMMON, + OPT_CIPHER, OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_KEYGEN_ENGINE, OPT_KEY, OPT_PUBKEY, OPT_NEW, OPT_CONFIG, OPT_KEYFORM, OPT_IN, OPT_OUT, OPT_KEYOUT, OPT_PASSIN, OPT_PASSOUT, OPT_NEWKEY, OPT_PKEYOPT, OPT_SIGOPT, OPT_VFYOPT, OPT_BATCH, OPT_NEWHDR, OPT_MODULUS, OPT_VERIFY, OPT_NOENC, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, - OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, - OPT_CA, OPT_CAKEY, - OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, - OPT_COPY_EXTENSIONS, OPT_ADDEXT, OPT_EXTENSIONS, - OPT_REQEXTS, OPT_PRECERT, OPT_MD, - OPT_SECTION, + OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, + OPT_X509, OPT_X509V1, OPT_CA, OPT_CAKEY, + OPT_MULTIVALUE_RDN, OPT_NOT_BEFORE, OPT_NOT_AFTER, OPT_DAYS, OPT_SET_SERIAL, + OPT_COPY_EXTENSIONS, OPT_EXTENSIONS, OPT_REQEXTS, OPT_ADDEXT, + OPT_PRECERT, OPT_MD, + OPT_SECTION, OPT_QUIET, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; const OPTIONS req_options[] = { OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, + {"cipher", OPT_CIPHER, 's', "Specify the cipher for private key encryption"}, #ifndef OPENSSL_NO_ENGINE {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, {"keygen_engine", OPT_KEYGEN_ENGINE, 's', "Specify engine to be used for key generation operations"}, #endif {"in", OPT_IN, '<', "X.509 request input file (default stdin)"}, - {"inform", OPT_INFORM, 'F', "Input format - DER or PEM"}, + {"inform", OPT_INFORM, 'F', + "CSR input format to use (PEM or DER; by default try PEM first)"}, {"verify", OPT_VERIFY, '-', "Verify self-signature on the request"}, OPT_SECTION("Certificate"), @@ -117,6 +120,7 @@ const OPTIONS req_options[] = { {"text", OPT_TEXT, '-', "Text form of request"}, {"x509", OPT_X509, '-', "Output an X.509 certificate structure instead of a cert request"}, + {"x509v1", OPT_X509V1, '-', "Request cert generation with X.509 version 1"}, {"CA", OPT_CA, '<', "Issuer cert to use for signing a cert, implies -x509"}, {"CAkey", OPT_CAKEY, 's', "Issuer private key to use with -CA; default is -CA arg"}, @@ -126,18 +130,20 @@ const OPTIONS req_options[] = { "Print the subject of the output request or cert"}, {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', "Deprecated; multi-valued RDNs support is always on."}, - {"days", OPT_DAYS, 'p', "Number of days cert is valid for"}, + {"not_before", OPT_NOT_BEFORE, 's', + "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"}, + {"not_after", OPT_NOT_AFTER, 's', + "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"}, + {"days", OPT_DAYS, 'p', "Number of days certificate is valid for"}, {"set_serial", OPT_SET_SERIAL, 's', "Serial number to use"}, {"copy_extensions", OPT_COPY_EXTENSIONS, 's', "copy extensions from request when using -x509"}, + {"extensions", OPT_EXTENSIONS, 's', + "Cert or request extension section (override value in config file)"}, + {"reqexts", OPT_REQEXTS, 's', "An alias for -extensions"}, {"addext", OPT_ADDEXT, 's', "Additional cert extension key=value pair (may be given more than once)"}, - {"extensions", OPT_EXTENSIONS, 's', - "Cert extension section (override value in config file)"}, - {"reqexts", OPT_REQEXTS, 's', - "Request extension section (override value in config file)"}, - {"precert", OPT_PRECERT, '-', - "Add a poison extension to the generated cert (implies -new)"}, + {"precert", OPT_PRECERT, '-', "Add a poison extension to generated cert (implies -new)"}, OPT_SECTION("Keys and Signing"), {"key", OPT_KEY, 's', "Key for signing, and to include unless -in given"}, @@ -159,6 +165,7 @@ const OPTIONS req_options[] = { {"batch", OPT_BATCH, '-', "Do not ask anything during request generation"}, {"verbose", OPT_VERBOSE, '-', "Verbose output"}, + {"quiet", OPT_QUIET, '-', "Terse output"}, {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"}, {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"}, {"noout", OPT_NOOUT, '-', "Do not output REQ"}, @@ -189,8 +196,8 @@ static void exts_cleanup(OPENSSL_STRING *x) } /* - * Is the |kv| key already duplicated? This is remarkably tricky to get right. - * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error. + * Is the |kv| key already duplicated? + * Return 0 if unique, -1 on runtime error, -2 on syntax error; 1 if found. */ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) { @@ -199,11 +206,12 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) /* Check syntax. */ /* Skip leading whitespace, make a copy. */ - while (*kv && isspace(_UC(*kv))) - if (*++kv == '\0') - return 1; - if ((p = strchr(kv, '=')) == NULL) - return 1; + while (isspace(_UC(*kv))) + kv++; + if ((p = strchr(kv, '=')) == NULL) { + BIO_printf(bio_err, "Parse error on -addext: missing '='\n"); + return -2; + } off = p - kv; if ((kv = OPENSSL_strdup(kv)) == NULL) return -1; @@ -213,14 +221,16 @@ static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) if (!isspace(_UC(p[-1]))) break; if (p == kv) { + BIO_printf(bio_err, "Parse error on -addext: missing key\n"); OPENSSL_free(kv); - return 1; + return -2; } *p = '\0'; /* Finally have a clean "key"; see if it's there [by attempt to add it]. */ p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING *)kv); if (p != NULL) { + BIO_printf(bio_err, "Duplicate extension name: %s\n", kv); OPENSSL_free(p); return 1; } else if (lh_OPENSSL_STRING_error(addexts)) { @@ -242,33 +252,32 @@ int req_main(int argc, char **argv) LHASH_OF(OPENSSL_STRING) *addexts = NULL; X509 *new_x509 = NULL, *CAcert = NULL; X509_REQ *req = NULL; - EVP_CIPHER *cipher = NULL; - EVP_MD *md = NULL; + const EVP_CIPHER *cipher = NULL; int ext_copy = EXT_COPY_UNSET; BIO *addext_bio = NULL; - char *extensions = NULL; + char *extsect = NULL; const char *infile = NULL, *CAfile = NULL, *CAkeyfile = NULL; char *outfile = NULL, *keyfile = NULL, *digest = NULL; char *keyalgstr = NULL, *p, *prog, *passargin = NULL, *passargout = NULL; char *passin = NULL, *passout = NULL; char *nofree_passin = NULL, *nofree_passout = NULL; - char *req_exts = NULL, *subj = NULL; + char *subj = NULL; X509_NAME *fsubj = NULL; char *template = default_config_file, *keyout = NULL; const char *keyalg = NULL; OPTION_CHOICE o; + char *not_before = NULL, *not_after = NULL; int days = UNSET_DAYS; - int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0; + int ret = 1, gen_x509 = 0, i = 0, newreq = 0, verbose = 0, progress = 1; int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF; int modulus = 0, multirdn = 1, verify = 0, noout = 0, text = 0; - int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + int noenc = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0, x509v1 = 0; long newkey_len = -1; unsigned long chtype = MBSTRING_ASC, reqflag = 0; -#ifndef OPENSSL_NO_DES - cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); -#endif + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, req_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -387,6 +396,11 @@ int req_main(int argc, char **argv) break; case OPT_VERBOSE: verbose = 1; + progress = 1; + break; + case OPT_QUIET: + verbose = 0; + progress = 0; break; case OPT_UTF8: chtype = MBSTRING_UTF8; @@ -402,6 +416,9 @@ int req_main(int argc, char **argv) case OPT_TEXT: text = 1; break; + case OPT_X509V1: + x509v1 = 1; + /* fall thru */ case OPT_X509: gen_x509 = 1; break; @@ -412,9 +429,15 @@ int req_main(int argc, char **argv) case OPT_CAKEY: CAkeyfile = opt_arg(); break; + case OPT_NOT_BEFORE: + not_before = opt_arg(); + break; + case OPT_NOT_AFTER: + not_after = opt_arg(); + break; case OPT_DAYS: days = atoi(opt_arg()); - if (days < -1) { + if (days <= UNSET_DAYS) { BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", prog); goto end; @@ -445,6 +468,10 @@ int req_main(int argc, char **argv) goto end; } break; + case OPT_EXTENSIONS: + case OPT_REQEXTS: + extsect = opt_arg(); + break; case OPT_ADDEXT: p = opt_arg(); if (addexts == NULL) { @@ -454,22 +481,23 @@ int req_main(int argc, char **argv) goto end; } i = duplicated(addexts, p); - if (i == 1) { - BIO_printf(bio_err, "Duplicate extension: %s\n", p); - goto opthelp; - } + if (i == 1) + goto end; + if (i == -1) + BIO_printf(bio_err, "Internal error handling -addext %s\n", p); if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0) goto end; break; - case OPT_EXTENSIONS: - extensions = opt_arg(); - break; - case OPT_REQEXTS: - req_exts = opt_arg(); - break; case OPT_PRECERT: newreq = precert = 1; break; + case OPT_CIPHER: + cipher = EVP_get_cipherbyname(opt_arg()); + if (cipher == NULL) { + BIO_printf(bio_err, "Unknown cipher: %s\n", opt_arg()); + goto opthelp; + } + break; case OPT_MD: digest = opt_unknown(); break; @@ -477,8 +505,7 @@ int req_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) @@ -486,12 +513,21 @@ int req_main(int argc, char **argv) if (!gen_x509) { if (days != UNSET_DAYS) - BIO_printf(bio_err, "Ignoring -days without -x509; not generating a certificate\n"); + BIO_printf(bio_err, "Warning: Ignoring -days without -x509; not generating a certificate\n"); + if (not_before != NULL) + BIO_printf(bio_err, "Warning: Ignoring -not_before without -x509; not generating a certificate\n"); + if (not_after != NULL) + BIO_printf(bio_err, "Warning: Ignoring -not_after without -x509; not generating a certificate\n"); if (ext_copy == EXT_COPY_NONE) - BIO_printf(bio_err, "Ignoring -copy_extensions 'none' when -x509 is not given\n"); + BIO_printf(bio_err, "Warning: Ignoring -copy_extensions 'none' when -x509 is not given\n"); + } + if (infile == NULL) { + if (gen_x509) + newreq = 1; + else if (!newreq && isatty(fileno_stdin())) + BIO_printf(bio_err, + "Warning: Will read cert request from stdin since no -in option is given\n"); } - if (gen_x509 && infile == NULL) - newreq = 1; if (!app_passwd(passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); @@ -511,9 +547,7 @@ int req_main(int argc, char **argv) goto end; if (req_conf != NULL) { - p = NCONF_get_string(req_conf, NULL, "oid_file"); - if (p == NULL) - ERR_clear_error(); + p = app_conf_try_string(req_conf, NULL, "oid_file"); if (p != NULL) { BIO *oid_bio = BIO_new_file(p, "r"); @@ -532,35 +566,28 @@ int req_main(int argc, char **argv) /* Check that any specified digest is fetchable */ if (digest != NULL) { - if (!opt_md(digest, &md)) { - ERR_clear_error(); + if (!opt_check_md(digest)) goto opthelp; - } - EVP_MD_free(md); } else { /* No digest specified, default to configuration */ - p = NCONF_get_string(req_conf, section, "default_md"); - if (p == NULL) - ERR_clear_error(); - else + p = app_conf_try_string(req_conf, section, "default_md"); + if (p != NULL) digest = p; } - if (extensions == NULL) { - extensions = NCONF_get_string(req_conf, section, V3_EXTENSIONS); - if (extensions == NULL) - ERR_clear_error(); - } - if (extensions != NULL) { - /* Check syntax of file */ + if (extsect == NULL) + extsect = app_conf_try_string(req_conf, section, + gen_x509 ? V3_EXTENSIONS : REQ_EXTENSIONS); + if (extsect != NULL) { + /* Check syntax of extension section in config file */ X509V3_CTX ctx; X509V3_set_ctx_test(&ctx); X509V3_set_nconf(&ctx, req_conf); - if (!X509V3_EXT_add_nconf(req_conf, &ctx, extensions, NULL)) { + if (!X509V3_EXT_add_nconf(req_conf, &ctx, extsect, NULL)) { BIO_printf(bio_err, - "Error checking x509 extension section %s\n", - extensions); + "Error checking %s extension section %s\n", + gen_x509 ? "x509" : "request", extsect); goto end; } } @@ -576,69 +603,42 @@ int req_main(int argc, char **argv) } } - if (passin == NULL) { + if (passin == NULL) passin = nofree_passin = - NCONF_get_string(req_conf, section, "input_password"); - if (passin == NULL) - ERR_clear_error(); - } + app_conf_try_string(req_conf, section, "input_password"); - if (passout == NULL) { + if (passout == NULL) passout = nofree_passout = - NCONF_get_string(req_conf, section, "output_password"); - if (passout == NULL) - ERR_clear_error(); - } - - p = NCONF_get_string(req_conf, section, STRING_MASK); - if (p == NULL) - ERR_clear_error(); + app_conf_try_string(req_conf, section, "output_password"); + p = app_conf_try_string(req_conf, section, STRING_MASK); if (p != NULL && !ASN1_STRING_set_default_mask_asc(p)) { BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); goto end; } if (chtype != MBSTRING_UTF8) { - p = NCONF_get_string(req_conf, section, UTF8_IN); - if (p == NULL) - ERR_clear_error(); - else if (strcmp(p, "yes") == 0) + p = app_conf_try_string(req_conf, section, UTF8_IN); + if (p != NULL && strcmp(p, "yes") == 0) chtype = MBSTRING_UTF8; } - if (req_exts == NULL) { - req_exts = NCONF_get_string(req_conf, section, REQ_EXTENSIONS); - if (req_exts == NULL) - ERR_clear_error(); - } - if (req_exts != NULL) { - /* Check syntax of file */ - X509V3_CTX ctx; - - X509V3_set_ctx_test(&ctx); - X509V3_set_nconf(&ctx, req_conf); - if (!X509V3_EXT_add_nconf(req_conf, &ctx, req_exts, NULL)) { - BIO_printf(bio_err, - "Error checking request extension section %s\n", - req_exts); - goto end; - } - } - if (keyfile != NULL) { pkey = load_key(keyfile, keyform, 0, passin, e, "private key"); if (pkey == NULL) goto end; app_RAND_load_conf(req_conf, section); } + if (keyalg != NULL && pkey != NULL) { + BIO_printf(bio_err, + "Warning: Not generating key via given -newkey option since -key is given\n"); + /* Better throw an error in this case */ + } if (newreq && pkey == NULL) { app_RAND_load_conf(req_conf, section); - if (!NCONF_get_number(req_conf, section, BITS, &newkey_len)) { - ERR_clear_error(); + if (!app_conf_try_number(req_conf, section, BITS, &newkey_len)) newkey_len = DEFAULT_KEY_LENGTH; - } genctx = set_keygen_ctx(keyalg, &keyalgstr, &newkey_len, gen_eng); if (genctx == NULL) @@ -681,8 +681,9 @@ int req_main(int argc, char **argv) } } - EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); EVP_PKEY_CTX_set_app_data(genctx, bio_err); + if (progress) + EVP_PKEY_CTX_set_cb(genctx, progress_cb); pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose); if (pkey == NULL) @@ -691,11 +692,8 @@ int req_main(int argc, char **argv) EVP_PKEY_CTX_free(genctx); genctx = NULL; } - if (keyout == NULL && keyfile == NULL) { - keyout = NCONF_get_string(req_conf, section, KEYFILE); - if (keyout == NULL) - ERR_clear_error(); - } + if (keyout == NULL && keyfile == NULL) + keyout = app_conf_try_string(req_conf, section, KEYFILE); if (pkey != NULL && (keyfile == NULL || keyout != NULL)) { if (verbose) { @@ -709,14 +707,10 @@ int req_main(int argc, char **argv) if (out == NULL) goto end; - p = NCONF_get_string(req_conf, section, "encrypt_rsa_key"); - if (p == NULL) { - ERR_clear_error(); - p = NCONF_get_string(req_conf, section, "encrypt_key"); - if (p == NULL) - ERR_clear_error(); - } - if ((p != NULL) && (strcmp(p, "no") == 0)) + p = app_conf_try_string(req_conf, section, "encrypt_rsa_key"); + if (p == NULL) + p = app_conf_try_string(req_conf, section, "encrypt_key"); + if (p != NULL && strcmp(p, "no") == 0) cipher = NULL; if (noenc) cipher = NULL; @@ -747,10 +741,17 @@ int req_main(int argc, char **argv) goto end; if (!newreq) { - req = load_csr(infile /* if NULL, reads from stdin */, - informat, "X509 request"); + if (keyfile != NULL) + BIO_printf(bio_err, + "Warning: Not placing -key in cert or request since request is used\n"); + req = load_csr_autofmt(infile /* if NULL, reads from stdin */, + informat, vfyopts, "X509 request"); if (req == NULL) goto end; + } else if (infile != NULL) { + BIO_printf(bio_err, + "Warning: Ignoring -in option since -new or -newkey or -precert is given\n"); + /* Better throw an error in this case, as done in the x509 app */ } if (CAkeyfile == NULL) @@ -791,7 +792,7 @@ int req_main(int argc, char **argv) goto end; } - if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)){ + if (!make_REQ(req, pkey, fsubj, multirdn, !gen_x509, chtype)) { BIO_printf(bio_err, "Error making certificate request\n"); goto end; } @@ -806,6 +807,10 @@ int req_main(int argc, char **argv) X509_NAME *n_subj = fsubj != NULL ? fsubj : X509_REQ_get_subject_name(req); + if (CAcert != NULL && keyfile != NULL) + BIO_printf(bio_err, + "Warning: Not using -key or -newkey for signing since -CA option is given\n"); + if ((new_x509 = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; @@ -820,10 +825,11 @@ int req_main(int argc, char **argv) if (!X509_set_issuer_name(new_x509, issuer)) goto end; - if (days == UNSET_DAYS) { + if (days == UNSET_DAYS) days = DEFAULT_DAYS; - } - if (!set_cert_times(new_x509, NULL, NULL, days)) + else if (not_after != NULL) + BIO_printf(bio_err,"Warning: -not_after option overriding -days option\n"); + if (!set_cert_times(new_x509, not_before, not_after, days, 1)) goto end; if (!X509_set_subject_name(new_x509, n_subj)) goto end; @@ -844,26 +850,23 @@ int req_main(int argc, char **argv) if (CAcert == NULL) { if (!X509V3_set_issuer_pkey(&ext_ctx, issuer_key)) goto end; - ERR_set_mark(); - if (!X509_check_private_key(new_x509, issuer_key)) + if (!cert_matches_key(new_x509, issuer_key)) BIO_printf(bio_err, "Warning: Signature key and public key of cert do not match\n"); - ERR_pop_to_mark(); } X509V3_set_nconf(&ext_ctx, req_conf); /* Add extensions */ - if (extensions != NULL - && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extensions, - new_x509)) { + if (extsect != NULL + && !X509V3_EXT_add_nconf(req_conf, &ext_ctx, extsect, new_x509)) { BIO_printf(bio_err, "Error adding x509 extensions from section %s\n", - extensions); + extsect); goto end; } if (addext_conf != NULL && !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, "default", new_x509)) { - BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); + BIO_printf(bio_err, "Error adding x509 extensions defined via -addext\n"); goto end; } @@ -876,28 +879,32 @@ int req_main(int argc, char **argv) } } - i = do_X509_sign(new_x509, issuer_key, digest, sigopts, &ext_ctx); + i = do_X509_sign(new_x509, x509v1, issuer_key, digest, sigopts, + &ext_ctx); if (!i) goto end; } else { X509V3_CTX ext_ctx; + if (precert) { + BIO_printf(bio_err, + "Warning: Ignoring -precert flag since no cert is produced\n"); + } /* Set up V3 context struct */ - X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); + X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, X509V3_CTX_REPLACE); X509V3_set_nconf(&ext_ctx, req_conf); /* Add extensions */ - if (req_exts != NULL - && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, - req_exts, req)) { + if (extsect != NULL + && !X509V3_EXT_REQ_add_nconf(req_conf, &ext_ctx, extsect, req)) { BIO_printf(bio_err, "Error adding request extensions from section %s\n", - req_exts); + extsect); goto end; } if (addext_conf != NULL && !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, "default", req)) { - BIO_printf(bio_err, "Error adding extensions defined via -addext\n"); + BIO_printf(bio_err, "Error adding request extensions defined via -addext\n"); goto end; } i = do_X509_REQ_sign(req, pkey, digest, sigopts); @@ -935,10 +942,11 @@ int req_main(int argc, char **argv) if (i < 0) goto end; - if (i == 0) + if (i == 0) { BIO_printf(bio_err, "Certificate request self-signature verify failure\n"); - else /* i > 0 */ - BIO_printf(bio_err, "Certificate request self-signature verify OK\n"); + goto end; + } else /* i > 0 */ + BIO_printf(bio_out, "Certificate request self-signature verify OK\n"); } if (noout && !text && !modulus && !subject && !pubkey) { @@ -1073,16 +1081,12 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj, STACK_OF(CONF_VALUE) *dn_sk = NULL, *attr_sk = NULL; char *tmp, *dn_sect, *attr_sect; - tmp = NCONF_get_string(req_conf, section, PROMPT); - if (tmp == NULL) - ERR_clear_error(); - if ((tmp != NULL) && strcmp(tmp, "no") == 0) + tmp = app_conf_try_string(req_conf, section, PROMPT); + if (tmp != NULL && strcmp(tmp, "no") == 0) no_prompt = 1; - dn_sect = NCONF_get_string(req_conf, section, DISTINGUISHED_NAME); - if (dn_sect == NULL) { - ERR_clear_error(); - } else { + dn_sect = app_conf_try_string(req_conf, section, DISTINGUISHED_NAME); + if (dn_sect != NULL) { dn_sk = NCONF_get_section(req_conf, dn_sect); if (dn_sk == NULL) { BIO_printf(bio_err, "Unable to get '%s' section\n", dn_sect); @@ -1090,10 +1094,8 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, X509_NAME *fsubj, } } - attr_sect = NCONF_get_string(req_conf, section, ATTRIBUTES); - if (attr_sect == NULL) { - ERR_clear_error(); - } else { + attr_sect = app_conf_try_string(req_conf, section, ATTRIBUTES); + if (attr_sect != NULL) { attr_sk = NCONF_get_section(req_conf, attr_sect); if (attr_sk == NULL) { BIO_printf(bio_err, "Unable to get '%s' section\n", attr_sect); @@ -1189,31 +1191,23 @@ static int prompt_info(X509_REQ *req, goto start; if (!join(buf, sizeof(buf), v->name, "_default", "Name")) return 0; - if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { - ERR_clear_error(); + if ((def = app_conf_try_string(req_conf, dn_sect, buf)) == NULL) def = ""; - } if (!join(buf, sizeof(buf), v->name, "_value", "Name")) return 0; - if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { - ERR_clear_error(); + if ((value = app_conf_try_string(req_conf, dn_sect, buf)) == NULL) value = NULL; - } if (!join(buf, sizeof(buf), v->name, "_min", "Name")) return 0; - if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { - ERR_clear_error(); + if (!app_conf_try_number(req_conf, dn_sect, buf, &n_min)) n_min = -1; - } if (!join(buf, sizeof(buf), v->name, "_max", "Name")) return 0; - if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { - ERR_clear_error(); + if (!app_conf_try_number(req_conf, dn_sect, buf, &n_max)) n_max = -1; - } if (!add_DN_object(subj, v->value, def, value, nid, n_min, n_max, chtype, mval)) @@ -1247,33 +1241,23 @@ static int prompt_info(X509_REQ *req, if (!join(buf, sizeof(buf), type, "_default", "Name")) return 0; - if ((def = NCONF_get_string(req_conf, attr_sect, buf)) - == NULL) { - ERR_clear_error(); + def = app_conf_try_string(req_conf, attr_sect, buf); + if (def == NULL) def = ""; - } if (!join(buf, sizeof(buf), type, "_value", "Name")) return 0; - if ((value = NCONF_get_string(req_conf, attr_sect, buf)) - == NULL) { - ERR_clear_error(); - value = NULL; - } + value = app_conf_try_string(req_conf, attr_sect, buf); if (!join(buf, sizeof(buf), type, "_min", "Name")) return 0; - if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { - ERR_clear_error(); + if (!app_conf_try_number(req_conf, attr_sect, buf, &n_min)) n_min = -1; - } if (!join(buf, sizeof(buf), type, "_max", "Name")) return 0; - if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { - ERR_clear_error(); + if (!app_conf_try_number(req_conf, attr_sect, buf, &n_max)) n_max = -1; - } if (!add_attribute_object(req, v->value, def, value, nid, n_min, @@ -1666,21 +1650,3 @@ static EVP_PKEY_CTX *set_keygen_ctx(const char *gstr, return gctx; } -static int genpkey_cb(EVP_PKEY_CTX *ctx) -{ - char c = '*'; - BIO *b = EVP_PKEY_CTX_get_app_data(ctx); - int p; - p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); - if (p == 0) - c = '.'; - if (p == 1) - c = '+'; - if (p == 2) - c = '*'; - if (p == 3) - c = '\n'; - BIO_write(b, &c, 1); - (void)BIO_flush(b); - return 1; -} diff --git a/apps/rsa.c b/apps/rsa.c index 0da342c38f2c..9a4d16cbb01c 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -1,5 +1,5 @@ /* - * 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 @@ -139,6 +139,7 @@ int rsa_main(int argc, char **argv) int selection = 0; OSSL_ENCODER_CTX *ectx = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, rsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -217,15 +218,12 @@ int rsa_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; - if (ciphername != NULL) { - if (!opt_cipher(ciphername, &enc)) - goto opthelp; - } - private = (text && !pubin) || (!pubout && !noout) ? 1 : 0; + if (!opt_cipher(ciphername, &enc)) + goto opthelp; + private = (text && !pubin) || (!pubout && !noout); if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); diff --git a/apps/rsautl.c b/apps/rsautl.c index df29069bc1f4..3ee8224f48d8 100644 --- a/apps/rsautl.c +++ b/apps/rsautl.c @@ -1,5 +1,5 @@ /* - * 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 @@ -47,9 +47,9 @@ const OPTIONS rsautl_options[] = { OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input file"}, - {"inkey", OPT_INKEY, 's', "Input key"}, + {"inkey", OPT_INKEY, 's', "Input key, by default an RSA private key"}, {"keyform", OPT_KEYFORM, 'E', "Private key format (ENGINE, other values ignored)"}, - {"pubin", OPT_PUBIN, '-', "Input is an RSA public"}, + {"pubin", OPT_PUBIN, '-', "Input key is an RSA public pkey"}, {"certin", OPT_CERTIN, '-', "Input is a cert carrying an RSA public key"}, {"rev", OPT_REV, '-', "Reverse the order of the input buffer"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, @@ -169,8 +169,7 @@ int rsautl_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) diff --git a/apps/s_client.c b/apps/s_client.c index efa2879ca0e7..ffb4597a197c 100644 --- a/apps/s_client.c +++ b/apps/s_client.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 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 @@ -8,13 +8,15 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include #include #include #include +#include "internal/nelem.h" +#include "internal/sockets.h" /* for openssl_fdset() */ #ifndef OPENSSL_NO_SOCK @@ -54,9 +56,49 @@ typedef unsigned int u_int; #endif #undef BUFSIZZ -#define BUFSIZZ 1024*8 +#define BUFSIZZ 1024*16 #define S_CLIENT_IRC_READ_TIMEOUT 8 +#define USER_DATA_MODE_NONE 0 +#define USER_DATA_MODE_BASIC 1 +#define USER_DATA_MODE_ADVANCED 2 + +#define USER_DATA_PROCESS_BAD_ARGUMENT 0 +#define USER_DATA_PROCESS_SHUT 1 +#define USER_DATA_PROCESS_RESTART 2 +#define USER_DATA_PROCESS_NO_DATA 3 +#define USER_DATA_PROCESS_CONTINUE 4 + +struct user_data_st { + /* SSL connection we are processing commands for */ + SSL *con; + + /* Buffer where we are storing data supplied by the user */ + char *buf; + + /* Allocated size of the buffer */ + size_t bufmax; + + /* Amount of the buffer actually used */ + size_t buflen; + + /* Current location in the buffer where we will read from next*/ + size_t bufoff; + + /* The mode we are using for processing commands */ + int mode; + + /* Whether FIN has ben sent on the stream */ + int isfin; +}; + +static void user_data_init(struct user_data_st *user_data, SSL *con, char *buf, + size_t bufmax, int mode); +static int user_data_add(struct user_data_st *user_data, size_t i); +static int user_data_process(struct user_data_st *user_data, size_t *len, + size_t *off); +static int user_data_has_data(struct user_data_st *user_data); + static char *prog; static int c_debug = 0; static int c_showcerts = 0; @@ -74,6 +116,9 @@ static int ocsp_resp_cb(SSL *s, void *arg); static int ldap_ExtendedResponse_parse(const char *buf, long rem); static int is_dNS_name(const char *host); +static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 }; +static int enable_server_rpk = 0; + static int saved_errno; static void save_errno(void) @@ -163,7 +208,8 @@ static int psk_use_session_cb(SSL *s, const EVP_MD *md, const SSL_CIPHER *cipher = NULL; if (psksess != NULL) { - SSL_SESSION_up_ref(psksess); + if (!SSL_SESSION_up_ref(psksess)) + goto err; usesess = psksess; } else { long key_len; @@ -434,7 +480,7 @@ typedef enum OPTION_choice { OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT, OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN, OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET, - OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO, + OPT_BRIEF, OPT_PREXIT, OPT_NO_INTERACTIVE, OPT_CRLF, OPT_QUIET, OPT_NBIO, OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF, OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG, OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG, @@ -446,8 +492,8 @@ typedef enum OPTION_choice { #endif OPT_SSL3, OPT_SSL_CONFIG, OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1, - OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS, - OPT_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, + OPT_DTLS1_2, OPT_QUIC, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, + OPT_PASS, OPT_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_NEXTPROTONEG, OPT_ALPN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH, OPT_CAFILE, OPT_NOCAFILE, OPT_CHAINCAFILE, OPT_VERIFYCAFILE, @@ -456,17 +502,21 @@ typedef enum OPTION_choice { OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST, OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE, + OPT_TFO, OPT_V_ENUM, OPT_X_ENUM, OPT_S_ENUM, OPT_IGNORE_UNEXPECTED_EOF, - OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASS, - OPT_DANE_TLSA_DOMAIN, + OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_ADV, OPT_PROXY, OPT_PROXY_USER, + OPT_PROXY_PASS, OPT_DANE_TLSA_DOMAIN, #ifndef OPENSSL_NO_CT OPT_CT, OPT_NOCT, OPT_CTLOG_FILE, #endif OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME, OPT_ENABLE_PHA, + OPT_ENABLE_SERVER_RPK, + OPT_ENABLE_CLIENT_RPK, OPT_SCTP_LABEL_BUG, + OPT_KTLS, OPT_R_ENUM, OPT_PROV_ENUM } OPTION_CHOICE; @@ -538,6 +588,9 @@ const OPTIONS s_client_options[] = { "Do not load certificates from the default certificates store"}, {"requestCAfile", OPT_REQCAFILE, '<', "PEM format file of CA names to send to the server"}, +#if defined(TCP_FASTOPEN) && !defined(OPENSSL_NO_TFO) + {"tfo", OPT_TFO, '-', "Connect using TCP Fast Open"}, +#endif {"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"}, {"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's', "DANE TLSA rrdata presentation form"}, @@ -568,6 +621,8 @@ const OPTIONS s_client_options[] = { "Restrict output to brief summary of connection parameters"}, {"prexit", OPT_PREXIT, '-', "Print session information when the program exits"}, + {"no-interactive", OPT_NO_INTERACTIVE, '-', + "Don't run the client in the interactive mode"}, OPT_SECTION("Debug"), {"showcerts", OPT_SHOWCERTS, '-', @@ -594,6 +649,7 @@ const OPTIONS s_client_options[] = { #endif {"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"}, {"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"}, + {"adv", OPT_ADV, '-', "Advanced command mode"}, {"servername", OPT_SERVERNAME, 's', "Set TLS extension servername (SNI) in ClientHello (default)"}, {"noservername", OPT_NOSERVERNAME, '-', @@ -630,6 +686,7 @@ const OPTIONS s_client_options[] = { #endif #ifndef OPENSSL_NO_DTLS {"dtls", OPT_DTLS, '-', "Use any version of DTLS"}, + {"quic", OPT_QUIC, '-', "Use QUIC"}, {"timeout", OPT_TIMEOUT, '-', "Enable send/receive timeout on DTLS connections"}, {"mtu", OPT_MTU, 'p', "Set the link layer MTU"}, @@ -650,6 +707,8 @@ const OPTIONS s_client_options[] = { #endif {"early_data", OPT_EARLY_DATA, '<', "File to send as early data"}, {"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"}, + {"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"}, + {"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"}, #ifndef OPENSSL_NO_SRTP {"use_srtp", OPT_USE_SRTP, 's', "Offer SRTP key management with a colon-separated profile list"}, @@ -664,6 +723,9 @@ const OPTIONS s_client_options[] = { {"srp_strength", OPT_SRP_STRENGTH, 'p', "(deprecated) Minimal length in bits for N"}, #endif +#ifndef OPENSSL_NO_KTLS + {"ktls", OPT_KTLS, '-', "Enable Kernel TLS for sending and receiving"}, +#endif OPT_R_OPTIONS, OPT_S_OPTIONS, @@ -736,7 +798,8 @@ static const OPT_PAIR services[] = { #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) + || o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2 \ + || o == OPT_QUIC) /* Free |*dest| and optionally set it to a copy of |source|. */ static void freeandcopy(char **dest, const char *source) @@ -814,16 +877,19 @@ int s_client_main(int argc, char **argv) struct timeval timeout, *timeoutp; fd_set readfds, writefds; int noCApath = 0, noCAfile = 0, noCAstore = 0; - int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_UNDEF; + int build_chain = 0, cert_format = FORMAT_UNDEF; + size_t cbuf_len, cbuf_off; int key_format = FORMAT_UNDEF, crlf = 0, full_log = 1, mbuf_len = 0; int prexit = 0; + int nointeractive = 0; int sdebug = 0; int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0; int ret = 1, in_init = 1, i, nbio_test = 0, sock = -1, k, width, state = 0; - int sbuf_len, sbuf_off, cmdletters = 1; + int sbuf_len, sbuf_off, cmdmode = USER_DATA_MODE_BASIC; int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0; int starttls_proto = PROTO_OFF, crl_format = FORMAT_UNDEF, crl_download = 0; int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; + int first_loop; #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS) int at_eof = 0; #endif @@ -879,15 +945,21 @@ int s_client_main(int argc, char **argv) #endif BIO *bio_c_msg = NULL; const char *keylog_file = NULL, *early_data_file = NULL; -#ifndef OPENSSL_NO_DTLS - int isdtls = 0; -#endif + int isdtls = 0, isquic = 0; char *psksessf = NULL; int enable_pha = 0; + int enable_client_rpk = 0; #ifndef OPENSSL_NO_SCTP int sctp_label_bug = 0; #endif int ignore_unexpected_eof = 0; +#ifndef OPENSSL_NO_KTLS + int enable_ktls = 0; +#endif + int tfo = 0; + int is_infinite; + BIO_ADDR *peer_addr = NULL; + struct user_data_st user_data; FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -1072,6 +1144,9 @@ int s_client_main(int argc, char **argv) case OPT_PREXIT: prexit = 1; break; + case OPT_NO_INTERACTIVE: + nointeractive = 1; + break; case OPT_CRLF: crlf = 1; break; @@ -1082,7 +1157,10 @@ int s_client_main(int argc, char **argv) c_nbio = 1; break; case OPT_NOCMDS: - cmdletters = 0; + cmdmode = USER_DATA_MODE_NONE; + break; + case OPT_ADV: + cmdmode = USER_DATA_MODE_ADVANCED; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 1); @@ -1209,6 +1287,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_DTLS isdtls = 0; #endif + isquic = 0; break; case OPT_TLS1_3: min_version = TLS1_3_VERSION; @@ -1217,6 +1296,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_DTLS isdtls = 0; #endif + isquic = 0; break; case OPT_TLS1_2: min_version = TLS1_2_VERSION; @@ -1225,6 +1305,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_DTLS isdtls = 0; #endif + isquic = 0; break; case OPT_TLS1_1: min_version = TLS1_1_VERSION; @@ -1233,6 +1314,7 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_DTLS isdtls = 0; #endif + isquic = 0; break; case OPT_TLS1: min_version = TLS1_VERSION; @@ -1241,12 +1323,14 @@ int s_client_main(int argc, char **argv) #ifndef OPENSSL_NO_DTLS isdtls = 0; #endif + isquic = 0; break; case OPT_DTLS: #ifndef OPENSSL_NO_DTLS meth = DTLS_client_method(); socket_type = SOCK_DGRAM; isdtls = 1; + isquic = 0; #endif break; case OPT_DTLS1: @@ -1256,6 +1340,7 @@ int s_client_main(int argc, char **argv) max_version = DTLS1_VERSION; socket_type = SOCK_DGRAM; isdtls = 1; + isquic = 0; #endif break; case OPT_DTLS1_2: @@ -1265,6 +1350,19 @@ int s_client_main(int argc, char **argv) max_version = DTLS1_2_VERSION; socket_type = SOCK_DGRAM; isdtls = 1; + isquic = 0; +#endif + break; + case OPT_QUIC: +#ifndef OPENSSL_NO_QUIC + meth = OSSL_QUIC_client_method(); + min_version = 0; + max_version = 0; + socket_type = SOCK_DGRAM; +# ifndef OPENSSL_NO_DTLS + isdtls = 0; +# endif + isquic = 1; #endif break; case OPT_SCTP: @@ -1398,6 +1496,9 @@ int s_client_main(int argc, char **argv) if (!opt_pair(opt_arg(), services, &starttls_proto)) goto end; break; + case OPT_TFO: + tfo = 1; + break; case OPT_SERVERNAME: servername = opt_arg(); break; @@ -1461,12 +1562,22 @@ int s_client_main(int argc, char **argv) case OPT_ENABLE_PHA: enable_pha = 1; break; + case OPT_KTLS: +#ifndef OPENSSL_NO_KTLS + enable_ktls = 1; +#endif + break; + case OPT_ENABLE_SERVER_RPK: + enable_server_rpk = 1; + break; + case OPT_ENABLE_CLIENT_RPK: + enable_client_rpk = 1; + break; } } /* Optional argument is connect string if -connect not used. */ - argc = opt_num_rest(); - if (argc == 1) { + if (opt_num_rest() == 1) { /* Don't allow -connect and a separate argument. */ if (connectstr != NULL) { BIO_printf(bio_err, @@ -1476,12 +1587,15 @@ int s_client_main(int argc, char **argv) } connect_type = use_inet; freeandcopy(&connectstr, *opt_rest()); - } else if (argc != 0) { + } else if (!opt_check_rest_arg(NULL)) { goto opthelp; } if (!app_RAND_load()) goto end; + if (c_ign_eof) + cmdmode = USER_DATA_MODE_NONE; + if (count4or6 >= 2) { BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog); goto opthelp; @@ -1526,6 +1640,7 @@ int s_client_main(int argc, char **argv) } if (proxystr != NULL) { +#ifndef OPENSSL_NO_HTTP int res; char *tmp_host = host, *tmp_port = port; @@ -1560,8 +1675,14 @@ int s_client_main(int argc, char **argv) "%s: -proxy argument malformed or ambiguous\n", prog); goto end; } +#else + BIO_printf(bio_err, + "%s: -proxy not supported in no-http build\n", prog); + goto end; +#endif } + if (bindstr != NULL) { int res; res = BIO_parse_hostserv(bindstr, &bindhost, &bindport, @@ -1723,6 +1844,10 @@ int s_client_main(int argc, char **argv) if (ignore_unexpected_eof) SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); +#ifndef OPENSSL_NO_KTLS + if (enable_ktls) + SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS); +#endif if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) { BIO_printf(bio_err, "Error setting verify params\n"); @@ -1932,7 +2057,7 @@ int s_client_main(int argc, char **argv) /* * In TLSv1.3 NewSessionTicket messages arrive after the handshake and can - * come at any time. Therefore we use a callback to write out the session + * come at any time. Therefore, we use a callback to write out the session * when we know about it. This approach works for < TLSv1.3 as well. */ SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT @@ -1949,6 +2074,18 @@ int s_client_main(int argc, char **argv) if (enable_pha) SSL_set_post_handshake_auth(con, 1); + if (enable_client_rpk) + if (!SSL_set1_client_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_err, "Error setting client certificate types\n"); + goto end; + } + if (enable_server_rpk) { + if (!SSL_set1_server_cert_type(con, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_err, "Error setting server certificate types\n"); + goto end; + } + } + if (sess_in != NULL) { SSL_SESSION *sess; BIO *stmp = BIO_new_file(sess_in, "r"); @@ -1978,7 +2115,7 @@ int s_client_main(int argc, char **argv) if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) { if (servername == NULL) { - if(host == NULL || is_dNS_name(host)) + if (host == NULL || is_dNS_name(host)) servername = (host == NULL) ? "localhost" : host; } if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) { @@ -2012,22 +2149,51 @@ int s_client_main(int argc, char **argv) "-dane_tlsa_domain option.\n", prog); goto end; } +#ifndef OPENSSL_NO_DTLS + if (isdtls && tfo) { + BIO_printf(bio_err, "%s: DTLS does not support the -tfo option\n", prog); + goto end; + } +#endif +#ifndef OPENSSL_NO_QUIC + if (isquic && tfo) { + BIO_printf(bio_err, "%s: QUIC does not support the -tfo option\n", prog); + goto end; + } + if (isquic && alpn_in == NULL) { + BIO_printf(bio_err, "%s: QUIC requires ALPN to be specified (e.g. \"h3\" for HTTP/3) via the -alpn option\n", prog); + goto end; + } +#endif + if (tfo) + BIO_printf(bio_c_out, "Connecting via TFO\n"); re_start: + /* peer_addr might be set from previous connections */ + BIO_ADDR_free(peer_addr); + peer_addr = NULL; if (init_client(&sock, host, port, bindhost, bindport, socket_family, - socket_type, protocol) == 0) { + socket_type, protocol, tfo, !isquic, &peer_addr) == 0) { BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error()); BIO_closesocket(sock); goto end; } BIO_printf(bio_c_out, "CONNECTED(%08X)\n", sock); - if (c_nbio) { + /* + * QUIC always uses a non-blocking socket - and we have to switch on + * non-blocking mode at the SSL level + */ + if (c_nbio || isquic) { if (!BIO_socket_nbio(sock, 1)) { ERR_print_errors(bio_err); goto end; } - BIO_printf(bio_c_out, "Turned on non blocking io\n"); + if (c_nbio) { + if (isquic && !SSL_set_blocking_mode(con, 0)) + goto end; + BIO_printf(bio_c_out, "Turned on non blocking io\n"); + } } #ifndef OPENSSL_NO_DTLS if (isdtls) { @@ -2088,6 +2254,15 @@ int s_client_main(int argc, char **argv) } } else #endif /* OPENSSL_NO_DTLS */ +#ifndef OPENSSL_NO_QUIC + if (isquic) { + sbio = BIO_new_dgram(sock, BIO_NOCLOSE); + if (!SSL_set1_initial_peer_addr(con, peer_addr)) { + BIO_printf(bio_err, "Failed to set the initial peer address\n"); + goto shut; + } + } else +#endif sbio = BIO_new_socket(sock, BIO_NOCLOSE); if (sbio == NULL) { @@ -2097,6 +2272,12 @@ int s_client_main(int argc, char **argv) goto end; } + /* Now that we're using a BIO... */ + if (tfo) { + (void)BIO_set_conn_address(sbio, peer_addr); + (void)BIO_set_tfo(sbio, 1); + } + if (nbio_test) { BIO *test; @@ -2149,18 +2330,21 @@ int s_client_main(int argc, char **argv) tty_on = 0; read_ssl = 1; write_ssl = 1; + first_loop = 1; cbuf_len = 0; cbuf_off = 0; sbuf_len = 0; sbuf_off = 0; +#ifndef OPENSSL_NO_HTTP if (proxystr != NULL) { /* Here we must use the connect string target host & port */ if (!OSSL_HTTP_proxy_connect(sbio, thost, tport, proxyuser, proxypass, 0 /* no timeout */, bio_err, prog)) goto shut; } +#endif switch ((PROTOCOL_CHOICE) starttls_proto) { case PROTO_OFF: @@ -2576,7 +2760,7 @@ int s_client_main(int argc, char **argv) */ if (mbuf_len > 1 && mbuf[0] == '"') { make_uppercase(mbuf); - if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0) + if (HAS_PREFIX(mbuf, "\"STARTTLS\"")) foundit = 1; } } while (mbuf_len > 1 && mbuf[0] == '"'); @@ -2604,7 +2788,7 @@ int s_client_main(int argc, char **argv) */ strncpy(sbuf, mbuf, 2); make_uppercase(sbuf); - if (strncmp(sbuf, "OK", 2) != 0) { + if (!HAS_PREFIX(sbuf, "OK")) { BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf); goto shut; } @@ -2719,11 +2903,14 @@ int s_client_main(int argc, char **argv) BIO_free(edfile); } + user_data_init(&user_data, con, cbuf, BUFSIZZ, cmdmode); for (;;) { FD_ZERO(&readfds); FD_ZERO(&writefds); - if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout)) + if ((isdtls || isquic) + && SSL_get_event_timeout(con, &timeout, &is_infinite) + && !is_infinite) timeoutp = &timeout; else timeoutp = NULL; @@ -2764,6 +2951,38 @@ int s_client_main(int argc, char **argv) } } + if (!write_ssl) { + do { + switch (user_data_process(&user_data, &cbuf_len, &cbuf_off)) { + default: + BIO_printf(bio_err, "ERROR\n"); + /* fall through */ + case USER_DATA_PROCESS_SHUT: + ret = 0; + goto shut; + + case USER_DATA_PROCESS_RESTART: + goto re_start; + + case USER_DATA_PROCESS_NO_DATA: + break; + + case USER_DATA_PROCESS_CONTINUE: + write_ssl = 1; + break; + } + } while (!write_ssl + && cbuf_len == 0 + && user_data_has_data(&user_data)); + if (cbuf_len > 0) { + read_tty = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } else { + read_tty = 1; + } + } + ssl_pending = read_ssl && SSL_has_pending(con); if (!ssl_pending) { @@ -2781,15 +3000,26 @@ int s_client_main(int argc, char **argv) openssl_fdset(fileno_stdout(), &writefds); #endif } - if (read_ssl) + + /* + * Note that for QUIC we never actually check FD_ISSET() for the + * underlying network fds. We just rely on select waking up when + * they become readable/writeable and then SSL_handle_events() doing + * the right thing. + */ + if ((!isquic && read_ssl) + || (isquic && SSL_net_read_desired(con))) openssl_fdset(SSL_get_fd(con), &readfds); - if (write_ssl) + if ((!isquic && write_ssl) + || (isquic && (first_loop || SSL_net_write_desired(con)))) openssl_fdset(SSL_get_fd(con), &writefds); #else if (!tty_on || !write_tty) { - if (read_ssl) + if ((!isquic && read_ssl) + || (isquic && SSL_net_read_desired(con))) openssl_fdset(SSL_get_fd(con), &readfds); - if (write_ssl) + if ((!isquic && write_ssl) + || (isquic && (first_loop || SSL_net_write_desired(con)))) openssl_fdset(SSL_get_fd(con), &writefds); } #endif @@ -2804,7 +3034,7 @@ int s_client_main(int argc, char **argv) #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) /* * Under Windows/DOS we make the assumption that we can always - * write to the tty: therefore if we need to write to the tty we + * write to the tty: therefore, if we need to write to the tty we * just fall through. Otherwise we timeout the select every * second and see if there are any keypresses. Note: this is a * hack, in a proper Windows application we wouldn't do this. @@ -2833,10 +3063,17 @@ int s_client_main(int argc, char **argv) } } - if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0) - BIO_printf(bio_err, "TIMEOUT occurred\n"); + if (timeoutp != NULL) { + SSL_handle_events(con); + if (isdtls + && !FD_ISSET(SSL_get_fd(con), &readfds) + && !FD_ISSET(SSL_get_fd(con), &writefds)) + BIO_printf(bio_err, "TIMEOUT occurred\n"); + } - if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) { + if (!ssl_pending + && ((!isquic && FD_ISSET(SSL_get_fd(con), &writefds)) + || (isquic && (cbuf_len > 0 || first_loop)))) { k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: @@ -2845,7 +3082,7 @@ int s_client_main(int argc, char **argv) if (k <= 0) goto end; /* we have done a write(con,NULL,0); */ - if (cbuf_len <= 0) { + if (cbuf_len == 0) { read_tty = 1; write_ssl = 0; } else { /* if (cbuf_len > 0) */ @@ -2887,9 +3124,12 @@ int s_client_main(int argc, char **argv) case SSL_ERROR_SYSCALL: if ((k != 0) || (cbuf_len != 0)) { - BIO_printf(bio_err, "write:errno=%d\n", - get_last_socket_error()); - goto shut; + int sockerr = get_last_socket_error(); + + if (!tfo || sockerr != EISCONN) { + BIO_printf(bio_err, "write:errno=%d\n", sockerr); + goto shut; + } } else { read_tty = 1; write_ssl = 0; @@ -2926,7 +3166,8 @@ int s_client_main(int argc, char **argv) read_ssl = 1; write_tty = 0; } - } else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) { + } else if (ssl_pending + || (!isquic && FD_ISSET(SSL_get_fd(con), &readfds))) { #ifdef RENEG { static int iiii; @@ -2936,7 +3177,7 @@ int s_client_main(int argc, char **argv) } } #endif - k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); + k = SSL_read(con, sbuf, BUFSIZZ); switch (SSL_get_error(con, k)) { case SSL_ERROR_NONE: @@ -2989,6 +3230,13 @@ int s_client_main(int argc, char **argv) goto shut; } } + + /* don't wait for client input in the non-interactive mode */ + else if (nointeractive) { + ret = 0; + goto shut; + } + /* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */ #if defined(OPENSSL_SYS_MSDOS) else if (has_stdin_waiting()) @@ -3021,34 +3269,19 @@ int s_client_main(int argc, char **argv) at_eof = 1; #endif - if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) { + if (!c_ign_eof && i <= 0) { BIO_printf(bio_err, "DONE\n"); ret = 0; goto shut; } - if ((!c_ign_eof) && (cbuf[0] == 'R' && cmdletters)) { - BIO_printf(bio_err, "RENEGOTIATING\n"); - SSL_renegotiate(con); - cbuf_len = 0; - } else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' ) - && cmdletters) { - BIO_printf(bio_err, "KEYUPDATE\n"); - SSL_key_update(con, - cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED - : SSL_KEY_UPDATE_NOT_REQUESTED); - cbuf_len = 0; - } else { - cbuf_len = i; - cbuf_off = 0; -#ifdef CHARSET_EBCDIC - ebcdic2ascii(cbuf, cbuf, i); -#endif + if (i > 0 && !user_data_add(&user_data, i)) { + ret = 0; + goto shut; } - - write_ssl = 1; read_tty = 0; } + first_loop = 0; } shut: @@ -3096,12 +3329,13 @@ int s_client_main(int argc, char **argv) X509_free(cert); sk_X509_CRL_pop_free(crls, X509_CRL_free); EVP_PKEY_free(key); - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); OPENSSL_free(pass); #ifndef OPENSSL_NO_SRP OPENSSL_free(srp_arg.srppassin); #endif OPENSSL_free(sname_alloc); + BIO_ADDR_free(peer_addr); OPENSSL_free(connectstr); OPENSSL_free(bindstr); OPENSSL_free(bindhost); @@ -3127,12 +3361,50 @@ int s_client_main(int argc, char **argv) return ret; } +static char *ec_curve_name(EVP_PKEY *pkey) +{ + char *curve = 0; + size_t namelen; + + if (EVP_PKEY_get_group_name(pkey, NULL, 0, &namelen)) { + curve = OPENSSL_malloc(++namelen); + if (!EVP_PKEY_get_group_name(pkey, curve, namelen, 0)) { + OPENSSL_free(curve); + curve = NULL; + } + } + return (curve); +} + +static void print_cert_key_info(BIO *bio, X509 *cert) +{ + EVP_PKEY *pkey = X509_get0_pubkey(cert); + char *curve = NULL; + const char *keyalg; + + if (pkey == NULL) + return; + keyalg = EVP_PKEY_get0_type_name(pkey); + if (keyalg == NULL) + keyalg = OBJ_nid2ln(EVP_PKEY_get_base_id(pkey)); + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) + curve = ec_curve_name(pkey); + if (curve != NULL) + BIO_printf(bio, " a:PKEY: %s, (%s); sigalg: %s\n", + keyalg, curve, + OBJ_nid2ln(X509_get_signature_nid(cert))); + else + BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n", + keyalg, EVP_PKEY_get_bits(pkey), + OBJ_nid2ln(X509_get_signature_nid(cert))); + OPENSSL_free(curve); +} + static void print_stuff(BIO *bio, SSL *s, int full) { X509 *peer = NULL; STACK_OF(X509) *sk; const SSL_CIPHER *c; - EVP_PKEY *public_key; int i, istls13 = (SSL_version(s) == TLS1_3_VERSION); long verify_result; #ifndef OPENSSL_NO_COMP @@ -3152,27 +3424,22 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_printf(bio, "---\nCertificate chain\n"); for (i = 0; i < sk_X509_num(sk); i++) { + X509 *chain_cert = sk_X509_value(sk, i); + BIO_printf(bio, "%2d s:", i); - X509_NAME_print_ex(bio, X509_get_subject_name(sk_X509_value(sk, i)), 0, get_nameopt()); + X509_NAME_print_ex(bio, X509_get_subject_name(chain_cert), 0, get_nameopt()); BIO_puts(bio, "\n"); BIO_printf(bio, " i:"); - X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt()); + X509_NAME_print_ex(bio, X509_get_issuer_name(chain_cert), 0, get_nameopt()); BIO_puts(bio, "\n"); - public_key = X509_get_pubkey(sk_X509_value(sk, i)); - if (public_key != NULL) { - BIO_printf(bio, " a:PKEY: %s, %d (bit); sigalg: %s\n", - OBJ_nid2sn(EVP_PKEY_get_base_id(public_key)), - EVP_PKEY_get_bits(public_key), - OBJ_nid2sn(X509_get_signature_nid(sk_X509_value(sk, i)))); - EVP_PKEY_free(public_key); - } + print_cert_key_info(bio, chain_cert); BIO_printf(bio, " v:NotBefore: "); - ASN1_TIME_print(bio, X509_get0_notBefore(sk_X509_value(sk, i))); + ASN1_TIME_print(bio, X509_get0_notBefore(chain_cert)); BIO_printf(bio, "; NotAfter: "); - ASN1_TIME_print(bio, X509_get0_notAfter(sk_X509_value(sk, i))); + ASN1_TIME_print(bio, X509_get0_notAfter(chain_cert)); BIO_puts(bio, "\n"); if (c_showcerts) - PEM_write_bio_X509(bio, sk_X509_value(sk, i)); + PEM_write_bio_X509(bio, chain_cert); } } @@ -3188,6 +3455,23 @@ static void print_stuff(BIO *bio, SSL *s, int full) } else { BIO_printf(bio, "no peer certificate available\n"); } + + /* Only display RPK information if configured */ + if (SSL_get_negotiated_client_cert_type(s) == TLSEXT_cert_type_rpk) + BIO_printf(bio, "Client-to-server raw public key negotiated\n"); + if (SSL_get_negotiated_server_cert_type(s) == TLSEXT_cert_type_rpk) + BIO_printf(bio, "Server-to-client raw public key negotiated\n"); + if (enable_server_rpk) { + EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s); + + if (peer_rpk != NULL) { + BIO_printf(bio, "Server raw public key\n"); + EVP_PKEY_print_public(bio, peer_rpk, 2, NULL); + } else { + BIO_printf(bio, "no peer rpk available\n"); + } + } + print_ca_names(bio, s); ssl_print_sigalgs(bio, s); @@ -3237,6 +3521,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) c = SSL_get_current_cipher(s); BIO_printf(bio, "%s, Cipher is %s\n", SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c)); + BIO_printf(bio, "Protocol: %s\n", SSL_get_version(s)); if (peer != NULL) { EVP_PKEY *pktmp; @@ -3244,8 +3529,9 @@ static void print_stuff(BIO *bio, SSL *s, int full) BIO_printf(bio, "Server public key is %d bit\n", EVP_PKEY_get_bits(pktmp)); } - BIO_printf(bio, "Secure Renegotiation IS%s supported\n", - SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); + + ssl_print_secure_renegotiation_notes(bio, s); + #ifndef OPENSSL_NO_COMP comp = SSL_get_current_compression(s); expansion = SSL_get_current_expansion(s); @@ -3327,7 +3613,7 @@ static void print_stuff(BIO *bio, SSL *s, int full) /* * We also print the verify results when we dump session information, * but in TLSv1.3 we may not get that right away (or at all) depending - * on when we get a NewSessionTicket. Therefore we print it now as well. + * on when we get a NewSessionTicket. Therefore, we print it now as well. */ verify_result = SSL_get_verify_result(s); BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result, @@ -3536,4 +3822,267 @@ static int is_dNS_name(const char *host) return isdnsname; } + +static void user_data_init(struct user_data_st *user_data, SSL *con, char *buf, + size_t bufmax, int mode) +{ + user_data->con = con; + user_data->buf = buf; + user_data->bufmax = bufmax; + user_data->buflen = 0; + user_data->bufoff = 0; + user_data->mode = mode; + user_data->isfin = 0; +} + +static int user_data_add(struct user_data_st *user_data, size_t i) +{ + if (user_data->buflen != 0 || i > user_data->bufmax) + return 0; + + user_data->buflen = i; + user_data->bufoff = 0; + + return 1; +} + +#define USER_COMMAND_HELP 0 +#define USER_COMMAND_QUIT 1 +#define USER_COMMAND_RECONNECT 2 +#define USER_COMMAND_RENEGOTIATE 3 +#define USER_COMMAND_KEY_UPDATE 4 +#define USER_COMMAND_FIN 5 + +static int user_data_execute(struct user_data_st *user_data, int cmd, char *arg) +{ + switch (cmd) { + case USER_COMMAND_HELP: + /* This only ever occurs in advanced mode, so just emit advanced help */ + BIO_printf(bio_err, "Enter text to send to the peer followed by \n"); + BIO_printf(bio_err, "To issue a command insert {cmd} or {cmd:arg} anywhere in the text\n"); + BIO_printf(bio_err, "Entering {{ will send { to the peer\n"); + BIO_printf(bio_err, "The following commands are available\n"); + BIO_printf(bio_err, " {help}: Get this help text\n"); + BIO_printf(bio_err, " {quit}: Close the connection to the peer\n"); + BIO_printf(bio_err, " {reconnect}: Reconnect to the peer\n"); + if (SSL_is_quic(user_data->con)) { + BIO_printf(bio_err, " {fin}: Send FIN on the stream. No further writing is possible\n"); + } else if(SSL_version(user_data->con) == TLS1_3_VERSION) { + BIO_printf(bio_err, " {keyup:req|noreq}: Send a Key Update message\n"); + BIO_printf(bio_err, " Arguments:\n"); + BIO_printf(bio_err, " req = peer update requested (default)\n"); + BIO_printf(bio_err, " noreq = peer update not requested\n"); + } else { + BIO_printf(bio_err, " {reneg}: Attempt to renegotiate\n"); + } + BIO_printf(bio_err, "\n"); + return USER_DATA_PROCESS_NO_DATA; + + case USER_COMMAND_QUIT: + BIO_printf(bio_err, "DONE\n"); + return USER_DATA_PROCESS_SHUT; + + case USER_COMMAND_RECONNECT: + BIO_printf(bio_err, "RECONNECTING\n"); + do_ssl_shutdown(user_data->con); + SSL_set_connect_state(user_data->con); + BIO_closesocket(SSL_get_fd(user_data->con)); + return USER_DATA_PROCESS_RESTART; + + case USER_COMMAND_RENEGOTIATE: + BIO_printf(bio_err, "RENEGOTIATING\n"); + if (!SSL_renegotiate(user_data->con)) + break; + return USER_DATA_PROCESS_CONTINUE; + + case USER_COMMAND_KEY_UPDATE: { + int updatetype; + + if (OPENSSL_strcasecmp(arg, "req") == 0) + updatetype = SSL_KEY_UPDATE_REQUESTED; + else if (OPENSSL_strcasecmp(arg, "noreq") == 0) + updatetype = SSL_KEY_UPDATE_NOT_REQUESTED; + else + return USER_DATA_PROCESS_BAD_ARGUMENT; + BIO_printf(bio_err, "KEYUPDATE\n"); + if (!SSL_key_update(user_data->con, updatetype)) + break; + return USER_DATA_PROCESS_CONTINUE; + } + + case USER_COMMAND_FIN: + if (!SSL_stream_conclude(user_data->con, 0)) + break; + user_data->isfin = 1; + return USER_DATA_PROCESS_NO_DATA; + + default: + break; + } + + BIO_printf(bio_err, "ERROR\n"); + ERR_print_errors(bio_err); + + return USER_DATA_PROCESS_SHUT; +} + +static int user_data_process(struct user_data_st *user_data, size_t *len, + size_t *off) +{ + char *buf_start = user_data->buf + user_data->bufoff; + size_t outlen = user_data->buflen; + + if (user_data->buflen == 0) { + *len = 0; + *off = 0; + return USER_DATA_PROCESS_NO_DATA; + } + + if (user_data->mode == USER_DATA_MODE_BASIC) { + switch (buf_start[0]) { + case 'Q': + user_data->buflen = user_data->bufoff = *len = *off = 0; + return user_data_execute(user_data, USER_COMMAND_QUIT, NULL); + + case 'C': + user_data->buflen = user_data->bufoff = *len = *off = 0; + return user_data_execute(user_data, USER_COMMAND_RECONNECT, NULL); + + case 'R': + user_data->buflen = user_data->bufoff = *len = *off = 0; + return user_data_execute(user_data, USER_COMMAND_RENEGOTIATE, NULL); + + case 'K': + case 'k': + user_data->buflen = user_data->bufoff = *len = *off = 0; + return user_data_execute(user_data, USER_COMMAND_KEY_UPDATE, + buf_start[0] == 'K' ? "req" : "noreq"); + default: + break; + } + } else if (user_data->mode == USER_DATA_MODE_ADVANCED) { + char *cmd_start = buf_start; + + cmd_start[outlen] = '\0'; + for (;;) { + cmd_start = strchr(cmd_start, '{'); + if (cmd_start == buf_start && *(cmd_start + 1) == '{') { + /* The "{" is escaped, so skip it */ + cmd_start += 2; + buf_start++; + user_data->bufoff++; + user_data->buflen--; + outlen--; + continue; + } + break; + } + + if (cmd_start == buf_start) { + /* Command detected */ + char *cmd_end = strchr(cmd_start, '}'); + char *arg_start; + int cmd = -1, ret = USER_DATA_PROCESS_NO_DATA; + size_t oldoff; + + if (cmd_end == NULL) { + /* Malformed command */ + cmd_start[outlen - 1] = '\0'; + BIO_printf(bio_err, + "ERROR PROCESSING COMMAND. REST OF LINE IGNORED: %s\n", + cmd_start); + user_data->buflen = user_data->bufoff = *len = *off = 0; + return USER_DATA_PROCESS_NO_DATA; + } + *cmd_end = '\0'; + arg_start = strchr(cmd_start, ':'); + if (arg_start != NULL) { + *arg_start = '\0'; + arg_start++; + } + /* Skip over the { */ + cmd_start++; + /* + * Now we have cmd_start pointing to a NUL terminated string for + * the command, and arg_start either being NULL or pointing to a + * NUL terminated string for the argument. + */ + if (OPENSSL_strcasecmp(cmd_start, "help") == 0) { + cmd = USER_COMMAND_HELP; + } else if (OPENSSL_strcasecmp(cmd_start, "quit") == 0) { + cmd = USER_COMMAND_QUIT; + } else if (OPENSSL_strcasecmp(cmd_start, "reconnect") == 0) { + cmd = USER_COMMAND_RECONNECT; + } else if(SSL_is_quic(user_data->con)) { + if (OPENSSL_strcasecmp(cmd_start, "fin") == 0) + cmd = USER_COMMAND_FIN; + } if (SSL_version(user_data->con) == TLS1_3_VERSION) { + if (OPENSSL_strcasecmp(cmd_start, "keyup") == 0) { + cmd = USER_COMMAND_KEY_UPDATE; + if (arg_start == NULL) + arg_start = "req"; + } + } else { + /* (D)TLSv1.2 or below */ + if (OPENSSL_strcasecmp(cmd_start, "reneg") == 0) + cmd = USER_COMMAND_RENEGOTIATE; + } + if (cmd == -1) { + BIO_printf(bio_err, "UNRECOGNISED COMMAND (IGNORED): %s\n", + cmd_start); + } else { + ret = user_data_execute(user_data, cmd, arg_start); + if (ret == USER_DATA_PROCESS_BAD_ARGUMENT) { + BIO_printf(bio_err, "BAD ARGUMENT (COMMAND IGNORED): %s\n", + arg_start); + ret = USER_DATA_PROCESS_NO_DATA; + } + } + oldoff = user_data->bufoff; + user_data->bufoff = (cmd_end - user_data->buf) + 1; + user_data->buflen -= user_data->bufoff - oldoff; + if (user_data->buf + 1 == cmd_start + && user_data->buflen == 1 + && user_data->buf[user_data->bufoff] == '\n') { + /* + * This command was the only thing on the whole line. We + * suppress the final `\n` + */ + user_data->bufoff = 0; + user_data->buflen = 0; + } + *len = *off = 0; + return ret; + } else if (cmd_start != NULL) { + /* + * There is a command on this line, but its not at the start. Output + * the start of the line, and we'll process the command next time + * we call this function + */ + outlen = cmd_start - buf_start; + } + } + + if (user_data->isfin) { + user_data->buflen = user_data->bufoff = *len = *off = 0; + return USER_DATA_PROCESS_NO_DATA; + } + +#ifdef CHARSET_EBCDIC + ebcdic2ascii(buf_start, buf_start, outlen); +#endif + *len = outlen; + *off = user_data->bufoff; + user_data->buflen -= outlen; + if (user_data->buflen == 0) + user_data->bufoff = 0; + else + user_data->bufoff += outlen; + return USER_DATA_PROCESS_CONTINUE; +} + +static int user_data_has_data(struct user_data_st *user_data) +{ + return user_data->buflen > 0; +} #endif /* OPENSSL_NO_SOCK */ diff --git a/apps/s_server.c b/apps/s_server.c index 3c3b209d62de..8a36122a25bf 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -9,6 +9,8 @@ * https://www.openssl.org/source/license.html */ +#include "internal/e_os.h" + #include #include #include @@ -22,6 +24,7 @@ #include #include #include +#include "internal/sockets.h" /* for openssl_fdset() */ #ifndef OPENSSL_NO_SOCK @@ -42,7 +45,6 @@ typedef unsigned int u_int; #include #include #include -#include #include #include #ifndef OPENSSL_NO_DH @@ -97,9 +99,13 @@ static int keymatexportlen = 20; static int async = 0; static int use_sendfile = 0; +static int use_zc_sendfile = 0; static const char *session_id_prefix = NULL; +static const unsigned char cert_type_rpk[] = { TLSEXT_cert_type_rpk, TLSEXT_cert_type_x509 }; +static int enable_client_rpk = 0; + #ifndef OPENSSL_NO_DTLS static int enable_timeouts = 0; static long socket_mtu; @@ -203,7 +209,9 @@ static int psk_find_session_cb(SSL *ssl, const unsigned char *identity, } if (psksess != NULL) { - SSL_SESSION_up_ref(psksess); + if (!SSL_SESSION_up_ref(psksess)) + return 0; + *sess = psksess; return 1; } @@ -263,7 +271,7 @@ typedef struct { char buff[1]; } EBCDIC_OUTBUFF; -static const BIO_METHOD *BIO_f_ebcdic_filter() +static const BIO_METHOD *BIO_f_ebcdic_filter(void) { if (methods_ebcdic == NULL) { methods_ebcdic = BIO_meth_new(BIO_TYPE_EBCDIC_FILTER, @@ -473,7 +481,10 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, char *proxy = NULL, *no_proxy = NULL; int use_ssl; STACK_OF(OPENSSL_STRING) *aia = NULL; - X509 *x = NULL; + X509 *x = NULL, *cert; + X509_NAME *iname; + STACK_OF(X509) *chain = NULL; + SSL_CTX *ssl_ctx; X509_STORE_CTX *inctx = NULL; X509_OBJECT *obj; OCSP_REQUEST *req = NULL; @@ -484,6 +495,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, /* Build up OCSP query from server certificate */ x = SSL_get_certificate(s); + iname = X509_get_issuer_name(x); aia = X509_get1_ocsp(x); if (aia != NULL) { if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl, @@ -508,21 +520,33 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx, proxy = srctx->proxy; no_proxy = srctx->no_proxy; - inctx = X509_STORE_CTX_new(); - if (inctx == NULL) + ssl_ctx = SSL_get_SSL_CTX(s); + if (!SSL_CTX_get0_chain_certs(ssl_ctx, &chain)) 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; + for (i = 0; i < sk_X509_num(chain); i++) { + /* check the untrusted certificate chain (-cert_chain option) */ + cert = sk_X509_value(chain, i); + if (X509_name_cmp(iname, X509_get_subject_name(cert)) == 0) { + /* the issuer certificate is found */ + id = OCSP_cert_to_id(NULL, x, cert); + break; + } + } + if (id == NULL) { + inctx = X509_STORE_CTX_new(); + if (inctx == NULL) + goto err; + if (!X509_STORE_CTX_init(inctx, SSL_CTX_get_cert_store(ssl_ctx), + NULL, NULL)) + goto err; + obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509, iname); + 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); } - 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(); @@ -717,7 +741,11 @@ typedef enum OPTION_choice { 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_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_KTLS, + OPT_USE_ZC_SENDFILE, + OPT_TFO, OPT_CERT_COMP, + OPT_ENABLE_SERVER_RPK, + OPT_ENABLE_CLIENT_RPK, OPT_R_ENUM, OPT_S_ENUM, OPT_V_ENUM, @@ -748,6 +776,9 @@ const OPTIONS s_server_options[] = { #endif {"4", OPT_4, '-', "Use IPv4 only"}, {"6", OPT_6, '-', "Use IPv6 only"}, +#if defined(TCP_FASTOPEN) && !defined(OPENSSL_NO_TFO) + {"tfo", OPT_TFO, '-', "Listen for TCP Fast Open connections"}, +#endif OPT_SECTION("Identity"), {"context", OPT_CONTEXT, 's', "Set session ID context"}, @@ -841,6 +872,9 @@ const OPTIONS s_server_options[] = { "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_COMP_ALG + {"cert_comp", OPT_CERT_COMP, '-', "Pre-compress server certificates"}, +#endif #ifndef OPENSSL_NO_OCSP OPT_SECTION("OCSP"), @@ -959,9 +993,12 @@ const OPTIONS s_server_options[] = { {"alpn", OPT_ALPN, 's', "Set the advertised protocols for the ALPN extension (comma-separated list)"}, #ifndef OPENSSL_NO_KTLS + {"ktls", OPT_KTLS, '-', "Enable Kernel TLS for sending and receiving"}, {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"}, + {"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"}, #endif - + {"enable_server_rpk", OPT_ENABLE_SERVER_RPK, '-', "Enable raw public keys (RFC7250) from the server"}, + {"enable_client_rpk", OPT_ENABLE_CLIENT_RPK, '-', "Enable raw public keys (RFC7250) from the client"}, OPT_R_OPTIONS, OPT_S_OPTIONS, OPT_V_OPTIONS, @@ -1054,6 +1091,12 @@ int s_server_main(int argc, char *argv[]) int sctp_label_bug = 0; #endif int ignore_unexpected_eof = 0; +#ifndef OPENSSL_NO_KTLS + int enable_ktls = 0; +#endif + int tfo = 0; + int cert_comp = 0; + int enable_server_rpk = 0; /* Init of few remaining global variables */ local_argc = argc; @@ -1069,6 +1112,7 @@ int s_server_main(int argc, char *argv[]) s_brief = 0; async = 0; use_sendfile = 0; + use_zc_sendfile = 0; port = OPENSSL_strdup(PORT); cctx = SSL_CONF_CTX_new(); @@ -1635,20 +1679,41 @@ int s_server_main(int argc, char *argv[]) case OPT_NOCANAMES: no_ca_names = 1; break; + case OPT_KTLS: +#ifndef OPENSSL_NO_KTLS + enable_ktls = 1; +#endif + break; case OPT_SENDFILE: #ifndef OPENSSL_NO_KTLS use_sendfile = 1; +#endif + break; + case OPT_USE_ZC_SENDFILE: +#ifndef OPENSSL_NO_KTLS + use_zc_sendfile = 1; #endif break; case OPT_IGNORE_UNEXPECTED_EOF: ignore_unexpected_eof = 1; break; + case OPT_TFO: + tfo = 1; + break; + case OPT_CERT_COMP: + cert_comp = 1; + break; + case OPT_ENABLE_SERVER_RPK: + enable_server_rpk = 1; + break; + case OPT_ENABLE_CLIENT_RPK: + enable_client_rpk = 1; + break; } } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) @@ -1677,6 +1742,11 @@ int s_server_main(int argc, char *argv[]) } #endif + if (tfo && socket_type != SOCK_STREAM) { + BIO_printf(bio_err, "Can only use -tfo with TLS\n"); + goto end; + } + if (stateless && socket_type != SOCK_STREAM) { BIO_printf(bio_err, "Can only use --stateless with TLS\n"); goto end; @@ -1689,9 +1759,9 @@ int s_server_main(int argc, char *argv[]) goto end; } #endif - if (early_data && (www > 0 || rev)) { + if (early_data && rev) { BIO_printf(bio_err, - "Can't use -early_data in combination with -www, -WWW, -HTTP, or -rev\n"); + "Can't use -early_data in combination with -rev\n"); goto end; } @@ -1707,6 +1777,16 @@ int s_server_main(int argc, char *argv[]) #endif #ifndef OPENSSL_NO_KTLS + if (use_zc_sendfile && !use_sendfile) { + BIO_printf(bio_out, "Warning: -zerocopy_sendfile depends on -sendfile, enabling -sendfile now.\n"); + use_sendfile = 1; + } + + if (use_sendfile && enable_ktls == 0) { + BIO_printf(bio_out, "Warning: -sendfile depends on -ktls, enabling -ktls now.\n"); + enable_ktls = 1; + } + if (use_sendfile && www <= 1) { BIO_printf(bio_err, "Can't use -sendfile without -WWW or -HTTP\n"); goto end; @@ -1904,6 +1984,12 @@ int s_server_main(int argc, char *argv[]) if (ignore_unexpected_eof) SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); +#ifndef OPENSSL_NO_KTLS + if (enable_ktls) + SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS); + if (use_zc_sendfile) + SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE); +#endif if (max_send_fragment > 0 && !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) { @@ -2220,6 +2306,24 @@ int s_server_main(int argc, char *argv[]) if (recv_max_early_data >= 0) SSL_CTX_set_recv_max_early_data(ctx, recv_max_early_data); + if (cert_comp) { + BIO_printf(bio_s_out, "Compressing certificates\n"); + if (!SSL_CTX_compress_certs(ctx, 0)) + BIO_printf(bio_s_out, "Error compressing certs on ctx\n"); + if (ctx2 != NULL && !SSL_CTX_compress_certs(ctx2, 0)) + BIO_printf(bio_s_out, "Error compressing certs on ctx2\n"); + } + if (enable_server_rpk) + if (!SSL_CTX_set1_server_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_s_out, "Error setting server certificate types\n"); + goto end; + } + if (enable_client_rpk) + if (!SSL_CTX_set1_client_cert_type(ctx, cert_type_rpk, sizeof(cert_type_rpk))) { + BIO_printf(bio_s_out, "Error setting server certificate types\n"); + goto end; + } + if (rev) server_cb = rev_body; else if (www) @@ -2231,8 +2335,10 @@ int s_server_main(int argc, char *argv[]) && unlink_unix_path) unlink(host); #endif + if (tfo) + BIO_printf(bio_s_out, "Listening for TFO\n"); do_server(&accept_socket, host, port, socket_family, socket_type, protocol, - server_cb, context, naccept, bio_s_out); + server_cb, context, naccept, bio_s_out, tfo); print_stats(bio_s_out, ctx); ret = 0; end: @@ -2244,8 +2350,8 @@ int s_server_main(int argc, char *argv[]) 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); + OSSL_STACK_OF_X509_free(s_chain); + OSSL_STACK_OF_X509_free(s_dchain); OPENSSL_free(pass); OPENSSL_free(dpass); OPENSSL_free(host); @@ -2333,7 +2439,7 @@ 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; + int k; unsigned long l; SSL *con = NULL; BIO *sbio; @@ -2449,7 +2555,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) BIO_free(sbio); goto err; } - sbio = BIO_push(test, sbio); } @@ -2521,6 +2626,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) else width = s + 1; for (;;) { + int i; int read_from_terminal; int read_from_sslcon; @@ -2620,7 +2726,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) 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'))) { @@ -2630,7 +2735,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) 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') @@ -2640,7 +2744,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) : 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'))) { @@ -2652,7 +2755,6 @@ static int sv_body(int s, int stype, int prot, unsigned char *context) } else { i = SSL_do_handshake(con); printf("SSL_do_handshake -> %d\n", i); - i = 0; } continue; } @@ -2969,6 +3071,19 @@ static void print_connection_info(SSL *con) dump_cert_text(bio_s_out, peer); peer = NULL; } + /* Only display RPK information if configured */ + if (SSL_get_negotiated_server_cert_type(con) == TLSEXT_cert_type_rpk) + BIO_printf(bio_s_out, "Server-to-client raw public key negotiated\n"); + if (SSL_get_negotiated_client_cert_type(con) == TLSEXT_cert_type_rpk) + BIO_printf(bio_s_out, "Client-to-server raw public key negotiated\n"); + if (enable_client_rpk) { + EVP_PKEY *client_rpk = SSL_get0_peer_rpk(con); + + if (client_rpk != NULL) { + BIO_printf(bio_s_out, "Client raw public key\n"); + EVP_PKEY_print_public(bio_s_out, client_rpk, 2, NULL); + } + } if (SSL_get_shared_ciphers(con, buf, sizeof(buf)) != NULL) BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); @@ -3001,8 +3116,9 @@ static void print_connection_info(SSL *con) #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"); + + ssl_print_secure_renegotiation_notes(bio_s_out, con); + if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION)) BIO_printf(bio_s_out, "Renegotiation is DISABLED\n"); @@ -3037,12 +3153,12 @@ static void print_connection_info(SSL *con) static int www_body(int s, int stype, int prot, unsigned char *context) { - char *buf = NULL; + char *buf = NULL, *p; int ret = 1; int i, j, k, dot; SSL *con; const SSL_CIPHER *c; - BIO *io, *ssl_bio, *sbio; + BIO *io, *ssl_bio, *sbio, *edio; #ifdef RENEG int total_bytes = 0; #endif @@ -3061,10 +3177,11 @@ static int www_body(int s, int stype, int prot, unsigned char *context) /* 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"); + p = 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)) + edio = BIO_new(BIO_s_mem()); + if ((io == NULL) || (ssl_bio == NULL) || (edio == NULL)) goto err; if (s_nbio) { @@ -3124,6 +3241,12 @@ static int www_body(int s, int stype, int prot, unsigned char *context) goto err; io = BIO_push(filter, io); + + filter = BIO_new(BIO_f_ebcdic_filter()); + if (filter == NULL) + goto err; + + edio = BIO_push(filter, edio); #endif if (s_debug) { @@ -3140,8 +3263,35 @@ static int www_body(int s, int stype, int prot, unsigned char *context) SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out); } + if (early_data) { + int 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) + BIO_write(edio, buf, (int)readbytes); + } + } + for (;;) { - i = BIO_gets(io, buf, bufsize + 1); + i = BIO_gets(!BIO_eof(edio) ? edio : io, buf, bufsize + 1); if (i < 0) { /* error */ if (!BIO_should_retry(io) && !SSL_waiting_for_async(con)) { if (!s_quiet) @@ -3159,7 +3309,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context) continue; } #endif - ossl_sleep(1000); + OSSL_sleep(1000); continue; } } else if (i == 0) { /* end of input */ @@ -3168,15 +3318,14 @@ static int www_body(int s, int stype, int prot, unsigned char *context) } /* else we have data */ - if (((www == 1) && (strncmp("GET ", buf, 4) == 0)) || - ((www == 2) && (strncmp("GET /stats ", buf, 11) == 0))) { - char *p; + if ((www == 1 && HAS_PREFIX(buf, "GET ")) + || (www == 2 && HAS_PREFIX(buf, "GET /stats "))) { 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) + if (www == 1 && HAS_PREFIX(buf, "GET /reneg")) { + if (HAS_PREFIX(buf, "GET /renegcert")) SSL_set_verify(con, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL); @@ -3217,6 +3366,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context) BIO_puts(io, "\n"); for (i = 0; i < local_argc; i++) { const char *myp; + for (myp = local_argv[i]; *myp; myp++) switch (*myp) { case '<': @@ -3236,10 +3386,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context) } BIO_puts(io, "\n"); - BIO_printf(io, - "Secure Renegotiation IS%s supported\n", - SSL_get_secure_renegotiation_support(con) ? - "" : " NOT"); + ssl_print_secure_renegotiation_notes(io, con); /* * The following is evil and should not really be done @@ -3299,16 +3446,12 @@ static int www_body(int s, int stype, int prot, unsigned char *context) } BIO_puts(io, "\r\n\r\n"); break; - } else if ((www == 2 || www == 3) - && (strncmp("GET /", buf, 5) == 0)) { + } else if ((www == 2 || www == 3) && CHECK_AND_SKIP_PREFIX(p, "GET /")) { BIO *file; - char *p, *e; + char *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] == ' ') @@ -3481,13 +3624,14 @@ static int www_body(int s, int stype, int prot, unsigned char *context) break; } end: - /* make sure we re-use sessions */ + /* make sure we reuse sessions */ do_ssl_shutdown(con); err: OPENSSL_free(buf); BIO_free(ssl_bio); BIO_free_all(io); + BIO_free_all(edio); return ret; } @@ -3607,7 +3751,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context) continue; } #endif - ossl_sleep(1000); + OSSL_sleep(1000); continue; } } else if (i == 0) { /* end of input */ @@ -3620,7 +3764,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context) p--; i--; } - if (!s_ign_eof && (i == 5) && (strncmp(buf, "CLOSE", 5) == 0)) { + if (!s_ign_eof && i == 5 && HAS_PREFIX(buf, "CLOSE")) { ret = 1; BIO_printf(bio_err, "CONNECTION CLOSED\n"); goto end; @@ -3638,7 +3782,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context) } } end: - /* make sure we re-use sessions */ + /* make sure we reuse sessions */ do_ssl_shutdown(con); err: @@ -3742,7 +3886,8 @@ static SSL_SESSION *get_session(SSL *ssl, const unsigned char *id, int idlen, 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); + return d2i_SSL_SESSION_ex(NULL, &p, sess->derlen, app_get0_libctx(), + app_get0_propq()); } } BIO_printf(bio_err, "Lookup session: cache miss\n"); diff --git a/apps/s_time.c b/apps/s_time.c index 1a58e19de53f..0d5bd1228729 100644 --- a/apps/s_time.c +++ b/apps/s_time.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -234,8 +234,7 @@ int s_time_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (cipher == NULL) @@ -311,7 +310,6 @@ int s_time_main(int argc, char **argv) } totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ - i = (int)((long)time(NULL) - finishtime + maxtime); printf ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n", nConn, totalTime, ((double)nConn / totalTime), bytes_read); @@ -339,7 +337,7 @@ int s_time_main(int argc, char **argv) buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path); if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0) goto end; - while ((i = SSL_read(scon, buf, sizeof(buf))) > 0) + while (SSL_read(scon, buf, sizeof(buf)) > 0) continue; } SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); diff --git a/apps/sess_id.c b/apps/sess_id.c index 714c0f77877e..54b3d055634b 100644 --- a/apps/sess_id.c +++ b/apps/sess_id.c @@ -98,8 +98,7 @@ int sess_id_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; x = load_sess_id(infile, informat); diff --git a/apps/smime.c b/apps/smime.c index 790a8d06ad0c..211ddce4ab37 100644 --- a/apps/smime.c +++ b/apps/smime.c @@ -28,9 +28,9 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx); #define SMIME_ENCRYPT (1 | SMIME_OP) #define SMIME_DECRYPT (2 | SMIME_IP) #define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) +#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) #define SMIME_VERIFY (4 | SMIME_IP) #define SMIME_PK7OUT (5 | SMIME_IP | SMIME_OP) -#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) typedef enum OPTION_choice { OPT_COMMON, @@ -75,12 +75,12 @@ const OPTIONS smime_options[] = { {"sign", OPT_SIGN, '-', "Sign message"}, {"resign", OPT_RESIGN, '-', "Resign a signed message"}, {"verify", OPT_VERIFY, '-', "Verify signed message"}, + {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, OPT_SECTION("Signing/Encryption"), {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, {"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"}, {"", OPT_CIPHER, '-', "Any supported cipher"}, - {"pk7out", OPT_PK7OUT, '-', "Output PKCS#7 structure"}, {"nointern", OPT_NOINTERN, '-', "Don't search certificates in message for signer"}, {"nodetach", OPT_NODETACH, '-', "Use opaque signing"}, @@ -96,7 +96,10 @@ const OPTIONS smime_options[] = { {"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"}, {"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"}, - {"certfile", OPT_CERTFILE, '<', "Other certificates file"}, + {"certfile", OPT_CERTFILE, '<', + "Extra signer and intermediate CA certificates to include when signing"}, + {OPT_MORE_STR, 0, 0, + "or to use as preferred signer certs and for chain building when verifying"}, {"recip", OPT_RECIP, '<', "Recipient certificate file for decryption"}, OPT_SECTION("Email"), @@ -129,6 +132,32 @@ const OPTIONS smime_options[] = { {NULL} }; +static const char *operation_name(int operation) +{ + switch (operation) { + case SMIME_ENCRYPT: + return "encrypt"; + case SMIME_DECRYPT: + return "decrypt"; + case SMIME_SIGN: + return "sign"; + case SMIME_RESIGN: + return "resign"; + case SMIME_VERIFY: + return "verify"; + case SMIME_PK7OUT: + return "pk7out"; + default: + return "(invalid operation)"; + } +} + +#define SET_OPERATION(op) \ + ((operation != 0 && (operation != (op))) \ + ? 0 * BIO_printf(bio_err, "%s: Cannot use -%s together with -%s\n", \ + prog, operation_name(op), operation_name(operation)) \ + : (operation = (op))) + int smime_main(int argc, char **argv) { CONF *conf = NULL; @@ -160,6 +189,7 @@ int smime_main(int argc, char **argv) if ((vpm = X509_VERIFY_PARAM_new()) == NULL) return 1; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, smime_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -187,22 +217,28 @@ int smime_main(int argc, char **argv) outfile = opt_arg(); break; case OPT_ENCRYPT: - operation = SMIME_ENCRYPT; + if (!SET_OPERATION(SMIME_ENCRYPT)) + goto end; break; case OPT_DECRYPT: - operation = SMIME_DECRYPT; + if (!SET_OPERATION(SMIME_DECRYPT)) + goto end; break; case OPT_SIGN: - operation = SMIME_SIGN; + if (!SET_OPERATION(SMIME_SIGN)) + goto end; break; case OPT_RESIGN: - operation = SMIME_RESIGN; + if (!SET_OPERATION(SMIME_RESIGN)) + goto end; break; case OPT_VERIFY: - operation = SMIME_VERIFY; + if (!SET_OPERATION(SMIME_VERIFY)) + goto end; break; case OPT_PK7OUT: - operation = SMIME_PK7OUT; + if (!SET_OPERATION(SMIME_PK7OUT)) + goto end; break; case OPT_TEXT: flags |= PKCS7_TEXT; @@ -370,10 +406,8 @@ int smime_main(int argc, char **argv) if (!opt_md(digestname, &sign_md)) goto opthelp; } - if (ciphername != NULL) { - if (!opt_cipher_any(ciphername, &cipher)) + if (!opt_cipher_any(ciphername, &cipher)) goto opthelp; - } if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) { BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); goto opthelp; @@ -443,14 +477,8 @@ int smime_main(int argc, char **argv) } if (operation == SMIME_ENCRYPT) { - if (cipher == NULL) { -#ifndef OPENSSL_NO_DES - cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); -#else - BIO_printf(bio_err, "No cipher selected\n"); - goto end; -#endif - } + if (cipher == NULL) + cipher = (EVP_CIPHER *)EVP_aes_256_cbc(); encerts = sk_X509_new_null(); if (encerts == NULL) goto end; @@ -660,8 +688,8 @@ int smime_main(int argc, char **argv) end: if (ret) ERR_print_errors(bio_err); - sk_X509_pop_free(encerts, X509_free); - sk_X509_pop_free(other, X509_free); + OSSL_STACK_OF_X509_free(encerts); + OSSL_STACK_OF_X509_free(other); X509_VERIFY_PARAM_free(vpm); sk_OPENSSL_STRING_free(sksigners); sk_OPENSSL_STRING_free(skkeys); diff --git a/apps/speed.c b/apps/speed.c index bafcacf7775e..f52f2c839d0d 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -19,9 +19,14 @@ #define EdDSA_SECONDS PKEY_SECONDS #define SM2_SECONDS PKEY_SECONDS #define FFDH_SECONDS PKEY_SECONDS +#define KEM_SECONDS PKEY_SECONDS +#define SIG_SECONDS PKEY_SECONDS + +#define MAX_ALGNAME_SUFFIX 100 /* We need to use some deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED +#include "internal/e_os.h" #include #include @@ -29,6 +34,7 @@ #include #include "apps.h" #include "progs.h" +#include "internal/nelem.h" #include "internal/numbers.h" #include #include @@ -37,18 +43,28 @@ #include #include #include +#include #if !defined(OPENSSL_SYS_MSDOS) # include #endif -#if defined(__TANDEM) -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif -#endif - #if defined(_WIN32) # include +/* + * While VirtualLock is available under the app partition (e.g. UWP), + * the headers do not define the API. Define it ourselves instead. + */ +WINBASEAPI +BOOL +WINAPI +VirtualLock( + _In_ LPVOID lpAddress, + _In_ SIZE_T dwSize + ); +#endif + +#if defined(OPENSSL_SYS_LINUX) +# include #endif #include @@ -95,6 +111,8 @@ typedef struct openssl_speed_sec_st { int eddsa; int sm2; int ffdh; + int kem; + int sig; } openssl_speed_sec_t; static volatile int run = 0; @@ -103,14 +121,19 @@ static int mr = 0; /* machine-readeable output format to merge fork results */ static int usertime = 1; static double Time_F(int s); -static void print_message(const char *s, long num, int length, int tm); +static void print_message(const char *s, int length, int tm); static void pkey_print_message(const char *str, const char *str2, - long num, unsigned int bits, int sec); + unsigned int bits, int sec); +static void kskey_print_message(const char *str, const char *str2, int tm); static void print_result(int alg, int run_no, int count, double time_used); #ifndef NO_FORK static int do_multi(int multi, int size_num); #endif +static int domlock = 0; +static int testmode = 0; +static int testmoderesult = 0; + static const int lengths_list[] = { 16, 64, 256, 1024, 8 * 1024, 16 * 1024 }; @@ -126,7 +149,7 @@ static const int aead_lengths_list[] = { #ifdef SIGALRM -static void alarmed(int sig) +static void alarmed(ossl_unused int sig) { signal(SIGALRM, alarmed); run = 0; @@ -212,11 +235,16 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI, OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, - OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC + OPT_CONFIG, OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, + OPT_MLOCK, OPT_TESTMODE, OPT_KEM, OPT_SIG } OPTION_CHOICE; const OPTIONS speed_options[] = { - {OPT_HELP_STR, 1, '-', "Usage: %s [options] [algorithm...]\n"}, + {OPT_HELP_STR, 1, '-', + "Usage: %s [options] [algorithm...]\n" + "All +int options consider prefix '0' as base-8 input, " + "prefix '0x'/'0X' as base-16 input.\n" + }, OPT_SECTION("General"), {"help", OPT_HELP, '-', "Display this summary"}, @@ -234,6 +262,9 @@ const OPTIONS speed_options[] = { {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, #endif {"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"}, + {"mlock", OPT_MLOCK, '-', "Lock memory for better result determinism"}, + {"testmode", OPT_TESTMODE, '-', "Run the speed command in test mode"}, + OPT_CONFIG_OPTION, OPT_SECTION("Selection"), {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"}, @@ -243,6 +274,10 @@ const OPTIONS speed_options[] = { "Time decryption instead of encryption (only EVP)"}, {"aead", OPT_AEAD, '-', "Benchmark EVP-named AEAD cipher in TLS-like sequence"}, + {"kem-algorithms", OPT_KEM, '-', + "Benchmark KEM algorithms"}, + {"signature-algorithms", OPT_SIG, '-', + "Benchmark signature algorithms"}, OPT_SECTION("Timing"), {"elapsed", OPT_ELAPSED, '-', @@ -269,17 +304,18 @@ enum { D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST, D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES, D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML, - D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM + D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_KMAC128, D_KMAC256, + ALGOR_NUM }; /* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */ static const char *names[ALGOR_NUM] = { "md2", "mdc2", "md4", "md5", "sha1", "rmd160", - "sha256", "sha512", "whirlpool", "hmac(md5)", + "sha256", "sha512", "whirlpool", "hmac(sha256)", "des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc", "rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc", "aes-128-cbc", "aes-192-cbc", "aes-256-cbc", "camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc", - "evp", "ghash", "rand", "cmac" + "evp", "ghash", "rand", "cmac", "kmac128", "kmac256" }; /* list of configured algorithm (remaining), with some few alias */ @@ -320,18 +356,21 @@ static const OPT_PAIR doit_choices[] = { {"cast", D_CBC_CAST}, {"cast5", D_CBC_CAST}, {"ghash", D_GHASH}, - {"rand", D_RAND} + {"rand", D_RAND}, + {"kmac128", D_KMAC128}, + {"kmac256", D_KMAC256}, }; static double results[ALGOR_NUM][SIZE_NUM]; -enum { R_DSA_512, R_DSA_1024, R_DSA_2048, DSA_NUM }; +#ifndef OPENSSL_NO_DSA +enum { R_DSA_1024, R_DSA_2048, DSA_NUM }; static const OPT_PAIR dsa_choices[DSA_NUM] = { - {"dsa512", R_DSA_512}, {"dsa1024", R_DSA_1024}, {"dsa2048", R_DSA_2048} }; static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_DSA */ enum { R_RSA_512, R_RSA_1024, R_RSA_2048, R_RSA_3072, R_RSA_4096, R_RSA_7680, @@ -347,7 +386,7 @@ static const OPT_PAIR rsa_choices[RSA_NUM] = { {"rsa15360", R_RSA_15360} }; -static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */ +static double rsa_results[RSA_NUM][4]; /* 4 ops: sign, verify, encrypt, decrypt */ #ifndef OPENSSL_NO_DH enum ff_params_t { @@ -401,7 +440,13 @@ static const OPT_PAIR ecdsa_choices[ECDSA_NUM] = { {"ecdsabrp512r1", R_EC_BRP512R1}, {"ecdsabrp512t1", R_EC_BRP512T1} }; -enum { R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM }; +enum { +#ifndef OPENSSL_NO_ECX + R_EC_X25519 = ECDSA_NUM, R_EC_X448, EC_NUM +#else + EC_NUM = ECDSA_NUM +#endif +}; /* list of ecdh curves, extension of |ecdsa_choices| list above */ static const OPT_PAIR ecdh_choices[EC_NUM] = { {"ecdhp160", R_EC_P160}, @@ -428,13 +473,16 @@ static const OPT_PAIR ecdh_choices[EC_NUM] = { {"ecdhbrp384t1", R_EC_BRP384T1}, {"ecdhbrp512r1", R_EC_BRP512R1}, {"ecdhbrp512t1", R_EC_BRP512T1}, +#ifndef OPENSSL_NO_ECX {"ecdhx25519", R_EC_X25519}, {"ecdhx448", R_EC_X448} +#endif }; static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */ static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */ +#ifndef OPENSSL_NO_ECX enum { R_EC_Ed25519, R_EC_Ed448, EdDSA_NUM }; static const OPT_PAIR eddsa_choices[EdDSA_NUM] = { {"ed25519", R_EC_Ed25519}, @@ -442,6 +490,7 @@ static const OPT_PAIR eddsa_choices[EdDSA_NUM] = { }; static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */ +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 enum { R_EC_CURVESM2, SM2_NUM }; @@ -453,16 +502,26 @@ static const OPT_PAIR sm2_choices[SM2_NUM] = { static double sm2_results[SM2_NUM][2]; /* 2 ops: sign then verify */ #endif /* OPENSSL_NO_SM2 */ -#define COND(unused_cond) (run && count < INT_MAX) +#define MAX_KEM_NUM 111 +static size_t kems_algs_len = 0; +static char *kems_algname[MAX_KEM_NUM] = { NULL }; +static double kems_results[MAX_KEM_NUM][3]; /* keygen, encaps, decaps */ + +#define MAX_SIG_NUM 111 +static size_t sigs_algs_len = 0; +static char *sigs_algname[MAX_SIG_NUM] = { NULL }; +static double sigs_results[MAX_SIG_NUM][3]; /* keygen, sign, verify */ + +#define COND(unused_cond) (run && count < (testmode ? 1 : INT_MAX)) #define COUNT(d) (count) -#define TAG_LEN 16 +#define TAG_LEN 16 /* 16 bytes tag length works for all AEAD modes */ +#define AEAD_IVLEN 12 /* 12 bytes iv length works for all AEAD modes */ static unsigned int mode_op; /* AE Mode of operation */ static unsigned int aead = 0; /* AEAD flag */ -static unsigned char aead_iv[12]; /* For AEAD modes */ +static unsigned char aead_iv[AEAD_IVLEN]; /* For AEAD modes */ static unsigned char aad[EVP_AEAD_TLS1_AAD_LEN] = { 0xcc }; -static int aead_ivlen = sizeof(aead_iv); typedef struct loopargs_st { ASYNC_JOB *inprogress_job; @@ -475,15 +534,22 @@ typedef struct loopargs_st { unsigned char tag[TAG_LEN]; size_t buflen; size_t sigsize; + size_t encsize; EVP_PKEY_CTX *rsa_sign_ctx[RSA_NUM]; EVP_PKEY_CTX *rsa_verify_ctx[RSA_NUM]; + EVP_PKEY_CTX *rsa_encrypt_ctx[RSA_NUM]; + EVP_PKEY_CTX *rsa_decrypt_ctx[RSA_NUM]; +#ifndef OPENSSL_NO_DSA EVP_PKEY_CTX *dsa_sign_ctx[DSA_NUM]; EVP_PKEY_CTX *dsa_verify_ctx[DSA_NUM]; +#endif EVP_PKEY_CTX *ecdsa_sign_ctx[ECDSA_NUM]; EVP_PKEY_CTX *ecdsa_verify_ctx[ECDSA_NUM]; EVP_PKEY_CTX *ecdh_ctx[EC_NUM]; +#ifndef OPENSSL_NO_ECX EVP_MD_CTX *eddsa_ctx[EdDSA_NUM]; EVP_MD_CTX *eddsa_ctx2[EdDSA_NUM]; +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 EVP_MD_CTX *sm2_ctx[SM2_NUM]; EVP_MD_CTX *sm2_vfy_ctx[SM2_NUM]; @@ -499,21 +565,38 @@ typedef struct loopargs_st { #endif EVP_CIPHER_CTX *ctx; EVP_MAC_CTX *mctx; + EVP_PKEY_CTX *kem_gen_ctx[MAX_KEM_NUM]; + EVP_PKEY_CTX *kem_encaps_ctx[MAX_KEM_NUM]; + EVP_PKEY_CTX *kem_decaps_ctx[MAX_KEM_NUM]; + size_t kem_out_len[MAX_KEM_NUM]; + size_t kem_secret_len[MAX_KEM_NUM]; + unsigned char *kem_out[MAX_KEM_NUM]; + unsigned char *kem_send_secret[MAX_KEM_NUM]; + unsigned char *kem_rcv_secret[MAX_KEM_NUM]; + EVP_PKEY_CTX *sig_gen_ctx[MAX_KEM_NUM]; + EVP_PKEY_CTX *sig_sign_ctx[MAX_KEM_NUM]; + EVP_PKEY_CTX *sig_verify_ctx[MAX_KEM_NUM]; + size_t sig_max_sig_len[MAX_KEM_NUM]; + size_t sig_act_sig_len[MAX_KEM_NUM]; + unsigned char *sig_sig[MAX_KEM_NUM]; } loopargs_t; static int run_benchmark(int async_jobs, int (*loop_function) (void *), - loopargs_t * loopargs); + loopargs_t *loopargs); static unsigned int testnum; -/* Nb of iterations to do per algorithm and key-size */ -static long c[ALGOR_NUM][SIZE_NUM]; - -static char *evp_mac_mdname = "md5"; +static char *evp_mac_mdname = "sha256"; static char *evp_hmac_name = NULL; static const char *evp_md_name = NULL; static char *evp_mac_ciphername = "aes-128-cbc"; static char *evp_cmac_name = NULL; +static void dofail(void) +{ + ERR_print_errors(bio_err); + testmoderesult = 1; +} + static int have_md(const char *name) { int ret = 0; @@ -547,24 +630,44 @@ static int have_cipher(const char *name) return ret; } -static int EVP_Digest_loop(const char *mdname, int algindex, void *args) +static int EVP_Digest_loop(const char *mdname, ossl_unused int algindex, void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; unsigned char digest[EVP_MAX_MD_SIZE]; int count; EVP_MD *md = NULL; + EVP_MD_CTX *ctx = NULL; if (!opt_md_silent(mdname, &md)) return -1; - for (count = 0; COND(c[algindex][testnum]); count++) { - if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md, - NULL)) { + if (EVP_MD_xof(md)) { + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { count = -1; - break; + goto out; + } + + for (count = 0; COND(c[algindex][testnum]); count++) { + if (!EVP_DigestInit_ex2(ctx, md, NULL) + || !EVP_DigestUpdate(ctx, buf, (size_t)lengths[testnum]) + || !EVP_DigestFinalXOF(ctx, digest, sizeof(digest))) { + count = -1; + break; + } + } + } else { + for (count = 0; COND(c[algindex][testnum]); count++) { + if (!EVP_Digest(buf, (size_t)lengths[testnum], digest, NULL, md, + NULL)) { + count = -1; + break; + } } } +out: EVP_MD_free(md); + EVP_MD_CTX_free(ctx); return count; } @@ -593,7 +696,42 @@ static int MD5_loop(void *args) return EVP_Digest_loop("md5", D_MD5, args); } -static int EVP_MAC_loop(int algindex, void *args) +static int mac_setup(const char *name, + EVP_MAC **mac, OSSL_PARAM params[], + loopargs_t *loopargs, unsigned int loopargs_len) +{ + unsigned int i; + + *mac = EVP_MAC_fetch(app_get0_libctx(), name, app_get0_propq()); + if (*mac == NULL) + return 0; + + for (i = 0; i < loopargs_len; i++) { + loopargs[i].mctx = EVP_MAC_CTX_new(*mac); + if (loopargs[i].mctx == NULL) + return 0; + + if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) + return 0; + } + + return 1; +} + +static void mac_teardown(EVP_MAC **mac, + loopargs_t *loopargs, unsigned int loopargs_len) +{ + unsigned int i; + + for (i = 0; i < loopargs_len; i++) + EVP_MAC_CTX_free(loopargs[i].mctx); + EVP_MAC_free(*mac); + *mac = NULL; + + return; +} + +static int EVP_MAC_loop(ossl_unused int algindex, void *args) { loopargs_t *tempargs = *(loopargs_t **) args; unsigned char *buf = tempargs->buf; @@ -622,6 +760,16 @@ static int CMAC_loop(void *args) return EVP_MAC_loop(D_EVP_CMAC, args); } +static int KMAC128_loop(void *args) +{ + return EVP_MAC_loop(D_KMAC128, args); +} + +static int KMAC256_loop(void *args) +{ + return EVP_MAC_loop(D_KMAC256, args); +} + static int SHA1_loop(void *args) { return EVP_Digest_loop("sha1", D_SHA1, args); @@ -742,7 +890,7 @@ static int EVP_Update_loop(void *args) rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); if (rc != 1) { /* reset iv in case of counter overflow */ - EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + rc = EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); } } } else { @@ -750,14 +898,17 @@ static int EVP_Update_loop(void *args) rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]); if (rc != 1) { /* reset iv in case of counter overflow */ - EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); + rc = EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1); } } } if (decrypt) - EVP_DecryptFinal_ex(ctx, buf, &outl); + rc = EVP_DecryptFinal_ex(ctx, buf, &outl); else - EVP_EncryptFinal_ex(ctx, buf, &outl); + rc = EVP_EncryptFinal_ex(ctx, buf, &outl); + + if (rc == 0) + BIO_printf(bio_err, "Error finalizing cipher loop\n"); return count; } @@ -781,25 +932,26 @@ static int EVP_Update_loop_aead_enc(void *args) /* Set length of iv (Doesn't apply to SIV mode) */ if (mode_op != EVP_CIPH_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, - aead_ivlen, NULL)) { + sizeof(aead_iv), NULL)) { BIO_printf(bio_err, "\nFailed to set iv length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } /* Set tag_len (Not for GCM/SIV at encryption stage) */ if (mode_op != EVP_CIPH_GCM_MODE - && mode_op != EVP_CIPH_SIV_MODE) { + && mode_op != EVP_CIPH_SIV_MODE + && mode_op != EVP_CIPH_GCM_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, TAG_LEN, NULL)) { BIO_printf(bio_err, "\nFailed to set tag length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, aead_iv, -1)) { BIO_printf(bio_err, "\nFailed to set key and iv\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } /* Set total length of input. Only required for CCM */ @@ -807,20 +959,20 @@ static int EVP_Update_loop_aead_enc(void *args) if (!EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum])) { BIO_printf(bio_err, "\nCouldn't set input text length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (aead) { if (!EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad))) { BIO_printf(bio_err, "\nCouldn't insert AAD when encrypting\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (!EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum])) { BIO_printf(bio_err, "\nFailed to encrypt the data\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } if (EVP_EncryptFinal_ex(ctx, buf, &outl)) @@ -852,33 +1004,34 @@ static int EVP_Update_loop_aead_dec(void *args) /* Set the length of iv (Doesn't apply to SIV mode) */ if (mode_op != EVP_CIPH_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, - aead_ivlen, NULL)) { + sizeof(aead_iv), NULL)) { BIO_printf(bio_err, "\nFailed to set iv length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } /* Set the tag length (Doesn't apply to SIV mode) */ if (mode_op != EVP_CIPH_SIV_MODE - && mode_op != EVP_CIPH_GCM_MODE) { + && mode_op != EVP_CIPH_GCM_MODE + && mode_op != EVP_CIPH_GCM_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, TAG_LEN, NULL)) { BIO_printf(bio_err, "\nFailed to set tag length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, aead_iv, -1)) { BIO_printf(bio_err, "\nFailed to set key and iv\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } /* Set iv before decryption (Doesn't apply to SIV mode) */ if (mode_op != EVP_CIPH_SIV_MODE) { if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, aead_iv)) { BIO_printf(bio_err, "\nFailed to set iv\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } @@ -887,7 +1040,7 @@ static int EVP_Update_loop_aead_dec(void *args) if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, TAG_LEN, tag)) { BIO_printf(bio_err, "\nFailed to set tag\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } /* Set the total length of cipher text. Only required for CCM */ @@ -895,20 +1048,20 @@ static int EVP_Update_loop_aead_dec(void *args) if (!EVP_DecryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum])) { BIO_printf(bio_err, "\nCouldn't set cipher text length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (aead) { if (!EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad))) { BIO_printf(bio_err, "\nCouldn't insert AAD when decrypting\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (!EVP_DecryptUpdate(ctx, outbuf, &outl, buf, lengths[testnum])) { BIO_printf(bio_err, "\nFailed to decrypt the data\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } if (EVP_DecryptFinal_ex(ctx, outbuf, &outl)) @@ -917,8 +1070,6 @@ static int EVP_Update_loop_aead_dec(void *args) return realcount; } -static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */ - static int RSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; @@ -933,7 +1084,7 @@ static int RSA_sign_loop(void *args) ret = EVP_PKEY_sign(rsa_sign_ctx[testnum], buf2, rsa_num, buf, 36); if (ret <= 0) { BIO_printf(bio_err, "RSA sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -954,7 +1105,51 @@ static int RSA_verify_loop(void *args) ret = EVP_PKEY_verify(rsa_verify_ctx[testnum], buf2, rsa_num, buf, 36); if (ret <= 0) { BIO_printf(bio_err, "RSA verify failure\n"); - ERR_print_errors(bio_err); + dofail(); + count = -1; + break; + } + } + return count; +} + +static int RSA_encrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + size_t *rsa_num = &tempargs->encsize; + EVP_PKEY_CTX **rsa_encrypt_ctx = tempargs->rsa_encrypt_ctx; + int ret, count; + + for (count = 0; COND(rsa_c[testnum][2]); count++) { + *rsa_num = tempargs->buflen; + ret = EVP_PKEY_encrypt(rsa_encrypt_ctx[testnum], buf2, rsa_num, buf, 36); + if (ret <= 0) { + BIO_printf(bio_err, "RSA encrypt failure\n"); + dofail(); + count = -1; + break; + } + } + return count; +} + +static int RSA_decrypt_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + unsigned char *buf = tempargs->buf; + unsigned char *buf2 = tempargs->buf2; + size_t rsa_num; + EVP_PKEY_CTX **rsa_decrypt_ctx = tempargs->rsa_decrypt_ctx; + int ret, count; + + for (count = 0; COND(rsa_c[testnum][3]); count++) { + rsa_num = tempargs->buflen; + ret = EVP_PKEY_decrypt(rsa_decrypt_ctx[testnum], buf, &rsa_num, buf2, tempargs->encsize); + if (ret <= 0) { + BIO_printf(bio_err, "RSA decrypt failure\n"); + dofail(); count = -1; break; } @@ -963,7 +1158,6 @@ static int RSA_verify_loop(void *args) } #ifndef OPENSSL_NO_DH -static long ffdh_c[FFDH_NUM][1]; static int FFDH_derive_key_loop(void *args) { @@ -982,7 +1176,7 @@ static int FFDH_derive_key_loop(void *args) } #endif /* OPENSSL_NO_DH */ -static long dsa_c[DSA_NUM][2]; +#ifndef OPENSSL_NO_DSA static int DSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; @@ -997,7 +1191,7 @@ static int DSA_sign_loop(void *args) ret = EVP_PKEY_sign(dsa_sign_ctx[testnum], buf2, dsa_num, buf, 20); if (ret <= 0) { BIO_printf(bio_err, "DSA sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1018,15 +1212,15 @@ static int DSA_verify_loop(void *args) ret = EVP_PKEY_verify(dsa_verify_ctx[testnum], buf2, dsa_num, buf, 20); if (ret <= 0) { BIO_printf(bio_err, "DSA verify failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } } return count; } +#endif /* OPENSSL_NO_DSA */ -static long ecdsa_c[ECDSA_NUM][2]; static int ECDSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; @@ -1041,7 +1235,7 @@ static int ECDSA_sign_loop(void *args) ret = EVP_PKEY_sign(ecdsa_sign_ctx[testnum], buf2, ecdsa_num, buf, 20); if (ret <= 0) { BIO_printf(bio_err, "ECDSA sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1063,7 +1257,7 @@ static int ECDSA_verify_loop(void *args) buf, 20); if (ret <= 0) { BIO_printf(bio_err, "ECDSA verify failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1072,7 +1266,6 @@ static int ECDSA_verify_loop(void *args) } /* ******************************************************************** */ -static long ecdh_c[EC_NUM][1]; static int ECDH_EVP_derive_key_loop(void *args) { @@ -1088,7 +1281,7 @@ static int ECDH_EVP_derive_key_loop(void *args) return count; } -static long eddsa_c[EdDSA_NUM][2]; +#ifndef OPENSSL_NO_ECX static int EdDSA_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; @@ -1102,14 +1295,14 @@ static int EdDSA_sign_loop(void *args) ret = EVP_DigestSignInit(edctx[testnum], NULL, NULL, NULL, NULL); if (ret == 0) { BIO_printf(bio_err, "EdDSA sign init failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20); if (ret == 0) { BIO_printf(bio_err, "EdDSA sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1130,23 +1323,23 @@ static int EdDSA_verify_loop(void *args) ret = EVP_DigestVerifyInit(edctx[testnum], NULL, NULL, NULL, NULL); if (ret == 0) { BIO_printf(bio_err, "EdDSA verify init failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20); if (ret != 1) { BIO_printf(bio_err, "EdDSA verify failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } } return count; } +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 -static long sm2_c[SM2_NUM][2]; static int SM2_sign_loop(void *args) { loopargs_t *tempargs = *(loopargs_t **) args; @@ -1164,7 +1357,7 @@ static int SM2_sign_loop(void *args) if (!EVP_DigestSignInit(sm2ctx[testnum], NULL, EVP_sm3(), NULL, sm2_pkey[testnum])) { BIO_printf(bio_err, "SM2 init sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1172,7 +1365,7 @@ static int SM2_sign_loop(void *args) buf, 20); if (ret == 0) { BIO_printf(bio_err, "SM2 sign failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1197,7 +1390,7 @@ static int SM2_verify_loop(void *args) if (!EVP_DigestVerifyInit(sm2ctx[testnum], NULL, EVP_sm3(), NULL, sm2_pkey[testnum])) { BIO_printf(bio_err, "SM2 verify init failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1205,7 +1398,7 @@ static int SM2_verify_loop(void *args) buf, 20); if (ret != 1) { BIO_printf(bio_err, "SM2 verify failure\n"); - ERR_print_errors(bio_err); + dofail(); count = -1; break; } @@ -1214,8 +1407,149 @@ static int SM2_verify_loop(void *args) } #endif /* OPENSSL_NO_SM2 */ +static int KEM_keygen_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->kem_gen_ctx[testnum]; + EVP_PKEY *pkey = NULL; + int count; + + for (count = 0; COND(kems_c[testnum][0]); count++) { + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + return -1; + /* + * runtime defined to quite some degree by randomness, + * so performance overhead of _free doesn't impact + * results significantly. In any case this test is + * meant to permit relative algorithm performance + * comparison. + */ + EVP_PKEY_free(pkey); + pkey = NULL; + } + return count; +} + +static int KEM_encaps_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->kem_encaps_ctx[testnum]; + size_t out_len = tempargs->kem_out_len[testnum]; + size_t secret_len = tempargs->kem_secret_len[testnum]; + unsigned char *out = tempargs->kem_out[testnum]; + unsigned char *secret = tempargs->kem_send_secret[testnum]; + int count; + + for (count = 0; COND(kems_c[testnum][1]); count++) { + if (EVP_PKEY_encapsulate(ctx, out, &out_len, secret, &secret_len) <= 0) + return -1; + } + return count; +} + +static int KEM_decaps_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->kem_decaps_ctx[testnum]; + size_t out_len = tempargs->kem_out_len[testnum]; + size_t secret_len = tempargs->kem_secret_len[testnum]; + unsigned char *out = tempargs->kem_out[testnum]; + unsigned char *secret = tempargs->kem_send_secret[testnum]; + int count; + + for (count = 0; COND(kems_c[testnum][2]); count++) { + if (EVP_PKEY_decapsulate(ctx, secret, &secret_len, out, out_len) <= 0) + return -1; + } + return count; +} + +static int SIG_keygen_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->sig_gen_ctx[testnum]; + EVP_PKEY *pkey = NULL; + int count; + + for (count = 0; COND(kems_c[testnum][0]); count++) { + EVP_PKEY_keygen(ctx, &pkey); + /* TBD: How much does free influence runtime? */ + EVP_PKEY_free(pkey); + pkey = NULL; + } + return count; +} + +static int SIG_sign_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->sig_sign_ctx[testnum]; + /* be sure to not change stored sig: */ + unsigned char *sig = app_malloc(tempargs->sig_max_sig_len[testnum], + "sig sign loop"); + unsigned char md[SHA256_DIGEST_LENGTH] = { 0 }; + size_t md_len = SHA256_DIGEST_LENGTH; + int count; + + for (count = 0; COND(kems_c[testnum][1]); count++) { + size_t sig_len = tempargs->sig_max_sig_len[testnum]; + int ret = EVP_PKEY_sign(ctx, sig, &sig_len, md, md_len); + + if (ret <= 0) { + BIO_printf(bio_err, "SIG sign failure at count %d\n", count); + dofail(); + count = -1; + break; + } + } + OPENSSL_free(sig); + return count; +} + +static int SIG_verify_loop(void *args) +{ + loopargs_t *tempargs = *(loopargs_t **) args; + EVP_PKEY_CTX *ctx = tempargs->sig_verify_ctx[testnum]; + size_t sig_len = tempargs->sig_act_sig_len[testnum]; + unsigned char *sig = tempargs->sig_sig[testnum]; + unsigned char md[SHA256_DIGEST_LENGTH] = { 0 }; + size_t md_len = SHA256_DIGEST_LENGTH; + int count; + + for (count = 0; COND(kems_c[testnum][2]); count++) { + int ret = EVP_PKEY_verify(ctx, sig, sig_len, md, md_len); + + if (ret <= 0) { + BIO_printf(bio_err, "SIG verify failure at count %d\n", count); + dofail(); + count = -1; + break; + } + + } + return count; +} + +static int check_block_size(EVP_CIPHER_CTX *ctx, int length) +{ + const EVP_CIPHER *ciph = EVP_CIPHER_CTX_get0_cipher(ctx); + int blocksize = EVP_CIPHER_CTX_get_block_size(ctx); + + if (ciph == NULL || blocksize <= 0) { + BIO_printf(bio_err, "\nInvalid cipher!\n"); + return 0; + } + if (length % blocksize != 0) { + BIO_printf(bio_err, + "\nRequested encryption length not a multiple of block size for %s!\n", + EVP_CIPHER_get0_name(ciph)); + return 0; + } + return 1; +} + static int run_benchmark(int async_jobs, - int (*loop_function) (void *), loopargs_t * loopargs) + int (*loop_function) (void *), loopargs_t *loopargs) { int job_op_count = 0; int total_op_count = 0; @@ -1249,7 +1583,7 @@ static int run_benchmark(int async_jobs, case ASYNC_NO_JOBS: case ASYNC_ERR: BIO_printf(bio_err, "Failure in the job\n"); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1273,7 +1607,7 @@ static int run_benchmark(int async_jobs, (loopargs[i].wait_ctx, NULL, &num_job_fds) || num_job_fds > 1) { BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1289,7 +1623,7 @@ static int run_benchmark(int async_jobs, "Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). " "Decrease the value of async_jobs\n", max_fd, FD_SETSIZE); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1300,7 +1634,7 @@ static int run_benchmark(int async_jobs, if (select_result == -1) { BIO_printf(bio_err, "Failure in the select\n"); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1317,7 +1651,7 @@ static int run_benchmark(int async_jobs, (loopargs[i].wait_ctx, NULL, &num_job_fds) || num_job_fds > 1) { BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n"); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1355,7 +1689,7 @@ static int run_benchmark(int async_jobs, --num_inprogress; loopargs[i].inprogress_job = NULL; BIO_printf(bio_err, "Failure in the job\n"); - ERR_print_errors(bio_err); + dofail(); error = 1; break; } @@ -1381,7 +1715,7 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) if (ERR_peek_error()) { BIO_printf(bio_err, "WARNING: the error queue contains previous unhandled errors.\n"); - ERR_print_errors(bio_err); + dofail(); } /* @@ -1413,7 +1747,7 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) if (ERR_peek_error()) { BIO_printf(bio_err, "Unhandled error in the error queue during EC key setup.\n"); - ERR_print_errors(bio_err); + dofail(); return NULL; } @@ -1424,7 +1758,7 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) curve->nid) <= 0 || EVP_PKEY_paramgen(pctx, ¶ms) <= 0) { BIO_printf(bio_err, "EC params init failure.\n"); - ERR_print_errors(bio_err); + dofail(); EVP_PKEY_CTX_free(pctx); return NULL; } @@ -1438,7 +1772,7 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) || EVP_PKEY_keygen_init(kctx) <= 0 || EVP_PKEY_keygen(kctx, &key) <= 0) { BIO_printf(bio_err, "EC key generation failure.\n"); - ERR_print_errors(bio_err); + dofail(); key = NULL; } EVP_PKEY_CTX_free(kctx); @@ -1448,8 +1782,103 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve) #define stop_it(do_it, test_num)\ memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num); +/* Checks to see if algorithms are fetchable */ +#define IS_FETCHABLE(type, TYPE) \ + static int is_ ## type ## _fetchable(const TYPE *alg) \ + { \ + TYPE *impl; \ + const char *propq = app_get0_propq(); \ + OSSL_LIB_CTX *libctx = app_get0_libctx(); \ + const char *name = TYPE ## _get0_name(alg); \ + \ + ERR_set_mark(); \ + impl = TYPE ## _fetch(libctx, name, propq); \ + ERR_pop_to_mark(); \ + if (impl == NULL) \ + return 0; \ + TYPE ## _free(impl); \ + return 1; \ + } + +IS_FETCHABLE(signature, EVP_SIGNATURE) +IS_FETCHABLE(kem, EVP_KEM) + +DEFINE_STACK_OF(EVP_KEM) + +static int kems_cmp(const EVP_KEM * const *a, + const EVP_KEM * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*b))); +} + +static void collect_kem(EVP_KEM *kem, void *stack) +{ + STACK_OF(EVP_KEM) *kem_stack = stack; + + if (is_kem_fetchable(kem) + && EVP_KEM_up_ref(kem) + && sk_EVP_KEM_push(kem_stack, kem) <= 0) + EVP_KEM_free(kem); /* up-ref successful but push to stack failed */ +} + +static int kem_locate(const char *algo, unsigned int *idx) +{ + unsigned int i; + + for (i = 0; i < kems_algs_len; i++) { + if (strcmp(kems_algname[i], algo) == 0) { + *idx = i; + return 1; + } + } + return 0; +} + +DEFINE_STACK_OF(EVP_SIGNATURE) + +static int signatures_cmp(const EVP_SIGNATURE * const *a, + const EVP_SIGNATURE * const *b) +{ + return strcmp(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*a)), + OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*b))); +} + +static void collect_signatures(EVP_SIGNATURE *sig, void *stack) +{ + STACK_OF(EVP_SIGNATURE) *sig_stack = stack; + + if (is_signature_fetchable(sig) + && EVP_SIGNATURE_up_ref(sig) + && sk_EVP_SIGNATURE_push(sig_stack, sig) <= 0) + EVP_SIGNATURE_free(sig); /* up-ref successful but push to stack failed */ +} + +static int sig_locate(const char *algo, unsigned int *idx) +{ + unsigned int i; + + for (i = 0; i < sigs_algs_len; i++) { + if (strcmp(sigs_algname[i], algo) == 0) { + *idx = i; + return 1; + } + } + return 0; +} + +static int get_max(const uint8_t doit[], size_t algs_len) { + size_t i = 0; + int maxcnt = 0; + + for (i = 0; i < algs_len; i++) + if (maxcnt < doit[i]) maxcnt = doit[i]; + return maxcnt; +} + int speed_main(int argc, char **argv) { + CONF *conf = NULL; ENGINE *e = NULL; loopargs_t *loopargs = NULL; const char *prog; @@ -1461,11 +1890,15 @@ int speed_main(int argc, char **argv) int async_init = 0, multiblock = 0, pr_header = 0; uint8_t doit[ALGOR_NUM] = { 0 }; int ret = 1, misalign = 0, lengths_single = 0; + STACK_OF(EVP_KEM) *kem_stack = NULL; + STACK_OF(EVP_SIGNATURE) *sig_stack = NULL; long count = 0; unsigned int size_num = SIZE_NUM; unsigned int i, k, loopargs_len = 0, async_jobs = 0; + unsigned int idx; int keylen = 0; int buflen; + size_t declen; BIGNUM *bn = NULL; EVP_PKEY_CTX *genctx = NULL; #ifndef NO_FORK @@ -1475,7 +1908,8 @@ int speed_main(int argc, char **argv) openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS, ECDSA_SECONDS, ECDH_SECONDS, EdDSA_SECONDS, SM2_SECONDS, - FFDH_SECONDS }; + FFDH_SECONDS, KEM_SECONDS, + SIG_SECONDS }; static const unsigned char key32[32] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, @@ -1520,8 +1954,10 @@ int speed_main(int argc, char **argv) uint8_t ffdh_doit[FFDH_NUM] = { 0 }; #endif /* OPENSSL_NO_DH */ - static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 }; +#ifndef OPENSSL_NO_DSA + static const unsigned int dsa_bits[DSA_NUM] = { 1024, 2048 }; uint8_t dsa_doit[DSA_NUM] = { 0 }; +#endif /* OPENSSL_NO_DSA */ /* * We only test over the following curves as they are representative, To * add tests over more curves, simply add the curve NID and curve name to @@ -1555,15 +1991,19 @@ int speed_main(int argc, char **argv) {"brainpoolP384t1", NID_brainpoolP384t1, 384}, {"brainpoolP512r1", NID_brainpoolP512r1, 512}, {"brainpoolP512t1", NID_brainpoolP512t1, 512}, +#ifndef OPENSSL_NO_ECX /* Other and ECDH only ones */ {"X25519", NID_X25519, 253}, {"X448", NID_X448, 448} +#endif }; +#ifndef OPENSSL_NO_ECX static const EC_CURVE ed_curves[EdDSA_NUM] = { /* EdDSA */ {"Ed25519", NID_ED25519, 253, 64}, {"Ed448", NID_ED448, 456, 114} }; +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 static const EC_CURVE sm2_curves[SM2_NUM] = { /* SM2 */ @@ -1573,9 +2013,18 @@ int speed_main(int argc, char **argv) #endif uint8_t ecdsa_doit[ECDSA_NUM] = { 0 }; uint8_t ecdh_doit[EC_NUM] = { 0 }; +#ifndef OPENSSL_NO_ECX uint8_t eddsa_doit[EdDSA_NUM] = { 0 }; +#endif /* OPENSSL_NO_ECX */ - /* checks declarated curves against choices list. */ + uint8_t kems_doit[MAX_KEM_NUM] = { 0 }; + uint8_t sigs_doit[MAX_SIG_NUM] = { 0 }; + + uint8_t do_kems = 0; + uint8_t do_sigs = 0; + + /* checks declared curves against choices list. */ +#ifndef OPENSSL_NO_ECX OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448); OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0); @@ -1584,6 +2033,7 @@ int speed_main(int argc, char **argv) OPENSSL_assert(ec_curves[ECDSA_NUM - 1].nid == NID_brainpoolP512t1); OPENSSL_assert(strcmp(ecdsa_choices[ECDSA_NUM - 1].name, "ecdsabrp512t1") == 0); +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 OPENSSL_assert(sm2_curves[SM2_NUM - 1].nid == NID_sm2); @@ -1656,7 +2106,7 @@ int speed_main(int argc, char **argv) break; case OPT_MULTI: #ifndef NO_FORK - multi = atoi(opt_arg()); + multi = opt_int_arg(); if ((size_t)multi >= SIZE_MAX / sizeof(int)) { BIO_printf(bio_err, "%s: multi argument too large\n", prog); return 0; @@ -1665,15 +2115,18 @@ int speed_main(int argc, char **argv) break; case OPT_ASYNCJOBS: #ifndef OPENSSL_NO_ASYNC - async_jobs = atoi(opt_arg()); + async_jobs = opt_int_arg(); + if (async_jobs > 99999) { + BIO_printf(bio_err, "%s: too many async_jobs\n", prog); + goto opterr; + } if (!ASYNC_is_capable()) { BIO_printf(bio_err, "%s: async_jobs specified but async not supported\n", prog); - goto opterr; - } - if (async_jobs > 99999) { - BIO_printf(bio_err, "%s: too many async_jobs\n", prog); + if (testmode) + /* Return success in the testmode. */ + return 0; goto opterr; } #endif @@ -1706,25 +2159,149 @@ int speed_main(int argc, char **argv) if (!opt_provider(o)) goto end; break; + case OPT_CONFIG: + conf = app_load_config_modules(opt_arg()); + if (conf == NULL) + goto end; + break; case OPT_PRIMES: primes = opt_int_arg(); break; case OPT_SECONDS: seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa = seconds.ecdh = seconds.eddsa - = seconds.sm2 = seconds.ffdh = atoi(opt_arg()); + = seconds.sm2 = seconds.ffdh + = seconds.kem = seconds.sig = opt_int_arg(); break; case OPT_BYTES: - lengths_single = atoi(opt_arg()); + lengths_single = opt_int_arg(); lengths = &lengths_single; size_num = 1; break; case OPT_AEAD: aead = 1; break; + case OPT_KEM: + do_kems = 1; + break; + case OPT_SIG: + do_sigs = 1; + break; + case OPT_MLOCK: + domlock = 1; +#if !defined(_WIN32) && !defined(OPENSSL_SYS_LINUX) + BIO_printf(bio_err, + "%s: -mlock not supported on this platform\n", + prog); + goto end; +#endif + break; + case OPT_TESTMODE: + testmode = 1; + break; } } + /* find all KEMs currently available */ + kem_stack = sk_EVP_KEM_new(kems_cmp); + EVP_KEM_do_all_provided(app_get0_libctx(), collect_kem, kem_stack); + + kems_algs_len = 0; + + for (idx = 0; idx < (unsigned int)sk_EVP_KEM_num(kem_stack); idx++) { + EVP_KEM *kem = sk_EVP_KEM_value(kem_stack, idx); + + if (strcmp(EVP_KEM_get0_name(kem), "RSA") == 0) { + if (kems_algs_len + OSSL_NELEM(rsa_choices) >= MAX_KEM_NUM) { + BIO_printf(bio_err, + "Too many KEMs registered. Change MAX_KEM_NUM.\n"); + goto end; + } + for (i = 0; i < OSSL_NELEM(rsa_choices); i++) { + kems_doit[kems_algs_len] = 1; + kems_algname[kems_algs_len++] = OPENSSL_strdup(rsa_choices[i].name); + } + } else if (strcmp(EVP_KEM_get0_name(kem), "EC") == 0) { + if (kems_algs_len + 3 >= MAX_KEM_NUM) { + BIO_printf(bio_err, + "Too many KEMs registered. Change MAX_KEM_NUM.\n"); + goto end; + } + kems_doit[kems_algs_len] = 1; + kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-256"); + kems_doit[kems_algs_len] = 1; + kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-384"); + kems_doit[kems_algs_len] = 1; + kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-521"); + } else { + if (kems_algs_len + 1 >= MAX_KEM_NUM) { + BIO_printf(bio_err, + "Too many KEMs registered. Change MAX_KEM_NUM.\n"); + goto end; + } + kems_doit[kems_algs_len] = 1; + kems_algname[kems_algs_len++] = OPENSSL_strdup(EVP_KEM_get0_name(kem)); + } + } + sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free); + kem_stack = NULL; + + /* find all SIGNATUREs currently available */ + sig_stack = sk_EVP_SIGNATURE_new(signatures_cmp); + EVP_SIGNATURE_do_all_provided(app_get0_libctx(), collect_signatures, sig_stack); + + sigs_algs_len = 0; + + for (idx = 0; idx < (unsigned int)sk_EVP_SIGNATURE_num(sig_stack); idx++) { + EVP_SIGNATURE *s = sk_EVP_SIGNATURE_value(sig_stack, idx); + const char *sig_name = EVP_SIGNATURE_get0_name(s); + + if (strcmp(sig_name, "RSA") == 0) { + if (sigs_algs_len + OSSL_NELEM(rsa_choices) >= MAX_SIG_NUM) { + BIO_printf(bio_err, + "Too many signatures registered. Change MAX_SIG_NUM.\n"); + goto end; + } + for (i = 0; i < OSSL_NELEM(rsa_choices); i++) { + sigs_doit[sigs_algs_len] = 1; + sigs_algname[sigs_algs_len++] = OPENSSL_strdup(rsa_choices[i].name); + } + } +#ifndef OPENSSL_NO_DSA + else if (strcmp(sig_name, "DSA") == 0) { + if (sigs_algs_len + DSA_NUM >= MAX_SIG_NUM) { + BIO_printf(bio_err, + "Too many signatures registered. Change MAX_SIG_NUM.\n"); + goto end; + } + for (i = 0; i < DSA_NUM; i++) { + sigs_doit[sigs_algs_len] = 1; + sigs_algname[sigs_algs_len++] = OPENSSL_strdup(dsa_choices[i].name); + } + } +#endif /* OPENSSL_NO_DSA */ + /* skipping these algs as tested elsewhere - and b/o setup is a pain */ + else if (strcmp(sig_name, "ED25519") && + strcmp(sig_name, "ED448") && + strcmp(sig_name, "ECDSA") && + strcmp(sig_name, "HMAC") && + strcmp(sig_name, "SIPHASH") && + strcmp(sig_name, "POLY1305") && + strcmp(sig_name, "CMAC") && + strcmp(sig_name, "SM2")) { /* skip alg */ + if (sigs_algs_len + 1 >= MAX_SIG_NUM) { + BIO_printf(bio_err, + "Too many signatures registered. Change MAX_SIG_NUM.\n"); + goto end; + } + /* activate this provider algorithm */ + sigs_doit[sigs_algs_len] = 1; + sigs_algname[sigs_algs_len++] = OPENSSL_strdup(sig_name); + } + } + sk_EVP_SIGNATURE_pop_free(sig_stack, EVP_SIGNATURE_free); + sig_stack = NULL; + /* Remaining arguments are algorithms. */ argc = opt_num_rest(); argv = opt_rest(); @@ -1734,103 +2311,129 @@ int speed_main(int argc, char **argv) for (; *argv; argv++) { const char *algo = *argv; + int algo_found = 0; if (opt_found(algo, doit_choices, &i)) { doit[i] = 1; - continue; + algo_found = 1; } if (strcmp(algo, "des") == 0) { doit[D_CBC_DES] = doit[D_EDE3_DES] = 1; - continue; + algo_found = 1; } if (strcmp(algo, "sha") == 0) { doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1; - continue; + algo_found = 1; } #ifndef OPENSSL_NO_DEPRECATED_3_0 if (strcmp(algo, "openssl") == 0) /* just for compatibility */ - continue; + algo_found = 1; #endif - if (strncmp(algo, "rsa", 3) == 0) { - if (algo[3] == '\0') { + if (HAS_PREFIX(algo, "rsa")) { + if (algo[sizeof("rsa") - 1] == '\0') { memset(rsa_doit, 1, sizeof(rsa_doit)); - continue; + algo_found = 1; } if (opt_found(algo, rsa_choices, &i)) { rsa_doit[i] = 1; - continue; + algo_found = 1; } } #ifndef OPENSSL_NO_DH - if (strncmp(algo, "ffdh", 4) == 0) { - if (algo[4] == '\0') { + if (HAS_PREFIX(algo, "ffdh")) { + if (algo[sizeof("ffdh") - 1] == '\0') { memset(ffdh_doit, 1, sizeof(ffdh_doit)); - continue; + algo_found = 1; } if (opt_found(algo, ffdh_choices, &i)) { ffdh_doit[i] = 2; - continue; + algo_found = 1; } } #endif - if (strncmp(algo, "dsa", 3) == 0) { - if (algo[3] == '\0') { +#ifndef OPENSSL_NO_DSA + if (HAS_PREFIX(algo, "dsa")) { + if (algo[sizeof("dsa") - 1] == '\0') { memset(dsa_doit, 1, sizeof(dsa_doit)); - continue; + algo_found = 1; } if (opt_found(algo, dsa_choices, &i)) { dsa_doit[i] = 2; - continue; + algo_found = 1; } } +#endif if (strcmp(algo, "aes") == 0) { doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1; - continue; + algo_found = 1; } if (strcmp(algo, "camellia") == 0) { doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1; - continue; + algo_found = 1; } - if (strncmp(algo, "ecdsa", 5) == 0) { - if (algo[5] == '\0') { + if (HAS_PREFIX(algo, "ecdsa")) { + if (algo[sizeof("ecdsa") - 1] == '\0') { memset(ecdsa_doit, 1, sizeof(ecdsa_doit)); - continue; + algo_found = 1; } if (opt_found(algo, ecdsa_choices, &i)) { ecdsa_doit[i] = 2; - continue; + algo_found = 1; } } - if (strncmp(algo, "ecdh", 4) == 0) { - if (algo[4] == '\0') { + if (HAS_PREFIX(algo, "ecdh")) { + if (algo[sizeof("ecdh") - 1] == '\0') { memset(ecdh_doit, 1, sizeof(ecdh_doit)); - continue; + algo_found = 1; } if (opt_found(algo, ecdh_choices, &i)) { ecdh_doit[i] = 2; - continue; + algo_found = 1; } } +#ifndef OPENSSL_NO_ECX if (strcmp(algo, "eddsa") == 0) { memset(eddsa_doit, 1, sizeof(eddsa_doit)); - continue; + algo_found = 1; } if (opt_found(algo, eddsa_choices, &i)) { eddsa_doit[i] = 2; - continue; + algo_found = 1; } +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 if (strcmp(algo, "sm2") == 0) { memset(sm2_doit, 1, sizeof(sm2_doit)); - continue; + algo_found = 1; } if (opt_found(algo, sm2_choices, &i)) { sm2_doit[i] = 2; - continue; + algo_found = 1; } #endif - BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo); - goto end; + if (kem_locate(algo, &idx)) { + kems_doit[idx]++; + do_kems = 1; + algo_found = 1; + } + if (sig_locate(algo, &idx)) { + sigs_doit[idx]++; + do_sigs = 1; + algo_found = 1; + } + if (strcmp(algo, "kmac") == 0) { + doit[D_KMAC128] = doit[D_KMAC256] = 1; + algo_found = 1; + } + if (strcmp(algo, "cmac") == 0) { + doit[D_EVP_CMAC] = 1; + algo_found = 1; + } + + if (!algo_found) { + BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo); + goto end; + } } /* Sanity checks */ @@ -1845,6 +2448,28 @@ int speed_main(int argc, char **argv) goto end; } } + if (kems_algs_len > 0) { + int maxcnt = get_max(kems_doit, kems_algs_len); + + if (maxcnt > 1) { + /* some algs explicitly selected */ + for (i = 0; i < kems_algs_len; i++) { + /* disable the rest */ + kems_doit[i]--; + } + } + } + if (sigs_algs_len > 0) { + int maxcnt = get_max(sigs_doit, sigs_algs_len); + + if (maxcnt > 1) { + /* some algs explicitly selected */ + for (i = 0; i < sigs_algs_len; i++) { + /* disable the rest */ + sigs_doit[i]--; + } + } + } if (multiblock) { if (evp_cipher == NULL) { BIO_printf(bio_err, "-mb can be used only with a multi-block" @@ -1875,6 +2500,14 @@ int speed_main(int argc, char **argv) app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs"); memset(loopargs, 0, loopargs_len * sizeof(loopargs_t)); + buflen = lengths[size_num - 1]; + if (buflen < 36) /* size of random vector in RSA benchmark */ + buflen = 36; + if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) { + BIO_printf(bio_err, "Error: buffer size too large\n"); + goto end; + } + buflen += MAX_MISALIGNMENT + 1; for (i = 0; i < loopargs_len; i++) { if (async_jobs > 0) { loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new(); @@ -1884,18 +2517,8 @@ int speed_main(int argc, char **argv) } } - buflen = lengths[size_num - 1]; - if (buflen < 36) /* size of random vector in RSA benchmark */ - buflen = 36; - if (INT_MAX - (MAX_MISALIGNMENT + 1) < buflen) { - BIO_printf(bio_err, "Error: buffer size too large\n"); - goto end; - } - buflen += MAX_MISALIGNMENT + 1; loopargs[i].buf_malloc = app_malloc(buflen, "input buffer"); loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer"); - memset(loopargs[i].buf_malloc, 0, buflen); - memset(loopargs[i].buf2_malloc, 0, buflen); /* Align the start of buffers on a 64 byte boundary */ loopargs[i].buf = loopargs[i].buf_malloc + misalign; @@ -1915,11 +2538,26 @@ int speed_main(int argc, char **argv) goto show_res; #endif + for (i = 0; i < loopargs_len; ++i) { + if (domlock) { +#if defined(_WIN32) + (void)VirtualLock(loopargs[i].buf_malloc, buflen); + (void)VirtualLock(loopargs[i].buf2_malloc, buflen); +#elif defined(OPENSSL_SYS_LINUX) + (void)mlock(loopargs[i].buf_malloc, buflen); + (void)mlock(loopargs[i].buf_malloc, buflen); +#endif + } + memset(loopargs[i].buf_malloc, 0, buflen); + memset(loopargs[i].buf2_malloc, 0, buflen); + } + /* Initialize the engine after the fork */ e = setup_engine(engine_id, 0); /* No parameters; turn on everything. */ - if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) { + if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] + && !doit[D_EVP_CMAC] && !do_kems && !do_sigs) { memset(doit, 1, sizeof(doit)); doit[D_EVP] = doit[D_EVP_CMAC] = 0; ERR_set_mark(); @@ -1950,13 +2588,21 @@ int speed_main(int argc, char **argv) #ifndef OPENSSL_NO_DH memset(ffdh_doit, 1, sizeof(ffdh_doit)); #endif +#ifndef OPENSSL_NO_DSA memset(dsa_doit, 1, sizeof(dsa_doit)); +#endif +#ifndef OPENSSL_NO_ECX memset(ecdsa_doit, 1, sizeof(ecdsa_doit)); memset(ecdh_doit, 1, sizeof(ecdh_doit)); memset(eddsa_doit, 1, sizeof(eddsa_doit)); +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 memset(sm2_doit, 1, sizeof(sm2_doit)); #endif + memset(kems_doit, 1, sizeof(kems_doit)); + do_kems = 1; + memset(sigs_doit, 1, sizeof(sigs_doit)); + do_sigs = 1; } for (i = 0; i < ALGOR_NUM; i++) if (doit[i]) @@ -1973,8 +2619,7 @@ int speed_main(int argc, char **argv) if (doit[D_MD2]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_MD2], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs); d = Time_F(STOP); @@ -1986,8 +2631,7 @@ int speed_main(int argc, char **argv) if (doit[D_MDC2]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_MDC2], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs); d = Time_F(STOP); @@ -1999,8 +2643,7 @@ int speed_main(int argc, char **argv) if (doit[D_MD4]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_MD4], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs); d = Time_F(STOP); @@ -2012,8 +2655,7 @@ int speed_main(int argc, char **argv) if (doit[D_MD5]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_MD5], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, MD5_loop, loopargs); d = Time_F(STOP); @@ -2025,8 +2667,7 @@ int speed_main(int argc, char **argv) if (doit[D_SHA1]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_SHA1], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, SHA1_loop, loopargs); d = Time_F(STOP); @@ -2038,8 +2679,7 @@ int speed_main(int argc, char **argv) if (doit[D_SHA256]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_SHA256], c[D_SHA256][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_SHA256], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, SHA256_loop, loopargs); d = Time_F(STOP); @@ -2051,8 +2691,7 @@ int speed_main(int argc, char **argv) if (doit[D_SHA512]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_SHA512], c[D_SHA512][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_SHA512], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, SHA512_loop, loopargs); d = Time_F(STOP); @@ -2064,8 +2703,7 @@ int speed_main(int argc, char **argv) if (doit[D_WHIRLPOOL]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_WHIRLPOOL], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs); d = Time_F(STOP); @@ -2077,8 +2715,7 @@ int speed_main(int argc, char **argv) if (doit[D_RMD160]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_RMD160], c[D_RMD160][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_RMD160], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs); d = Time_F(STOP); @@ -2094,8 +2731,7 @@ int speed_main(int argc, char **argv) size_t hmac_name_len = sizeof("hmac()") + strlen(evp_mac_mdname); OSSL_PARAM params[3]; - mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq()); - if (mac == NULL || evp_mac_mdname == NULL) + if (evp_mac_mdname == NULL) goto end; evp_hmac_name = app_malloc(hmac_name_len, "HMAC name"); BIO_snprintf(evp_hmac_name, hmac_name_len, "hmac(%s)", evp_mac_mdname); @@ -2109,17 +2745,10 @@ int speed_main(int argc, char **argv) (char *)hmac_key, len); params[2] = OSSL_PARAM_construct_end(); - for (i = 0; i < loopargs_len; i++) { - loopargs[i].mctx = EVP_MAC_CTX_new(mac); - if (loopargs[i].mctx == NULL) - goto end; - - if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) - goto skip_hmac; /* Digest not found */ - } + if (mac_setup("HMAC", &mac, params, loopargs, loopargs_len) < 1) + goto end; for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_HMAC], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, HMAC_loop, loopargs); d = Time_F(STOP); @@ -2127,12 +2756,9 @@ int speed_main(int argc, char **argv) if (count < 0) break; } - for (i = 0; i < loopargs_len; i++) - EVP_MAC_CTX_free(loopargs[i].mctx); - EVP_MAC_free(mac); - mac = NULL; + mac_teardown(&mac, loopargs, loopargs_len); } -skip_hmac: + if (doit[D_CBC_DES]) { int st = 1; @@ -2143,8 +2769,9 @@ skip_hmac: } algindex = D_CBC_DES; for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[D_CBC_DES], c[D_CBC_DES][testnum], - lengths[testnum], seconds.sym); + if (!check_block_size(loopargs[0].ctx, lengths[testnum])) + break; + print_message(names[D_CBC_DES], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); d = Time_F(STOP); @@ -2164,8 +2791,9 @@ skip_hmac: } algindex = D_EDE3_DES; for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum], - lengths[testnum], seconds.sym); + if (!check_block_size(loopargs[0].ctx, lengths[testnum])) + break; + print_message(names[D_EDE3_DES], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); @@ -2189,8 +2817,9 @@ skip_hmac: } for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[algindex], c[algindex][testnum], - lengths[testnum], seconds.sym); + if (!check_block_size(loopargs[0].ctx, lengths[testnum])) + break; + print_message(names[algindex], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); @@ -2215,8 +2844,9 @@ skip_hmac: } for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[algindex], c[algindex][testnum], - lengths[testnum], seconds.sym); + if (!check_block_size(loopargs[0].ctx, lengths[testnum])) + break; + print_message(names[algindex], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); @@ -2240,8 +2870,9 @@ skip_hmac: } for (testnum = 0; st && testnum < size_num; testnum++) { - print_message(names[algindex], c[algindex][testnum], - lengths[testnum], seconds.sym); + if (!check_block_size(loopargs[0].ctx, lengths[testnum])) + break; + print_message(names[algindex], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Cipher_loop, loopargs); @@ -2254,30 +2885,26 @@ skip_hmac: } if (doit[D_GHASH]) { static const char gmac_iv[] = "0123456789ab"; - OSSL_PARAM params[3]; - - mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq()); - if (mac == NULL) - goto end; + OSSL_PARAM params[4]; params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER, "aes-128-gcm", 0); params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV, (char *)gmac_iv, sizeof(gmac_iv) - 1); - params[2] = OSSL_PARAM_construct_end(); + params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)key32, 16); + params[3] = OSSL_PARAM_construct_end(); + if (mac_setup("GMAC", &mac, params, loopargs, loopargs_len) < 1) + goto end; + /* b/c of the definition of GHASH_loop(), init() calls are needed here */ for (i = 0; i < loopargs_len; i++) { - loopargs[i].mctx = EVP_MAC_CTX_new(mac); - if (loopargs[i].mctx == NULL) - goto end; - - if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params)) + if (!EVP_MAC_init(loopargs[i].mctx, NULL, 0, NULL)) goto end; } for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_GHASH], c[D_GHASH][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_GHASH], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, GHASH_loop, loopargs); d = Time_F(STOP); @@ -2285,16 +2912,12 @@ skip_hmac: if (count < 0) break; } - for (i = 0; i < loopargs_len; i++) - EVP_MAC_CTX_free(loopargs[i].mctx); - EVP_MAC_free(mac); - mac = NULL; + mac_teardown(&mac, loopargs, loopargs_len); } if (doit[D_RAND]) { for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_RAND], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs); d = Time_F(STOP); @@ -2334,7 +2957,8 @@ skip_hmac: if (mode_op == EVP_CIPH_GCM_MODE || mode_op == EVP_CIPH_CCM_MODE || mode_op == EVP_CIPH_OCB_MODE - || mode_op == EVP_CIPH_SIV_MODE) { + || mode_op == EVP_CIPH_SIV_MODE + || mode_op == EVP_CIPH_GCM_SIV_MODE) { ae_mode = 1; if (decrypt) loopfunc = EVP_Update_loop_aead_dec; @@ -2345,8 +2969,7 @@ skip_hmac: } for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_EVP], lengths[testnum], seconds.sym); for (k = 0; k < loopargs_len; k++) { loopargs[k].ctx = EVP_CIPHER_CTX_new(); @@ -2361,11 +2984,10 @@ skip_hmac: * encrypt first, we won't have a valid tag that enables * authenticity and hence decryption will fail. */ - if (!EVP_CipherInit_ex(loopargs[k].ctx, - evp_cipher, NULL, NULL, NULL, - ae_mode ? 1 : !decrypt)) { + if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, + NULL, NULL, ae_mode ? 1 : !decrypt)) { BIO_printf(bio_err, "\nCouldn't init the context\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } @@ -2380,10 +3002,11 @@ skip_hmac: if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, loopargs[k].key, iv, -1)) { BIO_printf(bio_err, "\nFailed to set the key\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } - } else if (mode_op == EVP_CIPH_SIV_MODE) { + } else if (mode_op == EVP_CIPH_SIV_MODE + || mode_op == EVP_CIPH_GCM_SIV_MODE) { EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, EVP_CTRL_SET_SPEED, 1, NULL); } @@ -2392,28 +3015,29 @@ skip_hmac: if (mode_op != EVP_CIPH_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, EVP_CTRL_AEAD_SET_IVLEN, - aead_ivlen, NULL)) { + sizeof(aead_iv), NULL)) { BIO_printf(bio_err, "\nFailed to set iv length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } - /* Set tag_len (Not for SIV at encryption stage) */ + /* Set tag_len (Not for GCM/SIV at encryption stage) */ if (mode_op != EVP_CIPH_GCM_MODE - && mode_op != EVP_CIPH_SIV_MODE) { + && mode_op != EVP_CIPH_SIV_MODE + && mode_op != EVP_CIPH_GCM_SIV_MODE) { if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, EVP_CTRL_AEAD_SET_TAG, TAG_LEN, NULL)) { BIO_printf(bio_err, "\nFailed to set tag length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, loopargs[k].key, aead_iv, -1)) { BIO_printf(bio_err, "\nFailed to set the key\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } /* Set total length of input. Only required for CCM */ @@ -2423,7 +3047,7 @@ skip_hmac: lengths[testnum])) { BIO_printf(bio_err, "\nCouldn't set input text length\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } @@ -2432,7 +3056,7 @@ skip_hmac: &outlen, aad, sizeof(aad))) { BIO_printf(bio_err, "\nCouldn't insert AAD when encrypting\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } } @@ -2441,7 +3065,7 @@ skip_hmac: lengths[testnum])) { BIO_printf(bio_err, "\nFailed to to encrypt the data\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } @@ -2449,15 +3073,14 @@ skip_hmac: loopargs[k].buf, &outlen)) { BIO_printf(bio_err, "\nFailed finalize the encryption\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } - if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, - EVP_CTRL_AEAD_GET_TAG, + if (!EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, EVP_CTRL_AEAD_GET_TAG, TAG_LEN, &loopargs[k].tag)) { BIO_printf(bio_err, "\nFailed to get the tag\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } @@ -2472,14 +3095,15 @@ skip_hmac: NULL, NULL, NULL, 0)) { BIO_printf(bio_err, "\nFailed initializing the context\n"); - ERR_print_errors(bio_err); + dofail(); exit(1); } EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0); - /* SIV only allows for one Update operation */ - if (mode_op == EVP_CIPH_SIV_MODE) + /* GCM-SIV/SIV only allows for a single Update operation */ + if (mode_op == EVP_CIPH_SIV_MODE + || mode_op == EVP_CIPH_GCM_SIV_MODE) EVP_CIPHER_CTX_ctrl(loopargs[k].ctx, EVP_CTRL_SET_SPEED, 1, NULL); } @@ -2498,8 +3122,7 @@ skip_hmac: names[D_EVP] = evp_md_name; for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_EVP], c[D_EVP][testnum], lengths[testnum], - seconds.sym); + print_message(names[D_EVP], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, EVP_Digest_md_loop, loopargs); d = Time_F(STOP); @@ -2515,9 +3138,6 @@ skip_hmac: OSSL_PARAM params[3]; EVP_CIPHER *cipher = NULL; - mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq()); - if (mac == NULL || evp_mac_ciphername == NULL) - goto end; if (!opt_cipher(evp_mac_ciphername, &cipher)) goto end; @@ -2537,18 +3157,10 @@ skip_hmac: (char *)key32, keylen); params[2] = OSSL_PARAM_construct_end(); - for (i = 0; i < loopargs_len; i++) { - loopargs[i].mctx = EVP_MAC_CTX_new(mac); - if (loopargs[i].mctx == NULL) - goto end; - - if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) - goto end; - } - + if (mac_setup("CMAC", &mac, params, loopargs, loopargs_len) < 1) + goto end; for (testnum = 0; testnum < size_num; testnum++) { - print_message(names[D_EVP_CMAC], c[D_EVP_CMAC][testnum], - lengths[testnum], seconds.sym); + print_message(names[D_EVP_CMAC], lengths[testnum], seconds.sym); Time_F(START); count = run_benchmark(async_jobs, CMAC_loop, loopargs); d = Time_F(STOP); @@ -2556,10 +3168,49 @@ skip_hmac: if (count < 0) break; } - for (i = 0; i < loopargs_len; i++) - EVP_MAC_CTX_free(loopargs[i].mctx); - EVP_MAC_free(mac); - mac = NULL; + mac_teardown(&mac, loopargs, loopargs_len); + } + + if (doit[D_KMAC128]) { + OSSL_PARAM params[2]; + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)key32, 16); + params[1] = OSSL_PARAM_construct_end(); + + if (mac_setup("KMAC-128", &mac, params, loopargs, loopargs_len) < 1) + goto end; + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_KMAC128], lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, KMAC128_loop, loopargs); + d = Time_F(STOP); + print_result(D_KMAC128, testnum, count, d); + if (count < 0) + break; + } + mac_teardown(&mac, loopargs, loopargs_len); + } + + if (doit[D_KMAC256]) { + OSSL_PARAM params[2]; + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)key32, 32); + params[1] = OSSL_PARAM_construct_end(); + + if (mac_setup("KMAC-256", &mac, params, loopargs, loopargs_len) < 1) + goto end; + for (testnum = 0; testnum < size_num; testnum++) { + print_message(names[D_KMAC256], lengths[testnum], seconds.sym); + Time_F(START); + count = run_benchmark(async_jobs, KMAC256_loop, loopargs); + d = Time_F(STOP); + print_result(D_KMAC256, testnum, count, d); + if (count < 0) + break; + } + mac_teardown(&mac, loopargs, loopargs_len); } for (i = 0; i < loopargs_len; i++) @@ -2582,7 +3233,7 @@ skip_hmac: && EVP_PKEY_CTX_set_rsa_keygen_bits(genctx, rsa_keys[testnum].bits) > 0 && EVP_PKEY_CTX_set1_rsa_keygen_pubexp(genctx, bn) > 0 && EVP_PKEY_CTX_set_rsa_keygen_primes(genctx, primes) > 0 - && EVP_PKEY_keygen(genctx, &rsa_key); + && EVP_PKEY_keygen(genctx, &rsa_key) > 0; BN_free(bn); bn = NULL; EVP_PKEY_CTX_free(genctx); @@ -2608,19 +3259,18 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "RSA sign setup failure. No RSA sign will be done.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { - pkey_print_message("private", "rsa", - rsa_c[testnum][0], rsa_keys[testnum].bits, - seconds.rsa); + pkey_print_message("private", "rsa sign", + rsa_keys[testnum].bits, seconds.rsa); /* RSA_blinding_on(rsa_key[testnum],NULL); */ Time_F(START); count = run_benchmark(async_jobs, RSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R1:%ld:%d:%.2f\n" - : "%ld %u bits private RSA's in %.2fs\n", + : "%ld %u bits private RSA sign ops in %.2fs\n", count, rsa_keys[testnum].bits, d); rsa_results[testnum][0] = (double)count / d; op_count = count; @@ -2640,22 +3290,84 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "RSA verify setup failure. No RSA verify will be done.\n"); - ERR_print_errors(bio_err); + dofail(); rsa_doit[testnum] = 0; } else { - pkey_print_message("public", "rsa", - rsa_c[testnum][1], rsa_keys[testnum].bits, - seconds.rsa); + pkey_print_message("public", "rsa verify", + rsa_keys[testnum].bits, seconds.rsa); Time_F(START); count = run_benchmark(async_jobs, RSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R2:%ld:%d:%.2f\n" - : "%ld %u bits public RSA's in %.2fs\n", + : "%ld %u bits public RSA verify ops in %.2fs\n", count, rsa_keys[testnum].bits, d); rsa_results[testnum][1] = (double)count / d; } + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].rsa_encrypt_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL); + loopargs[i].encsize = loopargs[i].buflen; + if (loopargs[i].rsa_encrypt_ctx[testnum] == NULL + || EVP_PKEY_encrypt_init(loopargs[i].rsa_encrypt_ctx[testnum]) <= 0 + || EVP_PKEY_encrypt(loopargs[i].rsa_encrypt_ctx[testnum], + loopargs[i].buf2, + &loopargs[i].encsize, + loopargs[i].buf, 36) <= 0) + st = 0; + } + if (!st) { + BIO_printf(bio_err, + "RSA encrypt setup failure. No RSA encrypt will be done.\n"); + dofail(); + op_count = 1; + } else { + pkey_print_message("public", "rsa encrypt", + rsa_keys[testnum].bits, seconds.rsa); + /* RSA_blinding_on(rsa_key[testnum],NULL); */ + Time_F(START); + count = run_benchmark(async_jobs, RSA_encrypt_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R3:%ld:%d:%.2f\n" + : "%ld %u bits public RSA encrypt ops in %.2fs\n", + count, rsa_keys[testnum].bits, d); + rsa_results[testnum][2] = (double)count / d; + op_count = count; + } + + for (i = 0; st && i < loopargs_len; i++) { + loopargs[i].rsa_decrypt_ctx[testnum] = EVP_PKEY_CTX_new(rsa_key, NULL); + declen = loopargs[i].buflen; + if (loopargs[i].rsa_decrypt_ctx[testnum] == NULL + || EVP_PKEY_decrypt_init(loopargs[i].rsa_decrypt_ctx[testnum]) <= 0 + || EVP_PKEY_decrypt(loopargs[i].rsa_decrypt_ctx[testnum], + loopargs[i].buf, + &declen, + loopargs[i].buf2, + loopargs[i].encsize) <= 0) + st = 0; + } + if (!st) { + BIO_printf(bio_err, + "RSA decrypt setup failure. No RSA decrypt will be done.\n"); + dofail(); + op_count = 1; + } else { + pkey_print_message("private", "rsa decrypt", + rsa_keys[testnum].bits, seconds.rsa); + /* RSA_blinding_on(rsa_key[testnum],NULL); */ + Time_F(START); + count = run_benchmark(async_jobs, RSA_decrypt_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R4:%ld:%d:%.2f\n" + : "%ld %u bits private RSA decrypt ops in %.2fs\n", + count, rsa_keys[testnum].bits, d); + rsa_results[testnum][3] = (double)count / d; + op_count = count; + } + if (op_count <= 1) { /* if longer than 10s, don't do any more */ stop_it(rsa_doit, testnum); @@ -2663,6 +3375,7 @@ skip_hmac: EVP_PKEY_free(rsa_key); } +#ifndef OPENSSL_NO_DSA for (testnum = 0; testnum < DSA_NUM; testnum++) { EVP_PKEY *dsa_key = NULL; int st; @@ -2678,7 +3391,6 @@ skip_hmac: loopargs[i].sigsize = loopargs[i].buflen; if (loopargs[i].dsa_sign_ctx[testnum] == NULL || EVP_PKEY_sign_init(loopargs[i].dsa_sign_ctx[testnum]) <= 0 - || EVP_PKEY_sign(loopargs[i].dsa_sign_ctx[testnum], loopargs[i].buf2, &loopargs[i].sigsize, @@ -2688,18 +3400,17 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "DSA sign setup failure. No DSA sign will be done.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { pkey_print_message("sign", "dsa", - dsa_c[testnum][0], dsa_bits[testnum], - seconds.dsa); + dsa_bits[testnum], seconds.dsa); Time_F(START); count = run_benchmark(async_jobs, DSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R3:%ld:%u:%.2f\n" - : "%ld %u bits DSA signs in %.2fs\n", + mr ? "+R5:%ld:%u:%.2f\n" + : "%ld %u bits DSA sign ops in %.2fs\n", count, dsa_bits[testnum], d); dsa_results[testnum][0] = (double)count / d; op_count = count; @@ -2719,18 +3430,17 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "DSA verify setup failure. No DSA verify will be done.\n"); - ERR_print_errors(bio_err); + dofail(); dsa_doit[testnum] = 0; } else { pkey_print_message("verify", "dsa", - dsa_c[testnum][1], dsa_bits[testnum], - seconds.dsa); + dsa_bits[testnum], seconds.dsa); Time_F(START); count = run_benchmark(async_jobs, DSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R4:%ld:%u:%.2f\n" - : "%ld %u bits DSA verify in %.2fs\n", + mr ? "+R6:%ld:%u:%.2f\n" + : "%ld %u bits DSA verify ops in %.2fs\n", count, dsa_bits[testnum], d); dsa_results[testnum][1] = (double)count / d; } @@ -2741,6 +3451,7 @@ skip_hmac: } EVP_PKEY_free(dsa_key); } +#endif /* OPENSSL_NO_DSA */ for (testnum = 0; testnum < ECDSA_NUM; testnum++) { EVP_PKEY *ecdsa_key = NULL; @@ -2757,7 +3468,6 @@ skip_hmac: loopargs[i].sigsize = loopargs[i].buflen; if (loopargs[i].ecdsa_sign_ctx[testnum] == NULL || EVP_PKEY_sign_init(loopargs[i].ecdsa_sign_ctx[testnum]) <= 0 - || EVP_PKEY_sign(loopargs[i].ecdsa_sign_ctx[testnum], loopargs[i].buf2, &loopargs[i].sigsize, @@ -2767,18 +3477,17 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "ECDSA sign setup failure. No ECDSA sign will be done.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { pkey_print_message("sign", "ecdsa", - ecdsa_c[testnum][0], ec_curves[testnum].bits, - seconds.ecdsa); + ec_curves[testnum].bits, seconds.ecdsa); Time_F(START); count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R5:%ld:%u:%.2f\n" - : "%ld %u bits ECDSA signs in %.2fs\n", + mr ? "+R7:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA sign ops in %.2fs\n", count, ec_curves[testnum].bits, d); ecdsa_results[testnum][0] = (double)count / d; op_count = count; @@ -2798,18 +3507,17 @@ skip_hmac: if (!st) { BIO_printf(bio_err, "ECDSA verify setup failure. No ECDSA verify will be done.\n"); - ERR_print_errors(bio_err); + dofail(); ecdsa_doit[testnum] = 0; } else { pkey_print_message("verify", "ecdsa", - ecdsa_c[testnum][1], ec_curves[testnum].bits, - seconds.ecdsa); + ec_curves[testnum].bits, seconds.ecdsa); Time_F(START); count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R6:%ld:%u:%.2f\n" - : "%ld %u bits ECDSA verify in %.2fs\n", + mr ? "+R8:%ld:%u:%.2f\n" + : "%ld %u bits ECDSA verify ops in %.2fs\n", count, ec_curves[testnum].bits, d); ecdsa_results[testnum][1] = (double)count / d; } @@ -2818,6 +3526,7 @@ skip_hmac: /* if longer than 10s, don't do any more */ stop_it(ecdsa_doit, testnum); } + EVP_PKEY_free(ecdsa_key); } for (testnum = 0; testnum < EC_NUM; testnum++) { @@ -2844,7 +3553,7 @@ skip_hmac: || outlen > MAX_ECDH_SIZE /* avoid buffer overflow */) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH key generation failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; break; } @@ -2864,7 +3573,7 @@ skip_hmac: || test_outlen != outlen /* compare output length */) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH computation failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; break; } @@ -2874,7 +3583,7 @@ skip_hmac: loopargs[i].secret_b, outlen)) { ecdh_checks = 0; BIO_printf(bio_err, "ECDH computations don't match.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; break; } @@ -2889,14 +3598,13 @@ skip_hmac: } if (ecdh_checks != 0) { pkey_print_message("", "ecdh", - ecdh_c[testnum][0], ec_curves[testnum].bits, seconds.ecdh); Time_F(START); count = run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R7:%ld:%d:%.2f\n" : + mr ? "+R9:%ld:%d:%.2f\n" : "%ld %u-bits ECDH ops in %.2fs\n", count, ec_curves[testnum].bits, d); ecdh_results[testnum][0] = (double)count / d; @@ -2909,6 +3617,7 @@ skip_hmac: } } +#ifndef OPENSSL_NO_ECX for (testnum = 0; testnum < EdDSA_NUM; testnum++) { int st = 1; EVP_PKEY *ed_pkey = NULL; @@ -2956,7 +3665,7 @@ skip_hmac: } if (st == 0) { BIO_printf(bio_err, "EdDSA failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { for (i = 0; i < loopargs_len; i++) { @@ -2971,19 +3680,18 @@ skip_hmac: if (st == 0) { BIO_printf(bio_err, "EdDSA sign failure. No EdDSA sign will be done.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { pkey_print_message("sign", ed_curves[testnum].name, - eddsa_c[testnum][0], ed_curves[testnum].bits, seconds.eddsa); Time_F(START); count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R8:%ld:%u:%s:%.2f\n" : - "%ld %u bits %s signs in %.2fs \n", + mr ? "+R10:%ld:%u:%s:%.2f\n" : + "%ld %u bits %s sign ops in %.2fs \n", count, ed_curves[testnum].bits, ed_curves[testnum].name, d); eddsa_results[testnum][0] = (double)count / d; @@ -3000,18 +3708,17 @@ skip_hmac: if (st != 1) { BIO_printf(bio_err, "EdDSA verify failure. No EdDSA verify will be done.\n"); - ERR_print_errors(bio_err); + dofail(); eddsa_doit[testnum] = 0; } else { pkey_print_message("verify", ed_curves[testnum].name, - eddsa_c[testnum][1], ed_curves[testnum].bits, seconds.eddsa); Time_F(START); count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R9:%ld:%u:%s:%.2f\n" - : "%ld %u bits %s verify in %.2fs\n", + mr ? "+R11:%ld:%u:%s:%.2f\n" + : "%ld %u bits %s verify ops in %.2fs\n", count, ed_curves[testnum].bits, ed_curves[testnum].name, d); eddsa_results[testnum][1] = (double)count / d; @@ -3023,6 +3730,7 @@ skip_hmac: } } } +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 for (testnum = 0; testnum < SM2_NUM; testnum++) { @@ -3089,7 +3797,7 @@ skip_hmac: } if (st == 0) { BIO_printf(bio_err, "SM2 init failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { for (i = 0; i < loopargs_len; i++) { @@ -3103,19 +3811,18 @@ skip_hmac: if (st == 0) { BIO_printf(bio_err, "SM2 sign failure. No SM2 sign will be done.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; } else { pkey_print_message("sign", sm2_curves[testnum].name, - sm2_c[testnum][0], sm2_curves[testnum].bits, seconds.sm2); Time_F(START); count = run_benchmark(async_jobs, SM2_sign_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R10:%ld:%u:%s:%.2f\n" : - "%ld %u bits %s signs in %.2fs \n", + mr ? "+R12:%ld:%u:%s:%.2f\n" : + "%ld %u bits %s sign ops in %.2fs \n", count, sm2_curves[testnum].bits, sm2_curves[testnum].name, d); sm2_results[testnum][0] = (double)count / d; @@ -3133,18 +3840,17 @@ skip_hmac: if (st != 1) { BIO_printf(bio_err, "SM2 verify failure. No SM2 verify will be done.\n"); - ERR_print_errors(bio_err); + dofail(); sm2_doit[testnum] = 0; } else { pkey_print_message("verify", sm2_curves[testnum].name, - sm2_c[testnum][1], sm2_curves[testnum].bits, seconds.sm2); Time_F(START); count = run_benchmark(async_jobs, SM2_verify_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R11:%ld:%u:%s:%.2f\n" - : "%ld %u bits %s verify in %.2fs\n", + mr ? "+R13:%ld:%u:%s:%.2f\n" + : "%ld %u bits %s verify ops in %.2fs\n", count, sm2_curves[testnum].bits, sm2_curves[testnum].name, d); sm2_results[testnum][1] = (double)count / d; @@ -3178,13 +3884,13 @@ skip_hmac: if (ERR_peek_error()) { BIO_printf(bio_err, "WARNING: the error queue contains previous unhandled errors.\n"); - ERR_print_errors(bio_err); + dofail(); } pkey_A = EVP_PKEY_new(); if (!pkey_A) { BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3192,7 +3898,7 @@ skip_hmac: pkey_B = EVP_PKEY_new(); if (!pkey_B) { BIO_printf(bio_err, "Error while initialising EVP_PKEY (out of memory?).\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3201,7 +3907,7 @@ skip_hmac: ffdh_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); if (!ffdh_ctx) { BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3209,14 +3915,14 @@ skip_hmac: if (EVP_PKEY_keygen_init(ffdh_ctx) <= 0) { BIO_printf(bio_err, "Error while initialising EVP_PKEY_CTX.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; } if (EVP_PKEY_CTX_set_dh_nid(ffdh_ctx, ffdh_params[testnum].nid) <= 0) { BIO_printf(bio_err, "Error setting DH key size for keygen.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3225,7 +3931,7 @@ skip_hmac: if (EVP_PKEY_keygen(ffdh_ctx, &pkey_A) <= 0 || EVP_PKEY_keygen(ffdh_ctx, &pkey_B) <= 0) { BIO_printf(bio_err, "FFDH key generation failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3241,28 +3947,28 @@ skip_hmac: ffdh_ctx = EVP_PKEY_CTX_new(pkey_A, NULL); if (ffdh_ctx == NULL) { BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; } if (EVP_PKEY_derive_init(ffdh_ctx) <= 0) { BIO_printf(bio_err, "FFDH derivation context init failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; } if (EVP_PKEY_derive_set_peer(ffdh_ctx, pkey_B) <= 0) { BIO_printf(bio_err, "Assigning peer key for derivation failed.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; } if (EVP_PKEY_derive(ffdh_ctx, NULL, &secret_size) <= 0) { BIO_printf(bio_err, "Checking size of shared secret failed.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3277,7 +3983,7 @@ skip_hmac: loopargs[i].secret_ff_a, &secret_size) <= 0) { BIO_printf(bio_err, "Shared secret derive failure.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3286,7 +3992,7 @@ skip_hmac: test_ctx = EVP_PKEY_CTX_new(pkey_B, NULL); if (!test_ctx) { BIO_printf(bio_err, "Error while allocating EVP_PKEY_CTX.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3306,7 +4012,7 @@ skip_hmac: if (CRYPTO_memcmp(loopargs[i].secret_ff_a, loopargs[i].secret_ff_b, secret_size)) { BIO_printf(bio_err, "FFDH computations don't match.\n"); - ERR_print_errors(bio_err); + dofail(); op_count = 1; ffdh_checks = 0; break; @@ -3322,14 +4028,14 @@ skip_hmac: test_ctx = NULL; } if (ffdh_checks != 0) { - pkey_print_message("", "ffdh", ffdh_c[testnum][0], + pkey_print_message("", "ffdh", ffdh_params[testnum].bits, seconds.ffdh); Time_F(START); count = run_benchmark(async_jobs, FFDH_derive_key_loop, loopargs); d = Time_F(STOP); BIO_printf(bio_err, - mr ? "+R12:%ld:%d:%.2f\n" : + mr ? "+R14:%ld:%d:%.2f\n" : "%ld %u-bits FFDH ops in %.2fs\n", count, ffdh_params[testnum].bits, d); ffdh_results[testnum][0] = (double)count / d; @@ -3341,6 +4047,376 @@ skip_hmac: } } #endif /* OPENSSL_NO_DH */ + + for (testnum = 0; testnum < kems_algs_len; testnum++) { + int kem_checks = 1; + const char *kem_name = kems_algname[testnum]; + + if (!kems_doit[testnum] || !do_kems) + continue; + + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *kem_gen_ctx = NULL; + EVP_PKEY_CTX *kem_encaps_ctx = NULL; + EVP_PKEY_CTX *kem_decaps_ctx = NULL; + size_t send_secret_len, out_len; + size_t rcv_secret_len; + unsigned char *out = NULL, *send_secret = NULL, *rcv_secret; + unsigned int bits; + char *name; + char sfx[MAX_ALGNAME_SUFFIX]; + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + int use_params = 0; + enum kem_type_t { KEM_RSA = 1, KEM_EC, KEM_X25519, KEM_X448 } kem_type; + + /* no string after rsa permitted: */ + if (strlen(kem_name) < MAX_ALGNAME_SUFFIX + 4 /* rsa+digit */ + && sscanf(kem_name, "rsa%u%s", &bits, sfx) == 1) + kem_type = KEM_RSA; + else if (strncmp(kem_name, "EC", 2) == 0) + kem_type = KEM_EC; + else if (strcmp(kem_name, "X25519") == 0) + kem_type = KEM_X25519; + else if (strcmp(kem_name, "X448") == 0) + kem_type = KEM_X448; + else kem_type = 0; + + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + dofail(); + } + + if (kem_type == KEM_RSA) { + params[0] = OSSL_PARAM_construct_uint(OSSL_PKEY_PARAM_RSA_BITS, + &bits); + use_params = 1; + } else if (kem_type == KEM_EC) { + name = (char *)(kem_name + 2); + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, + name, 0); + use_params = 1; + } + + kem_gen_ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), + (kem_type == KEM_RSA) ? "RSA": + (kem_type == KEM_EC) ? "EC": + kem_name, + app_get0_propq()); + + if ((!kem_gen_ctx || EVP_PKEY_keygen_init(kem_gen_ctx) <= 0) + || (use_params + && EVP_PKEY_CTX_set_params(kem_gen_ctx, params) <= 0)) { + BIO_printf(bio_err, "Error initializing keygen ctx for %s.\n", + kem_name); + goto kem_err_break; + } + if (EVP_PKEY_keygen(kem_gen_ctx, &pkey) <= 0) { + BIO_printf(bio_err, "Error while generating KEM EVP_PKEY.\n"); + goto kem_err_break; + } + /* Now prepare encaps data structs */ + kem_encaps_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), + pkey, + app_get0_propq()); + if (kem_encaps_ctx == NULL + || EVP_PKEY_encapsulate_init(kem_encaps_ctx, NULL) <= 0 + || (kem_type == KEM_RSA + && EVP_PKEY_CTX_set_kem_op(kem_encaps_ctx, "RSASVE") <= 0) + || ((kem_type == KEM_EC + || kem_type == KEM_X25519 + || kem_type == KEM_X448) + && EVP_PKEY_CTX_set_kem_op(kem_encaps_ctx, "DHKEM") <= 0) + || EVP_PKEY_encapsulate(kem_encaps_ctx, NULL, &out_len, + NULL, &send_secret_len) <= 0) { + BIO_printf(bio_err, + "Error while initializing encaps data structs for %s.\n", + kem_name); + goto kem_err_break; + } + out = app_malloc(out_len, "encaps result"); + send_secret = app_malloc(send_secret_len, "encaps secret"); + if (out == NULL || send_secret == NULL) { + BIO_printf(bio_err, "MemAlloc error in encaps for %s.\n", kem_name); + goto kem_err_break; + } + if (EVP_PKEY_encapsulate(kem_encaps_ctx, out, &out_len, + send_secret, &send_secret_len) <= 0) { + BIO_printf(bio_err, "Encaps error for %s.\n", kem_name); + goto kem_err_break; + } + /* Now prepare decaps data structs */ + kem_decaps_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), + pkey, + app_get0_propq()); + if (kem_decaps_ctx == NULL + || EVP_PKEY_decapsulate_init(kem_decaps_ctx, NULL) <= 0 + || (kem_type == KEM_RSA + && EVP_PKEY_CTX_set_kem_op(kem_decaps_ctx, "RSASVE") <= 0) + || ((kem_type == KEM_EC + || kem_type == KEM_X25519 + || kem_type == KEM_X448) + && EVP_PKEY_CTX_set_kem_op(kem_decaps_ctx, "DHKEM") <= 0) + || EVP_PKEY_decapsulate(kem_decaps_ctx, NULL, &rcv_secret_len, + out, out_len) <= 0) { + BIO_printf(bio_err, + "Error while initializing decaps data structs for %s.\n", + kem_name); + goto kem_err_break; + } + rcv_secret = app_malloc(rcv_secret_len, "KEM decaps secret"); + if (rcv_secret == NULL) { + BIO_printf(bio_err, "MemAlloc failure in decaps for %s.\n", + kem_name); + goto kem_err_break; + } + if (EVP_PKEY_decapsulate(kem_decaps_ctx, rcv_secret, + &rcv_secret_len, out, out_len) <= 0 + || rcv_secret_len != send_secret_len + || memcmp(send_secret, rcv_secret, send_secret_len)) { + BIO_printf(bio_err, "Decaps error for %s.\n", kem_name); + goto kem_err_break; + } + loopargs[i].kem_gen_ctx[testnum] = kem_gen_ctx; + loopargs[i].kem_encaps_ctx[testnum] = kem_encaps_ctx; + loopargs[i].kem_decaps_ctx[testnum] = kem_decaps_ctx; + loopargs[i].kem_out_len[testnum] = out_len; + loopargs[i].kem_secret_len[testnum] = send_secret_len; + loopargs[i].kem_out[testnum] = out; + loopargs[i].kem_send_secret[testnum] = send_secret; + loopargs[i].kem_rcv_secret[testnum] = rcv_secret; + EVP_PKEY_free(pkey); + pkey = NULL; + continue; + + kem_err_break: + dofail(); + EVP_PKEY_free(pkey); + op_count = 1; + kem_checks = 0; + break; + } + if (kem_checks != 0) { + kskey_print_message(kem_name, "keygen", seconds.kem); + Time_F(START); + count = + run_benchmark(async_jobs, KEM_keygen_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R15:%ld:%s:%.2f\n" : + "%ld %s KEM keygen ops in %.2fs\n", count, + kem_name, d); + kems_results[testnum][0] = (double)count / d; + op_count = count; + kskey_print_message(kem_name, "encaps", seconds.kem); + Time_F(START); + count = + run_benchmark(async_jobs, KEM_encaps_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R16:%ld:%s:%.2f\n" : + "%ld %s KEM encaps ops in %.2fs\n", count, + kem_name, d); + kems_results[testnum][1] = (double)count / d; + op_count = count; + kskey_print_message(kem_name, "decaps", seconds.kem); + Time_F(START); + count = + run_benchmark(async_jobs, KEM_decaps_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R17:%ld:%s:%.2f\n" : + "%ld %s KEM decaps ops in %.2fs\n", count, + kem_name, d); + kems_results[testnum][2] = (double)count / d; + op_count = count; + } + if (op_count <= 1) { + /* if longer than 10s, don't do any more */ + stop_it(kems_doit, testnum); + } + } + + for (testnum = 0; testnum < sigs_algs_len; testnum++) { + int sig_checks = 1; + const char *sig_name = sigs_algname[testnum]; + + if (!sigs_doit[testnum] || !do_sigs) + continue; + + for (i = 0; i < loopargs_len; i++) { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx_params = NULL; + EVP_PKEY* pkey_params = NULL; + EVP_PKEY_CTX *sig_gen_ctx = NULL; + EVP_PKEY_CTX *sig_sign_ctx = NULL; + EVP_PKEY_CTX *sig_verify_ctx = NULL; + unsigned char md[SHA256_DIGEST_LENGTH]; + unsigned char *sig; + char sfx[MAX_ALGNAME_SUFFIX]; + size_t md_len = SHA256_DIGEST_LENGTH; + size_t max_sig_len, sig_len; + unsigned int bits; + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + int use_params = 0; + + /* only sign little data to avoid measuring digest performance */ + memset(md, 0, SHA256_DIGEST_LENGTH); + + if (ERR_peek_error()) { + BIO_printf(bio_err, + "WARNING: the error queue contains previous unhandled errors.\n"); + dofail(); + } + + /* no string after rsa permitted: */ + if (strlen(sig_name) < MAX_ALGNAME_SUFFIX + 4 /* rsa+digit */ + && sscanf(sig_name, "rsa%u%s", &bits, sfx) == 1) { + params[0] = OSSL_PARAM_construct_uint(OSSL_PKEY_PARAM_RSA_BITS, + &bits); + use_params = 1; + } + + if (strncmp(sig_name, "dsa", 3) == 0) { + ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL); + if (ctx_params == NULL + || EVP_PKEY_paramgen_init(ctx_params) <= 0 + || EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params, + atoi(sig_name + 3)) <= 0 + || EVP_PKEY_paramgen(ctx_params, &pkey_params) <= 0 + || (sig_gen_ctx = EVP_PKEY_CTX_new(pkey_params, NULL)) == NULL + || EVP_PKEY_keygen_init(sig_gen_ctx) <= 0) { + BIO_printf(bio_err, + "Error initializing classic keygen ctx for %s.\n", + sig_name); + goto sig_err_break; + } + } + + if (sig_gen_ctx == NULL) + sig_gen_ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), + use_params == 1 ? "RSA" : sig_name, + app_get0_propq()); + + if (!sig_gen_ctx || EVP_PKEY_keygen_init(sig_gen_ctx) <= 0 + || (use_params && + EVP_PKEY_CTX_set_params(sig_gen_ctx, params) <= 0)) { + BIO_printf(bio_err, "Error initializing keygen ctx for %s.\n", + sig_name); + goto sig_err_break; + } + if (EVP_PKEY_keygen(sig_gen_ctx, &pkey) <= 0) { + BIO_printf(bio_err, + "Error while generating signature EVP_PKEY for %s.\n", + sig_name); + goto sig_err_break; + } + /* Now prepare signature data structs */ + sig_sign_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), + pkey, + app_get0_propq()); + if (sig_sign_ctx == NULL + || EVP_PKEY_sign_init(sig_sign_ctx) <= 0 + || (use_params == 1 + && (EVP_PKEY_CTX_set_rsa_padding(sig_sign_ctx, + RSA_PKCS1_PADDING) <= 0)) + || EVP_PKEY_sign(sig_sign_ctx, NULL, &max_sig_len, + md, md_len) <= 0) { + BIO_printf(bio_err, + "Error while initializing signing data structs for %s.\n", + sig_name); + goto sig_err_break; + } + sig = app_malloc(sig_len = max_sig_len, "signature buffer"); + if (sig == NULL) { + BIO_printf(bio_err, "MemAlloc error in sign for %s.\n", sig_name); + goto sig_err_break; + } + if (EVP_PKEY_sign(sig_sign_ctx, sig, &sig_len, md, md_len) <= 0) { + BIO_printf(bio_err, "Signing error for %s.\n", sig_name); + goto sig_err_break; + } + /* Now prepare verify data structs */ + memset(md, 0, SHA256_DIGEST_LENGTH); + sig_verify_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), + pkey, + app_get0_propq()); + if (sig_verify_ctx == NULL + || EVP_PKEY_verify_init(sig_verify_ctx) <= 0 + || (use_params == 1 + && (EVP_PKEY_CTX_set_rsa_padding(sig_verify_ctx, + RSA_PKCS1_PADDING) <= 0))) { + BIO_printf(bio_err, + "Error while initializing verify data structs for %s.\n", + sig_name); + goto sig_err_break; + } + if (EVP_PKEY_verify(sig_verify_ctx, sig, sig_len, md, md_len) <= 0) { + BIO_printf(bio_err, "Verify error for %s.\n", sig_name); + goto sig_err_break; + } + if (EVP_PKEY_verify(sig_verify_ctx, sig, sig_len, md, md_len) <= 0) { + BIO_printf(bio_err, "Verify 2 error for %s.\n", sig_name); + goto sig_err_break; + } + loopargs[i].sig_gen_ctx[testnum] = sig_gen_ctx; + loopargs[i].sig_sign_ctx[testnum] = sig_sign_ctx; + loopargs[i].sig_verify_ctx[testnum] = sig_verify_ctx; + loopargs[i].sig_max_sig_len[testnum] = max_sig_len; + loopargs[i].sig_act_sig_len[testnum] = sig_len; + loopargs[i].sig_sig[testnum] = sig; + EVP_PKEY_free(pkey); + pkey = NULL; + continue; + + sig_err_break: + dofail(); + EVP_PKEY_free(pkey); + op_count = 1; + sig_checks = 0; + break; + } + + if (sig_checks != 0) { + kskey_print_message(sig_name, "keygen", seconds.sig); + Time_F(START); + count = run_benchmark(async_jobs, SIG_keygen_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R18:%ld:%s:%.2f\n" : + "%ld %s signature keygen ops in %.2fs\n", count, + sig_name, d); + sigs_results[testnum][0] = (double)count / d; + op_count = count; + kskey_print_message(sig_name, "signs", seconds.sig); + Time_F(START); + count = + run_benchmark(async_jobs, SIG_sign_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R19:%ld:%s:%.2f\n" : + "%ld %s signature sign ops in %.2fs\n", count, + sig_name, d); + sigs_results[testnum][1] = (double)count / d; + op_count = count; + + kskey_print_message(sig_name, "verify", seconds.sig); + Time_F(START); + count = + run_benchmark(async_jobs, SIG_verify_loop, loopargs); + d = Time_F(STOP); + BIO_printf(bio_err, + mr ? "+R20:%ld:%s:%.2f\n" : + "%ld %s signature verify ops in %.2fs\n", count, + sig_name, d); + sigs_results[testnum][2] = (double)count / d; + op_count = count; + } + if (op_count <= 1) + stop_it(sigs_doit, testnum); + } + #ifndef NO_FORK show_res: #endif @@ -3394,18 +4470,23 @@ skip_hmac: if (!rsa_doit[k]) continue; if (testnum && !mr) { - printf("%18ssign verify sign/s verify/s\n", " "); + printf("%19ssign verify encrypt decrypt sign/s verify/s encr./s decr./s\n", " "); testnum = 0; } if (mr) - printf("+F2:%u:%u:%f:%f\n", - k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1]); + printf("+F2:%u:%u:%f:%f:%f:%f\n", + k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1], + rsa_results[k][2], rsa_results[k][3]); else - printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n", - rsa_keys[k].bits, 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1], - rsa_results[k][0], rsa_results[k][1]); + printf("rsa %5u bits %8.6fs %8.6fs %8.6fs %8.6fs %8.1f %8.1f %8.1f %8.1f\n", + rsa_keys[k].bits, 1.0 / rsa_results[k][0], + 1.0 / rsa_results[k][1], 1.0 / rsa_results[k][2], + 1.0 / rsa_results[k][3], + rsa_results[k][0], rsa_results[k][1], + rsa_results[k][2], rsa_results[k][3]); } testnum = 1; +#ifndef OPENSSL_NO_DSA for (k = 0; k < DSA_NUM; k++) { if (!dsa_doit[k]) continue; @@ -3421,6 +4502,7 @@ skip_hmac: dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1], dsa_results[k][0], dsa_results[k][1]); } +#endif /* OPENSSL_NO_DSA */ testnum = 1; for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) { if (!ecdsa_doit[k]) @@ -3460,6 +4542,7 @@ skip_hmac: 1.0 / ecdh_results[k][0], ecdh_results[k][0]); } +#ifndef OPENSSL_NO_ECX testnum = 1; for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) { if (!eddsa_doit[k]) @@ -3479,6 +4562,7 @@ skip_hmac: 1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1], eddsa_results[k][0], eddsa_results[k][1]); } +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 testnum = 1; @@ -3522,9 +4606,53 @@ skip_hmac: } #endif /* OPENSSL_NO_DH */ + testnum = 1; + for (k = 0; k < kems_algs_len; k++) { + const char *kem_name = kems_algname[k]; + + if (!kems_doit[k] || !do_kems) + continue; + if (testnum && !mr) { + printf("%31skeygen encaps decaps keygens/s encaps/s decaps/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F9:%u:%f:%f:%f\n", + k, kems_results[k][0], kems_results[k][1], + kems_results[k][2]); + else + printf("%27s %8.6fs %8.6fs %8.6fs %9.1f %9.1f %9.1f\n", kem_name, + 1.0 / kems_results[k][0], + 1.0 / kems_results[k][1], 1.0 / kems_results[k][2], + kems_results[k][0], kems_results[k][1], kems_results[k][2]); + } + ret = 0; + + testnum = 1; + for (k = 0; k < sigs_algs_len; k++) { + const char *sig_name = sigs_algname[k]; + + if (!sigs_doit[k] || !do_sigs) + continue; + if (testnum && !mr) { + printf("%31skeygen signs verify keygens/s sign/s verify/s\n", " "); + testnum = 0; + } + if (mr) + printf("+F10:%u:%f:%f:%f\n", + k, sigs_results[k][0], sigs_results[k][1], + sigs_results[k][2]); + else + printf("%27s %8.6fs %8.6fs %8.6fs %9.1f %9.1f %9.1f\n", sig_name, + 1.0 / sigs_results[k][0], 1.0 / sigs_results[k][1], + 1.0 / sigs_results[k][2], sigs_results[k][0], + sigs_results[k][1], sigs_results[k][2]); + } ret = 0; end: + if (ret == 0 && testmode) + ret = testmoderesult; ERR_print_errors(bio_err); for (i = 0; i < loopargs_len; i++) { OPENSSL_free(loopargs[i].buf_malloc); @@ -3535,6 +4663,8 @@ skip_hmac: for (k = 0; k < RSA_NUM; k++) { EVP_PKEY_CTX_free(loopargs[i].rsa_sign_ctx[k]); EVP_PKEY_CTX_free(loopargs[i].rsa_verify_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].rsa_encrypt_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].rsa_decrypt_ctx[k]); } #ifndef OPENSSL_NO_DH OPENSSL_free(loopargs[i].secret_ff_a); @@ -3542,20 +4672,24 @@ skip_hmac: for (k = 0; k < FFDH_NUM; k++) EVP_PKEY_CTX_free(loopargs[i].ffdh_ctx[k]); #endif +#ifndef OPENSSL_NO_DSA for (k = 0; k < DSA_NUM; k++) { EVP_PKEY_CTX_free(loopargs[i].dsa_sign_ctx[k]); EVP_PKEY_CTX_free(loopargs[i].dsa_verify_ctx[k]); } +#endif for (k = 0; k < ECDSA_NUM; k++) { EVP_PKEY_CTX_free(loopargs[i].ecdsa_sign_ctx[k]); EVP_PKEY_CTX_free(loopargs[i].ecdsa_verify_ctx[k]); } for (k = 0; k < EC_NUM; k++) EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]); +#ifndef OPENSSL_NO_ECX for (k = 0; k < EdDSA_NUM; k++) { EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]); EVP_MD_CTX_free(loopargs[i].eddsa_ctx2[k]); } +#endif /* OPENSSL_NO_ECX */ #ifndef OPENSSL_NO_SM2 for (k = 0; k < SM2_NUM; k++) { EVP_PKEY_CTX *pctx = NULL; @@ -3574,11 +4708,33 @@ skip_hmac: EVP_PKEY_free(loopargs[i].sm2_pkey[k]); } #endif + for (k = 0; k < kems_algs_len; k++) { + EVP_PKEY_CTX_free(loopargs[i].kem_gen_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].kem_encaps_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].kem_decaps_ctx[k]); + OPENSSL_free(loopargs[i].kem_out[k]); + OPENSSL_free(loopargs[i].kem_send_secret[k]); + OPENSSL_free(loopargs[i].kem_rcv_secret[k]); + } + for (k = 0; k < sigs_algs_len; k++) { + EVP_PKEY_CTX_free(loopargs[i].sig_gen_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].sig_sign_ctx[k]); + EVP_PKEY_CTX_free(loopargs[i].sig_verify_ctx[k]); + OPENSSL_free(loopargs[i].sig_sig[k]); + } OPENSSL_free(loopargs[i].secret_a); OPENSSL_free(loopargs[i].secret_b); } OPENSSL_free(evp_hmac_name); OPENSSL_free(evp_cmac_name); + for (k = 0; k < kems_algs_len; k++) + OPENSSL_free(kems_algname[k]); + if (kem_stack != NULL) + sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free); + for (k = 0; k < sigs_algs_len; k++) + OPENSSL_free(sigs_algname[k]); + if (sig_stack != NULL) + sk_EVP_SIGNATURE_pop_free(sig_stack, EVP_SIGNATURE_free); if (async_jobs > 0) { for (i = 0; i < loopargs_len; i++) @@ -3592,25 +4748,36 @@ skip_hmac: release_engine(e); EVP_CIPHER_free(evp_cipher); EVP_MAC_free(mac); + NCONF_free(conf); return ret; } -static void print_message(const char *s, long num, int length, int tm) +static void print_message(const char *s, int length, int tm) { BIO_printf(bio_err, mr ? "+DT:%s:%d:%d\n" - : "Doing %s for %ds on %d size blocks: ", s, tm, length); + : "Doing %s ops for %ds on %d size blocks: ", s, tm, length); (void)BIO_flush(bio_err); run = 1; alarm(tm); } -static void pkey_print_message(const char *str, const char *str2, long num, - unsigned int bits, int tm) +static void pkey_print_message(const char *str, const char *str2, unsigned int bits, + int tm) { BIO_printf(bio_err, mr ? "+DTP:%d:%s:%s:%d\n" - : "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm); + : "Doing %u bits %s %s ops for %ds: ", bits, str, str2, tm); + (void)BIO_flush(bio_err); + run = 1; + alarm(tm); +} + +static void kskey_print_message(const char *str, const char *str2, int tm) +{ + BIO_printf(bio_err, + mr ? "+DTP:%s:%s:%d\n" + : "Doing %s %s ops for %ds: ", str, str2, tm); (void)BIO_flush(bio_err); run = 1; alarm(tm); @@ -3620,12 +4787,12 @@ static void print_result(int alg, int run_no, int count, double time_used) { if (count == -1) { BIO_printf(bio_err, "%s error!\n", names[alg]); - ERR_print_errors(bio_err); + dofail(); return; } BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" - : "%d %s's in %.2fs\n", count, names[alg], time_used); + : "%d %s ops in %.2fs\n", count, names[alg], time_used); results[alg][run_no] = ((double)count) / time_used * lengths[run_no]; } @@ -3635,9 +4802,6 @@ static char *sstrsep(char **string, const char *delim) char isdelim[256]; char *token = *string; - if (**string == 0) - return NULL; - memset(isdelim, 0, sizeof(isdelim)); isdelim[0] = 1; @@ -3657,6 +4821,23 @@ static char *sstrsep(char **string, const char *delim) return token; } +static int strtoint(const char *str, const int min_val, const int upper_val, + int *res) +{ + char *end = NULL; + long int val = 0; + + errno = 0; + val = strtol(str, &end, 10); + if (errno == 0 && end != str && *end == 0 + && min_val <= val && val < upper_val) { + *res = (int)val; + return 1; + } else { + return 0; + } +} + static int do_multi(int multi, int size_num) { int n; @@ -3697,6 +4878,9 @@ static int do_multi(int multi, int size_num) FILE *f; char buf[1024]; char *p; + char *tk; + int k; + double d; if ((f = fdopen(fds[n], "r")) == NULL) { BIO_printf(bio_err, "fdopen failure with 0x%x\n", @@ -3715,109 +4899,128 @@ static int do_multi(int multi, int size_num) continue; } printf("Got: %s from %d\n", buf, n); - if (strncmp(buf, "+F:", 3) == 0) { + p = buf; + if (CHECK_AND_SKIP_PREFIX(p, "+F:")) { int alg; int j; - p = buf + 3; - alg = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); - for (j = 0; j < size_num; ++j) - results[alg][j] += atof(sstrsep(&p, sep)); - } else if (strncmp(buf, "+F2:", 4) == 0) { - int k; - double d; + if (strtoint(sstrsep(&p, sep), 0, ALGOR_NUM, &alg)) { + sstrsep(&p, sep); + for (j = 0; j < size_num; ++j) + results[alg][j] += atof(sstrsep(&p, sep)); + } + } else if (CHECK_AND_SKIP_PREFIX(p, "+F2:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(rsa_results), &k)) { + sstrsep(&p, sep); - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); + d = atof(sstrsep(&p, sep)); + rsa_results[k][0] += d; - d = atof(sstrsep(&p, sep)); - rsa_results[k][0] += d; + d = atof(sstrsep(&p, sep)); + rsa_results[k][1] += d; - d = atof(sstrsep(&p, sep)); - rsa_results[k][1] += d; - } else if (strncmp(buf, "+F3:", 4) == 0) { - int k; - double d; + d = atof(sstrsep(&p, sep)); + rsa_results[k][2] += d; - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); + d = atof(sstrsep(&p, sep)); + rsa_results[k][3] += d; + } +# ifndef OPENSSL_NO_DSA + } else if (CHECK_AND_SKIP_PREFIX(p, "+F3:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(dsa_results), &k)) { + sstrsep(&p, sep); - d = atof(sstrsep(&p, sep)); - dsa_results[k][0] += d; + d = atof(sstrsep(&p, sep)); + dsa_results[k][0] += d; - d = atof(sstrsep(&p, sep)); - dsa_results[k][1] += d; - } else if (strncmp(buf, "+F4:", 4) == 0) { - int k; - double d; + d = atof(sstrsep(&p, sep)); + dsa_results[k][1] += d; + } +# endif /* OPENSSL_NO_DSA */ + } else if (CHECK_AND_SKIP_PREFIX(p, "+F4:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(ecdsa_results), &k)) { + sstrsep(&p, sep); - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); + d = atof(sstrsep(&p, sep)); + ecdsa_results[k][0] += d; - d = atof(sstrsep(&p, sep)); - ecdsa_results[k][0] += d; + d = atof(sstrsep(&p, sep)); + ecdsa_results[k][1] += d; + } + } else if (CHECK_AND_SKIP_PREFIX(p, "+F5:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(ecdh_results), &k)) { + sstrsep(&p, sep); - d = atof(sstrsep(&p, sep)); - ecdsa_results[k][1] += d; - } else if (strncmp(buf, "+F5:", 4) == 0) { - int k; - double d; + d = atof(sstrsep(&p, sep)); + ecdh_results[k][0] += d; + } +# ifndef OPENSSL_NO_ECX + } else if (CHECK_AND_SKIP_PREFIX(p, "+F6:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(eddsa_results), &k)) { + sstrsep(&p, sep); + sstrsep(&p, sep); - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); + d = atof(sstrsep(&p, sep)); + eddsa_results[k][0] += d; - d = atof(sstrsep(&p, sep)); - ecdh_results[k][0] += d; - } else if (strncmp(buf, "+F6:", 4) == 0) { - int k; - double d; - - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); - sstrsep(&p, sep); - - d = atof(sstrsep(&p, sep)); - eddsa_results[k][0] += d; - - d = atof(sstrsep(&p, sep)); - eddsa_results[k][1] += d; + d = atof(sstrsep(&p, sep)); + eddsa_results[k][1] += d; + } +# endif /* OPENSSL_NO_ECX */ # ifndef OPENSSL_NO_SM2 - } else if (strncmp(buf, "+F7:", 4) == 0) { - int k; - double d; + } else if (CHECK_AND_SKIP_PREFIX(p, "+F7:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(sm2_results), &k)) { + sstrsep(&p, sep); + sstrsep(&p, sep); - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); - sstrsep(&p, sep); + d = atof(sstrsep(&p, sep)); + sm2_results[k][0] += d; - d = atof(sstrsep(&p, sep)); - sm2_results[k][0] += d; - - d = atof(sstrsep(&p, sep)); - sm2_results[k][1] += d; + d = atof(sstrsep(&p, sep)); + sm2_results[k][1] += d; + } # endif /* OPENSSL_NO_SM2 */ # ifndef OPENSSL_NO_DH - } else if (strncmp(buf, "+F8:", 4) == 0) { - int k; - double d; + } else if (CHECK_AND_SKIP_PREFIX(p, "+F8:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(ffdh_results), &k)) { + sstrsep(&p, sep); - p = buf + 4; - k = atoi(sstrsep(&p, sep)); - sstrsep(&p, sep); - - d = atof(sstrsep(&p, sep)); - ffdh_results[k][0] += d; + d = atof(sstrsep(&p, sep)); + ffdh_results[k][0] += d; + } # endif /* OPENSSL_NO_DH */ - } else if (strncmp(buf, "+H:", 3) == 0) { - ; - } else { + } else if (CHECK_AND_SKIP_PREFIX(p, "+F9:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(kems_results), &k)) { + d = atof(sstrsep(&p, sep)); + kems_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + kems_results[k][1] += d; + + d = atof(sstrsep(&p, sep)); + kems_results[k][2] += d; + } + } else if (CHECK_AND_SKIP_PREFIX(p, "+F10:")) { + tk = sstrsep(&p, sep); + if (strtoint(tk, 0, OSSL_NELEM(sigs_results), &k)) { + d = atof(sstrsep(&p, sep)); + sigs_results[k][0] += d; + + d = atof(sstrsep(&p, sep)); + sigs_results[k][1] += d; + + d = atof(sstrsep(&p, sep)); + sigs_results[k][2] += d; + } + } else if (!HAS_PREFIX(buf, "+H:")) { BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf, n); } @@ -3847,10 +5050,11 @@ static int do_multi(int multi, int size_num) static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, const openssl_speed_sec_t *seconds) { - static const int mblengths_list[] = - { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 }; + static const int mblengths_list[] = { + 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 + }; const int *mblengths = mblengths_list; - int j, count, keylen, num = OSSL_NELEM(mblengths_list); + int j, count, keylen, num = OSSL_NELEM(mblengths_list), ciph_success = 1; const char *alg_name; unsigned char *inp = NULL, *out = NULL, *key, no_key[32], no_iv[16]; EVP_CIPHER_CTX *ctx = NULL; @@ -3886,9 +5090,9 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, app_bail_out("failed to get cipher name\n"); for (j = 0; j < num; j++) { - print_message(alg_name, 0, mblengths[j], seconds->sym); + print_message(alg_name, mblengths[j], seconds->sym); Time_F(START); - for (count = 0; run && count < INT_MAX; count++) { + for (count = 0; run && COND(count); count++) { EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param; size_t len = mblengths[j]; int packlen; @@ -3924,12 +5128,14 @@ static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single, aad[12] = (unsigned char)(len); pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, EVP_AEAD_TLS1_AAD_LEN, aad); - EVP_Cipher(ctx, out, inp, len + pad); + ciph_success = EVP_Cipher(ctx, out, inp, len + pad); } } d = Time_F(STOP); BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n" - : "%d %s's in %.2fs\n", count, "evp", d); + : "%d %s ops in %.2fs\n", count, "evp", d); + if ((ciph_success <= 0) && (mr == 0)) + BIO_printf(bio_err, "Error performing cipher op\n"); results[D_EVP][j] = ((double)count) / d * mblengths[j]; } diff --git a/apps/spkac.c b/apps/spkac.c index d92be7d6450e..5a129a7fa775 100644 --- a/apps/spkac.c +++ b/apps/spkac.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -133,8 +133,7 @@ int spkac_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_passwd(passinarg, NULL, &passin, NULL)) { @@ -153,9 +152,10 @@ int spkac_main(int argc, char **argv) spki = NETSCAPE_SPKI_new(); if (spki == NULL) goto end; - if (challenge != NULL) - ASN1_STRING_set(spki->spkac->challenge, - challenge, (int)strlen(challenge)); + if (challenge != NULL + && !ASN1_STRING_set(spki->spkac->challenge, + challenge, (int)strlen(challenge))) + goto end; if (!NETSCAPE_SPKI_set_pubkey(spki, pkey)) { BIO_printf(bio_err, "Error setting public key\n"); goto end; diff --git a/apps/storeutl.c b/apps/storeutl.c index 30c9915de3e8..b131278a8592 100644 --- a/apps/storeutl.c +++ b/apps/storeutl.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,9 +18,11 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, int expected, int criterion, OSSL_STORE_SEARCH *search, - int text, int noout, int recursive, int indent, BIO *out, + int text, int noout, int recursive, int indent, const char *outfile, const char *prog, OSSL_LIB_CTX *libctx); +static BIO *out = NULL; + typedef enum OPTION_choice { OPT_COMMON, OPT_ENGINE, OPT_OUT, OPT_PASSIN, @@ -71,10 +73,9 @@ int storeutl_main(int argc, char *argv[]) { int ret = 1, noout = 0, text = 0, recursive = 0; char *outfile = NULL, *passin = NULL, *passinarg = NULL; - BIO *out = NULL; ENGINE *e = NULL; OPTION_CHOICE o; - char *prog = opt_init(argc, argv, storeutl_options); + char *prog; PW_CB_DATA pw_cb_data; int expected = 0; int criterion = 0; @@ -87,6 +88,8 @@ int storeutl_main(int argc, char *argv[]) EVP_MD *digest = NULL; OSSL_LIB_CTX *libctx = app_get0_libctx(); + opt_set_unknown_name("digest"); + prog = opt_init(argc, argv, storeutl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: @@ -256,15 +259,12 @@ int storeutl_main(int argc, char *argv[]) } /* One argument, the URI */ - argc = opt_num_rest(); - argv = opt_rest(); - if (argc != 1) + if (!opt_check_rest_arg("URI")) goto opthelp; + argv = opt_rest(); - if (digestname != NULL) { - if (!opt_md(digestname, &digest)) - goto opthelp; - } + if (!opt_md(digestname, &digest)) + goto opthelp; if (criterion != 0) { switch (criterion) { @@ -312,13 +312,9 @@ int storeutl_main(int argc, char *argv[]) pw_cb_data.password = passin; pw_cb_data.prompt_info = argv[0]; - out = bio_open_default(outfile, 'w', FORMAT_TEXT); - if (out == NULL) - goto end; - ret = process(argv[0], get_ui_method(), &pw_cb_data, expected, criterion, search, - text, noout, recursive, 0, out, prog, libctx); + text, noout, recursive, 0, outfile, prog, libctx); end: EVP_MD_free(digest); @@ -349,7 +345,7 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...) static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, int expected, int criterion, OSSL_STORE_SEARCH *search, - int text, int noout, int recursive, int indent, BIO *out, + int text, int noout, int recursive, int indent, const char *outfile, const char *prog, OSSL_LIB_CTX *libctx) { OSSL_STORE_CTX *store_ctx = NULL; @@ -428,6 +424,13 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, indent_printf(indent, bio_out, "%d: %s\n", items, infostr); } + if (out == NULL) { + if ((out = bio_open_default(outfile, 'w', FORMAT_TEXT)) == NULL) { + ret++; + goto end2; + } + } + /* * Unfortunately, PEM_X509_INFO_write_bio() is sorely lacking in * functionality, so we must figure out how exactly to write things @@ -439,7 +442,7 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata, const char *suburi = OSSL_STORE_INFO_get0_NAME(info); ret += process(suburi, uimeth, uidata, expected, criterion, search, - text, noout, recursive, indent + 2, out, prog, + text, noout, recursive, indent + 2, outfile, prog, libctx); } break; diff --git a/apps/ts.c b/apps/ts.c index 01b73f380428..e59bc3b4b4a2 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -181,6 +181,7 @@ int ts_main(int argc, char **argv) if ((vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, ts_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -204,8 +205,10 @@ int ts_main(int argc, char **argv) case OPT_QUERY: case OPT_REPLY: case OPT_VERIFY: - if (mode != OPT_ERR) + if (mode != OPT_ERR) { + BIO_printf(bio_err, "%s: Must give only one of -query, -reply, or -verify\n", prog); goto opthelp; + } mode = o; break; case OPT_DATA: @@ -288,17 +291,18 @@ int ts_main(int argc, char **argv) } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0 || mode == OPT_ERR) + if (!opt_check_rest_arg(NULL)) goto opthelp; + if (mode == OPT_ERR) { + BIO_printf(bio_err, "%s: Must give one of -query, -reply, or -verify\n", prog); + goto opthelp; + } if (!app_RAND_load()) goto end; - if (digestname != NULL) { - if (!opt_md(digestname, &md)) - goto opthelp; - } + if (!opt_md(digestname, &md)) + goto opthelp; if (mode == OPT_REPLY && passin && !app_passwd(passin, NULL, &password, NULL)) { BIO_printf(bio_err, "Error getting password.\n"); @@ -371,7 +375,7 @@ static CONF *load_config_file(const char *configfile) const char *p; BIO_printf(bio_err, "Using configuration from %s\n", configfile); - p = NCONF_get_string(conf, NULL, ENV_OID_FILE); + p = app_conf_try_string(conf, NULL, ENV_OID_FILE); if (p != NULL) { BIO *oid_bio = BIO_new_file(p, "r"); if (!oid_bio) @@ -380,8 +384,7 @@ static CONF *load_config_file(const char *configfile) OBJ_create_objects(oid_bio); BIO_free_all(oid_bio); } - } else - ERR_clear_error(); + } if (!add_oid_section(conf)) ERR_print_errors(bio_err); } @@ -510,7 +513,7 @@ static int create_digest(BIO *input, const char *digest, const EVP_MD *md, EVP_MD_CTX *md_ctx = NULL; md_value_len = EVP_MD_get_size(md); - if (md_value_len < 0) + if (md_value_len <= 0) return 0; if (input != NULL) { @@ -917,7 +920,7 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, f |= TS_VFY_DATA; if ((out = BIO_new_file(data, "rb")) == NULL) goto err; - if (TS_VERIFY_CTX_set_data(ctx, out) == NULL) { + if (!TS_VERIFY_CTX_set0_data(ctx, out)) { BIO_free_all(out); goto err; } @@ -925,7 +928,7 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, long imprint_len; unsigned char *hexstr = OPENSSL_hexstr2buf(digest, &imprint_len); f |= TS_VFY_IMPRINT; - if (TS_VERIFY_CTX_set_imprint(ctx, hexstr, imprint_len) == NULL) { + if (!TS_VERIFY_CTX_set0_imprint(ctx, hexstr, imprint_len)) { BIO_printf(bio_err, "invalid digest string\n"); goto err; } @@ -946,16 +949,15 @@ static TS_VERIFY_CTX *create_verify_ctx(const char *data, const char *digest, TS_VERIFY_CTX_add_flags(ctx, f | TS_VFY_SIGNATURE); /* Initialising the X509_STORE object. */ - if (TS_VERIFY_CTX_set_store(ctx, - create_cert_store(CApath, CAfile, CAstore, vpm)) - == NULL) + if (!TS_VERIFY_CTX_set0_store(ctx, create_cert_store(CApath, CAfile, + CAstore, vpm))) goto err; /* Loading any extra untrusted certificates. */ if (untrusted != NULL) { certs = load_certs_multifile(untrusted, NULL, "extra untrusted certs", vpm); - if (certs == NULL || TS_VERIFY_CTX_set_certs(ctx, certs) == NULL) + if (certs == NULL || !TS_VERIFY_CTX_set0_certs(ctx, certs)) goto err; } ret = 1; @@ -1015,7 +1017,7 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile, BIO_printf(bio_err, "memory allocation failure\n"); goto err; } - if (X509_LOOKUP_load_store_ex(lookup, CAstore, libctx, propq) <= 0) { + if (X509_LOOKUP_add_store_ex(lookup, CAstore, libctx, propq) <= 0) { BIO_printf(bio_err, "Error loading store URI %s\n", CAstore); goto err; } diff --git a/apps/tsget.in b/apps/tsget.in index 3b5f83cf9b57..8eab6a8f1f57 100644 --- a/apps/tsget.in +++ b/apps/tsget.in @@ -1,5 +1,5 @@ #!{- $config{HASHBANGPERL} -} -# Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2002 The OpenTSA Project. All rights reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/apps/verify.c b/apps/verify.c index 3aae931f69df..93b214281ea5 100644 --- a/apps/verify.c +++ b/apps/verify.c @@ -234,8 +234,8 @@ int verify_main(int argc, char **argv) end: X509_VERIFY_PARAM_free(vpm); X509_STORE_free(store); - sk_X509_pop_free(untrusted, X509_free); - sk_X509_pop_free(trusted, X509_free); + OSSL_STACK_OF_X509_free(untrusted); + OSSL_STACK_OF_X509_free(trusted); sk_X509_CRL_pop_free(crls, X509_CRL_free); sk_OPENSSL_STRING_free(vfyopts); release_engine(e); @@ -308,7 +308,7 @@ static int check(X509_STORE *ctx, const char *file, BIO_printf(bio_out, " (untrusted)"); BIO_printf(bio_out, "\n"); } - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); } } else { BIO_printf(bio_err, @@ -352,7 +352,7 @@ static int cb(int ok, X509_STORE_CTX *ctx) switch (cert_error) { case X509_V_ERR_NO_EXPLICIT_POLICY: policies_print(ctx); - /* fall thru */ + /* fall through */ case X509_V_ERR_CERT_HAS_EXPIRED: /* Continue even if the leaf is a self-signed cert */ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: diff --git a/apps/version.c b/apps/version.c index cab17a46bf18..89fb64b70a4d 100644 --- a/apps/version.c +++ b/apps/version.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,9 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_B, OPT_D, OPT_E, OPT_M, OPT_F, OPT_O, OPT_P, OPT_V, OPT_A, OPT_R, OPT_C +#if defined(_WIN32) + ,OPT_W +#endif } OPTION_CHOICE; const OPTIONS version_options[] = { @@ -37,6 +40,9 @@ const OPTIONS version_options[] = { {"r", OPT_R, '-', "Show random seeding options"}, {"v", OPT_V, '-', "Show library version"}, {"c", OPT_C, '-', "Show CPU settings info"}, +#if defined(_WIN32) + {"w", OPT_W, '-', "Show Windows install context"}, +#endif {NULL} }; @@ -45,6 +51,9 @@ int version_main(int argc, char **argv) int ret = 1, dirty = 0, seed = 0; int cflags = 0, version = 0, date = 0, options = 0, platform = 0, dir = 0; int engdir = 0, moddir = 0, cpuinfo = 0; +#if defined(_WIN32) + int windows = 0; +#endif char *prog; OPTION_CHOICE o; @@ -90,6 +99,11 @@ opthelp: case OPT_C: dirty = cpuinfo = 1; break; +#if defined(_WIN32) + case OPT_W: + dirty = windows = 1; + break; +#endif case OPT_A: seed = options = cflags = version = date = platform = dir = engdir = moddir = cpuinfo @@ -99,8 +113,7 @@ opthelp: } /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!dirty) @@ -132,6 +145,10 @@ opthelp: } if (cpuinfo) printf("%s\n", OpenSSL_version(OPENSSL_CPU_INFO)); +#if defined(_WIN32) + if (windows) + printf("%s\n", OpenSSL_version(OPENSSL_WINCTX)); +#endif ret = 0; end: return ret; diff --git a/apps/x509.c b/apps/x509.c index a919d787457c..fdae8f383a66 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -25,11 +25,12 @@ #ifndef OPENSSL_NO_DSA # include #endif +#include "internal/e_os.h" /* For isatty() */ #undef POSTFIX #define POSTFIX ".srl" -#define DEFAULT_DAYS 30 /* default cert validity period in days */ -#define UNSET_DAYS -2 /* -1 is used for testing expiration checks */ +#define DEFAULT_DAYS 30 /* default certificate validity period in days */ +#define UNSET_DAYS -2 /* -1 may be used for testing expiration checks */ #define EXT_COPY_UNSET -1 static int callb(int ok, X509_STORE_CTX *ctx); @@ -43,7 +44,7 @@ typedef enum OPTION_choice { OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, - OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ, + OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_ISSU, OPT_SUBJ, OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, @@ -53,6 +54,7 @@ typedef enum OPTION_choice { OPT_CLRREJECT, OPT_ALIAS, OPT_CACREATESERIAL, OPT_CLREXT, OPT_OCSPID, OPT_SUBJECT_HASH_OLD, OPT_ISSUER_HASH_OLD, OPT_COPY_EXTENSIONS, OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES, + OPT_NOT_BEFORE, OPT_NOT_AFTER, OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT } OPTION_CHOICE; @@ -70,7 +72,7 @@ const OPTIONS x509_options[] = { {"copy_extensions", OPT_COPY_EXTENSIONS, 's', "copy extensions when converting from CSR to x509 or vice versa"}, {"inform", OPT_INFORM, 'f', - "CSR input file format (DER or PEM) - default PEM"}, + "CSR input format to use (PEM or DER; by default try PEM first)"}, {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"}, {"key", OPT_KEY, 's', "Key for signing, and to include unless using -force_pubkey"}, @@ -87,7 +89,8 @@ const OPTIONS x509_options[] = { OPT_SECTION("Certificate printing"), {"text", OPT_TEXT, '-', "Print the certificate in text form"}, - {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, + {"dateopt", OPT_DATEOPT, 's', + "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"}, {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"}, {"alias", OPT_ALIAS, '-', "Print certificate alias"}, @@ -133,13 +136,19 @@ const OPTIONS x509_options[] = { "Serial number to use, overrides -CAserial"}, {"next_serial", OPT_NEXT_SERIAL, '-', "Increment current certificate serial number"}, + {"not_before", OPT_NOT_BEFORE, 's', + "[CC]YYMMDDHHMMSSZ value for notBefore certificate field"}, + {"not_after", OPT_NOT_AFTER, 's', + "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days"}, {"days", OPT_DAYS, 'n', "Number of days until newly generated certificate expires - default 30"}, {"preserve_dates", OPT_PRESERVE_DATES, '-', "Preserve existing validity dates"}, - {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"}, + {"set_issuer", OPT_ISSU, 's', "Set or override certificate issuer"}, + {"set_subject", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"}, + {"subj", OPT_SUBJ, 's', "Alias for -set_subject"}, {"force_pubkey", OPT_FORCE_PUBKEY, '<', - "Place the given key in new certificate"}, + "Key to be placed in new certificate or certificate request"}, {"clrext", OPT_CLREXT, '-', "Do not take over any extensions from the source certificate or request"}, {"extfile", OPT_EXTFILE, '<', "Config file with X509V3 extensions to add"}, @@ -261,8 +270,8 @@ int x509_main(int argc, char **argv) EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL; EVP_PKEY *pkey; int newcert = 0; - char *subj = NULL, *digest = NULL; - X509_NAME *fsubj = NULL; + char *issu = NULL, *subj = NULL, *digest = NULL; + X509_NAME *fissu = NULL, *fsubj = NULL; const unsigned long chtype = MBSTRING_ASC; const int multirdn = 1; STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL; @@ -275,7 +284,7 @@ int x509_main(int argc, char **argv) char *ext_names = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL; - char *prog; + char *prog, *not_before = NULL, *not_after = NULL; int days = UNSET_DAYS; /* not explicitly set */ int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0; int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF; @@ -299,9 +308,10 @@ int x509_main(int argc, char **argv) ctx = X509_STORE_new(); if (ctx == NULL) - goto end; + goto err; X509_STORE_set_verify_cb(ctx, callb); + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, x509_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -309,7 +319,7 @@ int x509_main(int argc, char **argv) case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - goto end; + goto err; case OPT_HELP: opt_help(x509_options); ret = 0; @@ -348,14 +358,14 @@ int x509_main(int argc, char **argv) if (!set_dateopt(&dateopt, opt_arg())) { BIO_printf(bio_err, "Invalid date format: %s\n", opt_arg()); - goto end; + goto err; } break; case OPT_COPY_EXTENSIONS: if (!set_ext_copy(&ext_copy, opt_arg())) { BIO_printf(bio_err, "Invalid extension copy option: %s\n", opt_arg()); - goto end; + goto err; } break; @@ -371,12 +381,18 @@ int x509_main(int argc, char **argv) if (!vfyopts || !sk_OPENSSL_STRING_push(vfyopts, opt_arg())) goto opthelp; break; + case OPT_NOT_BEFORE: + not_before = opt_arg(); + break; + case OPT_NOT_AFTER: + not_after = opt_arg(); + break; case OPT_DAYS: days = atoi(opt_arg()); - if (days < -1) { + if (days <= UNSET_DAYS) { BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", prog); - goto end; + goto err; } break; case OPT_PASSIN: @@ -423,6 +439,9 @@ int x509_main(int argc, char **argv) case OPT_FORCE_PUBKEY: pubkeyfile = opt_arg(); break; + case OPT_ISSU: + issu = opt_arg(); + break; case OPT_SUBJ: subj = opt_arg(); break; @@ -434,7 +453,8 @@ int x509_main(int argc, char **argv) prog, opt_arg()); goto opthelp; } - sk_ASN1_OBJECT_push(trust, objtmp); + if (!sk_ASN1_OBJECT_push(trust, objtmp)) + goto end; trustout = 1; break; case OPT_ADDREJECT: @@ -445,7 +465,8 @@ int x509_main(int argc, char **argv) prog, opt_arg()); goto opthelp; } - sk_ASN1_OBJECT_push(reject, objtmp); + if (!sk_ASN1_OBJECT_push(trust, objtmp)) + goto end; trustout = 1; break; case OPT_SETALIAS: @@ -592,25 +613,36 @@ int x509_main(int argc, char **argv) break; } } - /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) goto opthelp; if (!app_RAND_load()) goto end; + if (!opt_check_md(digest)) + goto opthelp; + + if (preserve_dates && not_before != NULL) { + BIO_printf(bio_err, "Cannot use -preserve_dates with -not_before option\n"); + goto err; + } + if (preserve_dates && not_after != NULL) { + BIO_printf(bio_err, "Cannot use -preserve_dates with -not_after option\n"); + goto err; + } if (preserve_dates && days != UNSET_DAYS) { BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n"); - goto end; + goto err; } if (days == UNSET_DAYS) days = DEFAULT_DAYS; + else if (not_after != NULL) + BIO_printf(bio_err, "Warning: -not_after option overriding -days option\n"); if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); - goto end; + goto err; } if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(), @@ -619,12 +651,11 @@ int x509_main(int argc, char **argv) if (newcert && infile != NULL) { BIO_printf(bio_err, "The -in option cannot be used with -new\n"); - goto end; + goto err; } if (newcert && reqfile) { - BIO_printf(bio_err, - "The -req option cannot be used with -new\n"); - goto end; + BIO_printf(bio_err, "The -req option cannot be used with -new\n"); + goto err; } if (privkeyfile != NULL) { privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key"); @@ -641,14 +672,17 @@ int x509_main(int argc, char **argv) if (subj == NULL) { BIO_printf(bio_err, "The -new option requires a subject to be set using -subj\n"); - goto end; + goto err; } if (privkeyfile == NULL && pubkeyfile == NULL) { BIO_printf(bio_err, "The -new option requires using the -key or -force_pubkey option\n"); - goto end; + goto err; } } + if (issu != NULL + && (fissu = parse_name(issu, chtype, multirdn, "issuer")) == NULL) + goto end; if (subj != NULL && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL) goto end; @@ -658,7 +692,7 @@ int x509_main(int argc, char **argv) if (CAfile != NULL) { if (privkeyfile != NULL) { BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n"); - goto end; + goto err; } } else { #define WARN_NO_CA(opt) BIO_printf(bio_err, \ @@ -685,36 +719,38 @@ int x509_main(int argc, char **argv) if ((extconf = app_load_config(extfile)) == NULL) goto end; if (extsect == NULL) { - extsect = NCONF_get_string(extconf, "default", "extensions"); - if (extsect == NULL) { - ERR_clear_error(); + extsect = app_conf_try_string(extconf, "default", "extensions"); + if (extsect == NULL) extsect = "default"; - } } X509V3_set_ctx_test(&ctx2); X509V3_set_nconf(&ctx2, extconf); if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error checking extension section %s\n", extsect); - goto end; + goto err; } } if (reqfile) { - req = load_csr(infile, informat, "certificate request input"); + if (infile == NULL && isatty(fileno_stdin())) + BIO_printf(bio_err, + "Warning: Reading cert request from stdin since no -in option is given\n"); + req = load_csr_autofmt(infile, informat, vfyopts, + "certificate request input"); if (req == NULL) goto end; if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { BIO_printf(bio_err, "Error unpacking public key from CSR\n"); - goto end; + goto err; } i = do_X509_REQ_verify(req, pkey, vfyopts); if (i <= 0) { BIO_printf(bio_err, i < 0 ? "Error while verifying certificate request self-signature\n" : "Certificate request self-signature did not match the contents\n"); - goto end; + goto err; } BIO_printf(bio_err, "Certificate request self-signature ok\n"); @@ -731,7 +767,7 @@ int x509_main(int argc, char **argv) if (privkeyfile == NULL && CAkeyfile == NULL) { BIO_printf(bio_err, "We need a private key to sign with, use -key or -CAkey or -CA with private key\n"); - goto end; + goto err; } if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; @@ -743,13 +779,16 @@ int x509_main(int argc, char **argv) if (req != NULL && ext_copy != EXT_COPY_UNSET) { if (clrext && ext_copy != EXT_COPY_NONE) { BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); - goto end; + goto err; } else if (!copy_extensions(x, req, ext_copy)) { BIO_printf(bio_err, "Error copying extensions from request\n"); - goto end; + goto err; } } } else { + if (infile == NULL && isatty(fileno_stdin())) + BIO_printf(bio_err, + "Warning: Reading certificate from stdin since no -in or -new option is given\n"); x = load_cert_pass(infile, informat, 1, passin, "certificate"); if (x == NULL) goto end; @@ -774,9 +813,6 @@ int x509_main(int argc, char **argv) if (out == NULL) goto end; - if (!noout || text || next_serial) - OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); - if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); @@ -814,16 +850,25 @@ int x509_main(int argc, char **argv) goto end; if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x)) goto end; + } else { + if (privkey != NULL && !cert_matches_key(x, privkey)) + BIO_printf(bio_err, + "Warning: Signature key and public key of cert do not match\n"); } if (sno != NULL && !X509_set_serialNumber(x, sno)) goto end; if (reqfile || newcert || privkey != NULL || CAfile != NULL) { - if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) - goto end; - if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) + if (!preserve_dates && !set_cert_times(x, not_before, not_after, days, 1)) goto end; + if (fissu != NULL) { + if (!X509_set_issuer_name(x, fissu)) + goto end; + } else { + if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) + goto end; + } } X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE); @@ -837,7 +882,7 @@ int x509_main(int argc, char **argv) if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) { BIO_printf(bio_err, "Error adding extensions from section %s\n", extsect); - goto end; + goto err; } } @@ -846,17 +891,17 @@ int x509_main(int argc, char **argv) pkey = X509_get0_pubkey(x); if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) { BIO_printf(bio_err, "Error getting public key\n"); - goto end; + goto err; } if (x509toreq) { /* also works in conjunction with -req */ if (privkey == NULL) { BIO_printf(bio_err, "Must specify request signing key using -key\n"); - goto end; + goto err; } if (clrext && ext_copy != EXT_COPY_NONE) { BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); - goto end; + goto err; } if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL) goto end; @@ -865,7 +910,7 @@ int x509_main(int argc, char **argv) if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) { BIO_printf(bio_err, "Error adding request extensions from section %s\n", extsect); - goto end; + goto err; } } if (!do_X509_REQ_sign(rq, privkey, digest, sigopts)) @@ -880,13 +925,10 @@ int x509_main(int argc, char **argv) if (!i) { BIO_printf(bio_err, "Unable to write certificate request\n"); - goto end; + goto err; } } noout = 1; - } else if (privkey != NULL) { - if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx)) - goto end; } else if (CAfile != NULL) { if ((CAkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA private key")) == NULL) @@ -894,10 +936,13 @@ int x509_main(int argc, char **argv) if (!X509_check_private_key(xca, CAkey)) { BIO_printf(bio_err, "CA certificate and CA private key do not match\n"); - goto end; + goto err; } - if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx)) + if (!do_X509_sign(x, 0, CAkey, digest, sigopts, &ext_ctx)) + goto end; + } else if (privkey != NULL) { + if (!do_X509_sign(x, 0, privkey, digest, sigopts, &ext_ctx)) goto end; } if (badsig) { @@ -1007,13 +1052,13 @@ int x509_main(int argc, char **argv) if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname, app_get0_propq())) == NULL) { BIO_printf(bio_err, "Unknown digest\n"); - goto end; + goto err; } digres = X509_digest(x, fdig, md, &n); EVP_MD_free(fdig); if (!digres) { BIO_printf(bio_err, "Out of memory\n"); - goto end; + goto err; } BIO_printf(out, "%s Fingerprint=", fdigname); @@ -1037,7 +1082,8 @@ int x509_main(int argc, char **argv) goto end; } - print_cert_checks(out, x, checkhost, checkemail, checkip); + if (!check_cert_attributes(out, x, checkhost, checkemail, checkip, 1)) + goto err; if (noout || nocert) { ret = 0; @@ -1053,20 +1099,24 @@ int x509_main(int argc, char **argv) i = PEM_write_bio_X509(out, x); } else { BIO_printf(bio_err, "Bad output format specified for outfile\n"); - goto end; + goto err; } if (!i) { BIO_printf(bio_err, "Unable to write certificate\n"); - goto end; + goto err; } + ret = 0; + goto end; + + err: + ERR_print_errors(bio_err); end: - if (ret != 0) - ERR_print_errors(bio_err); NCONF_free(extconf); BIO_free_all(out); X509_STORE_free(ctx); + X509_NAME_free(fissu); X509_NAME_free(fsubj); X509_REQ_free(req); X509_free(x); @@ -1137,16 +1187,7 @@ static int callb(int ok, X509_STORE_CTX *ctx) if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) return 1; - /* - * BAD we should have gotten an error. Normally if everything worked - * X509_STORE_CTX_get_error(ctx) will still be set to - * DEPTH_ZERO_SELF_.... - */ - if (ok) { - BIO_printf(bio_err, - "Error with certificate to be certified - should be self-signed\n"); - return 0; - } else { + if (!ok) { err_cert = X509_STORE_CTX_get_current_cert(ctx); print_name(bio_err, "subject=", X509_get_subject_name(err_cert)); BIO_printf(bio_err, @@ -1155,6 +1196,8 @@ static int callb(int ok, X509_STORE_CTX *ctx) X509_verify_cert_error_string(err)); return 1; } + + return 1; } static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt) diff --git a/build.info b/build.info index 5a8421623b97..22c7c8a94b1f 100644 --- a/build.info +++ b/build.info @@ -5,9 +5,13 @@ SUBDIRS=crypto ssl apps util tools fuzz providers doc IF[{- !$disabled{tests} -}] SUBDIRS=test ENDIF +IF[{- !$disabled{demos} -}] + SUBDIRS=demos +ENDIF IF[{- !$disabled{'deprecated-3.0'} -}] SUBDIRS=engines ENDIF +SUBDIRS=exporters LIBS=libcrypto libssl INCLUDE[libcrypto]=. include @@ -22,6 +26,8 @@ DEPEND[]=include/openssl/asn1.h \ include/openssl/cmp.h \ include/openssl/cms.h \ include/openssl/conf.h \ + include/openssl/comp.h \ + include/openssl/core_names.h \ include/openssl/crmf.h \ include/openssl/crypto.h \ include/openssl/ct.h \ @@ -39,8 +45,10 @@ DEPEND[]=include/openssl/asn1.h \ include/openssl/ui.h \ include/openssl/x509.h \ include/openssl/x509v3.h \ + include/openssl/x509_acert.h \ include/openssl/x509_vfy.h \ - include/crypto/bn_conf.h include/crypto/dso_conf.h + include/crypto/bn_conf.h include/crypto/dso_conf.h \ + include/internal/param_names.h crypto/params_idx.c GENERATE[include/openssl/asn1.h]=include/openssl/asn1.h.in GENERATE[include/openssl/asn1t.h]=include/openssl/asn1t.h.in @@ -48,6 +56,7 @@ GENERATE[include/openssl/bio.h]=include/openssl/bio.h.in GENERATE[include/openssl/cmp.h]=include/openssl/cmp.h.in GENERATE[include/openssl/cms.h]=include/openssl/cms.h.in GENERATE[include/openssl/conf.h]=include/openssl/conf.h.in +GENERATE[include/openssl/comp.h]=include/openssl/comp.h.in # include/openssl/configuration.h is generated by configdata.pm # We still need this information for the FIPS module checksum, but the attribute # 'skip' ensures that nothing is actually done with it. @@ -69,10 +78,18 @@ GENERATE[include/openssl/ssl.h]=include/openssl/ssl.h.in GENERATE[include/openssl/ui.h]=include/openssl/ui.h.in GENERATE[include/openssl/x509.h]=include/openssl/x509.h.in GENERATE[include/openssl/x509v3.h]=include/openssl/x509v3.h.in +GENERATE[include/openssl/x509_acert.h]=include/openssl/x509_acert.h.in GENERATE[include/openssl/x509_vfy.h]=include/openssl/x509_vfy.h.in GENERATE[include/crypto/bn_conf.h]=include/crypto/bn_conf.h.in GENERATE[include/crypto/dso_conf.h]=include/crypto/dso_conf.h.in +DEPEND[crypto/params_idx.c \ + include/internal/param_names.h \ + include/openssl/core_names.h]=util/perl|OpenSSL/paramnames.pm +GENERATE[crypto/params_idx.c]=crypto/params_idx.c.in +GENERATE[include/internal/param_names.h]=include/internal/param_names.h.in +GENERATE[include/openssl/core_names.h]=include/openssl/core_names.h.in + IF[{- defined $target{shared_defflag} -}] SHARED_SOURCE[libcrypto]=libcrypto.ld SHARED_SOURCE[libssl]=libssl.ld @@ -90,3 +107,33 @@ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] SHARED_SOURCE[libcrypto]=libcrypto.rc SHARED_SOURCE[libssl]=libssl.rc ENDIF + +# This file sets the build directory up for CMake inclusion +# Note: This generation of OpenSSLConfig[Version].cmake is used +# for building openssl locally, and so the build variables are +# taken from builddata.pm rather than installdata.pm. For exportable +# versions of these generated files, you'll find them in the exporters +# directory +GENERATE[OpenSSLConfig.cmake]=exporters/cmake/OpenSSLConfig.cmake.in +DEPEND[OpenSSLConfig.cmake]=builddata.pm +GENERATE[OpenSSLConfigVersion.cmake]=exporters/cmake/OpenSSLConfigVersion.cmake.in +DEPEND[OpenSSLConfigVersion.cmake]=builddata.pm +DEPEND[OpenSSLConfigVersion.cmake]=OpenSSLConfig.cmake +DEPEND[""]=OpenSSLConfigVersion.cmake + +# This file sets the build directory up for pkg-config +GENERATE[libcrypto.pc]=exporters/pkg-config/libcrypto.pc.in +DEPEND[libcrypto.pc]=builddata.pm +GENERATE[libssl.pc]=exporters/pkg-config/libssl.pc.in +DEPEND[libssl.pc]=builddata.pm +GENERATE[openssl.pc]=exporters/pkg-config/openssl.pc.in +DEPEND[openssl.pc]=builddata.pm +DEPEND[openssl.pc]=libcrypto.pc libssl.pc + +GENERATE[builddata.pm]=util/mkinstallvars.pl \ + PREFIX=. BINDIR=apps APPLINKDIR=ms \ + LIBDIR= INCLUDEDIR=include "INCLUDEDIR=$(SRCDIR)/include" \ + ENGINESDIR=engines MODULESDIR=providers \ + "VERSION=$(VERSION)" "LDLIBS=$(LIB_EX_LIBS)" + +DEPEND[""]=openssl.pc diff --git a/configdata.pm.in b/configdata.pm.in index a4ae90729995..fea6004d6c9d 100644 --- a/configdata.pm.in +++ b/configdata.pm.in @@ -20,7 +20,7 @@ # Unix form /VOLUME/DIR1/DIR2/FILE, which is what VMS perl supports # for 'use lib'. - # Start with spliting the native path + # Start with splitting the native path (my $vol, my $dirs, my $file) = File::Spec->splitpath($path); my @dirs = File::Spec->splitdir($dirs); @@ -89,7 +89,7 @@ unless (caller) { if (scalar @ARGV == 0) { # With no arguments, re-create the build file # We do that in two steps, where the first step emits perl - # snipets. + # snippets. my $buildfile = $config{build_file}; my $buildfile_template = "$buildfile.in"; diff --git a/crypto/aes/aes_x86core.c b/crypto/aes/aes_x86core.c index da525b6566c4..3e5b24ed193d 100644 --- a/crypto/aes/aes_x86core.c +++ b/crypto/aes/aes_x86core.c @@ -63,12 +63,13 @@ #if 1 static void prefetch256(const void *table) { - volatile unsigned long *t=(void *)table,ret; + volatile unsigned long *t = (void *)table, ret; unsigned long sum; int i; /* 32 is common least cache-line size */ - for (sum=0,i=0;i<256/sizeof(t[0]);i+=32/sizeof(t[0])) sum ^= t[i]; + for (sum = 0, i = 0; i < 256/sizeof(t[0]); i += 32/sizeof(t[0])) + sum ^= t[i]; ret = sum; } @@ -80,13 +81,10 @@ static void prefetch256(const void *table) #define GETU32(p) (*((u32*)(p))) #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) -typedef unsigned __int64 u64; #define U64(C) C##UI64 #elif defined(__arch64__) -typedef unsigned long u64; #define U64(C) C##UL #else -typedef unsigned long long u64; #define U64(C) C##ULL #endif diff --git a/crypto/aes/asm/aes-x86_64.pl b/crypto/aes/asm/aes-x86_64.pl index 25f7ded947ed..8c7b205a0512 100755 --- a/crypto/aes/asm/aes-x86_64.pl +++ b/crypto/aes/asm/aes-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -2221,6 +2221,7 @@ ___ } $code.=<<___; +.section .rodata align=64 .align 64 .LAES_Te: ___ @@ -2643,6 +2644,7 @@ $code.=<<___; .long 0x1b1b1b1b, 0x1b1b1b1b, 0, 0 .asciz "AES for x86_64, CRYPTOGAMS by " .align 64 +.previous ___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, diff --git a/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/aes/asm/aesni-sha1-x86_64.pl index dbe33a3f1a02..4e8fa1d753d7 100644 --- a/crypto/aes/asm/aesni-sha1-x86_64.pl +++ b/crypto/aes/asm/aesni-sha1-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1738,6 +1738,7 @@ ___ }}} } $code.=<<___; +.section .rodata align=64 .align 64 K_XX_XX: .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 @@ -1749,6 +1750,7 @@ K_XX_XX: .asciz "AESNI-CBC+SHA1 stitch for x86_64, CRYPTOGAMS by " .align 64 +.previous ___ if ($shaext) {{{ ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10"); diff --git a/crypto/aes/asm/aesni-sha256-x86_64.pl b/crypto/aes/asm/aesni-sha256-x86_64.pl index 5521766a6a7d..39d29ddbb022 100644 --- a/crypto/aes/asm/aesni-sha256-x86_64.pl +++ b/crypto/aes/asm/aesni-sha256-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -168,6 +168,7 @@ $code.=<<___; .cfi_endproc .size $func,.-$func +.section .rodata align=64 .align 64 .type $TABLE,\@object $TABLE: @@ -210,6 +211,7 @@ $TABLE: .long 0,0,0,0, 0,0,0,0 .asciz "AESNI-CBC+SHA256 stitch for x86_64, CRYPTOGAMS by " .align 64 +.previous ___ ###################################################################### diff --git a/crypto/aes/asm/aesni-x86.pl b/crypto/aes/asm/aesni-x86.pl index d8cc378b5f9b..7cf838db170b 100644 --- a/crypto/aes/asm/aesni-x86.pl +++ b/crypto/aes/asm/aesni-x86.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/aes/asm/aesni-x86_64.pl b/crypto/aes/asm/aesni-x86_64.pl index 09c8f78890ed..bff33f2b8dcd 100644 --- a/crypto/aes/asm/aesni-x86_64.pl +++ b/crypto/aes/asm/aesni-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2009-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -4743,6 +4743,7 @@ ___ } $code.=<<___; +.section .rodata align=64 .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -4765,6 +4766,7 @@ $code.=<<___; .asciz "AES for Intel AES-NI, CRYPTOGAMS by " .align 64 +.previous ___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, diff --git a/crypto/aes/asm/aesp8-ppc.pl b/crypto/aes/asm/aesp8-ppc.pl index f7f78d04b0e1..38b9405a283b 100755 --- a/crypto/aes/asm/aesp8-ppc.pl +++ b/crypto/aes/asm/aesp8-ppc.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl index d0e0be6187bd..4f503a31ca67 100755 --- a/crypto/aes/asm/aesv8-armx.pl +++ b/crypto/aes/asm/aesv8-armx.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -106,13 +106,21 @@ my ($zero,$rcon,$mask,$in0,$in1,$tmp,$key)= $flavour=~/64/? map("q$_",(0..6)) : map("q$_",(0..3,8..10)); +# +# This file generates .s file for 64-bit and 32-bit CPUs. +# We don't implement .rodata on 32-bit CPUs yet. +# +$code.=".rodata\n" if ($flavour =~ /64/); $code.=<<___; .align 5 .Lrcon: .long 0x01,0x01,0x01,0x01 .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d // rotate-n-splat .long 0x1b,0x1b,0x1b,0x1b +___ +$code.=".previous\n" if ($flavour =~ /64/); +$code.=<<___; .globl ${prefix}_set_encrypt_key .type ${prefix}_set_encrypt_key,%function .align 5 @@ -120,6 +128,8 @@ ${prefix}_set_encrypt_key: .Lenc_key: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 ___ @@ -137,7 +147,15 @@ $code.=<<___; tst $bits,#0x3f b.ne .Lenc_key_abort +___ +$code.=<<___ if ($flavour =~ /64/); + adrp $ptr,.Lrcon + add $ptr,$ptr,:lo12:.Lrcon +___ +$code.=<<___ if ($flavour =~ /32/); adr $ptr,.Lrcon +___ +$code.=<<___; cmp $bits,#192 veor $zero,$zero,$zero @@ -295,7 +313,7 @@ $code.=<<___; ${prefix}_set_decrypt_key: ___ $code.=<<___ if ($flavour =~ /64/); - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 ___ @@ -339,7 +357,7 @@ $code.=<<___ if ($flavour !~ /64/); ___ $code.=<<___ if ($flavour =~ /64/); ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret ___ $code.=<<___; @@ -359,6 +377,11 @@ $code.=<<___; .type ${prefix}_${dir}crypt,%function .align 5 ${prefix}_${dir}crypt: +___ +$code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET +___ +$code.=<<___; ldr $rounds,[$key,#240] vld1.32 {$rndkey0},[$key],#16 vld1.8 {$inout},[$inp] @@ -410,7 +433,7 @@ ___ # 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 +# = 16 bytes, we will treat it separately to improve the # performance: one independent code block without LR, FP load and # store, just looks like what the original ECB implementation does. @@ -442,6 +465,7 @@ $code.=<<___; ${prefix}_ecb_encrypt: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET subs $len,$len,#16 // Original input data size bigger than 16, jump to big size processing. b.ne .Lecb_big_size @@ -1236,6 +1260,8 @@ $code.=<<___; ${prefix}_cbc_encrypt: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 ___ @@ -1741,6 +1767,755 @@ $code.=<<___; .size ${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt ___ }}} + +{{{ +my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); +my ($rounds,$roundsx,$cnt,$key_)=("w5","x5","w6","x7"); +my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12)); +my ($tctr3,$tctr4,$tctr5,$tctr6)=map("w$_",(11,13..15)); +my ($tctr7,$tctr8,$tctr9,$tctr10,$tctr11)=map("w$_",(19..23)); + +# q0-q7 => v0-v7; q8-q23 => v16-v31; q24-q31 => v8-v15 +my ($ivec,$rndlast,$rndping,$rndpang)=map("q$_",(0..3)); +my ($in0,$in1,$in2,$in3,$in4,$in5)=map("q$_",(4..9)); +my ($in6,$in7,$in8,$in9,$in10,$in11)=map("q$_",(10..15)); +my ($dat0,$dat1,$dat2,$dat3,$dat4,$dat5)=map("q$_",(16..21)); +my ($dat6,$dat7,$dat8,$dat9,$dat10,$dat11)=map("q$_",(22..27)); +my ($tmp0,$tmp1,$tmp2)=map("q$_",(25..27)); + +#q_X => qX, for ldp & stp +my ($in0q,$in1q,$in2q,$in3q)=map("q_$_",(4..7)); +my ($in4q,$in5q,$in6q,$in7q,$in8q,$in9q,$in10q,$in11q)=map("q_$_",(16..23)); + +my ($dat8d,$dat9d,$dat10d,$dat11d)=map("d$_",(8..11)); + +$code.=<<___ if ($flavour =~ /64/); +.globl ${prefix}_ctr32_encrypt_blocks_unroll12_eor3 +.type ${prefix}_ctr32_encrypt_blocks_unroll12_eor3,%function +.align 5 +${prefix}_ctr32_encrypt_blocks_unroll12_eor3: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. + stp x29,x30,[sp,#-80]! + stp d8,d9,[sp, #16] + stp d10,d11,[sp, #32] + stp d12,d13,[sp, #48] + stp d14,d15,[sp, #64] + add x29,sp,#0 + + ldr $rounds,[$key,#240] + + ldr $ctr, [$ivp, #12] +#ifdef __AARCH64EB__ + vld1.8 {$dat0},[$ivp] +#else + vld1.32 {$dat0},[$ivp] +#endif + vld1.32 {$rndping-$rndpang},[$key] // load key schedule... + sub $rounds,$rounds,#4 + cmp $len,#2 + add $key_,$key,$roundsx,lsl#4 // pointer to last round key + sub $rounds,$rounds,#2 + add $key_, $key_, #64 + vld1.32 {$rndlast},[$key_] + add $key_,$key,#32 + mov $cnt,$rounds +#ifndef __AARCH64EB__ + rev $ctr, $ctr +#endif + + 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_unroll + cmp $len,#6 + rev $tctr2, $ctr + sub $len,$len,#3 // bias + vmov.32 ${dat2}[3],$tctr2 + b.lo .Loop3x_ctr32_unroll + cmp $len,#9 + vorr $dat3,$dat0,$dat0 + add $tctr3, $ctr, #1 + vorr $dat4,$dat0,$dat0 + add $tctr4, $ctr, #2 + rev $tctr3, $tctr3 + vorr $dat5,$dat0,$dat0 + add $ctr, $ctr, #3 + rev $tctr4, $tctr4 + vmov.32 ${dat3}[3],$tctr3 + rev $tctr5, $ctr + vmov.32 ${dat4}[3],$tctr4 + vmov.32 ${dat5}[3],$tctr5 + sub $len,$len,#3 + b.lo .Loop6x_ctr32_unroll + + // push regs to stack when 12 data chunks are interleaved + stp x19,x20,[sp,#-16]! + stp x21,x22,[sp,#-16]! + stp x23,x24,[sp,#-16]! + stp $dat8d,$dat9d,[sp,#-32]! + stp $dat10d,$dat11d,[sp,#-32]! + + add $tctr6,$ctr,#1 + add $tctr7,$ctr,#2 + add $tctr8,$ctr,#3 + add $tctr9,$ctr,#4 + add $tctr10,$ctr,#5 + add $ctr,$ctr,#6 + vorr $dat6,$dat0,$dat0 + rev $tctr6,$tctr6 + vorr $dat7,$dat0,$dat0 + rev $tctr7,$tctr7 + vorr $dat8,$dat0,$dat0 + rev $tctr8,$tctr8 + vorr $dat9,$dat0,$dat0 + rev $tctr9,$tctr9 + vorr $dat10,$dat0,$dat0 + rev $tctr10,$tctr10 + vorr $dat11,$dat0,$dat0 + rev $tctr11,$ctr + + sub $len,$len,#6 // bias + vmov.32 ${dat6}[3],$tctr6 + vmov.32 ${dat7}[3],$tctr7 + vmov.32 ${dat8}[3],$tctr8 + vmov.32 ${dat9}[3],$tctr9 + vmov.32 ${dat10}[3],$tctr10 + vmov.32 ${dat11}[3],$tctr11 + b .Loop12x_ctr32_unroll + +.align 4 +.Loop12x_ctr32_unroll: + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + aese $dat6,$rndping + aesmc $dat6,$dat6 + aese $dat7,$rndping + aesmc $dat7,$dat7 + aese $dat8,$rndping + aesmc $dat8,$dat8 + aese $dat9,$rndping + aesmc $dat9,$dat9 + aese $dat10,$rndping + aesmc $dat10,$dat10 + aese $dat11,$rndping + aesmc $dat11,$dat11 + vld1.32 {$rndping},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + aese $dat6,$rndpang + aesmc $dat6,$dat6 + aese $dat7,$rndpang + aesmc $dat7,$dat7 + aese $dat8,$rndpang + aesmc $dat8,$dat8 + aese $dat9,$rndpang + aesmc $dat9,$dat9 + aese $dat10,$rndpang + aesmc $dat10,$dat10 + aese $dat11,$rndpang + aesmc $dat11,$dat11 + vld1.32 {$rndpang},[$key_],#16 + b.gt .Loop12x_ctr32_unroll + + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + aese $dat6,$rndping + aesmc $dat6,$dat6 + aese $dat7,$rndping + aesmc $dat7,$dat7 + aese $dat8,$rndping + aesmc $dat8,$dat8 + aese $dat9,$rndping + aesmc $dat9,$dat9 + aese $dat10,$rndping + aesmc $dat10,$dat10 + aese $dat11,$rndping + aesmc $dat11,$dat11 + vld1.32 {$rndping},[$key_],#16 + + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + aese $dat6,$rndpang + aesmc $dat6,$dat6 + aese $dat7,$rndpang + aesmc $dat7,$dat7 + aese $dat8,$rndpang + aesmc $dat8,$dat8 + aese $dat9,$rndpang + aesmc $dat9,$dat9 + aese $dat10,$rndpang + aesmc $dat10,$dat10 + aese $dat11,$rndpang + aesmc $dat11,$dat11 + vld1.32 {$rndpang},[$key_],#16 + + aese $dat0,$rndping + aesmc $dat0,$dat0 + add $tctr0,$ctr,#1 + add $tctr1,$ctr,#2 + aese $dat1,$rndping + aesmc $dat1,$dat1 + add $tctr2,$ctr,#3 + add $tctr3,$ctr,#4 + aese $dat2,$rndping + aesmc $dat2,$dat2 + add $tctr4,$ctr,#5 + add $tctr5,$ctr,#6 + rev $tctr0,$tctr0 + aese $dat3,$rndping + aesmc $dat3,$dat3 + add $tctr6,$ctr,#7 + add $tctr7,$ctr,#8 + rev $tctr1,$tctr1 + rev $tctr2,$tctr2 + aese $dat4,$rndping + aesmc $dat4,$dat4 + add $tctr8,$ctr,#9 + add $tctr9,$ctr,#10 + rev $tctr3,$tctr3 + rev $tctr4,$tctr4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + add $tctr10,$ctr,#11 + add $tctr11,$ctr,#12 + rev $tctr5,$tctr5 + rev $tctr6,$tctr6 + aese $dat6,$rndping + aesmc $dat6,$dat6 + rev $tctr7,$tctr7 + rev $tctr8,$tctr8 + aese $dat7,$rndping + aesmc $dat7,$dat7 + rev $tctr9,$tctr9 + rev $tctr10,$tctr10 + aese $dat8,$rndping + aesmc $dat8,$dat8 + rev $tctr11,$tctr11 + aese $dat9,$rndping + aesmc $dat9,$dat9 + aese $dat10,$rndping + aesmc $dat10,$dat10 + aese $dat11,$rndping + aesmc $dat11,$dat11 + vld1.32 {$rndping},[$key_],#16 + + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + vld1.8 {$in0,$in1,$in2,$in3},[$inp],#64 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + aese $dat6,$rndpang + aesmc $dat6,$dat6 + aese $dat7,$rndpang + aesmc $dat7,$dat7 + vld1.8 {$in4,$in5,$in6,$in7},[$inp],#64 + aese $dat8,$rndpang + aesmc $dat8,$dat8 + aese $dat9,$rndpang + aesmc $dat9,$dat9 + aese $dat10,$rndpang + aesmc $dat10,$dat10 + aese $dat11,$rndpang + aesmc $dat11,$dat11 + vld1.8 {$in8,$in9,$in10,$in11},[$inp],#64 + vld1.32 {$rndpang},[$key_],#16 + + mov $key_, $key + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + aese $dat6,$rndping + aesmc $dat6,$dat6 + aese $dat7,$rndping + aesmc $dat7,$dat7 + aese $dat8,$rndping + aesmc $dat8,$dat8 + aese $dat9,$rndping + aesmc $dat9,$dat9 + aese $dat10,$rndping + aesmc $dat10,$dat10 + aese $dat11,$rndping + aesmc $dat11,$dat11 + vld1.32 {$rndping},[$key_],#16 // re-pre-load rndkey[0] + + aese $dat0,$rndpang + eor3 $in0,$in0,$rndlast,$dat0 + vorr $dat0,$ivec,$ivec + aese $dat1,$rndpang + eor3 $in1,$in1,$rndlast,$dat1 + vorr $dat1,$ivec,$ivec + aese $dat2,$rndpang + eor3 $in2,$in2,$rndlast,$dat2 + vorr $dat2,$ivec,$ivec + aese $dat3,$rndpang + eor3 $in3,$in3,$rndlast,$dat3 + vorr $dat3,$ivec,$ivec + aese $dat4,$rndpang + eor3 $in4,$in4,$rndlast,$dat4 + vorr $dat4,$ivec,$ivec + aese $dat5,$rndpang + eor3 $in5,$in5,$rndlast,$dat5 + vorr $dat5,$ivec,$ivec + aese $dat6,$rndpang + eor3 $in6,$in6,$rndlast,$dat6 + vorr $dat6,$ivec,$ivec + aese $dat7,$rndpang + eor3 $in7,$in7,$rndlast,$dat7 + vorr $dat7,$ivec,$ivec + aese $dat8,$rndpang + eor3 $in8,$in8,$rndlast,$dat8 + vorr $dat8,$ivec,$ivec + aese $dat9,$rndpang + eor3 $in9,$in9,$rndlast,$dat9 + vorr $dat9,$ivec,$ivec + aese $dat10,$rndpang + eor3 $in10,$in10,$rndlast,$dat10 + vorr $dat10,$ivec,$ivec + aese $dat11,$rndpang + eor3 $in11,$in11,$rndlast,$dat11 + vorr $dat11,$ivec,$ivec + vld1.32 {$rndpang},[$key_],#16 // re-pre-load rndkey[1] + + vmov.32 ${dat0}[3],$tctr0 + vmov.32 ${dat1}[3],$tctr1 + vmov.32 ${dat2}[3],$tctr2 + vmov.32 ${dat3}[3],$tctr3 + vst1.8 {$in0,$in1,$in2,$in3},[$out],#64 + vmov.32 ${dat4}[3],$tctr4 + vmov.32 ${dat5}[3],$tctr5 + vmov.32 ${dat6}[3],$tctr6 + vmov.32 ${dat7}[3],$tctr7 + vst1.8 {$in4,$in5,$in6,$in7},[$out],#64 + vmov.32 ${dat8}[3],$tctr8 + vmov.32 ${dat9}[3],$tctr9 + vmov.32 ${dat10}[3],$tctr10 + vmov.32 ${dat11}[3],$tctr11 + vst1.8 {$in8,$in9,$in10,$in11},[$out],#64 + + mov $cnt,$rounds + + add $ctr,$ctr,#12 + subs $len,$len,#12 + b.hs .Loop12x_ctr32_unroll + + // pop regs from stack when 12 data chunks are interleaved + ldp $dat10d,$dat11d,[sp],#32 + ldp $dat8d,$dat9d,[sp],#32 + ldp x23,x24,[sp],#16 + ldp x21,x22,[sp],#16 + ldp x19,x20,[sp],#16 + + add $len,$len,#12 + cbz $len,.Lctr32_done_unroll + sub $ctr,$ctr,#12 + + cmp $len,#2 + b.ls .Lctr32_tail_unroll + + cmp $len,#6 + sub $len,$len,#3 // bias + add $ctr,$ctr,#3 + b.lo .Loop3x_ctr32_unroll + + sub $len,$len,#3 + add $ctr,$ctr,#3 + b.lo .Loop6x_ctr32_unroll + +.align 4 +.Loop6x_ctr32_unroll: + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + vld1.32 {$rndping},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + vld1.32 {$rndpang},[$key_],#16 + b.gt .Loop6x_ctr32_unroll + + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + vld1.32 {$rndping},[$key_],#16 + + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + vld1.32 {$rndpang},[$key_],#16 + + aese $dat0,$rndping + aesmc $dat0,$dat0 + add $tctr0,$ctr,#1 + add $tctr1,$ctr,#2 + aese $dat1,$rndping + aesmc $dat1,$dat1 + add $tctr2,$ctr,#3 + add $tctr3,$ctr,#4 + aese $dat2,$rndping + aesmc $dat2,$dat2 + add $tctr4,$ctr,#5 + add $tctr5,$ctr,#6 + rev $tctr0,$tctr0 + aese $dat3,$rndping + aesmc $dat3,$dat3 + rev $tctr1,$tctr1 + rev $tctr2,$tctr2 + aese $dat4,$rndping + aesmc $dat4,$dat4 + rev $tctr3,$tctr3 + rev $tctr4,$tctr4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + rev $tctr5,$tctr5 + vld1.32 {$rndping},[$key_],#16 + + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + vld1.8 {$in0,$in1,$in2,$in3},[$inp],#64 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + aese $dat3,$rndpang + aesmc $dat3,$dat3 + vld1.8 {$in4,$in5},[$inp],#32 + aese $dat4,$rndpang + aesmc $dat4,$dat4 + aese $dat5,$rndpang + aesmc $dat5,$dat5 + vld1.32 {$rndpang},[$key_],#16 + + mov $key_, $key + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + aese $dat3,$rndping + aesmc $dat3,$dat3 + aese $dat4,$rndping + aesmc $dat4,$dat4 + aese $dat5,$rndping + aesmc $dat5,$dat5 + vld1.32 {$rndping},[$key_],#16 // re-pre-load rndkey[0] + + aese $dat0,$rndpang + eor3 $in0,$in0,$rndlast,$dat0 + aese $dat1,$rndpang + eor3 $in1,$in1,$rndlast,$dat1 + aese $dat2,$rndpang + eor3 $in2,$in2,$rndlast,$dat2 + aese $dat3,$rndpang + eor3 $in3,$in3,$rndlast,$dat3 + aese $dat4,$rndpang + eor3 $in4,$in4,$rndlast,$dat4 + aese $dat5,$rndpang + eor3 $in5,$in5,$rndlast,$dat5 + vld1.32 {$rndpang},[$key_],#16 // re-pre-load rndkey[1] + + vorr $dat0,$ivec,$ivec + vorr $dat1,$ivec,$ivec + vorr $dat2,$ivec,$ivec + vorr $dat3,$ivec,$ivec + vorr $dat4,$ivec,$ivec + vorr $dat5,$ivec,$ivec + + vmov.32 ${dat0}[3],$tctr0 + vmov.32 ${dat1}[3],$tctr1 + vst1.8 {$in0,$in1,$in2,$in3},[$out],#64 + vmov.32 ${dat2}[3],$tctr2 + vmov.32 ${dat3}[3],$tctr3 + vst1.8 {$in4,$in5},[$out],#32 + vmov.32 ${dat4}[3],$tctr4 + vmov.32 ${dat5}[3],$tctr5 + + cbz $len,.Lctr32_done_unroll + mov $cnt,$rounds + + cmp $len,#2 + b.ls .Lctr32_tail_unroll + + sub $len,$len,#3 // bias + add $ctr,$ctr,#3 + b .Loop3x_ctr32_unroll + +.align 4 +.Loop3x_ctr32_unroll: + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat2,$rndping + aesmc $dat2,$dat2 + vld1.32 {$rndping},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + aese $dat2,$rndpang + aesmc $dat2,$dat2 + vld1.32 {$rndpang},[$key_],#16 + b.gt .Loop3x_ctr32_unroll + + aese $dat0,$rndping + aesmc $tmp0,$dat0 + aese $dat1,$rndping + aesmc $tmp1,$dat1 + vld1.8 {$in0,$in1,$in2},[$inp],#48 + vorr $dat0,$ivec,$ivec + aese $dat2,$rndping + aesmc $dat2,$dat2 + vld1.32 {$rndping},[$key_],#16 + vorr $dat1,$ivec,$ivec + aese $tmp0,$rndpang + aesmc $tmp0,$tmp0 + aese $tmp1,$rndpang + aesmc $tmp1,$tmp1 + aese $dat2,$rndpang + aesmc $tmp2,$dat2 + vld1.32 {$rndpang},[$key_],#16 + vorr $dat2,$ivec,$ivec + add $tctr0,$ctr,#1 + aese $tmp0,$rndping + aesmc $tmp0,$tmp0 + aese $tmp1,$rndping + aesmc $tmp1,$tmp1 + add $tctr1,$ctr,#2 + aese $tmp2,$rndping + aesmc $tmp2,$tmp2 + vld1.32 {$rndping},[$key_],#16 + add $ctr,$ctr,#3 + aese $tmp0,$rndpang + aesmc $tmp0,$tmp0 + aese $tmp1,$rndpang + aesmc $tmp1,$tmp1 + + rev $tctr0,$tctr0 + aese $tmp2,$rndpang + aesmc $tmp2,$tmp2 + vld1.32 {$rndpang},[$key_],#16 + vmov.32 ${dat0}[3], $tctr0 + mov $key_,$key + rev $tctr1,$tctr1 + aese $tmp0,$rndping + aesmc $tmp0,$tmp0 + + aese $tmp1,$rndping + aesmc $tmp1,$tmp1 + vmov.32 ${dat1}[3], $tctr1 + rev $tctr2,$ctr + aese $tmp2,$rndping + aesmc $tmp2,$tmp2 + vmov.32 ${dat2}[3], $tctr2 + + aese $tmp0,$rndpang + aese $tmp1,$rndpang + aese $tmp2,$rndpang + + eor3 $in0,$in0,$rndlast,$tmp0 + vld1.32 {$rndping},[$key_],#16 // re-pre-load rndkey[0] + eor3 $in1,$in1,$rndlast,$tmp1 + mov $cnt,$rounds + eor3 $in2,$in2,$rndlast,$tmp2 + vld1.32 {$rndpang},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$in0,$in1,$in2},[$out],#48 + + cbz $len,.Lctr32_done_unroll + +.Lctr32_tail_unroll: + cmp $len,#1 + b.eq .Lctr32_tail_1_unroll + +.Lctr32_tail_2_unroll: + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + vld1.32 {$rndping},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + vld1.32 {$rndpang},[$key_],#16 + b.gt .Lctr32_tail_2_unroll + + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + vld1.32 {$rndping},[$key_],#16 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + vld1.32 {$rndpang},[$key_],#16 + vld1.8 {$in0,$in1},[$inp],#32 + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + vld1.32 {$rndping},[$key_],#16 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + aese $dat1,$rndpang + aesmc $dat1,$dat1 + vld1.32 {$rndpang},[$key_],#16 + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat1,$rndping + aesmc $dat1,$dat1 + aese $dat0,$rndpang + aese $dat1,$rndpang + + eor3 $in0,$in0,$rndlast,$dat0 + eor3 $in1,$in1,$rndlast,$dat1 + vst1.8 {$in0,$in1},[$out],#32 + b .Lctr32_done_unroll + +.Lctr32_tail_1_unroll: + aese $dat0,$rndping + aesmc $dat0,$dat0 + vld1.32 {$rndping},[$key_],#16 + subs $cnt,$cnt,#2 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + vld1.32 {$rndpang},[$key_],#16 + b.gt .Lctr32_tail_1_unroll + + aese $dat0,$rndping + aesmc $dat0,$dat0 + vld1.32 {$rndping},[$key_],#16 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + vld1.32 {$rndpang},[$key_],#16 + vld1.8 {$in0},[$inp] + aese $dat0,$rndping + aesmc $dat0,$dat0 + vld1.32 {$rndping},[$key_],#16 + aese $dat0,$rndpang + aesmc $dat0,$dat0 + vld1.32 {$rndpang},[$key_],#16 + aese $dat0,$rndping + aesmc $dat0,$dat0 + aese $dat0,$rndpang + + eor3 $in0,$in0,$rndlast,$dat0 + vst1.8 {$in0},[$out],#16 + +.Lctr32_done_unroll: + ldp d8,d9,[sp, #16] + ldp d10,d11,[sp, #32] + ldp d12,d13,[sp, #48] + ldp d14,d15,[sp, #64] + ldr x29,[sp],#80 + ret +.size ${prefix}_ctr32_encrypt_blocks_unroll12_eor3,.-${prefix}_ctr32_encrypt_blocks_unroll12_eor3 +___ +}}} + {{{ my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4)); my ($rounds,$cnt,$key_)=("w5","w6","x7"); @@ -1764,6 +2539,8 @@ $code.=<<___; ${prefix}_ctr32_encrypt_blocks: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 ___ @@ -2210,7 +2987,7 @@ ___ # 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 +# = 16 bytes, we will treat it separately to improve the # performance: one independent code block without LR, FP load and # store. # Encryption will process the (length -tailcnt) bytes as mentioned @@ -2256,6 +3033,7 @@ $code.=<<___ if ($flavour =~ /64/); ${prefix}_xts_encrypt: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET cmp $len,#16 // Original input data size bigger than 16, jump to big size processing. b.ne .Lxts_enc_big_size @@ -2930,6 +3708,7 @@ $code.=<<___ if ($flavour =~ /64/); .type ${prefix}_xts_decrypt,%function .align 5 ${prefix}_xts_decrypt: + AARCH64_VALID_CALL_TARGET ___ $code.=<<___ if ($flavour =~ /64/); cmp $len,#16 @@ -3543,7 +4322,7 @@ $code.=<<___ if ($flavour =~ /64/); cbnz x2,.Lxts_dec_1st_done vld1.8 {$dat0},[$inp],#16 - // Decrypt the last secod block to get the last plain text block + // Decrypt the last second block to get the last plain text block .Lxts_dec_1st_done: eor $tmpin,$dat0,$iv1 ldr $rounds,[$key1,#240] @@ -3626,7 +4405,8 @@ ___ if ($flavour =~ /64/) { ######## 64-bit code my %opcode = ( "aesd" => 0x4e285800, "aese" => 0x4e284800, - "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800 ); + "aesimc"=> 0x4e287800, "aesmc" => 0x4e286800, + "eor3" => 0xce000000, ); local *unaes = sub { my ($mnemonic,$arg)=@_; @@ -3637,10 +4417,21 @@ if ($flavour =~ /64/) { ######## 64-bit code $mnemonic,$arg; }; + sub unsha3 { + my ($mnemonic,$arg)=@_; + + $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv#]([0-9\-]+))?)?/ + && + sprintf ".inst\t0x%08x\t//%s %s", + $opcode{$mnemonic}|$1|($2<<5)|($3<<16)|(eval($4)<<10), + $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/\bq([0-9]+)\b/"v".($1<8?$1:($1<24?$1+8:$1-16)).".16b"/geo; # old->new registers + s/\bq_([0-9]+)\b/"q".$1/geo; # old->new registers s/@\s/\/\//o; # old->new style commentary #s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo or @@ -3653,6 +4444,7 @@ if ($flavour =~ /64/) { ######## 64-bit code s/vshr/ushr/o or s/^(\s+)v/$1/o or # strip off v prefix s/\bbx\s+lr\b/ret/o; + s/\b(eor3)\s+(v.*)/unsha3($1,$2)/ge; # fix up remaining legacy suffixes s/\.[ui]?8//o; diff --git a/crypto/aes/asm/bsaes-x86_64.pl b/crypto/aes/asm/bsaes-x86_64.pl index 6498cfe908c8..7230f760856a 100644 --- a/crypto/aes/asm/bsaes-x86_64.pl +++ b/crypto/aes/asm/bsaes-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -2182,6 +2182,7 @@ $code.=<<___; .align 16 ossl_bsaes_xts_encrypt: .cfi_startproc + endbranch mov %rsp, %rax .Lxts_enc_prologue: push %rbp @@ -2581,6 +2582,7 @@ $code.=<<___; .align 16 ossl_bsaes_xts_decrypt: .cfi_startproc + endbranch mov %rsp, %rax .Lxts_dec_prologue: push %rbp @@ -3003,6 +3005,7 @@ ___ } $code.=<<___; .type _bsaes_const,\@object +.section .rodata align=64 .align 64 _bsaes_const: .LM0ISR: # InvShiftRows constants @@ -3054,9 +3057,9 @@ _bsaes_const: .quad 0x02060a0e03070b0f, 0x0004080c0105090d .L63: .quad 0x6363636363636363, 0x6363636363636363 -.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov" .align 64 .size _bsaes_const,.-_bsaes_const +.asciz "Bit-sliced AES for x86_64/SSSE3, Emilia Käsper, Peter Schwabe, Andy Polyakov" ___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, diff --git a/crypto/aes/asm/vpaes-armv8.pl b/crypto/aes/asm/vpaes-armv8.pl index dcd5065e68c0..78c8d90ba48b 100755 --- a/crypto/aes/asm/vpaes-armv8.pl +++ b/crypto/aes/asm/vpaes-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -53,7 +53,9 @@ open OUT,"| \"$^X\" $xlate $flavour \"$output\"" *STDOUT=*OUT; $code.=<<___; -.text +#include "arm_arch.h" + +.rodata .type _vpaes_consts,%object .align 7 // totally strategic alignment @@ -144,6 +146,9 @@ _vpaes_consts: .asciz "Vector Permutation AES for ARMv8, Mike Hamburg (Stanford University)" .size _vpaes_consts,.-_vpaes_consts .align 6 + +.text + ___ { @@ -163,7 +168,8 @@ $code.=<<___; .type _vpaes_encrypt_preheat,%function .align 4 _vpaes_encrypt_preheat: - adr x10, .Lk_inv + adrp x10, .Lk_inv + add x10, x10, :lo12:.Lk_inv movi v17.16b, #0x0f ld1 {v18.2d-v19.2d}, [x10],#32 // .Lk_inv ld1 {v20.2d-v23.2d}, [x10],#64 // .Lk_ipt, .Lk_sbo @@ -191,7 +197,8 @@ _vpaes_encrypt_preheat: _vpaes_encrypt_core: mov x9, $key ldr w8, [$key,#240] // pull rounds - adr x11, .Lk_mc_forward+16 + adrp x11, .Lk_mc_forward+16 + add x11, x11, :lo12:.Lk_mc_forward+16 // vmovdqa .Lk_ipt(%rip), %xmm2 # iptlo ld1 {v16.2d}, [x9], #16 // vmovdqu (%r9), %xmm5 # round0 key and v1.16b, v7.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 @@ -259,7 +266,7 @@ _vpaes_encrypt_core: .type vpaes_encrypt,%function .align 4 vpaes_encrypt: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -269,7 +276,7 @@ vpaes_encrypt: st1 {v0.16b}, [$out] ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_encrypt,.-vpaes_encrypt @@ -278,7 +285,8 @@ vpaes_encrypt: _vpaes_encrypt_2x: mov x9, $key ldr w8, [$key,#240] // pull rounds - adr x11, .Lk_mc_forward+16 + adrp x11, .Lk_mc_forward+16 + add x11, x11, :lo12:.Lk_mc_forward+16 // vmovdqa .Lk_ipt(%rip), %xmm2 # iptlo ld1 {v16.2d}, [x9], #16 // vmovdqu (%r9), %xmm5 # round0 key and v1.16b, v14.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 @@ -381,9 +389,11 @@ _vpaes_encrypt_2x: .type _vpaes_decrypt_preheat,%function .align 4 _vpaes_decrypt_preheat: - adr x10, .Lk_inv + adrp x10, .Lk_inv + add x10, x10, :lo12:.Lk_inv movi v17.16b, #0x0f - adr x11, .Lk_dipt + adrp x11, .Lk_dipt + add x11, x11, :lo12:.Lk_dipt ld1 {v18.2d-v19.2d}, [x10],#32 // .Lk_inv ld1 {v20.2d-v23.2d}, [x11],#64 // .Lk_dipt, .Lk_dsbo ld1 {v24.2d-v27.2d}, [x11],#64 // .Lk_dsb9, .Lk_dsbd @@ -405,10 +415,12 @@ _vpaes_decrypt_core: // vmovdqa .Lk_dipt(%rip), %xmm2 # iptlo lsl x11, x8, #4 // mov %rax, %r11; shl \$4, %r11 eor x11, x11, #0x30 // xor \$0x30, %r11 - adr x10, .Lk_sr + adrp x10, .Lk_sr + add x10, x10, :lo12:.Lk_sr and x11, x11, #0x30 // and \$0x30, %r11 add x11, x11, x10 - adr x10, .Lk_mc_forward+48 + adrp x10, .Lk_mc_forward+48 + add x10, x10, :lo12:.Lk_mc_forward+48 ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm4 # round0 key and v1.16b, v7.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 @@ -492,7 +504,7 @@ _vpaes_decrypt_core: .type vpaes_decrypt,%function .align 4 vpaes_decrypt: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -502,7 +514,7 @@ vpaes_decrypt: st1 {v0.16b}, [$out] ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_decrypt,.-vpaes_decrypt @@ -516,10 +528,12 @@ _vpaes_decrypt_2x: // vmovdqa .Lk_dipt(%rip), %xmm2 # iptlo lsl x11, x8, #4 // mov %rax, %r11; shl \$4, %r11 eor x11, x11, #0x30 // xor \$0x30, %r11 - adr x10, .Lk_sr + adrp x10, .Lk_sr + add x10, x10, :lo12:.Lk_sr and x11, x11, #0x30 // and \$0x30, %r11 add x11, x11, x10 - adr x10, .Lk_mc_forward+48 + adrp x10, .Lk_mc_forward+48 + add x10, x10, :lo12:.Lk_mc_forward+48 ld1 {v16.2d}, [x9],#16 // vmovdqu (%r9), %xmm4 # round0 key and v1.16b, v14.16b, v17.16b // vpand %xmm9, %xmm0, %xmm1 @@ -655,14 +669,18 @@ $code.=<<___; .type _vpaes_key_preheat,%function .align 4 _vpaes_key_preheat: - adr x10, .Lk_inv + adrp x10, .Lk_inv + add x10, x10, :lo12:.Lk_inv movi v16.16b, #0x5b // .Lk_s63 - adr x11, .Lk_sb1 + adrp x11, .Lk_sb1 + add x11, x11, :lo12:.Lk_sb1 movi v17.16b, #0x0f // .Lk_s0F ld1 {v18.2d-v21.2d}, [x10] // .Lk_inv, .Lk_ipt - adr x10, .Lk_dksd + adrp x10, .Lk_dksd + add x10, x10, :lo12:.Lk_dksd ld1 {v22.2d-v23.2d}, [x11] // .Lk_sb1 - adr x11, .Lk_mc_forward + adrp x11, .Lk_mc_forward + add x11, x11, :lo12:.Lk_mc_forward ld1 {v24.2d-v27.2d}, [x10],#64 // .Lk_dksd, .Lk_dksb ld1 {v28.2d-v31.2d}, [x10],#64 // .Lk_dkse, .Lk_dks9 ld1 {v8.2d}, [x10] // .Lk_rcon @@ -673,7 +691,7 @@ _vpaes_key_preheat: .type _vpaes_schedule_core,%function .align 4 _vpaes_schedule_core: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29, x30, [sp,#-16]! add x29,sp,#0 @@ -686,7 +704,8 @@ _vpaes_schedule_core: bl _vpaes_schedule_transform mov v7.16b, v0.16b // vmovdqa %xmm0, %xmm7 - adr x10, .Lk_sr // lea .Lk_sr(%rip),%r10 + adrp x10, .Lk_sr // lea .Lk_sr(%rip),%r10 + add x10, x10, :lo12:.Lk_sr add x8, x8, x10 cbnz $dir, .Lschedule_am_decrypting @@ -812,12 +831,14 @@ _vpaes_schedule_core: .align 4 .Lschedule_mangle_last: // schedule last round key from xmm0 - adr x11, .Lk_deskew // lea .Lk_deskew(%rip),%r11 # prepare to deskew + adrp x11, .Lk_deskew // lea .Lk_deskew(%rip),%r11 # prepare to deskew + add x11, x11, :lo12:.Lk_deskew cbnz $dir, .Lschedule_mangle_last_dec // encrypting ld1 {v1.2d}, [x8] // vmovdqa (%r8,%r10),%xmm1 - adr x11, .Lk_opt // lea .Lk_opt(%rip), %r11 # prepare to output transform + adrp x11, .Lk_opt // lea .Lk_opt(%rip), %r11 # prepare to output transform + add x11, x11, :lo12:.Lk_opt add $out, $out, #32 // add \$32, %rdx tbl v0.16b, {v0.16b}, v1.16b // vpshufb %xmm1, %xmm0, %xmm0 # output permute @@ -838,7 +859,7 @@ _vpaes_schedule_core: eor v6.16b, v6.16b, v6.16b // vpxor %xmm6, %xmm6, %xmm6 eor v7.16b, v7.16b, v7.16b // vpxor %xmm7, %xmm7, %xmm7 ldp x29, x30, [sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size _vpaes_schedule_core,.-_vpaes_schedule_core @@ -1051,7 +1072,7 @@ _vpaes_schedule_mangle: .type vpaes_set_encrypt_key,%function .align 4 vpaes_set_encrypt_key: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 stp d8,d9,[sp,#-16]! // ABI spec says so @@ -1067,7 +1088,7 @@ vpaes_set_encrypt_key: ldp d8,d9,[sp],#16 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key @@ -1075,7 +1096,7 @@ vpaes_set_encrypt_key: .type vpaes_set_decrypt_key,%function .align 4 vpaes_set_decrypt_key: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 stp d8,d9,[sp,#-16]! // ABI spec says so @@ -1095,7 +1116,7 @@ vpaes_set_decrypt_key: ldp d8,d9,[sp],#16 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key ___ @@ -1108,11 +1129,11 @@ $code.=<<___; .type vpaes_cbc_encrypt,%function .align 4 vpaes_cbc_encrypt: + AARCH64_SIGN_LINK_REGISTER cbz $len, .Lcbc_abort cmp w5, #0 // check direction b.eq vpaes_cbc_decrypt - .inst 0xd503233f // paciasp stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -1135,15 +1156,16 @@ vpaes_cbc_encrypt: st1 {v0.16b}, [$ivec] // write ivec ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp .Lcbc_abort: + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt .type vpaes_cbc_decrypt,%function .align 4 vpaes_cbc_decrypt: - .inst 0xd503233f // paciasp + // Not adding AARCH64_SIGN_LINK_REGISTER here because vpaes_cbc_decrypt is jumped to + // only from vpaes_cbc_encrypt which has already signed the return address. stp x29,x30,[sp,#-16]! add x29,sp,#0 stp d8,d9,[sp,#-16]! // ABI spec says so @@ -1185,7 +1207,7 @@ vpaes_cbc_decrypt: ldp d10,d11,[sp],#16 ldp d8,d9,[sp],#16 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_cbc_decrypt,.-vpaes_cbc_decrypt ___ @@ -1195,7 +1217,7 @@ $code.=<<___; .type vpaes_ecb_encrypt,%function .align 4 vpaes_ecb_encrypt: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 stp d8,d9,[sp,#-16]! // ABI spec says so @@ -1229,7 +1251,7 @@ vpaes_ecb_encrypt: ldp d10,d11,[sp],#16 ldp d8,d9,[sp],#16 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_ecb_encrypt,.-vpaes_ecb_encrypt @@ -1237,7 +1259,7 @@ vpaes_ecb_encrypt: .type vpaes_ecb_decrypt,%function .align 4 vpaes_ecb_decrypt: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 stp d8,d9,[sp,#-16]! // ABI spec says so @@ -1271,7 +1293,7 @@ vpaes_ecb_decrypt: ldp d10,d11,[sp],#16 ldp d8,d9,[sp],#16 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size vpaes_ecb_decrypt,.-vpaes_ecb_decrypt ___ diff --git a/crypto/aes/asm/vpaes-x86_64.pl b/crypto/aes/asm/vpaes-x86_64.pl index 845528f41ac2..f62818841526 100644 --- a/crypto/aes/asm/vpaes-x86_64.pl +++ b/crypto/aes/asm/vpaes-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1006,6 +1006,7 @@ _vpaes_preheat: ## ## ######################################################## .type _vpaes_consts,\@object +.section .rodata align=64 .align 64 _vpaes_consts: .Lk_inv: # inv, inva @@ -1101,9 +1102,9 @@ _vpaes_consts: .Lk_dsbo: # decryption sbox final output .quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D .quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C -.asciz "Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)" .align 64 .size _vpaes_consts,.-_vpaes_consts +.asciz "Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)" ___ if ($win64) { diff --git a/crypto/aes/build.info b/crypto/aes/build.info index d6ad4ea3d068..11d27d0451c7 100644 --- a/crypto/aes/build.info +++ b/crypto/aes/build.info @@ -9,7 +9,8 @@ IF[{- !$disabled{asm} -}] $AESASM_x86_64=\ aes-x86_64.s vpaes-x86_64.s bsaes-x86_64.s aesni-x86_64.s \ - aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s + aesni-sha1-x86_64.s aesni-sha256-x86_64.s aesni-mb-x86_64.s \ + aesni-xts-avx512.s $AESDEF_x86_64=AES_ASM VPAES_ASM BSAES_ASM $AESASM_ia64=aes_core.c aes_cbc.c aes-ia64.s @@ -30,8 +31,8 @@ IF[{- !$disabled{asm} -}] $AESASM_armv4=aes_cbc.c aes-armv4.S bsaes-armv7.S aesv8-armx.S $AESDEF_armv4=AES_ASM BSAES_ASM - $AESASM_aarch64=aes_core.c aes_cbc.c aesv8-armx.S vpaes-armv8.S - $AESDEF_aarch64=VPAES_ASM + $AESASM_aarch64=aes_core.c aes_cbc.c aesv8-armx.S bsaes-armv8.S vpaes-armv8.S + $AESDEF_aarch64=BSAES_ASM VPAES_ASM $AESASM_parisc11=aes_core.c aes_cbc.c aes-parisc.s $AESDEF_parisc11=AES_ASM @@ -39,7 +40,7 @@ IF[{- !$disabled{asm} -}] $AESDEF_parisc20_64=$AESDEF_parisc11 IF[{- $target{sys_id} ne "MACOSX" -}] - $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s + $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s aesp8-ppc.s ELSE $AESASM_ppc32=aes_core.c aes_cbc.c aes-ppc.s vpaes-ppc.s ENDIF @@ -51,6 +52,13 @@ IF[{- !$disabled{asm} -}] # aes-c64xplus.s implements AES_ctr32_encrypt $AESDEF_c64xplus=AES_ASM AES_CTR_ASM + $AESASM_riscv64=aes_cbc.c aes-riscv64.s aes-riscv64-zkn.s aes-riscv64-zvkb-zvkned.s aes-riscv64-zvkned.s aes-riscv64-zvbb-zvkg-zvkned.s + $AESDEF_riscv64=AES_ASM + $AESASM_riscv32=aes_core.c aes_cbc.c aes-riscv32-zkn.s + + $AESASM_loongarch64=aes_core.c aes_cbc.c vpaes-loongarch64.S + $AESDEF_loongarch64=VPAES_ASM + # Now that we have defined all the arch specific variables, use the # appropriate one, and define the appropriate macros IF[$AESASM_{- $target{asm_arch} -}] @@ -84,6 +92,7 @@ IF[{- !$disabled{module} && !$disabled{shared} -}] ENDIF GENERATE[aes-ia64.s]=asm/aes-ia64.S +GENERATE[bsaes-armv8.S]=asm/bsaes-armv8.pl GENERATE[aes-586.S]=asm/aes-586.pl DEPEND[aes-586.S]=../perlasm/x86asm.pl @@ -117,9 +126,17 @@ GENERATE[aes-parisc.s]=asm/aes-parisc.pl GENERATE[aes-mips.S]=asm/aes-mips.pl INCLUDE[aes-mips.o]=.. +GENERATE[aes-riscv64.s]=asm/aes-riscv64.pl +GENERATE[aes-riscv64-zkn.s]=asm/aes-riscv64-zkn.pl +GENERATE[aes-riscv32-zkn.s]=asm/aes-riscv32-zkn.pl +GENERATE[aes-riscv64-zvkb-zvkned.s]=asm/aes-riscv64-zvkb-zvkned.pl +GENERATE[aes-riscv64-zvkned.s]=asm/aes-riscv64-zvkned.pl +GENERATE[aes-riscv64-zvbb-zvkg-zvkned.s]=asm/aes-riscv64-zvbb-zvkg-zvkned.pl + GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl INCLUDE[aesv8-armx.o]=.. GENERATE[vpaes-armv8.S]=asm/vpaes-armv8.pl +INCLUDE[vpaes-armv8.o]=.. GENERATE[aes-armv4.S]=asm/aes-armv4.pl INCLUDE[aes-armv4.o]=.. @@ -129,4 +146,9 @@ INCLUDE[bsaes-armv7.o]=.. GENERATE[aes-s390x.S]=asm/aes-s390x.pl INCLUDE[aes-s390x.o]=.. +GENERATE[aesni-xts-avx512.s]=asm/aesni-xts-avx512.pl + GENERATE[aes-c64xplus.S]=asm/aes-c64xplus.pl + +GENERATE[vpaes-loongarch64.S]=asm/vpaes-loongarch64.pl +INCLUDE[vpaes-loongarch64.o]=.. diff --git a/crypto/aria/aria.c b/crypto/aria/aria.c index 5e60bc521023..84ddd00cd827 100644 --- a/crypto/aria/aria.c +++ b/crypto/aria/aria.c @@ -498,7 +498,7 @@ void ossl_aria_encrypt(const unsigned char *in, unsigned char *out, ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); rk++; - while(Nr -= 2){ + while ((Nr -= 2) > 0) { ARIA_SUBST_DIFF_EVEN(reg0, reg1, reg2, reg3); ARIA_ADD_ROUND_KEY(rk, reg0, reg1, reg2, reg3); rk++; diff --git a/crypto/arm64cpuid.pl b/crypto/arm64cpuid.pl index ac76dd449f37..8dc06dd52a8f 100755 --- a/crypto/arm64cpuid.pl +++ b/crypto/arm64cpuid.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -31,6 +31,7 @@ $code.=<<___; .globl _armv7_neon_probe .type _armv7_neon_probe,%function _armv7_neon_probe: + AARCH64_VALID_CALL_TARGET orr v15.16b, v15.16b, v15.16b ret .size _armv7_neon_probe,.-_armv7_neon_probe @@ -38,6 +39,7 @@ _armv7_neon_probe: .globl _armv7_tick .type _armv7_tick,%function _armv7_tick: + AARCH64_VALID_CALL_TARGET #ifdef __APPLE__ mrs x0, CNTPCT_EL0 #else @@ -49,6 +51,7 @@ _armv7_tick: .globl _armv8_aes_probe .type _armv8_aes_probe,%function _armv8_aes_probe: + AARCH64_VALID_CALL_TARGET aese v0.16b, v0.16b ret .size _armv8_aes_probe,.-_armv8_aes_probe @@ -56,6 +59,7 @@ _armv8_aes_probe: .globl _armv8_sha1_probe .type _armv8_sha1_probe,%function _armv8_sha1_probe: + AARCH64_VALID_CALL_TARGET sha1h s0, s0 ret .size _armv8_sha1_probe,.-_armv8_sha1_probe @@ -63,6 +67,7 @@ _armv8_sha1_probe: .globl _armv8_sha256_probe .type _armv8_sha256_probe,%function _armv8_sha256_probe: + AARCH64_VALID_CALL_TARGET sha256su0 v0.4s, v0.4s ret .size _armv8_sha256_probe,.-_armv8_sha256_probe @@ -70,28 +75,72 @@ _armv8_sha256_probe: .globl _armv8_pmull_probe .type _armv8_pmull_probe,%function _armv8_pmull_probe: + AARCH64_VALID_CALL_TARGET pmull v0.1q, v0.1d, v0.1d ret .size _armv8_pmull_probe,.-_armv8_pmull_probe +.globl _armv8_sm4_probe +.type _armv8_sm4_probe,%function +_armv8_sm4_probe: + AARCH64_VALID_CALL_TARGET + .inst 0xcec08400 // sm4e v0.4s, v0.4s + ret +.size _armv8_sm4_probe,.-_armv8_sm4_probe + .globl _armv8_sha512_probe .type _armv8_sha512_probe,%function _armv8_sha512_probe: - .long 0xcec08000 // sha512su0 v0.2d,v0.2d + AARCH64_VALID_CALL_TARGET + .inst 0xcec08000 // sha512su0 v0.2d,v0.2d ret .size _armv8_sha512_probe,.-_armv8_sha512_probe +.globl _armv8_eor3_probe +.type _armv8_eor3_probe,%function +_armv8_eor3_probe: + AARCH64_VALID_CALL_TARGET + .inst 0xce010800 // eor3 v0.16b, v0.16b, v1.16b, v2.16b + ret +.size _armv8_eor3_probe,.-_armv8_eor3_probe + +.globl _armv8_sve_probe +.type _armv8_sve_probe,%function +_armv8_sve_probe: + AARCH64_VALID_CALL_TARGET + .inst 0x04a03000 // eor z0.d,z0.d,z0.d + ret +.size _armv8_sve_probe,.-_armv8_sve_probe + +.globl _armv8_sve2_probe +.type _armv8_sve2_probe,%function +_armv8_sve2_probe: + AARCH64_VALID_CALL_TARGET + .inst 0x04e03400 // xar z0.d,z0.d,z0.d + ret +.size _armv8_sve2_probe,.-_armv8_sve2_probe + .globl _armv8_cpuid_probe .type _armv8_cpuid_probe,%function _armv8_cpuid_probe: + AARCH64_VALID_CALL_TARGET mrs x0, midr_el1 ret .size _armv8_cpuid_probe,.-_armv8_cpuid_probe +.globl _armv8_sm3_probe +.type _armv8_sm3_probe,%function +_armv8_sm3_probe: + AARCH64_VALID_CALL_TARGET + .inst 0xce63c004 // sm3partw1 v4.4s, v0.4s, v3.4s + ret +.size _armv8_sm3_probe,.-_armv8_sm3_probe + .globl OPENSSL_cleanse .type OPENSSL_cleanse,%function .align 5 OPENSSL_cleanse: + AARCH64_VALID_CALL_TARGET cbz x1,.Lret // len==0? cmp x1,#15 b.hi .Lot // len>15 @@ -123,6 +172,7 @@ OPENSSL_cleanse: .type CRYPTO_memcmp,%function .align 4 CRYPTO_memcmp: + AARCH64_VALID_CALL_TARGET eor w3,w3,w3 cbz x2,.Lno_data // len==0? cmp x2,#16 @@ -151,7 +201,70 @@ CRYPTO_memcmp: lsr w0,w0,#31 ret .size CRYPTO_memcmp,.-CRYPTO_memcmp + +.globl _armv8_rng_probe +.type _armv8_rng_probe,%function +_armv8_rng_probe: + AARCH64_VALID_CALL_TARGET + mrs x0, s3_3_c2_c4_0 // rndr + mrs x0, s3_3_c2_c4_1 // rndrrs + ret +.size _armv8_rng_probe,.-_armv8_rng_probe ___ +sub gen_random { +my $rdop = shift; +my $rand_reg = $rdop eq "rndr" ? "s3_3_c2_c4_0" : "s3_3_c2_c4_1"; + +return <<___; +// Fill buffer with Randomly Generated Bytes +// inputs: char * in x0 - Pointer to buffer +// size_t in x1 - Number of bytes to write to buffer +// outputs: size_t in x0 - Number of bytes successfully written to buffer +.globl OPENSSL_${rdop}_asm +.type OPENSSL_${rdop}_asm,%function +.align 4 +OPENSSL_${rdop}_asm: + AARCH64_VALID_CALL_TARGET + mov x2,xzr + mov x3,xzr + +.align 4 +.Loop_${rdop}: + cmp x1,#0 + b.eq .${rdop}_done + mov x3,xzr + mrs x3,$rand_reg + b.eq .${rdop}_done + + cmp x1,#8 + b.lt .Loop_single_byte_${rdop} + + str x3,[x0] + add x0,x0,#8 + add x2,x2,#8 + subs x1,x1,#8 + b.ge .Loop_${rdop} + +.align 4 +.Loop_single_byte_${rdop}: + strb w3,[x0] + lsr x3,x3,#8 + add x2,x2,#1 + add x0,x0,#1 + subs x1,x1,#1 + b.gt .Loop_single_byte_${rdop} + +.align 4 +.${rdop}_done: + mov x0,x2 + ret +.size OPENSSL_${rdop}_asm,.-OPENSSL_${rdop}_asm +___ +} + +$code .= gen_random("rndr"); +$code .= gen_random("rndrrs"); + print $code; close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h index ec4a087fede2..acd8aee4d519 100644 --- a/crypto/arm_arch.h +++ b/crypto/arm_arch.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -49,6 +49,8 @@ # else # error "unsupported ARM architecture" # endif +# elif defined(__ARM_ARCH) +# define __ARM_ARCH__ __ARM_ARCH # endif # endif @@ -78,6 +80,15 @@ extern unsigned int OPENSSL_armv8_rsa_neonized; # define ARMV8_PMULL (1<<5) # define ARMV8_SHA512 (1<<6) # define ARMV8_CPUID (1<<7) +# define ARMV8_RNG (1<<8) +# define ARMV8_SM3 (1<<9) +# define ARMV8_SM4 (1<<10) +# define ARMV8_SHA3 (1<<11) +# define ARMV8_UNROLL8_EOR3 (1<<12) +# define ARMV8_SVE (1<<13) +# define ARMV8_SVE2 (1<<14) +# define ARMV8_HAVE_SHA3_AND_WORTH_USING (1<<15) +# define ARMV8_UNROLL12_EOR3 (1<<16) /* * MIDR_EL1 system register @@ -90,9 +101,32 @@ extern unsigned int OPENSSL_armv8_rsa_neonized; */ # define ARM_CPU_IMP_ARM 0x41 +# define HISI_CPU_IMP 0x48 +# define ARM_CPU_IMP_APPLE 0x61 +# define ARM_CPU_IMP_MICROSOFT 0x6D +# define ARM_CPU_IMP_AMPERE 0xC0 # define ARM_CPU_PART_CORTEX_A72 0xD08 # define ARM_CPU_PART_N1 0xD0C +# define ARM_CPU_PART_V1 0xD40 +# define ARM_CPU_PART_N2 0xD49 +# define HISI_CPU_PART_KP920 0xD01 +# define ARM_CPU_PART_V2 0xD4F + +# define APPLE_CPU_PART_M1_ICESTORM 0x022 +# define APPLE_CPU_PART_M1_FIRESTORM 0x023 +# define APPLE_CPU_PART_M1_ICESTORM_PRO 0x024 +# define APPLE_CPU_PART_M1_FIRESTORM_PRO 0x025 +# define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028 +# define APPLE_CPU_PART_M1_FIRESTORM_MAX 0x029 +# define APPLE_CPU_PART_M2_BLIZZARD 0x032 +# define APPLE_CPU_PART_M2_AVALANCHE 0x033 +# define APPLE_CPU_PART_M2_BLIZZARD_PRO 0x034 +# define APPLE_CPU_PART_M2_AVALANCHE_PRO 0x035 +# define APPLE_CPU_PART_M2_BLIZZARD_MAX 0x038 +# define APPLE_CPU_PART_M2_AVALANCHE_MAX 0x039 + +# define MICROSOFT_CPU_PART_COBALT_100 0xD49 # define MIDR_PARTNUM_SHIFT 4 # define MIDR_PARTNUM_MASK (0xfffU << MIDR_PARTNUM_SHIFT) @@ -121,4 +155,65 @@ extern unsigned int OPENSSL_armv8_rsa_neonized; # define MIDR_IS_CPU_MODEL(midr, imp, partnum) \ (((midr) & MIDR_CPU_MODEL_MASK) == MIDR_CPU_MODEL(imp, partnum)) + +#if defined(__ASSEMBLER__) + + /* + * Support macros for + * - Armv8.3-A Pointer Authentication and + * - Armv8.5-A Branch Target Identification + * features which require emitting a .note.gnu.property section with the + * appropriate architecture-dependent feature bits set. + * Read more: "ELF for the Arm® 64-bit Architecture" + */ + +# if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1 +# define GNU_PROPERTY_AARCH64_BTI (1 << 0) /* Has Branch Target Identification */ +# define AARCH64_VALID_CALL_TARGET hint #34 /* BTI 'c' */ +# else +# define GNU_PROPERTY_AARCH64_BTI 0 /* No Branch Target Identification */ +# define AARCH64_VALID_CALL_TARGET +# endif + +# if defined(__ARM_FEATURE_PAC_DEFAULT) && \ + (__ARM_FEATURE_PAC_DEFAULT & 1) == 1 /* Signed with A-key */ +# define GNU_PROPERTY_AARCH64_POINTER_AUTH \ + (1 << 1) /* Has Pointer Authentication */ +# define AARCH64_SIGN_LINK_REGISTER hint #25 /* PACIASP */ +# define AARCH64_VALIDATE_LINK_REGISTER hint #29 /* AUTIASP */ +# elif defined(__ARM_FEATURE_PAC_DEFAULT) && \ + (__ARM_FEATURE_PAC_DEFAULT & 2) == 2 /* Signed with B-key */ +# define GNU_PROPERTY_AARCH64_POINTER_AUTH \ + (1 << 1) /* Has Pointer Authentication */ +# define AARCH64_SIGN_LINK_REGISTER hint #27 /* PACIBSP */ +# define AARCH64_VALIDATE_LINK_REGISTER hint #31 /* AUTIBSP */ +# else +# define GNU_PROPERTY_AARCH64_POINTER_AUTH 0 /* No Pointer Authentication */ +# if GNU_PROPERTY_AARCH64_BTI != 0 +# define AARCH64_SIGN_LINK_REGISTER AARCH64_VALID_CALL_TARGET +# else +# define AARCH64_SIGN_LINK_REGISTER +# endif +# define AARCH64_VALIDATE_LINK_REGISTER +# endif + +# if GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_BTI != 0 + .pushsection .note.gnu.property, "a"; + .balign 8; + .long 4; + .long 0x10; + .long 0x5; + .asciz "GNU"; + .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4; + .long (GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI); + .long 0; + .popsection; +# endif + +# endif /* defined __ASSEMBLER__ */ + +# define IS_CPU_SUPPORT_UNROLL8_EOR3() \ + (OPENSSL_armcap_P & ARMV8_UNROLL8_EOR3) + #endif diff --git a/crypto/armcap.c b/crypto/armcap.c index c021330e32fd..66c9001089a5 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,21 +10,44 @@ #include #include #include -#include -#include #include #ifdef __APPLE__ #include +#else +#include +#include #endif #include "internal/cryptlib.h" - +#ifdef _WIN32 +#include +#else +#include +#endif #include "arm_arch.h" unsigned int OPENSSL_armcap_P = 0; unsigned int OPENSSL_arm_midr = 0; unsigned int OPENSSL_armv8_rsa_neonized = 0; -#if __ARM_MAX_ARCH__<7 +#ifdef _WIN32 +void OPENSSL_cpuid_setup(void) +{ + OPENSSL_armcap_P |= ARMV7_NEON; + OPENSSL_armv8_rsa_neonized = 1; + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) { + /* These are all covered by one call in Windows */ + OPENSSL_armcap_P |= ARMV8_AES; + OPENSSL_armcap_P |= ARMV8_PMULL; + OPENSSL_armcap_P |= ARMV8_SHA1; + OPENSSL_armcap_P |= ARMV8_SHA256; + } +} + +uint32_t OPENSSL_rdtsc(void) +{ + return 0; +} +#elif __ARM_MAX_ARCH__ < 7 void OPENSSL_cpuid_setup(void) { } @@ -33,37 +56,11 @@ uint32_t OPENSSL_rdtsc(void) { return 0; } -#else -static sigset_t all_masked; +#else /* !_WIN32 && __ARM_MAX_ARCH__ >= 7 */ -static sigjmp_buf ill_jmp; -static void ill_handler(int sig) -{ - siglongjmp(ill_jmp, sig); -} + /* 3 ways of handling things here: __APPLE__, getauxval() or SIGILL detect */ -/* - * Following subroutines could have been inlined, but it's not all - * ARM compilers support inline assembler... - */ -void _armv7_neon_probe(void); -void _armv8_aes_probe(void); -void _armv8_sha1_probe(void); -void _armv8_sha256_probe(void); -void _armv8_pmull_probe(void); -# ifdef __aarch64__ -void _armv8_sha512_probe(void); -unsigned int _armv8_cpuid_probe(void); -# endif -uint32_t _armv7_tick(void); - -uint32_t OPENSSL_rdtsc(void) -{ - if (OPENSSL_armcap_P & ARMV7_TICK) - return _armv7_tick(); - else - return 0; -} + /* First determine if getauxval() is available (OSSL_IMPLEMENT_GETAUXVAL) */ # if defined(__GNUC__) && __GNUC__>=2 void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); @@ -81,9 +78,10 @@ void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); # define OSSL_IMPLEMENT_GETAUXVAL # endif # endif -# if defined(__FreeBSD__) +# if defined(__FreeBSD__) || defined(__OpenBSD__) # include -# if __FreeBSD_version >= 1200000 +# if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ + (defined(__OpenBSD__) && OpenBSD >= 202409) # include # define OSSL_IMPLEMENT_GETAUXVAL @@ -103,10 +101,10 @@ static unsigned long getauxval(unsigned long key) * Android: according to https://developer.android.com/ndk/guides/cpu-features, * getauxval is supported starting with API level 18 */ -# if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 18 -# include -# define OSSL_IMPLEMENT_GETAUXVAL -# endif +# if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 18 +# include +# define OSSL_IMPLEMENT_GETAUXVAL +# endif /* * ARM puts the feature bits for Crypto Extensions in AT_HWCAP2, whereas @@ -119,32 +117,144 @@ static unsigned long getauxval(unsigned long key) # define AT_HWCAP2 26 # endif # if defined(__arm__) || defined (__arm) -# define HWCAP AT_HWCAP -# define HWCAP_NEON (1 << 12) +# define OSSL_HWCAP AT_HWCAP +# define OSSL_HWCAP_NEON (1 << 12) -# define HWCAP_CE AT_HWCAP2 -# define HWCAP_CE_AES (1 << 0) -# define HWCAP_CE_PMULL (1 << 1) -# define HWCAP_CE_SHA1 (1 << 2) -# define HWCAP_CE_SHA256 (1 << 3) +# define OSSL_HWCAP_CE AT_HWCAP2 +# define OSSL_HWCAP_CE_AES (1 << 0) +# define OSSL_HWCAP_CE_PMULL (1 << 1) +# define OSSL_HWCAP_CE_SHA1 (1 << 2) +# define OSSL_HWCAP_CE_SHA256 (1 << 3) # elif defined(__aarch64__) -# define HWCAP AT_HWCAP -# define HWCAP_NEON (1 << 1) +# define OSSL_HWCAP AT_HWCAP +# define OSSL_HWCAP_NEON (1 << 1) -# define HWCAP_CE HWCAP -# define HWCAP_CE_AES (1 << 3) -# define HWCAP_CE_PMULL (1 << 4) -# define HWCAP_CE_SHA1 (1 << 5) -# define HWCAP_CE_SHA256 (1 << 6) -# define HWCAP_CPUID (1 << 11) -# define HWCAP_CE_SHA512 (1 << 21) +# define OSSL_HWCAP_CE AT_HWCAP +# define OSSL_HWCAP_CE_AES (1 << 3) +# define OSSL_HWCAP_CE_PMULL (1 << 4) +# define OSSL_HWCAP_CE_SHA1 (1 << 5) +# define OSSL_HWCAP_CE_SHA256 (1 << 6) +# define OSSL_HWCAP_CPUID (1 << 11) +# define OSSL_HWCAP_SHA3 (1 << 17) +# define OSSL_HWCAP_CE_SM3 (1 << 18) +# define OSSL_HWCAP_CE_SM4 (1 << 19) +# define OSSL_HWCAP_CE_SHA512 (1 << 21) +# define OSSL_HWCAP_SVE (1 << 22) + /* AT_HWCAP2 */ +# define OSSL_HWCAP2 26 +# define OSSL_HWCAP2_SVE2 (1 << 1) +# define OSSL_HWCAP2_RNG (1 << 16) +# endif + +uint32_t _armv7_tick(void); + +uint32_t OPENSSL_rdtsc(void) +{ + if (OPENSSL_armcap_P & ARMV7_TICK) + return _armv7_tick(); + else + return 0; +} + +# ifdef __aarch64__ +size_t OPENSSL_rndr_asm(unsigned char *buf, size_t len); +size_t OPENSSL_rndrrs_asm(unsigned char *buf, size_t len); + +size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len); +size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len); + +static size_t OPENSSL_rndr_wrapper(size_t (*func)(unsigned char *, size_t), unsigned char *buf, size_t len) +{ + size_t buffer_size = 0; + int i; + + for (i = 0; i < 8; i++) { + buffer_size = func(buf, len); + if (buffer_size == len) + break; + usleep(5000); /* 5000 microseconds (5 milliseconds) */ + } + return buffer_size; +} + +size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len) +{ + return OPENSSL_rndr_wrapper(OPENSSL_rndr_asm, buf, len); +} + +size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len) +{ + return OPENSSL_rndr_wrapper(OPENSSL_rndrrs_asm, buf, len); +} +# endif + +# if !defined(__APPLE__) && !defined(OSSL_IMPLEMENT_GETAUXVAL) +static sigset_t all_masked; + +static sigjmp_buf ill_jmp; +static void ill_handler(int sig) +{ + siglongjmp(ill_jmp, sig); +} + +/* + * Following subroutines could have been inlined, but not all + * ARM compilers support inline assembler, and we'd then have to + * worry about the compiler optimising out the detection code... + */ +void _armv7_neon_probe(void); +void _armv8_aes_probe(void); +void _armv8_sha1_probe(void); +void _armv8_sha256_probe(void); +void _armv8_pmull_probe(void); +# ifdef __aarch64__ +void _armv8_sm3_probe(void); +void _armv8_sm4_probe(void); +void _armv8_sha512_probe(void); +void _armv8_eor3_probe(void); +void _armv8_sve_probe(void); +void _armv8_sve2_probe(void); +void _armv8_rng_probe(void); +# endif +# endif /* !__APPLE__ && !OSSL_IMPLEMENT_GETAUXVAL */ + +/* We only call _armv8_cpuid_probe() if (OPENSSL_armcap_P & ARMV8_CPUID) != 0 */ +unsigned int _armv8_cpuid_probe(void); + +# if defined(__APPLE__) +/* + * Checks the specified integer sysctl, returning `value` if it's 1, otherwise returning 0. + */ +static unsigned int sysctl_query(const char *name, unsigned int value) +{ + unsigned int sys_value = 0; + size_t len = sizeof(sys_value); + + return (sysctlbyname(name, &sys_value, &len, NULL, 0) == 0 && sys_value == 1) ? value : 0; +} +# elif !defined(OSSL_IMPLEMENT_GETAUXVAL) +/* + * Calls a provided probe function, which may SIGILL. If it doesn't, return `value`, otherwise return 0. + */ +static unsigned int arm_probe_for(void (*probe)(void), volatile unsigned int value) +{ + if (sigsetjmp(ill_jmp, 1) == 0) { + probe(); + return value; + } else { + /* The probe function gave us SIGILL */ + return 0; + } +} # endif void OPENSSL_cpuid_setup(void) { const char *e; +# if !defined(__APPLE__) && !defined(OSSL_IMPLEMENT_GETAUXVAL) struct sigaction ill_oact, ill_act; sigset_t oset; +# endif static int trigger = 0; if (trigger) @@ -159,7 +269,7 @@ void OPENSSL_cpuid_setup(void) } # if defined(__APPLE__) -# if !defined(__aarch64__) +# if !defined(__aarch64__) /* * Capability probing by catching SIGILL appears to be problematic * on iOS. But since Apple universe is "monocultural", it's actually @@ -169,50 +279,85 @@ void OPENSSL_cpuid_setup(void) OPENSSL_armcap_P = ARMV7_NEON; return; } - /* - * One could do same even for __aarch64__ iOS builds. It's not done - * exclusively for reasons of keeping code unified across platforms. - * Unified code works because it never triggers SIGILL on Apple - * devices... - */ -# else +# else { - unsigned int sha512; - size_t len = sizeof(sha512); + /* + * From + * https://github.com/llvm/llvm-project/blob/412237dcd07e5a2afbb1767858262a5f037149a3/llvm/lib/Target/AArch64/AArch64.td#L719 + * all of these have been available on 64-bit Apple Silicon from the + * beginning (the A7). + */ + OPENSSL_armcap_P |= ARMV7_NEON | ARMV8_PMULL | ARMV8_AES | ARMV8_SHA1 | ARMV8_SHA256; - if (sysctlbyname("hw.optional.armv8_2_sha512", &sha512, &len, NULL, 0) == 0 && sha512 == 1) - OPENSSL_armcap_P |= ARMV8_SHA512; + /* More recent extensions are indicated by sysctls */ + OPENSSL_armcap_P |= sysctl_query("hw.optional.armv8_2_sha512", ARMV8_SHA512); + OPENSSL_armcap_P |= sysctl_query("hw.optional.armv8_2_sha3", ARMV8_SHA3); + + if (OPENSSL_armcap_P & ARMV8_SHA3) { + char uarch[64]; + + size_t len = sizeof(uarch); + if ((sysctlbyname("machdep.cpu.brand_string", uarch, &len, NULL, 0) == 0) && + ((strncmp(uarch, "Apple M1", 8) == 0) || + (strncmp(uarch, "Apple M2", 8) == 0) || + (strncmp(uarch, "Apple M3", 8) == 0) || + (strncmp(uarch, "Apple M4", 8) == 0))) { + OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3; + OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING; + } + } } -# endif -# endif +# endif /* __aarch64__ */ -# ifdef OSSL_IMPLEMENT_GETAUXVAL - if (getauxval(HWCAP) & HWCAP_NEON) { - unsigned long hwcap = getauxval(HWCAP_CE); +# elif defined(OSSL_IMPLEMENT_GETAUXVAL) + + if (getauxval(OSSL_HWCAP) & OSSL_HWCAP_NEON) { + unsigned long hwcap = getauxval(OSSL_HWCAP_CE); OPENSSL_armcap_P |= ARMV7_NEON; - if (hwcap & HWCAP_CE_AES) + if (hwcap & OSSL_HWCAP_CE_AES) OPENSSL_armcap_P |= ARMV8_AES; - if (hwcap & HWCAP_CE_PMULL) + if (hwcap & OSSL_HWCAP_CE_PMULL) OPENSSL_armcap_P |= ARMV8_PMULL; - if (hwcap & HWCAP_CE_SHA1) + if (hwcap & OSSL_HWCAP_CE_SHA1) OPENSSL_armcap_P |= ARMV8_SHA1; - if (hwcap & HWCAP_CE_SHA256) + if (hwcap & OSSL_HWCAP_CE_SHA256) OPENSSL_armcap_P |= ARMV8_SHA256; # ifdef __aarch64__ - if (hwcap & HWCAP_CE_SHA512) + if (hwcap & OSSL_HWCAP_CE_SM4) + OPENSSL_armcap_P |= ARMV8_SM4; + + if (hwcap & OSSL_HWCAP_CE_SHA512) OPENSSL_armcap_P |= ARMV8_SHA512; - if (hwcap & HWCAP_CPUID) + if (hwcap & OSSL_HWCAP_CPUID) OPENSSL_armcap_P |= ARMV8_CPUID; + + if (hwcap & OSSL_HWCAP_CE_SM3) + OPENSSL_armcap_P |= ARMV8_SM3; + if (hwcap & OSSL_HWCAP_SHA3) + OPENSSL_armcap_P |= ARMV8_SHA3; # endif } -# endif +# ifdef __aarch64__ + if (getauxval(OSSL_HWCAP) & OSSL_HWCAP_SVE) + OPENSSL_armcap_P |= ARMV8_SVE; + + if (getauxval(OSSL_HWCAP2) & OSSL_HWCAP2_SVE2) + OPENSSL_armcap_P |= ARMV8_SVE2; + + if (getauxval(OSSL_HWCAP2) & OSSL_HWCAP2_RNG) + OPENSSL_armcap_P |= ARMV8_RNG; +# endif + +# else /* !__APPLE__ && !OSSL_IMPLEMENT_GETAUXVAL */ + + /* If all else fails, do brute force SIGILL-based feature detection */ sigfillset(&all_masked); sigdelset(&all_masked, SIGILL); @@ -228,44 +373,42 @@ void OPENSSL_cpuid_setup(void) sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); sigaction(SIGILL, &ill_act, &ill_oact); - /* If we used getauxval, we already have all the values */ -# ifndef OSSL_IMPLEMENT_GETAUXVAL - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv7_neon_probe(); - OPENSSL_armcap_P |= ARMV7_NEON; - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv8_pmull_probe(); - OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; - } else if (sigsetjmp(ill_jmp, 1) == 0) { - _armv8_aes_probe(); - OPENSSL_armcap_P |= ARMV8_AES; - } - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv8_sha1_probe(); - OPENSSL_armcap_P |= ARMV8_SHA1; - } - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv8_sha256_probe(); - OPENSSL_armcap_P |= ARMV8_SHA256; - } -# if defined(__aarch64__) && !defined(__APPLE__) - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv8_sha512_probe(); - OPENSSL_armcap_P |= ARMV8_SHA512; + OPENSSL_armcap_P |= arm_probe_for(_armv7_neon_probe, ARMV7_NEON); + + if (OPENSSL_armcap_P & ARMV7_NEON) { + + OPENSSL_armcap_P |= arm_probe_for(_armv8_pmull_probe, ARMV8_PMULL | ARMV8_AES); + if (!(OPENSSL_armcap_P & ARMV8_AES)) { + OPENSSL_armcap_P |= arm_probe_for(_armv8_aes_probe, ARMV8_AES); } + + OPENSSL_armcap_P |= arm_probe_for(_armv8_sha1_probe, ARMV8_SHA1); + OPENSSL_armcap_P |= arm_probe_for(_armv8_sha256_probe, ARMV8_SHA256); + +# if defined(__aarch64__) + OPENSSL_armcap_P |= arm_probe_for(_armv8_sm3_probe, ARMV8_SM3); + OPENSSL_armcap_P |= arm_probe_for(_armv8_sm4_probe, ARMV8_SM4); + OPENSSL_armcap_P |= arm_probe_for(_armv8_sha512_probe, ARMV8_SHA512); + OPENSSL_armcap_P |= arm_probe_for(_armv8_eor3_probe, ARMV8_SHA3); # endif } -# endif +# ifdef __aarch64__ + OPENSSL_armcap_P |= arm_probe_for(_armv8_sve_probe, ARMV8_SVE); + OPENSSL_armcap_P |= arm_probe_for(_armv8_sve2_probe, ARMV8_SVE2); + OPENSSL_armcap_P |= arm_probe_for(_armv8_rng_probe, ARMV8_RNG); +# endif /* * Probing for ARMV7_TICK is known to produce unreliable results, - * so we will only use the feature when the user explicitly enables - * it with OPENSSL_armcap. + * so we only use the feature when the user explicitly enables it + * with OPENSSL_armcap. */ sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); +# endif /* __APPLE__, OSSL_IMPLEMENT_GETAUXVAL */ + # ifdef __aarch64__ if (OPENSSL_armcap_P & ARMV8_CPUID) OPENSSL_arm_midr = _armv8_cpuid_probe(); @@ -275,6 +418,32 @@ void OPENSSL_cpuid_setup(void) (OPENSSL_armcap_P & ARMV7_NEON)) { OPENSSL_armv8_rsa_neonized = 1; } + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_N2) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_COBALT_100) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || + MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE) && + (OPENSSL_armcap_P & ARMV8_SHA3)) + OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3; + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V1) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_ARM, ARM_CPU_PART_V2) || + MIDR_IMPLEMENTER(OPENSSL_arm_midr) == ARM_CPU_IMP_AMPERE) && + (OPENSSL_armcap_P & ARMV8_SHA3)) + OPENSSL_armcap_P |= ARMV8_UNROLL12_EOR3; + if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) || + MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX)) && + (OPENSSL_armcap_P & ARMV8_SHA3)) + OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING; # endif } -#endif +#endif /* _WIN32, __ARM_MAX_ARCH__ >= 7 */ diff --git a/crypto/armv4cpuid.pl b/crypto/armv4cpuid.pl index 8991fd4afe8e..9b933c70c4d8 100644 --- a/crypto/armv4cpuid.pl +++ b/crypto/armv4cpuid.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -292,7 +292,7 @@ atomic_add_spinlock: .word 0 #endif -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P .hidden OPENSSL_armcap_P ___ diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c index 549c0e885549..a87cb15b44d4 100644 --- a/crypto/asn1/a_bitstr.c +++ b/crypto/asn1/a_bitstr.c @@ -87,7 +87,7 @@ ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, ASN1_BIT_STRING *ret = NULL; const unsigned char *p; unsigned char *s; - int i; + int i = 0; if (len < 1) { i = ASN1_R_STRING_TOO_SHORT; @@ -115,13 +115,11 @@ ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, * 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 */ + ossl_asn1_string_set_bits_left(ret, i); 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); @@ -130,16 +128,15 @@ ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, } else s = NULL; - ret->length = (int)len; - OPENSSL_free(ret->data); - ret->data = s; + ASN1_STRING_set0(ret, s, (int)len); ret->type = V_ASN1_BIT_STRING; if (a != NULL) (*a) = ret; *pp = p; return ret; err: - ERR_raise(ERR_LIB_ASN1, i); + if (i != 0) + ERR_raise(ERR_LIB_ASN1, i); if ((a == NULL) || (*a != ret)) ASN1_BIT_STRING_free(ret); return NULL; @@ -171,10 +168,8 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) 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); + if (c == NULL) return 0; - } if (w + 1 - a->length > 0) memset(c + a->length, 0, w + 1 - a->length); a->data = c; diff --git a/crypto/asn1/a_d2i_fp.c b/crypto/asn1/a_d2i_fp.c index bd549215b400..4999ac1f65ba 100644 --- a/crypto/asn1/a_d2i_fp.c +++ b/crypto/asn1/a_d2i_fp.c @@ -123,7 +123,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) b = BUF_MEM_new(); if (b == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return -1; } @@ -134,7 +134,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) want -= diff; if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); goto err; } i = BIO_read(in, &(b->data[len]), want); @@ -209,7 +209,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) size_t chunk = want > chunk_max ? chunk_max : want; if (!BUF_MEM_grow_clean(b, len + chunk)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); goto err; } want -= chunk; diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c index 72cc8807799d..67e8a96ba15f 100644 --- a/crypto/asn1/a_digest.c +++ b/crypto/asn1/a_digest.c @@ -36,10 +36,8 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR); return 0; } - if ((str = OPENSSL_malloc(inl)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((str = OPENSSL_malloc(inl)) == NULL) return 0; - } p = str; i2d(data, &p); diff --git a/crypto/asn1/a_dup.c b/crypto/asn1/a_dup.c index 93e8b2aa8dab..e673023faee8 100644 --- a/crypto/asn1/a_dup.c +++ b/crypto/asn1/a_dup.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -28,10 +28,8 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x) return NULL; b = OPENSSL_malloc(i + 10); - if (b == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (b == NULL) return NULL; - } p = b; i = i2d(x, &p); p2 = b; @@ -77,8 +75,8 @@ void *ASN1_item_dup(const ASN1_ITEM *it, const void *x) } i = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (i < 0 || b == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return NULL; } p = b; diff --git a/crypto/asn1/a_i2d_fp.c b/crypto/asn1/a_i2d_fp.c index 4cc4773666c4..23e0b0f70003 100644 --- a/crypto/asn1/a_i2d_fp.c +++ b/crypto/asn1/a_i2d_fp.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -42,10 +42,8 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x) return 0; b = OPENSSL_malloc(n); - if (b == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (b == NULL) return 0; - } p = (unsigned char *)b; i2d(x, &p); @@ -90,8 +88,8 @@ int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x) int i, j = 0, n, ret = 1; n = ASN1_item_i2d(x, &b, it); - if (b == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (n < 0 || b == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return 0; } diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c index 19e41ec73e35..854844e7eaf1 100644 --- a/crypto/asn1/a_int.c +++ b/crypto/asn1/a_int.c @@ -40,7 +40,7 @@ int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) return ret; } -/*- +/* * This converts a big endian buffer and sign into its content encoding. * This is used for INTEGER and ENUMERATED types. * The internal representation is an ASN1_STRING whose data is a big endian @@ -260,12 +260,16 @@ static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen, return 0; if (neg) { if (r <= INT64_MAX) { - /* Most significant bit is guaranteed to be clear, negation - * is guaranteed to be meaningful in platform-neutral sense. */ + /* + * Most significant bit is guaranteed to be clear, negation + * is guaranteed to be meaningful in platform-neutral sense. + */ *pr = -(int64_t)r; } else if (r == ABS_INT64_MIN) { - /* This never happens if INT64_MAX == ABS_INT64_MIN, e.g. - * on ones'-complement system. */ + /* + * This never happens if INT64_MAX == ABS_INT64_MIN, e.g. + * on ones'-complement system. + */ *pr = (int64_t)(0 - r); } else { ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL); @@ -303,8 +307,10 @@ ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, } else ret = *a; - if (ASN1_STRING_set(ret, NULL, r) == 0) + if (ASN1_STRING_set(ret, NULL, r) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; + } c2i_ibuf(ret->data, &neg, *pp, len); @@ -318,7 +324,6 @@ ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, (*a) = ret; return ret; err: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); if (a == NULL || *a != ret) ASN1_INTEGER_free(ret); return NULL; @@ -344,11 +349,13 @@ static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype) a->type = itype; if (r < 0) { - /* Most obvious '-r' triggers undefined behaviour for most + /* + * Most obvious '-r' triggers undefined behaviour for most * common INT64_MIN. Even though below '0 - (uint64_t)r' can * appear two's-complement centric, it does produce correct/ - * expected result even on one's-complement. This is because - * cast to unsigned has to change bit pattern... */ + * expected result even on ones' complement. This is because + * cast to unsigned has to change bit pattern... + */ off = asn1_put_uint64(tbuf, 0 - (uint64_t)r); a->type |= V_ASN1_NEG; } else { @@ -400,7 +407,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, unsigned char *s; long len = 0; int inf, tag, xclass; - int i; + int i = 0; if ((a == NULL) || ((*a) == NULL)) { if ((ret = ASN1_INTEGER_new()) == NULL) @@ -430,10 +437,8 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, * a missing NULL parameter. */ s = OPENSSL_malloc((int)len + 1); - if (s == NULL) { - i = ERR_R_MALLOC_FAILURE; + if (s == NULL) goto err; - } ret->type = V_ASN1_INTEGER; if (len) { if ((*p == 0) && (len != 1)) { @@ -444,15 +449,14 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, p += len; } - OPENSSL_free(ret->data); - ret->data = s; - ret->length = (int)len; + ASN1_STRING_set0(ret, s, (int)len); if (a != NULL) (*a) = ret; *pp = p; return ret; err: - ERR_raise(ERR_LIB_ASN1, i); + if (i != 0) + ERR_raise(ERR_LIB_ASN1, i); if ((a == NULL) || (*a != ret)) ASN1_INTEGER_free(ret); return NULL; @@ -485,7 +489,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, len = 1; if (ASN1_STRING_set(ret, NULL, len) == 0) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c index bca1458ad6a1..c8170e16267d 100644 --- a/crypto/asn1/a_mbstr.c +++ b/crypto/asn1/a_mbstr.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -145,7 +145,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, free_out = 1; dest = ASN1_STRING_type_new(str_type); if (dest == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return -1; } *out = dest; @@ -157,7 +157,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, ASN1_STRING_free(dest); *out = NULL; } - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return -1; } return str_type; @@ -191,7 +191,6 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, ASN1_STRING_free(dest); *out = NULL; } - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } dest->length = outlen; diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c index c96c36e73029..6eb9feb16c4b 100644 --- a/crypto/asn1/a_object.c +++ b/crypto/asn1/a_object.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -31,10 +31,8 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) return objsize; if (*pp == NULL) { - if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) return 0; - } } else { p = *pp; } @@ -135,10 +133,8 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) OPENSSL_free(tmp); tmpsize = blsize + 32; tmp = OPENSSL_malloc(tmpsize); - if (tmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (tmp == NULL) goto err; - } } while (blsize--) { BN_ULONG t = BN_div_word(bl, 0x80L); @@ -196,15 +192,14 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) ERR_raise(ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG); return -1; } - if ((p = OPENSSL_malloc(i + 1)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((p = OPENSSL_malloc(i + 1)) == NULL) return -1; - } i2t_ASN1_OBJECT(p, i + 1, a); } if (i <= 0) { i = BIO_write(bp, "", 9); - i += BIO_dump(bp, (const char *)a->data, a->length); + if (i > 0) + i += BIO_dump(bp, (const char *)a->data, a->length); return i; } BIO_write(bp, p, i); @@ -308,10 +303,8 @@ ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, ret->length = 0; OPENSSL_free(data); data = OPENSSL_malloc(length); - if (data == NULL) { - i = ERR_R_MALLOC_FAILURE; + if (data == NULL) goto err; - } ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; } memcpy(data, p, length); @@ -345,10 +338,8 @@ ASN1_OBJECT *ASN1_OBJECT_new(void) ASN1_OBJECT *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; return ret; } diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c index 302045cfcdfa..8507fc366811 100644 --- a/crypto/asn1/a_sign.c +++ b/crypto/asn1/a_sign.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -35,7 +35,7 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, X509_ALGOR *a; if (ctx == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } for (i = 0; i < 2; i++) { @@ -82,7 +82,6 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, buf_out = OPENSSL_malloc(outll); if (buf_in == NULL || buf_out == NULL) { outl = 0; - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } p = buf_in; @@ -96,16 +95,13 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } - OPENSSL_free(signature->data); - signature->data = buf_out; + ASN1_STRING_set0(signature, buf_out, outl); buf_out = NULL; - signature->length = outl; /* * In the interests of compatibility, I'll make sure that the bit string * has a 'not-used bits' value of 0 */ - signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(signature, 0); err: EVP_MD_CTX_free(ctx); OPENSSL_clear_free((char *)buf_in, inll); @@ -133,7 +129,7 @@ int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1, EVP_MD_CTX *ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq); if (ctx == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return 0; } /* We can use the non _ex variant here since the pkey is already setup */ @@ -247,16 +243,14 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, goto err; } - if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) - paramtype = V_ASN1_NULL; - else - paramtype = V_ASN1_UNDEF; - - if (algor1) - X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL); - if (algor2) - X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL); - + paramtype = pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL ? + V_ASN1_NULL : V_ASN1_UNDEF; + if (algor1 != NULL + && !X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL)) + goto err; + if (algor2 != NULL + && !X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL)) + goto err; } buf_len = ASN1_item_i2d(data, &buf_in, it); @@ -275,7 +269,6 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, buf_out = OPENSSL_malloc(outll); if (buf_in == NULL || buf_out == NULL) { outl = 0; - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); goto err; } @@ -284,16 +277,13 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } - OPENSSL_free(signature->data); - signature->data = buf_out; + ASN1_STRING_set0(signature, buf_out, outl); buf_out = NULL; - signature->length = outl; /* * In the interests of compatibility, I'll make sure that the bit string * has a 'not-used bits' value of 0 */ - signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - signature->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(signature, 0); err: OPENSSL_clear_free((char *)buf_in, inl); OPENSSL_clear_free((char *)buf_out, outll); diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c index a6049f7dd2ed..4b031a73add5 100644 --- a/crypto/asn1/a_strex.c +++ b/crypto/asn1/a_strex.c @@ -235,15 +235,14 @@ static int do_buf(unsigned char *buf, int buflen, static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen) { - static const char hexdig[] = "0123456789ABCDEF"; unsigned char *p, *q; char hextmp[2]; + if (arg) { p = buf; q = buf + buflen; while (p != q) { - hextmp[0] = hexdig[*p >> 4]; - hextmp[1] = hexdig[*p & 0xf]; + ossl_to_hex(hextmp, *p); if (!io_ch(arg, hextmp, 2)) return -1; p++; @@ -283,10 +282,8 @@ static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, der_len = i2d_ASN1_TYPE(&t, NULL); if (der_len <= 0) return -1; - if ((der_buf = OPENSSL_malloc(der_len)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((der_buf = OPENSSL_malloc(der_len)) == NULL) return -1; - } p = der_buf; i2d_ASN1_TYPE(&t, &p); outlen = do_hex_dump(io_ch, arg, der_buf, der_len); diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c index 20cfabc8a7a4..8f85971130e7 100644 --- a/crypto/asn1/a_strnid.c +++ b/crypto/asn1/a_strnid.c @@ -50,10 +50,10 @@ int ASN1_STRING_set_default_mask_asc(const char *p) unsigned long mask; char *end; - if (strncmp(p, "MASK:", 5) == 0) { - if (p[5] == '\0') + if (CHECK_AND_SKIP_PREFIX(p, "MASK:")) { + if (*p == '\0') return 0; - mask = strtoul(p + 5, &end, 0); + mask = strtoul(p, &end, 0); if (*end) return 0; } else if (strcmp(p, "nombstr") == 0) @@ -135,7 +135,9 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) #endif fnd.nid = nid; - if (stable) { + if (stable != NULL) { + /* Ideally, this would be done under lock */ + sk_ASN1_STRING_TABLE_sort(stable); idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); if (idx >= 0) return sk_ASN1_STRING_TABLE_value(stable, idx); @@ -161,10 +163,8 @@ static ASN1_STRING_TABLE *stable_get(int nid) tmp = ASN1_STRING_TABLE_get(nid); if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) return tmp; - if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) return NULL; - } if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { OPENSSL_free(rv); return NULL; @@ -192,7 +192,7 @@ int ASN1_STRING_TABLE_add(int nid, tmp = stable_get(nid); if (tmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return 0; } if (minsize >= 0) diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c index 5ef6d0d1cd1c..194504415dd1 100644 --- a/crypto/asn1/a_time.c +++ b/crypto/asn1/a_time.c @@ -79,7 +79,7 @@ int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; char *a; - int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md; + int n, i, i2, l, o, min_l, strict = 0, end = 6, btz = 5, md; struct tm tmp; #if defined(CHARSET_EBCDIC) const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B; @@ -92,21 +92,19 @@ int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d) * * 1. "seconds" is a 'MUST' * 2. "Zulu" timezone is a 'MUST' - * 3. "+|-" is not allowed to indicate a time zone + * 3. "+|-" is not allowed to indicate a timezone */ if (d->type == V_ASN1_UTCTIME) { + min_l = 13; if (d->flags & ASN1_STRING_FLAG_X509_TIME) { - min_l = 13; strict = 1; } } else if (d->type == V_ASN1_GENERALIZEDTIME) { end = 7; btz = 6; + min_l = 15; if (d->flags & ASN1_STRING_FLAG_X509_TIME) { - min_l = 15; strict = 1; - } else { - min_l = 13; } } else { return 0; @@ -295,16 +293,22 @@ ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type) tmps->type = type; p = (char*)tmps->data; - if (type == V_ASN1_GENERALIZEDTIME) + if (ts->tm_mon > INT_MAX - 1) + goto err; + + if (type == V_ASN1_GENERALIZEDTIME) { + if (ts->tm_year > INT_MAX - 1900) + goto err; tmps->length = BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); - else + } else { tmps->length = BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); + } #ifdef CHARSET_EBCDIC ebcdic2ascii(tmps->data, tmps->data, tmps->length); @@ -420,10 +424,8 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str) * new t.data would be freed after ASN1_STRING_copy is done. */ t.data = OPENSSL_zalloc(t.length + 1); - if (t.data == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (t.data == NULL) goto out; - } memcpy(t.data, str + 2, t.length); t.type = V_ASN1_UTCTIME; } @@ -566,7 +568,7 @@ int ASN1_TIME_normalize(ASN1_TIME *t) { struct tm tm; - if (!ASN1_TIME_to_tm(t, &tm)) + if (t == NULL || !ASN1_TIME_to_tm(t, &tm)) return 0; return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL; diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c index 66809bd6d2ff..f6cac8096204 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -33,7 +33,7 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature, int ret = -1, i, inl; if (ctx == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } i = OBJ_obj2nid(a->algorithm); @@ -54,10 +54,8 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature, goto err; } buf_in = OPENSSL_malloc((unsigned int)inl); - if (buf_in == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (buf_in == NULL) goto err; - } p = buf_in; i2d(data, &p); @@ -182,8 +180,9 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, if (mdnid != NID_undef) { type = EVP_get_digestbynid(mdnid); if (type == NULL) { - ERR_raise(ERR_LIB_ASN1, - ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + ERR_raise_data(ERR_LIB_ASN1, + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM, + "nid=0x%x", mdnid); goto err; } } @@ -207,7 +206,7 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, goto err; } if (buf_in == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); ret = -1; goto err; } diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c index 8b15da3beed6..6ba13dd7f22e 100644 --- a/crypto/asn1/ameth_lib.c +++ b/crypto/asn1/ameth_lib.c @@ -222,10 +222,8 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, { EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth)); - if (ameth == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ameth == NULL) return NULL; - } ameth->pkey_id = id; ameth->pkey_base_id = id; @@ -247,7 +245,6 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, err: EVP_PKEY_asn1_free(ameth); - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c index a7b32e3a6e1a..f52584244970 100644 --- a/crypto/asn1/asn1_err.c +++ b/crypto/asn1/asn1_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -55,6 +55,8 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = { {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "field missing"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE), "first num too large"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT), + "generalizedtime is too short"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "header too long"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT), "illegal bitstring format"}, @@ -192,6 +194,8 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = { {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "unsupported type"}, + {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UTCTIME_IS_TOO_SHORT), + "utctime is too short"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_INTEGER_TYPE), "wrong integer type"}, {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_PUBLIC_KEY_TYPE), diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c index 152dc870a558..50b4db97aa65 100644 --- a/crypto/asn1/asn1_gen.c +++ b/crypto/asn1/asn1_gen.c @@ -7,9 +7,10 @@ * https://www.openssl.org/source/license.html */ -#include "internal/cryptlib.h" #include #include +#include "internal/cryptlib.h" +#include "crypto/asn1.h" #define ASN1_GEN_FLAG 0x10000 #define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1) @@ -324,13 +325,13 @@ static int asn1_cb(const char *elem, int len, void *bitstr) ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT); return -1; } - if (strncmp(vstart, "ASCII", 5) == 0) + if (HAS_PREFIX(vstart, "ASCII")) arg->format = ASN1_GEN_FORMAT_ASCII; - else if (strncmp(vstart, "UTF8", 4) == 0) + else if (HAS_PREFIX(vstart, "UTF8")) arg->format = ASN1_GEN_FORMAT_UTF8; - else if (strncmp(vstart, "HEX", 3) == 0) + else if (HAS_PREFIX(vstart, "HEX")) arg->format = ASN1_GEN_FORMAT_HEX; - else if (strncmp(vstart, "BITLIST", 7) == 0) + else if (HAS_PREFIX(vstart, "BITLIST")) arg->format = ASN1_GEN_FORMAT_BITLIST; else { ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT); @@ -582,7 +583,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) int no_unused = 1; if ((atmp = ASN1_TYPE_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return NULL; } @@ -643,11 +644,11 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) goto bad_form; } if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } atmp->value.asn1_string->type = utype; @@ -678,7 +679,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str, -1, format, ASN1_tag2bit(utype)) <= 0) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } @@ -687,7 +688,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_form; } @@ -701,7 +702,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) atmp->value.asn1_string->type = utype; } else if (format == ASN1_GEN_FORMAT_ASCII) { if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto bad_str; } } else if ((format == ASN1_GEN_FORMAT_BITLIST) @@ -718,11 +719,8 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype) goto bad_form; } - if ((utype == V_ASN1_BIT_STRING) && no_unused) { - atmp->value.asn1_string->flags - &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT; - } + if ((utype == V_ASN1_BIT_STRING) && no_unused) + ossl_asn1_string_set_bits_left(atmp->value.asn1_string, 0); break; @@ -757,7 +755,7 @@ static int bitstr_cb(const char *elem, int len, void *bitstr) return 0; } if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return 0; } return 1; @@ -769,7 +767,7 @@ static int mask_cb(const char *elem, int len, void *arg) int tag; if (elem == NULL) return 0; - if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) { + if (len == 3 && HAS_PREFIX(elem, "DIR")) { *pmask |= B_ASN1_DIRECTORYSTRING; return 1; } diff --git a/crypto/asn1/asn1_item_list.c b/crypto/asn1/asn1_item_list.c index b5a83ba8914b..2b57694e336e 100644 --- a/crypto/asn1/asn1_item_list.c +++ b/crypto/asn1/asn1_item_list.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,6 +21,7 @@ #include #include #include +#include #include "asn1_item_list.h" diff --git a/crypto/asn1/asn1_item_list.h b/crypto/asn1/asn1_item_list.h index 1432012b7c7c..3d678ae18fd5 100644 --- a/crypto/asn1/asn1_item_list.h +++ b/crypto/asn1/asn1_item_list.h @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -52,6 +52,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = { ASN1_ITEM_ref(CERTIFICATEPOLICIES), #ifndef OPENSSL_NO_CMS ASN1_ITEM_ref(CMS_ContentInfo), + ASN1_ITEM_ref(CMS_EnvelopedData), ASN1_ITEM_ref(CMS_ReceiptRequest), #endif ASN1_ITEM_ref(CRL_DIST_POINTS), @@ -149,6 +150,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = { ASN1_ITEM_ref(SXNET), ASN1_ITEM_ref(ISSUER_SIGN_TOOL), ASN1_ITEM_ref(USERNOTICE), + ASN1_ITEM_ref(X509_ACERT), ASN1_ITEM_ref(X509_ALGORS), ASN1_ITEM_ref(X509_ALGOR), ASN1_ITEM_ref(X509_ATTRIBUTE), diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c index 5359cbc11720..e3a8480eef3f 100644 --- a/crypto/asn1/asn1_lib.c +++ b/crypto/asn1/asn1_lib.c @@ -248,6 +248,12 @@ int ASN1_object_size(int constructed, int length, int tag) return ret + length; } +void ossl_asn1_string_set_bits_left(ASN1_STRING *str, unsigned int num) +{ + str->flags &= ~0x07; + str->flags |= ASN1_STRING_FLAG_BITS_LEFT | (num & 0x07); +} + int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) { if (str == NULL) @@ -308,7 +314,6 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in) str->data = OPENSSL_realloc(c, len + 1); #endif if (str->data == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); str->data = c; return 0; } @@ -348,10 +353,8 @@ ASN1_STRING *ASN1_STRING_type_new(int type) ASN1_STRING *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->type = type; return ret; } diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h index f73bd8fc6a30..10e9fcb7de45 100644 --- a/crypto/asn1/asn1_local.h +++ b/crypto/asn1/asn1_local.h @@ -9,6 +9,8 @@ /* Internal ASN1 structures and functions: not for application use */ +#include "crypto/asn1.h" + typedef const ASN1_VALUE const_ASN1_VALUE; SKM_DEFINE_STACK_OF(const_ASN1_VALUE, const ASN1_VALUE, ASN1_VALUE) diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c index 8bb7089292d0..806adade7ffc 100644 --- a/crypto/asn1/asn_mime.c +++ b/crypto/asn1/asn_mime.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -76,7 +76,7 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, BIO *bio, *tbio; bio = BIO_new_NDEF(out, val, it); if (!bio) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return 0; } if (!SMIME_crlf_copy(in, bio, flags)) { @@ -96,7 +96,7 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, * internally */ else - ASN1_item_i2d_bio(it, out, val); + rv = ASN1_item_i2d_bio(it, out, val); return rv; } @@ -109,7 +109,7 @@ static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, int r; b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BIO_LIB); return 0; } /* @@ -142,7 +142,7 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x, ASN1_VALUE *val; if ((b64 = BIO_new(BIO_f_base64())) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BIO_LIB); return 0; } bio = BIO_push(b64, bio); @@ -530,7 +530,7 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags) */ bf = BIO_new(BIO_f_buffer()); if (bf == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BIO_LIB); return 0; } out = BIO_push(bf, out); @@ -687,7 +687,7 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) char linebuf[MAX_SMLEN]; MIME_HEADER *mhdr = NULL, *new_hdr = NULL; STACK_OF(MIME_HEADER) *headers; - int len, state, save_state = 0; + int i, len, state, save_state = 0; headers = sk_MIME_HEADER_new(mime_hdr_cmp); if (headers == NULL) @@ -793,6 +793,12 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) break; /* Blank line means end of headers */ } + /* Sort the headers and their params for faster searching */ + sk_MIME_HEADER_sort(headers); + for (i = 0; i < sk_MIME_HEADER_num(headers); i++) + if ((mhdr = sk_MIME_HEADER_value(headers, i)) != NULL + && mhdr->params != NULL) + sk_MIME_PARAM_sort(mhdr->params); return headers; err: @@ -991,13 +997,8 @@ static int mime_bound_check(char *line, int linelen, const char *bound, int blen if (blen + 2 > linelen) return 0; /* Check for part boundary */ - if ((strncmp(line, "--", 2) == 0) - && strncmp(line + 2, bound, blen) == 0) { - if (strncmp(line + blen + 2, "--", 2) == 0) - return 2; - else - return 1; - } + if ((CHECK_AND_SKIP_PREFIX(line, "--")) && strncmp(line, bound, blen) == 0) + return HAS_PREFIX(line + blen, "--") ? 2 : 1; return 0; } diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c index 9aaab8a269d3..1e183f4f18aa 100644 --- a/crypto/asn1/asn_moid.c +++ b/crypto/asn1/asn_moid.c @@ -87,10 +87,8 @@ static int do_create(const char *value, const char *name) p--; } p++; - if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) return 0; - } memcpy(lntmp, ln, p - ln); lntmp[p - ln] = '\0'; ln = lntmp; diff --git a/crypto/asn1/asn_mstbl.c b/crypto/asn1/asn_mstbl.c index 1208d5663d25..b9309576559b 100644 --- a/crypto/asn1/asn_mstbl.c +++ b/crypto/asn1/asn_mstbl.c @@ -110,7 +110,7 @@ static int do_tcreate(const char *value, const char *name) rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max, tbl_mask, tbl_flags); if (!rv) - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); } sk_CONF_VALUE_pop_free(lst, X509V3_conf_free); return rv; diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c index 2389264f17da..54f4ae3a67b2 100644 --- a/crypto/asn1/asn_pack.c +++ b/crypto/asn1/asn_pack.c @@ -17,24 +17,23 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) { ASN1_STRING *octmp; - if (oct == NULL || *oct == NULL) { + if (oct == NULL || *oct == NULL) { if ((octmp = ASN1_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return NULL; } } else { octmp = *oct; } - OPENSSL_free(octmp->data); - octmp->data = NULL; + ASN1_STRING_set0(octmp, NULL, 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); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } @@ -60,3 +59,16 @@ void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); return ret; } + +void *ASN1_item_unpack_ex(const ASN1_STRING *oct, const ASN1_ITEM *it, + OSSL_LIB_CTX *libctx, const char *propq) +{ + const unsigned char *p; + void *ret; + + p = oct->data; + if ((ret = ASN1_item_d2i_ex(NULL, &p, oct->length, it,\ + libctx, propq)) == NULL) + ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c index 0ff239120451..f1499425010d 100644 --- a/crypto/asn1/bio_asn1.c +++ b/crypto/asn1/bio_asn1.c @@ -100,10 +100,8 @@ static int asn1_bio_new(BIO *b) { BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ctx == NULL) return 0; - } if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { OPENSSL_free(ctx); return 0; @@ -116,10 +114,12 @@ static int asn1_bio_new(BIO *b) static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) { - if (size <= 0 || (ctx->buf = OPENSSL_malloc(size)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (size <= 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } + if ((ctx->buf = OPENSSL_malloc(size)) == NULL) + return 0; ctx->bufsize = size; ctx->asn1_class = V_ASN1_UNIVERSAL; ctx->asn1_tag = V_ASN1_OCTET_STRING; diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c index e5b5319d7fd0..279609e60354 100644 --- a/crypto/asn1/bio_ndef.c +++ b/crypto/asn1/bio_ndef.c @@ -140,10 +140,8 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); if (derlen < 0) return 0; - if ((p = OPENSSL_malloc(derlen)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((p = OPENSSL_malloc(derlen)) == NULL) return 0; - } ndef_aux->derbuf = p; *pbuf = p; @@ -215,10 +213,8 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); if (derlen < 0) return 0; - if ((p = OPENSSL_malloc(derlen)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((p = OPENSSL_malloc(derlen)) == NULL) return 0; - } ndef_aux->derbuf = p; *pbuf = p; diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c index 720b7fd6c050..7f68e5732800 100644 --- a/crypto/asn1/d2i_pr.c +++ b/crypto/asn1/d2i_pr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,7 +21,9 @@ #include #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/x509.h" #include "internal/asn1.h" +#include "internal/sizes.h" static EVP_PKEY * d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, @@ -32,8 +34,12 @@ d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, EVP_PKEY *pkey = NULL, *bak_a = NULL; EVP_PKEY **ppkey = &pkey; const char *key_name = NULL; - const char *input_structures[] = { "type-specific", "PrivateKeyInfo", NULL }; - int i, ret; + char keytypebuf[OSSL_MAX_NAME_SIZE]; + int ret; + const unsigned char *p = *pp; + const char *structure; + PKCS8_PRIV_KEY_INFO *p8info; + const ASN1_OBJECT *algoid; if (keytype != EVP_PKEY_NONE) { key_name = evp_pkey_type2name(keytype); @@ -41,34 +47,52 @@ d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp, return NULL; } - for (i = 0; i < (int)OSSL_NELEM(input_structures); ++i) { - const unsigned char *p = *pp; + /* This is just a probe. It might fail, so we ignore errors */ + ERR_set_mark(); + p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, len); + ERR_pop_to_mark(); + if (p8info != NULL) { + int64_t v; - if (a != NULL && (bak_a = *a) != NULL) - ppkey = a; - dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", - input_structures[i], key_name, - EVP_PKEY_KEYPAIR, libctx, propq); - if (a != NULL) - *a = bak_a; - if (dctx == NULL) - continue; - - ret = OSSL_DECODER_from_data(dctx, pp, &len); - OSSL_DECODER_CTX_free(dctx); - if (ret) { - if (*ppkey != NULL - && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { - if (a != NULL) - *a = *ppkey; - return *ppkey; - } + /* ascertain version is 0 or 1 as per RFC5958 */ + if (!ASN1_INTEGER_get_int64(&v, p8info->version) + || (v != 0 && v != 1)) { *pp = p; - goto err; + ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR); + PKCS8_PRIV_KEY_INFO_free(p8info); + return NULL; } + if (key_name == NULL + && PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8info) + && OBJ_obj2txt(keytypebuf, sizeof(keytypebuf), algoid, 0)) + key_name = keytypebuf; + structure = "PrivateKeyInfo"; + PKCS8_PRIV_KEY_INFO_free(p8info); + } else { + structure = "type-specific"; } - /* Fall through to error if all decodes failed */ -err: + *pp = p; + + if (a != NULL && (bak_a = *a) != NULL) + ppkey = a; + dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER", structure, key_name, + EVP_PKEY_KEYPAIR, libctx, propq); + if (a != NULL) + *a = bak_a; + if (dctx == NULL) + goto err; + + ret = OSSL_DECODER_from_data(dctx, pp, &len); + OSSL_DECODER_CTX_free(dctx); + if (ret + && *ppkey != NULL + && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) { + if (a != NULL) + *a = *ppkey; + return *ppkey; + } + + err: if (ppkey != a) EVP_PKEY_free(*ppkey); return NULL; diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c index d41e0069af63..5b5dda4ce120 100644 --- a/crypto/asn1/f_int.c +++ b/crypto/asn1/f_int.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,7 +16,6 @@ int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) { int i, n = 0; - static const char *h = "0123456789ABCDEF"; char buf[2]; if (a == NULL) @@ -39,8 +38,7 @@ int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) goto err; n += 2; } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + ossl_to_hex(buf, a->data[i]); if (BIO_write(bp, buf, 2) != 2) goto err; n += 2; @@ -76,8 +74,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) again = (buf[i - 1] == '\\'); for (j = 0; j < i; j++) { - if (!ossl_isxdigit(buf[j])) - { + if (!ossl_isxdigit(buf[j])) { i = j; break; } @@ -108,7 +105,6 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) if (num + i > slen) { sp = OPENSSL_clear_realloc(s, slen, num + i * 2); if (sp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); OPENSSL_free(s); return 0; } diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c index 4b65110d9866..7e4e5985149d 100644 --- a/crypto/asn1/f_string.c +++ b/crypto/asn1/f_string.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,7 +16,6 @@ int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) { int i, n = 0; - static const char *h = "0123456789ABCDEF"; char buf[2]; if (a == NULL) @@ -33,8 +32,7 @@ int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) goto err; n += 2; } - buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; - buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; + ossl_to_hex(buf, a->data[i]); if (BIO_write(bp, buf, 2) != 2) goto err; n += 2; @@ -99,7 +97,6 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) if (num + i > slen) { sp = OPENSSL_realloc(s, (unsigned int)num + i * 2); if (sp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); OPENSSL_free(s); return 0; } diff --git a/crypto/asn1/i2d_evp.c b/crypto/asn1/i2d_evp.c index 0d66411be8fd..106ea152733c 100644 --- a/crypto/asn1/i2d_evp.c +++ b/crypto/asn1/i2d_evp.c @@ -1,5 +1,5 @@ /* - * 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 @@ -34,7 +34,6 @@ static int i2d_provided(const EVP_PKEY *a, int selection, const struct type_and_structure_st *output_info, unsigned char **pp) { - OSSL_ENCODER_CTX *ctx = NULL; int ret; for (ret = -1; @@ -49,6 +48,7 @@ static int i2d_provided(const EVP_PKEY *a, int selection, */ size_t len = INT_MAX; int pp_was_NULL = (pp == NULL || *pp == NULL); + OSSL_ENCODER_CTX *ctx; ctx = OSSL_ENCODER_CTX_new_for_pkey(a, selection, output_info->output_type, @@ -63,7 +63,6 @@ static int i2d_provided(const EVP_PKEY *a, int selection, ret = INT_MAX - (int)len; } OSSL_ENCODER_CTX_free(ctx); - ctx = NULL; } if (ret == -1) diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c index 9bc8aaa7a31e..a90c200d42a5 100644 --- a/crypto/asn1/p5_pbe.c +++ b/crypto/asn1/p5_pbe.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -12,6 +12,7 @@ #include #include #include +#include "crypto/evp.h" /* PKCS#5 password based encryption structure */ @@ -34,25 +35,24 @@ int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter, pbe = PBEPARAM_new(); if (pbe == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + /* ERR_R_ASN1_LIB, because PBEPARAM_new() is defined in crypto/asn1 */ + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } if (iter <= 0) iter = PKCS5_DEFAULT_ITER; if (!ASN1_INTEGER_set(pbe->iter, iter)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } if (!saltlen) - saltlen = PKCS5_SALT_LEN; + saltlen = PKCS5_DEFAULT_PBE1_SALT_LEN; if (saltlen < 0) goto err; sstr = OPENSSL_malloc(saltlen); - if (sstr == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (sstr == NULL) goto err; - } if (salt) memcpy(sstr, salt, saltlen); else if (RAND_bytes_ex(ctx, sstr, saltlen, 0) <= 0) @@ -62,7 +62,7 @@ int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter, sstr = NULL; if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } @@ -94,7 +94,7 @@ X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter, X509_ALGOR *ret; ret = X509_ALGOR_new(); if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); return NULL; } diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c index 711743a77b59..b9ad4db4a79a 100644 --- a/crypto/asn1/p5_pbev2.c +++ b/crypto/asn1/p5_pbev2.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,8 @@ #include #include "internal/cryptlib.h" +#include "crypto/asn1.h" +#include "crypto/evp.h" #include #include #include @@ -33,6 +35,13 @@ ASN1_SEQUENCE(PBKDF2PARAM) = { IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM) +ASN1_SEQUENCE(PBMAC1PARAM) = { + ASN1_SIMPLE(PBMAC1PARAM, keyDerivationFunc, X509_ALGOR), + ASN1_SIMPLE(PBMAC1PARAM, messageAuthScheme, X509_ALGOR) +} ASN1_SEQUENCE_END(PBMAC1PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBMAC1PARAM) + /* * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know * this is horrible! Extended version to allow application supplied PRF NID @@ -56,14 +65,18 @@ X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter, goto err; } - if ((pbe2 = PBE2PARAM_new()) == NULL) - goto merr; + if ((pbe2 = PBE2PARAM_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = OBJ_nid2obj(alg_nid); - if ((scheme->parameter = ASN1_TYPE_new()) == NULL) - goto merr; + if ((scheme->parameter = ASN1_TYPE_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Create random IV */ ivlen = EVP_CIPHER_get_iv_length(cipher); @@ -75,8 +88,10 @@ X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter, } ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) - goto merr; + if (ctx == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); + goto err; + } /* Dummy cipherinit to just setup the IV, and PRF */ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0)) @@ -112,30 +127,33 @@ X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter, pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, libctx); - if (pbe2->keyfunc == NULL) - goto merr; + if (pbe2->keyfunc == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Now set up top level AlgorithmIdentifier */ - if ((ret = X509_ALGOR_new()) == NULL) - goto merr; + if ((ret = X509_ALGOR_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); + goto err; + } ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, - &ret->parameter)) - goto merr; + &ret->parameter)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; - merr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); - err: EVP_CIPHER_CTX_free(ctx); PBE2PARAM_free(pbe2); @@ -169,70 +187,89 @@ X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen, PBKDF2PARAM *kdf = NULL; ASN1_OCTET_STRING *osalt = NULL; - if ((kdf = PBKDF2PARAM_new()) == NULL) - goto merr; - if ((osalt = ASN1_OCTET_STRING_new()) == NULL) - goto merr; + if ((kdf = PBKDF2PARAM_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } + if ((osalt = ASN1_OCTET_STRING_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } kdf->salt->value.octet_string = osalt; kdf->salt->type = V_ASN1_OCTET_STRING; - if (saltlen < 0) - goto merr; + if (saltlen < 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_INVALID_ARGUMENT); + goto err; + } if (saltlen == 0) - saltlen = PKCS5_SALT_LEN; + saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN; if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL) - goto merr; + goto err; + osalt->length = saltlen; - if (salt) + if (salt) { memcpy(osalt->data, salt, saltlen); - else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0) - goto merr; + } else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_RAND_LIB); + goto err; + } if (iter <= 0) iter = PKCS5_DEFAULT_ITER; - if (!ASN1_INTEGER_set(kdf->iter, iter)) - goto merr; + if (!ASN1_INTEGER_set(kdf->iter, iter)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* If have a key len set it up */ if (keylen > 0) { - if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) - goto merr; - if (!ASN1_INTEGER_set(kdf->keylength, keylen)) - goto merr; + if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } + if (!ASN1_INTEGER_set(kdf->keylength, keylen)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } } /* prf can stay NULL if we are using hmacWithSHA1 */ if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) { - kdf->prf = X509_ALGOR_new(); - if (kdf->prf == NULL) - goto merr; - X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL); + kdf->prf = ossl_X509_ALGOR_from_nid(prf_nid, V_ASN1_NULL, NULL); + if (kdf->prf == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); + goto err; + } } /* Finally setup the keyfunc structure */ keyfunc = X509_ALGOR_new(); - if (keyfunc == NULL) - goto merr; + if (keyfunc == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); + goto err; + } keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); /* Encode PBKDF2PARAM into parameter of pbe2 */ if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf, - &keyfunc->parameter)) - goto merr; + &keyfunc->parameter)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } PBKDF2PARAM_free(kdf); return keyfunc; - merr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + err: PBKDF2PARAM_free(kdf); X509_ALGOR_free(keyfunc); return NULL; diff --git a/crypto/asn1/p5_scrypt.c b/crypto/asn1/p5_scrypt.c index a02190d0dc11..4f3dcecd41ab 100644 --- a/crypto/asn1/p5_scrypt.c +++ b/crypto/asn1/p5_scrypt.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -67,16 +67,20 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, } pbe2 = PBE2PARAM_new(); - if (pbe2 == NULL) - goto merr; + if (pbe2 == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Setup the AlgorithmIdentifier for the encryption scheme */ scheme = pbe2->encryption; scheme->algorithm = OBJ_nid2obj(alg_nid); scheme->parameter = ASN1_TYPE_new(); - if (scheme->parameter == NULL) - goto merr; + if (scheme->parameter == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Create random IV */ if (EVP_CIPHER_get_iv_length(cipher)) { @@ -87,8 +91,10 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, } ctx = EVP_CIPHER_CTX_new(); - if (ctx == NULL) - goto merr; + if (ctx == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); + goto err; + } /* Dummy cipherinit to just setup the IV */ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0) @@ -111,31 +117,34 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p); - if (pbe2->keyfunc == NULL) - goto merr; + if (pbe2->keyfunc == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* Now set up top level AlgorithmIdentifier */ ret = X509_ALGOR_new(); - if (ret == NULL) - goto merr; + if (ret == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } ret->algorithm = OBJ_nid2obj(NID_pbes2); /* Encode PBE2PARAM into parameter */ if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, - &ret->parameter) == NULL) - goto merr; + &ret->parameter) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } PBE2PARAM_free(pbe2); pbe2 = NULL; return ret; - merr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); - err: PBE2PARAM_free(pbe2); X509_ALGOR_free(ret); @@ -151,57 +160,73 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen, X509_ALGOR *keyfunc = NULL; SCRYPT_PARAMS *sparam = SCRYPT_PARAMS_new(); - if (sparam == NULL) - goto merr; + if (sparam == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } if (!saltlen) - saltlen = PKCS5_SALT_LEN; + saltlen = PKCS5_DEFAULT_PBE2_SALT_LEN; /* This will either copy salt or grow the buffer */ - if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) - goto merr; + if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } if (salt == NULL && RAND_bytes(sparam->salt->data, saltlen) <= 0) goto err; - if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0) - goto merr; + if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } - if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0) - goto merr; + if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } - if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0) - goto merr; + if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } /* If have a key len set it up */ if (keylen > 0) { sparam->keyLength = ASN1_INTEGER_new(); - if (sparam->keyLength == NULL) - goto merr; - if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0) - goto merr; + if (sparam->keyLength == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } + if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } } /* Finally setup the keyfunc structure */ keyfunc = X509_ALGOR_new(); - if (keyfunc == NULL) - goto merr; + if (keyfunc == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } keyfunc->algorithm = OBJ_nid2obj(NID_id_scrypt); /* Encode SCRYPT_PARAMS into parameter of pbe2 */ if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), sparam, - &keyfunc->parameter) == NULL) - goto merr; + &keyfunc->parameter) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + goto err; + } SCRYPT_PARAMS_free(sparam); return keyfunc; - merr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); err: SCRYPT_PARAMS_free(sparam); X509_ALGOR_free(keyfunc); diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c index dee188519c22..a33445d49e76 100644 --- a/crypto/asn1/p8_pkey.c +++ b/crypto/asn1/p8_pkey.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,11 +17,25 @@ static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) { - /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ - if (operation == ASN1_OP_FREE_PRE) { - PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; + PKCS8_PRIV_KEY_INFO *key; + int version; + + switch (operation) { + case ASN1_OP_FREE_PRE: + /* The structure is still valid during ASN1_OP_FREE_PRE */ + key = (PKCS8_PRIV_KEY_INFO *)*pval; if (key->pkey) OPENSSL_cleanse(key->pkey->data, key->pkey->length); + break; + case ASN1_OP_D2I_POST: + /* Insist on a valid version now that the structure is decoded */ + key = (PKCS8_PRIV_KEY_INFO *)*pval; + version = ASN1_INTEGER_get(key->version); + if (version < 0 || version > 1) + return 0; + if (version == 0 && key->kpub != NULL) + return 0; + break; } return 1; } @@ -30,7 +44,8 @@ ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING), - ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) + ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0), + ASN1_IMP_OPT(PKCS8_PRIV_KEY_INFO, kpub, ASN1_BIT_STRING, 1) } ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) @@ -40,6 +55,9 @@ int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int ptype, void *pval, unsigned char *penc, int penclen) { if (version >= 0) { + /* We only support PKCS#8 v1 (0) and v2 (1). */ + if (version > 1) + return 0; if (!ASN1_INTEGER_set(priv->version, version)) return 0; } diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h index 0b0c7ef6864f..0d81a2d4634d 100644 --- a/crypto/asn1/standard_methods.h +++ b/crypto/asn1/standard_methods.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,7 +23,6 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { &ossl_dsa_asn1_meths[1], &ossl_dsa_asn1_meths[2], &ossl_dsa_asn1_meths[3], - &ossl_dsa_asn1_meths[4], #endif #ifndef OPENSSL_NO_EC &ossl_eckey_asn1_meth, @@ -32,11 +31,9 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { #ifndef OPENSSL_NO_DH &ossl_dhx_asn1_meth, #endif -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECX &ossl_ecx25519_asn1_meth, &ossl_ecx448_asn1_meth, -#endif -#ifndef OPENSSL_NO_EC &ossl_ed25519_asn1_meth, &ossl_ed448_asn1_meth, #endif @@ -44,4 +41,3 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { &ossl_sm2_asn1_meth, #endif }; - diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c index 11198087a57b..c4f9d61514eb 100644 --- a/crypto/asn1/tasn_dec.c +++ b/crypto/asn1/tasn_dec.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -629,7 +629,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, } if (*val == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); goto err; } @@ -658,7 +658,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, } len -= p - q; if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); goto err; } @@ -802,7 +802,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, len = buf.length; /* Append a final null to string */ if (!BUF_MEM_grow_clean(&buf, len + 1)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); goto err; } buf.data[len] = 0; @@ -921,11 +921,19 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, ERR_raise(ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); goto err; } + if (utype == V_ASN1_GENERALIZEDTIME && (len < 15)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT); + goto err; + } + if (utype == V_ASN1_UTCTIME && (len < 13)) { + ERR_raise(ERR_LIB_ASN1, ASN1_R_UTCTIME_IS_TOO_SHORT); + goto err; + } /* All based on ASN1_STRING and handled the same */ if (*pval == NULL) { stmp = ASN1_STRING_type_new(utype); if (stmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); goto err; } *pval = (ASN1_VALUE *)stmp; @@ -935,13 +943,11 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, } /* If we've already allocated a buffer use it */ if (*free_cont) { - OPENSSL_free(stmp->data); - stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ - stmp->length = len; + ASN1_STRING_set0(stmp, (unsigned char *)cont /* UGLY CAST! */, len); *free_cont = 0; } else { if (!ASN1_STRING_set(stmp, cont, len)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); ASN1_STRING_free(stmp); *pval = NULL; goto err; @@ -1100,7 +1106,7 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) if (buf) { len = buf->length; if (!BUF_MEM_grow_clean(buf, len + plen)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); return 0; } memcpy(buf->data + len, *p, plen); diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c index 3ea18b0280dd..f302b4b2e1e8 100644 --- a/crypto/asn1/tasn_enc.c +++ b/crypto/asn1/tasn_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -62,10 +62,8 @@ static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out, len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); if (len <= 0) return len; - if ((buf = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(len)) == NULL) return -1; - } p = buf; ASN1_item_ex_i2d(&val, &p, it, -1, flags); *out = buf; @@ -415,15 +413,11 @@ static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk, else { derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk) * sizeof(*derlst)); - if (derlst == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (derlst == NULL) return 0; - } tmpdat = OPENSSL_malloc(skcontlen); - if (tmpdat == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (tmpdat == NULL) goto err; - } } } /* If not sorting just output each item */ @@ -571,6 +565,9 @@ static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype return -1; break; + case V_ASN1_UNDEF: + return -2; + case V_ASN1_NULL: cont = NULL; len = 0; diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c index 4b624bbdd4e5..00a5397a5e6c 100644 --- a/crypto/asn1/tasn_new.c +++ b/crypto/asn1/tasn_new.c @@ -78,10 +78,10 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, if (ef != NULL) { if (ef->asn1_ex_new_ex != NULL) { if (!ef->asn1_ex_new_ex(pval, it, libctx, propq)) - goto memerr; + goto asn1err; } else if (ef->asn1_ex_new != NULL) { if (!ef->asn1_ex_new(pval, it)) - goto memerr; + goto asn1err; } } break; @@ -89,14 +89,14 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, case ASN1_ITYPE_PRIMITIVE: if (it->templates) { if (!asn1_template_new(pval, it->templates, libctx, propq)) - goto memerr; + goto asn1err; } else if (!asn1_primitive_new(pval, it, embed)) - goto memerr; + goto asn1err; break; case ASN1_ITYPE_MSTRING: if (!asn1_primitive_new(pval, it, embed)) - goto memerr; + goto asn1err; break; case ASN1_ITYPE_CHOICE: @@ -113,7 +113,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, } else { *pval = OPENSSL_zalloc(it->size); if (*pval == NULL) - goto memerr; + return 0; } ossl_asn1_set_choice_selector(pval, -1, it); if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) @@ -135,7 +135,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, } else { *pval = OPENSSL_zalloc(it->size); if (*pval == NULL) - goto memerr; + return 0; } /* 0 : init. lock */ if (ossl_asn1_do_lock(pval, 0, it) < 0) { @@ -143,13 +143,13 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, OPENSSL_free(*pval); *pval = NULL; } - goto memerr; + goto asn1err; } ossl_asn1_enc_init(pval, it); for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { pseqval = ossl_asn1_get_field_ptr(pval, tt); if (!asn1_template_new(pseqval, tt, libctx, propq)) - goto memerr2; + goto asn1err2; } if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) goto auxerr2; @@ -157,10 +157,10 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed, } return 1; - memerr2: + asn1err2: ossl_asn1_item_embed_free(pval, it, embed); - memerr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + asn1err: + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); return 0; auxerr2: @@ -230,7 +230,7 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, STACK_OF(ASN1_VALUE) *skval; skval = sk_ASN1_VALUE_new_null(); if (!skval) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); ret = 0; goto done; } @@ -298,10 +298,8 @@ static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, return 1; case V_ASN1_ANY: - if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) return 0; - } typ->value.ptr = NULL; typ->type = -1; *pval = (ASN1_VALUE *)typ; diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c index 7d8618e26c22..73eadc5fd4f6 100644 --- a/crypto/asn1/tasn_prn.c +++ b/crypto/asn1/tasn_prn.c @@ -37,10 +37,8 @@ ASN1_PCTX *ASN1_PCTX_new(void) ASN1_PCTX *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } return ret; } diff --git a/crypto/asn1/tasn_scn.c b/crypto/asn1/tasn_scn.c index bde697ee9925..7ada313b9449 100644 --- a/crypto/asn1/tasn_scn.c +++ b/crypto/asn1/tasn_scn.c @@ -26,10 +26,8 @@ ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx)) { ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->scan_cb = scan_cb; return ret; } diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c index e5f25d88df69..67a9ccde62db 100644 --- a/crypto/asn1/tasn_utl.c +++ b/crypto/asn1/tasn_utl.c @@ -1,5 +1,5 @@ /* - * 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 @@ -59,7 +59,7 @@ int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value, /* * Do atomic reference counting. The value 'op' decides what to do. * If it is +1 then the count is incremented. - * If |op| is 0, lock is initialised and count is set to 1. + * If |op| is 0, count is initialised and set to 1. * If |op| is -1, count is decremented and the return value is the current * reference count or 0 if no reference count is active. * It returns -1 on initialisation error. @@ -68,8 +68,8 @@ int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value, int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) { const ASN1_AUX *aux; - CRYPTO_REF_COUNT *lck; CRYPTO_RWLOCK **lock; + CRYPTO_REF_COUNT *refcnt; int ret = -1; if ((it->itype != ASN1_ITYPE_SEQUENCE) @@ -78,30 +78,34 @@ int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) aux = it->funcs; if (aux == NULL || (aux->flags & ASN1_AFLG_REFCOUNT) == 0) return 0; - lck = offset2ptr(*pval, aux->ref_offset); lock = offset2ptr(*pval, aux->ref_lock); + refcnt = offset2ptr(*pval, aux->ref_offset); switch (op) { case 0: - *lck = ret = 1; + if (!CRYPTO_NEW_REF(refcnt, 1)) + return -1; *lock = CRYPTO_THREAD_lock_new(); if (*lock == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + CRYPTO_FREE_REF(refcnt); + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); return -1; } + ret = 1; break; case 1: - if (!CRYPTO_UP_REF(lck, &ret, *lock)) + if (!CRYPTO_UP_REF(refcnt, &ret)) return -1; break; case -1: - if (!CRYPTO_DOWN_REF(lck, &ret, *lock)) + if (!CRYPTO_DOWN_REF(refcnt, &ret)) return -1; /* failed */ REF_PRINT_EX(it->sname, ret, (void *)it); REF_ASSERT_ISNT(ret < 0); if (ret == 0) { CRYPTO_THREAD_lock_free(*lock); *lock = NULL; + CRYPTO_FREE_REF(refcnt); } break; } @@ -168,10 +172,8 @@ int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, OPENSSL_free(enc->enc); if (inlen <= 0) return 0; - if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) return 0; - } memcpy(enc->enc, in, inlen); enc->len = inlen; enc->modified = 0; diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c index 2c4a8d4b4ee8..db9dd06e4940 100644 --- a/crypto/asn1/x_algor.c +++ b/crypto/asn1/x_algor.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -33,17 +33,14 @@ int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) if (alg == NULL) return 0; - if (ptype != V_ASN1_UNDEF) { - if (alg->parameter == NULL) - alg->parameter = ASN1_TYPE_new(); - if (alg->parameter == NULL) - return 0; - } + if (ptype != V_ASN1_UNDEF && alg->parameter == NULL + && (alg->parameter = ASN1_TYPE_new()) == NULL) + return 0; ASN1_OBJECT_free(alg->algorithm); alg->algorithm = aobj; - if (ptype == 0) + if (ptype == V_ASN1_EOC) return 1; if (ptype == V_ASN1_UNDEF) { ASN1_TYPE_free(alg->parameter); @@ -53,6 +50,25 @@ int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) return 1; } +X509_ALGOR *ossl_X509_ALGOR_from_nid(int nid, int ptype, void *pval) +{ + ASN1_OBJECT *algo = OBJ_nid2obj(nid); + X509_ALGOR *alg = NULL; + + if (algo == NULL) + return NULL; + if ((alg = X509_ALGOR_new()) == NULL) + goto err; + if (X509_ALGOR_set0(alg, algo, ptype, pval)) + return alg; + alg->algorithm = NULL; /* precaution to prevent double free */ + + err: + X509_ALGOR_free(alg); + /* ASN1_OBJECT_free(algo) is not needed due to OBJ_nid2obj() */ + return NULL; +} + void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval, const X509_ALGOR *algor) { @@ -70,18 +86,12 @@ void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, } /* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */ - void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md) { - int param_type; - - if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT) - param_type = V_ASN1_UNDEF; - else - param_type = V_ASN1_NULL; - - X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), param_type, NULL); + int type = md->flags & EVP_MD_FLAG_DIGALGID_ABSENT ? V_ASN1_UNDEF + : V_ASN1_NULL; + (void)X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), type, NULL); } int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b) @@ -131,13 +141,15 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src) /* allocate and set algorithm ID from EVP_MD, default SHA1 */ int ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md) { + X509_ALGOR *alg; + /* Default is SHA1 so no need to create it - still success */ if (md == NULL || EVP_MD_is_a(md, "SHA1")) return 1; - *palg = X509_ALGOR_new(); - if (*palg == NULL) + if ((alg = X509_ALGOR_new()) == NULL) return 0; - X509_ALGOR_set_md(*palg, md); + X509_ALGOR_set_md(alg, md); + *palg = alg; return 1; } @@ -176,19 +188,12 @@ int ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) goto err; if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL) goto err; - *palg = X509_ALGOR_new(); + *palg = ossl_X509_ALGOR_from_nid(NID_mgf1, V_ASN1_SEQUENCE, stmp); if (*palg == NULL) goto err; - if (!X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp)) { - X509_ALGOR_free(*palg); - *palg = NULL; - goto err; - } stmp = NULL; err: ASN1_STRING_free(stmp); X509_ALGOR_free(algtmp); - if (*palg != NULL) - return 1; - return 0; + return *palg != NULL; } diff --git a/crypto/asn1/x_info.c b/crypto/asn1/x_info.c index f8bc4789884e..8a4d2dba0a7b 100644 --- a/crypto/asn1/x_info.c +++ b/crypto/asn1/x_info.c @@ -18,10 +18,8 @@ X509_INFO *X509_INFO_new(void) X509_INFO *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } return ret; } diff --git a/crypto/asn1/x_int64.c b/crypto/asn1/x_int64.c index eb78c7e36723..b7251b8ad8b6 100644 --- a/crypto/asn1/x_int64.c +++ b/crypto/asn1/x_int64.c @@ -28,10 +28,8 @@ static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) return 0; - } return 1; } @@ -123,10 +121,8 @@ static int uint64_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it) { - if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) return 0; - } return 1; } @@ -224,8 +220,8 @@ static int uint32_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx) { if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) - return BIO_printf(out, "%d\n", **(int32_t **)pval); - return BIO_printf(out, "%u\n", **(uint32_t **)pval); + return BIO_printf(out, "%d\n", (int)**(int32_t **)pval); + return BIO_printf(out, "%u\n", (unsigned int)**(uint32_t **)pval); } diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c index b63c7c6489f4..34b7286d7e32 100644 --- a/crypto/asn1/x_pkey.c +++ b/crypto/asn1/x_pkey.c @@ -19,18 +19,17 @@ X509_PKEY *X509_PKEY_new(void) ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) - goto err; + return NULL; ret->enc_algor = X509_ALGOR_new(); ret->enc_pkey = ASN1_OCTET_STRING_new(); - if (ret->enc_algor == NULL || ret->enc_pkey == NULL) - goto err; + if (ret->enc_algor == NULL || ret->enc_pkey == NULL) { + X509_PKEY_free(ret); + ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); + return NULL; + } return ret; -err: - X509_PKEY_free(ret); - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); - return NULL; } void X509_PKEY_free(X509_PKEY *x) diff --git a/crypto/async/arch/async_null.c b/crypto/async/arch/async_null.c index 675c1d35bf0c..306c43df41f4 100644 --- a/crypto/async/arch/async_null.c +++ b/crypto/async/arch/async_null.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,6 +16,21 @@ int ASYNC_is_capable(void) return 0; } +int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn, + ASYNC_stack_free_fn free_fn) +{ + return 0; +} + +void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn, + ASYNC_stack_free_fn *free_fn) +{ + if (alloc_fn != NULL) + *alloc_fn = NULL; + if (free_fn != NULL) + *free_fn = NULL; +} + void async_local_cleanup(void) { } diff --git a/crypto/async/arch/async_null.h b/crypto/async/arch/async_null.h index c62aba69a874..536c9829cd2e 100644 --- a/crypto/async/arch/async_null.h +++ b/crypto/async/arch/async_null.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -26,5 +26,7 @@ typedef struct async_fibre_st { # define async_fibre_makecontext(c) 0 # define async_fibre_free(f) # define async_fibre_init_dispatcher(f) +# define async_local_init() 1 +# define async_local_deinit() #endif diff --git a/crypto/async/arch/async_posix.c b/crypto/async/arch/async_posix.c index e107e09a352f..f2b507c7d0a6 100644 --- a/crypto/async/arch/async_posix.c +++ b/crypto/async/arch/async_posix.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,9 +14,31 @@ # include # include +# include +# include #define STACKSIZE 32768 +static CRYPTO_RWLOCK *async_mem_lock; + +static void *async_stack_alloc(size_t *num); +static void async_stack_free(void *addr); + +int async_local_init(void) +{ + async_mem_lock = CRYPTO_THREAD_lock_new(); + return async_mem_lock != NULL; +} + +void async_local_deinit(void) +{ + CRYPTO_THREAD_lock_free(async_mem_lock); +} + +static int allow_customize = 1; +static ASYNC_stack_alloc_fn stack_alloc_impl = async_stack_alloc; +static ASYNC_stack_free_fn stack_free_impl = async_stack_free; + int ASYNC_is_capable(void) { ucontext_t ctx; @@ -28,6 +50,45 @@ int ASYNC_is_capable(void) return getcontext(&ctx) == 0; } +int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn, + ASYNC_stack_free_fn free_fn) +{ + OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL); + + if (!CRYPTO_THREAD_write_lock(async_mem_lock)) + return 0; + if (!allow_customize) { + CRYPTO_THREAD_unlock(async_mem_lock); + return 0; + } + CRYPTO_THREAD_unlock(async_mem_lock); + + if (alloc_fn != NULL) + stack_alloc_impl = alloc_fn; + if (free_fn != NULL) + stack_free_impl = free_fn; + return 1; +} + +void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn, + ASYNC_stack_free_fn *free_fn) +{ + if (alloc_fn != NULL) + *alloc_fn = stack_alloc_impl; + if (free_fn != NULL) + *free_fn = stack_free_impl; +} + +static void *async_stack_alloc(size_t *num) +{ + return OPENSSL_malloc(*num); +} + +static void async_stack_free(void *addr) +{ + OPENSSL_free(addr); +} + void async_local_cleanup(void) { } @@ -38,9 +99,22 @@ int async_fibre_makecontext(async_fibre *fibre) fibre->env_init = 0; #endif if (getcontext(&fibre->fibre) == 0) { - fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE); + size_t num = STACKSIZE; + + /* + * Disallow customisation after the first + * stack is allocated. + */ + if (allow_customize) { + if (!CRYPTO_THREAD_write_lock(async_mem_lock)) + return 0; + allow_customize = 0; + CRYPTO_THREAD_unlock(async_mem_lock); + } + + fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num); if (fibre->fibre.uc_stack.ss_sp != NULL) { - fibre->fibre.uc_stack.ss_size = STACKSIZE; + fibre->fibre.uc_stack.ss_size = num; fibre->fibre.uc_link = NULL; makecontext(&fibre->fibre, async_start_func, 0); return 1; @@ -53,7 +127,7 @@ int async_fibre_makecontext(async_fibre *fibre) void async_fibre_free(async_fibre *fibre) { - OPENSSL_free(fibre->fibre.uc_stack.ss_sp); + stack_free_impl(fibre->fibre.uc_stack.ss_sp); fibre->fibre.uc_stack.ss_sp = NULL; } diff --git a/crypto/async/arch/async_posix.h b/crypto/async/arch/async_posix.h index a17c6b8e68af..ceb86e24bf35 100644 --- a/crypto/async/arch/async_posix.h +++ b/crypto/async/arch/async_posix.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,7 +18,7 @@ # include # if _POSIX_VERSION >= 200112L \ - && (_POSIX_VERSION < 200809L || defined(__GLIBC__)) + && (_POSIX_VERSION < 200809L || defined(__GLIBC__) || defined(__FreeBSD__)) # include @@ -61,6 +61,9 @@ typedef struct async_fibre_st { # endif } async_fibre; +int async_local_init(void); +void async_local_deinit(void); + static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r) { # ifdef USE_SWAPCONTEXT diff --git a/crypto/async/arch/async_win.c b/crypto/async/arch/async_win.c index 0b276fd504d8..cbb8ef24ed78 100644 --- a/crypto/async/arch/async_win.c +++ b/crypto/async/arch/async_win.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,6 +20,21 @@ int ASYNC_is_capable(void) return 1; } +int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn, + ASYNC_stack_free_fn free_fn) +{ + return 0; +} + +void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn, + ASYNC_stack_free_fn *free_fn) +{ + if (alloc_fn != NULL) + *alloc_fn = NULL; + if (free_fn != NULL) + *free_fn = NULL; +} + void async_local_cleanup(void) { async_ctx *ctx = async_get_ctx(); diff --git a/crypto/async/arch/async_win.h b/crypto/async/arch/async_win.h index 0fab95996e27..6a61a9a380d1 100644 --- a/crypto/async/arch/async_win.h +++ b/crypto/async/arch/async_win.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -37,6 +37,8 @@ typedef struct async_fibre_st { # endif # define async_fibre_free(f) (DeleteFiber((f)->fibre)) +# define async_local_init() 1 +# define async_local_deinit() int async_fibre_init_dispatcher(async_fibre *fibre); VOID CALLBACK async_start_func_win(PVOID unused); diff --git a/crypto/async/async.c b/crypto/async/async.c index a320d455b7bb..46c87d6a5af2 100644 --- a/crypto/async/async.c +++ b/crypto/async/async.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -40,10 +40,8 @@ static async_ctx *async_ctx_new(void) return NULL; nctx = OPENSSL_malloc(sizeof(*nctx)); - if (nctx == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); + if (nctx == NULL) goto err; - } async_fibre_init_dispatcher(&nctx->dispatcher); nctx->currjob = NULL; @@ -82,10 +80,8 @@ static ASYNC_JOB *async_job_new(void) ASYNC_JOB *job = NULL; job = OPENSSL_zalloc(sizeof(*job)); - if (job == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); + if (job == NULL) return NULL; - } job->status = ASYNC_JOB_RUNNING; @@ -256,7 +252,6 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, if (args != NULL) { ctx->currjob->funcargs = OPENSSL_malloc(size); if (ctx->currjob->funcargs == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); async_release_job(ctx->currjob); ctx->currjob = NULL; return ASYNC_ERR; @@ -340,13 +335,14 @@ int async_init(void) return 0; } - return 1; + return async_local_init(); } void async_deinit(void) { CRYPTO_THREAD_cleanup_local(&ctxkey); CRYPTO_THREAD_cleanup_local(&poolkey); + async_local_deinit(); } int ASYNC_init_thread(size_t max_size, size_t init_size) @@ -366,14 +362,12 @@ int ASYNC_init_thread(size_t max_size, size_t init_size) return 0; pool = OPENSSL_zalloc(sizeof(*pool)); - if (pool == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); + if (pool == NULL) return 0; - } pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size); if (pool->jobs == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASYNC, ERR_R_CRYPTO_LIB); OPENSSL_free(pool); return 0; } diff --git a/crypto/async/async_wait.c b/crypto/async/async_wait.c index df7d29302182..cf4db49dae39 100644 --- a/crypto/async/async_wait.c +++ b/crypto/async/async_wait.c @@ -40,6 +40,7 @@ void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx) OPENSSL_free(ctx); } + int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, OSSL_ASYNC_FD fd, void *custom_data, void (*cleanup)(ASYNC_WAIT_CTX *, const void *, @@ -47,10 +48,8 @@ int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key, { struct fd_lookup_st *fdlookup; - if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) { - ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); + if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) return 0; - } fdlookup->key = key; fdlookup->fd = fd; diff --git a/crypto/bf/bf_local.h b/crypto/bf/bf_local.h index 080f37a5f94c..53c6963e6b08 100644 --- a/crypto/bf/bf_local.h +++ b/crypto/bf/bf_local.h @@ -17,19 +17,19 @@ l1=l2=0; \ switch (n) { \ case 8: l2 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((unsigned long)(*(--(c))))<<24; \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((unsigned long)(*(--(c))))<<24; \ } \ } @@ -39,19 +39,19 @@ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ } \ } diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c index 53bd02fe1416..737910cc7514 100644 --- a/crypto/bio/bf_buff.c +++ b/crypto/bio/bf_buff.c @@ -1,5 +1,5 @@ /* - * 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 @@ -291,7 +291,7 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) return 0; p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) - goto malloc_error; + return 0; OPENSSL_free(ctx->ibuf); ctx->ibuf = p1; } @@ -322,14 +322,14 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) return 0; p1 = OPENSSL_malloc((size_t)num); if (p1 == NULL) - goto malloc_error; + return 0; } if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) { p2 = OPENSSL_malloc((size_t)num); if (p2 == NULL) { if (p1 != ctx->ibuf) OPENSSL_free(p1); - goto malloc_error; + return 0; } } if (ctx->ibuf != p1) { @@ -360,6 +360,7 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) return 0; if (ctx->obuf_len <= 0) { ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); break; } @@ -380,6 +381,7 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) } } ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; @@ -405,9 +407,6 @@ static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) break; } return ret; - malloc_error: - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); - return 0; } static long buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) diff --git a/crypto/bio/bf_lbuf.c b/crypto/bio/bf_lbuf.c index 6908e64d3652..eed3dc4633e0 100644 --- a/crypto/bio/bf_lbuf.c +++ b/crypto/bio/bf_lbuf.c @@ -1,5 +1,5 @@ /* - * 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 @@ -57,13 +57,10 @@ static int linebuffer_new(BIO *bi) { BIO_LINEBUFFER_CTX *ctx; - if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) return 0; - } ctx->obuf = OPENSSL_malloc(DEFAULT_LINEBUFFER_SIZE); if (ctx->obuf == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); OPENSSL_free(ctx); return 0; } @@ -237,7 +234,7 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) if ((obs > DEFAULT_LINEBUFFER_SIZE) && (obs != ctx->obuf_size)) { p = OPENSSL_malloc((size_t)obs); if (p == NULL) - goto malloc_error; + return 0; } if (ctx->obuf != p) { if (ctx->obuf_len > obs) { @@ -262,6 +259,7 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) return 0; if (ctx->obuf_len <= 0) { ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); break; } @@ -281,6 +279,7 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) } } ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + BIO_copy_next_retry(b); break; case BIO_CTRL_DUP: dbio = (BIO *)ptr; @@ -294,9 +293,6 @@ static long linebuffer_ctrl(BIO *b, int cmd, long num, void *ptr) break; } return ret; - malloc_error: - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); - return 0; } static long linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c index f9ea1730ba31..01138729b002 100644 --- a/crypto/bio/bf_nbio.c +++ b/crypto/bio/bf_nbio.c @@ -55,10 +55,8 @@ static int nbiof_new(BIO *bi) { NBIO_TEST *nt; - if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((nt = OPENSSL_zalloc(sizeof(*nt))) == NULL) return 0; - } nt->lrn = -1; nt->lwn = -1; bi->ptr = (char *)nt; diff --git a/crypto/bio/bio_addr.c b/crypto/bio/bio_addr.c index d462f424d3a4..4bdce0bbe84f 100644 --- a/crypto/bio/bio_addr.c +++ b/crypto/bio/bio_addr.c @@ -53,10 +53,8 @@ BIO_ADDR *BIO_ADDR_new(void) { BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->sa.sa_family = AF_UNSPEC; return ret; @@ -67,6 +65,33 @@ void BIO_ADDR_free(BIO_ADDR *ap) OPENSSL_free(ap); } +int BIO_ADDR_copy(BIO_ADDR *dst, const BIO_ADDR *src) +{ + if (dst == NULL || src == NULL) + return 0; + + if (src->sa.sa_family == AF_UNSPEC) { + BIO_ADDR_clear(dst); + return 1; + } + + return BIO_ADDR_make(dst, &src->sa); +} + +BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap) +{ + BIO_ADDR *ret = NULL; + + if (ap != NULL) { + ret = BIO_ADDR_new(); + if (ret != NULL && !BIO_ADDR_copy(ret, ap)) { + BIO_ADDR_free(ret); + ret = NULL; + } + } + return ret; +} + void BIO_ADDR_clear(BIO_ADDR *ap) { memset(ap, 0, sizeof(*ap)); @@ -79,17 +104,18 @@ void BIO_ADDR_clear(BIO_ADDR *ap) */ int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa) { + memset(ap, 0, sizeof(BIO_ADDR)); if (sa->sa_family == AF_INET) { memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in)); return 1; } -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 if (sa->sa_family == AF_INET6) { memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6)); return 1; } #endif -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (sa->sa_family == AF_UNIX) { memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un)); return 1; @@ -103,7 +129,7 @@ int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, const void *where, size_t wherelen, unsigned short port) { -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (family == AF_UNIX) { if (wherelen + 1 > sizeof(ap->s_un.sun_path)) return 0; @@ -122,7 +148,7 @@ int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, ap->s_in.sin_addr = *(struct in_addr *)where; return 1; } -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 if (family == AF_INET6) { if (wherelen != sizeof(struct in6_addr)) return 0; @@ -151,13 +177,13 @@ int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l) len = sizeof(ap->s_in.sin_addr); addrptr = &ap->s_in.sin_addr; } -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 else if (ap->sa.sa_family == AF_INET6) { len = sizeof(ap->s_in6.sin6_addr); addrptr = &ap->s_in6.sin6_addr; } #endif -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK else if (ap->sa.sa_family == AF_UNIX) { len = strlen(ap->s_un.sun_path); addrptr = &ap->s_un.sun_path; @@ -180,7 +206,7 @@ unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) { if (ap->sa.sa_family == AF_INET) return ap->s_in.sin_port; -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 if (ap->sa.sa_family == AF_INET6) return ap->s_in6.sin6_port; #endif @@ -193,7 +219,7 @@ unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap) * @numeric: 0 if actual names should be returned, 1 if the numeric * representation should be returned. * @hostname: a pointer to a pointer to a memory area to store the - * host name or numeric representation. Unused if NULL. + * hostname or numeric representation. Unused if NULL. * @service: a pointer to a pointer to a memory area to store the * service name or numeric representation. Unused if NULL. * @@ -267,7 +293,6 @@ static int addr_strings(const BIO_ADDR *ap, int numeric, OPENSSL_free(*service); *service = NULL; } - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return 0; } @@ -296,7 +321,7 @@ char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric) char *BIO_ADDR_path_string(const BIO_ADDR *ap) { -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (ap->sa.sa_family == AF_UNIX) return OPENSSL_strdup(ap->s_un.sun_path); #endif @@ -334,11 +359,11 @@ socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap) { if (ap->sa.sa_family == AF_INET) return sizeof(ap->s_in); -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 if (ap->sa.sa_family == AF_INET6) return sizeof(ap->s_in6); #endif -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (ap->sa.sa_family == AF_UNIX) return sizeof(ap->s_un); #endif @@ -378,7 +403,7 @@ int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai) if (bai->bai_protocol != 0) return bai->bai_protocol; -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (bai->bai_family == AF_UNIX) return 0; #endif @@ -430,7 +455,7 @@ void BIO_ADDRINFO_free(BIO_ADDRINFO *bai) return; #ifdef AI_PASSIVE -# ifdef AF_UNIX +# ifndef OPENSSL_NO_UNIX_SOCK # define _cond bai->bai_family != AF_UNIX # else # define _cond 1 @@ -538,7 +563,7 @@ int BIO_parse_hostserv(const char *hostserv, char **host, char **service, } else { *host = OPENSSL_strndup(h, hl); if (*host == NULL) - goto memerr; + return 0; } } if (p != NULL && service != NULL) { @@ -552,7 +577,7 @@ int BIO_parse_hostserv(const char *hostserv, char **host, char **service, OPENSSL_free(*host); *host = NULL; } - goto memerr; + return 0; } } } @@ -564,9 +589,6 @@ int BIO_parse_hostserv(const char *hostserv, char **host, char **service, spec_err: ERR_raise(ERR_LIB_BIO, BIO_R_MALFORMED_HOST_OR_SERVICE); return 0; - memerr: - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); - return 0; } /* addrinfo_wrap is used to build our own addrinfo "chain". @@ -583,10 +605,8 @@ static int addrinfo_wrap(int family, int socktype, unsigned short port, BIO_ADDRINFO **bai) { - if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) return 0; - } (*bai)->bai_family = family; (*bai)->bai_socktype = socktype; @@ -594,7 +614,7 @@ static int addrinfo_wrap(int family, int socktype, (*bai)->bai_protocol = IPPROTO_TCP; if (socktype == SOCK_DGRAM) (*bai)->bai_protocol = IPPROTO_UDP; -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (family == AF_UNIX) (*bai)->bai_protocol = 0; #endif @@ -659,12 +679,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, { int ret = 0; /* Assume failure */ - switch(family) { + switch (family) { case AF_INET: -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 case AF_INET6: #endif -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK case AF_UNIX: #endif #ifdef AF_UNSPEC @@ -676,12 +696,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, return 0; } -#ifdef AF_UNIX +#ifndef OPENSSL_NO_UNIX_SOCK if (family == AF_UNIX) { if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res)) return 1; else - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB); return 0; } #endif @@ -725,7 +745,8 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, # endif # ifdef EAI_MEMORY case EAI_MEMORY: - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise_data(ERR_LIB_BIO, ERR_R_SYS_LIB, + gai_strerror(old_ret ? old_ret : gai_ret)); break; # endif case 0: @@ -759,16 +780,19 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, /* Windows doesn't seem to have in_addr_t */ #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) static uint32_t he_fallback_address; - static const char *he_fallback_addresses[] = - { (char *)&he_fallback_address, NULL }; + static const char *he_fallback_addresses[] = { + (char *)&he_fallback_address, NULL + }; #else static in_addr_t he_fallback_address; - static const char *he_fallback_addresses[] = - { (char *)&he_fallback_address, NULL }; + static const char *he_fallback_addresses[] = { + (char *)&he_fallback_address, NULL + }; #endif - static const struct hostent he_fallback = - { NULL, NULL, AF_INET, sizeof(he_fallback_address), - (char **)&he_fallback_addresses }; + static const struct hostent he_fallback = { + NULL, NULL, AF_INET, sizeof(he_fallback_address), + (char **)&he_fallback_addresses + }; #if defined(OPENSSL_SYS_VMS) && defined(__DECC) # pragma pointer_size restore #endif @@ -782,7 +806,8 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, #endif if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + /* Should this be raised inside do_bio_lookup_init()? */ + ERR_raise(ERR_LIB_BIO, ERR_R_CRYPTO_LIB); return 0; } @@ -792,7 +817,7 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, he_fallback_address = INADDR_ANY; if (host == NULL) { he = &he_fallback; - switch(lookup_type) { + switch (lookup_type) { case BIO_LOOKUP_CLIENT: he_fallback_address = INADDR_LOOPBACK; break; @@ -909,23 +934,23 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, /* The easiest way to create a linked list from an array is to start from the back */ - for(addrlistp = he->h_addr_list; *addrlistp != NULL; - addrlistp++) + for (addrlistp = he->h_addr_list; *addrlistp != NULL; + addrlistp++) ; - for(addresses = addrlistp - he->h_addr_list; - addrlistp--, addresses-- > 0; ) { + for (addresses = addrlistp - he->h_addr_list; + addrlistp--, addresses-- > 0; ) { if (!addrinfo_wrap(he->h_addrtype, socktype, *addrlistp, he->h_length, se->s_port, &tmp_bai)) - goto addrinfo_malloc_err; + goto addrinfo_wrap_err; tmp_bai->bai_next = *res; *res = tmp_bai; continue; - addrinfo_malloc_err: + addrinfo_wrap_err: BIO_ADDRINFO_free(*res); *res = NULL; - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB); ret = 0; goto err; } diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c index 522a05369dc7..8e4f79ea3cd7 100644 --- a/crypto/bio/bio_cb.c +++ b/crypto/bio/bio_cb.c @@ -24,6 +24,8 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, char *p; int left; size_t l = 0; + BIO_MMSG_CB_ARGS *args; + long ret_ = ret; if (processed != NULL) l = *processed; @@ -69,6 +71,16 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi, bio->method->name); break; + case BIO_CB_RECVMMSG: + args = (BIO_MMSG_CB_ARGS *)argp; + BIO_snprintf(p, left, "recvmmsg(%zu) - %s", + args->num_msg, bio->method->name); + break; + case BIO_CB_SENDMMSG: + args = (BIO_MMSG_CB_ARGS *)argp; + BIO_snprintf(p, left, "sendmmsg(%zu) - %s", + args->num_msg, bio->method->name); + break; case BIO_CB_RETURN | BIO_CB_READ: BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l); break; @@ -84,6 +96,14 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, case BIO_CB_RETURN | BIO_CB_CTRL: BIO_snprintf(p, left, "ctrl return %d\n", ret); break; + case BIO_CB_RETURN | BIO_CB_RECVMMSG: + BIO_snprintf(p, left, "recvmmsg processed: %zu\n", len); + ret_ = (long)len; + break; + case BIO_CB_RETURN | BIO_CB_SENDMMSG: + BIO_snprintf(p, left, "sendmmsg processed: %zu\n", len); + ret_ = (long)len; + break; default: BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd); break; @@ -96,7 +116,7 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, else fputs(buf, stderr); #endif - return ret; + return ret_; } #ifndef OPENSSL_NO_DEPRECATED_3_0 diff --git a/crypto/bio/bio_dump.c b/crypto/bio/bio_dump.c index c453da62688c..40c18410e4cf 100644 --- a/crypto/bio/bio_dump.c +++ b/crypto/bio/bio_dump.c @@ -141,9 +141,10 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data, BIO_printf(out, "%02X:", d[i]); - j = (j + 1) % width; - if (!j) + if (++j >= width) { + j = 0; BIO_printf(out, "\n"); + } } if (i && !j) diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c index 7a36c61148a7..6fe295ee52f2 100644 --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -46,6 +46,10 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { "no hostname or service specified"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_PORT_DEFINED), "no port defined"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NO_SUCH_FILE), "no such file"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PORT_MISMATCH), "port mismatch"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TFO_DISABLED), "tfo disabled"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TFO_NO_KERNEL_SUPPORT), + "tfo no kernel support"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_ERROR), "transfer error"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_TRANSFER_TIMEOUT), "transfer timeout"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_BIND_SOCKET), @@ -59,6 +63,7 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_NODELAY), "unable to nodelay"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_REUSEADDR), "unable to reuseaddr"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNABLE_TO_TFO), "unable to tfo"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNAVAILABLE_IP_FAMILY), "unavailable ip family"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_UNINITIALIZED), "uninitialized"}, @@ -71,6 +76,14 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOCAL_ADDR_NOT_AVAILABLE), + "local address not available"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PEER_ADDR_NOT_AVAILABLE), + "peer address not available"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NON_FATAL), + "non-fatal or transient error"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PORT_MISMATCH), + "port mismatch"}, {0, NULL} }; @@ -84,3 +97,18 @@ int ossl_err_load_BIO_strings(void) #endif return 1; } + +#ifndef OPENSSL_NO_SOCK + +int BIO_err_is_non_fatal(unsigned int errcode) +{ + if (ERR_SYSTEM_ERROR(errcode)) + return BIO_sock_non_fatal_error(ERR_GET_REASON(errcode)); + else if (ERR_GET_LIB(errcode) == ERR_LIB_BIO + && ERR_GET_REASON(errcode) == BIO_R_NON_FATAL) + return 1; + else + return 0; +} + +#endif diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index 245a75afa1b8..85ab4afe182a 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -82,30 +82,22 @@ 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); + if (bio == NULL) return NULL; - } bio->libctx = libctx; bio->method = method; bio->shutdown = 1; - bio->references = 1; + + if (!CRYPTO_NEW_REF(&bio->references, 1)) + goto err; 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) @@ -114,6 +106,7 @@ BIO *BIO_new_ex(OSSL_LIB_CTX *libctx, const BIO_METHOD *method) return bio; err: + CRYPTO_FREE_REF(&bio->references); OPENSSL_free(bio); return NULL; } @@ -130,10 +123,10 @@ int BIO_free(BIO *a) if (a == NULL) return 0; - if (CRYPTO_DOWN_REF(&a->references, &ret, a->lock) <= 0) + if (CRYPTO_DOWN_REF(&a->references, &ret) <= 0) return 0; - REF_PRINT_COUNT("BIO", a); + REF_PRINT_COUNT("BIO", ret, a); if (ret > 0) return 1; REF_ASSERT_ISNT(ret < 0); @@ -149,7 +142,7 @@ int BIO_free(BIO *a) CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); - CRYPTO_THREAD_lock_free(a->lock); + CRYPTO_FREE_REF(&a->references); OPENSSL_free(a); @@ -195,10 +188,10 @@ int BIO_up_ref(BIO *a) { int i; - if (CRYPTO_UP_REF(&a->references, &i, a->lock) <= 0) + if (CRYPTO_UP_REF(&a->references, &i) <= 0) return 0; - REF_PRINT_COUNT("BIO", a); + REF_PRINT_COUNT("BIO", i, a); REF_ASSERT_ISNT(i < 2); return i > 1; } @@ -398,6 +391,110 @@ int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) || (b != NULL && dlen == 0); /* order is important for *written */ } +int BIO_sendmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + size_t ret; + BIO_MMSG_CB_ARGS args; + + if (b == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (b->method == NULL || b->method->bsendmmsg == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (HAS_CALLBACK(b)) { + args.msg = msg; + args.stride = stride; + args.num_msg = num_msg; + args.flags = flags; + args.msgs_processed = msgs_processed; + + ret = (size_t)bio_call_callback(b, BIO_CB_SENDMMSG, (void *)&args, + 0, 0, 0, 1, NULL); + if (ret <= 0) + return 0; + } + + if (!b->init) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return 0; + } + + ret = b->method->bsendmmsg(b, msg, stride, num_msg, flags, msgs_processed); + + if (HAS_CALLBACK(b)) + ret = (size_t)bio_call_callback(b, BIO_CB_SENDMMSG | BIO_CB_RETURN, + (void *)&args, ret, 0, 0, ret, NULL); + + return ret; +} + +int BIO_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + size_t ret; + BIO_MMSG_CB_ARGS args; + + if (b == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (b->method == NULL || b->method->brecvmmsg == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (HAS_CALLBACK(b)) { + args.msg = msg; + args.stride = stride; + args.num_msg = num_msg; + args.flags = flags; + args.msgs_processed = msgs_processed; + + ret = bio_call_callback(b, BIO_CB_RECVMMSG, (void *)&args, + 0, 0, 0, 1, NULL); + if (ret <= 0) + return 0; + } + + if (!b->init) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return 0; + } + + ret = b->method->brecvmmsg(b, msg, stride, num_msg, flags, msgs_processed); + + if (HAS_CALLBACK(b)) + ret = (size_t)bio_call_callback(b, BIO_CB_RECVMMSG | BIO_CB_RETURN, + (void *)&args, ret, 0, 0, ret, NULL); + + return ret; +} + +int BIO_get_rpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc) +{ + return BIO_ctrl(b, BIO_CTRL_GET_RPOLL_DESCRIPTOR, 0, desc); +} + +int BIO_get_wpoll_descriptor(BIO *b, BIO_POLL_DESCRIPTOR *desc) +{ + return BIO_ctrl(b, BIO_CTRL_GET_WPOLL_DESCRIPTOR, 0, desc); +} + int BIO_puts(BIO *b, const char *buf) { int ret; @@ -720,7 +817,7 @@ BIO *BIO_find_type(BIO *bio, int type) ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); return NULL; } - mask = type & 0xff; + mask = type & BIO_TYPE_MASK; do { if (bio->method != NULL) { mt = bio->method->type; @@ -756,7 +853,7 @@ void BIO_free_all(BIO *bio) while (bio != NULL) { b = bio; - ref = b->references; + CRYPTO_GET_REF(&b->references, &ref); bio = bio->next_bio; BIO_free(b); /* Since ref count > 1, don't free anyone else. */ @@ -853,11 +950,10 @@ void bio_cleanup(void) CRYPTO_THREAD_lock_free(bio_lookup_lock); bio_lookup_lock = NULL; #endif - CRYPTO_THREAD_lock_free(bio_type_lock); - bio_type_lock = NULL; + CRYPTO_FREE_REF(&bio_type_count); } -/* Internal variant of the below BIO_wait() not calling BIOerr() */ +/* Internal variant of the below BIO_wait() not calling ERR_raise(...) */ static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) { #ifndef OPENSSL_NO_SOCK @@ -890,7 +986,7 @@ static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) if ((unsigned long)sec_diff * 1000 < nap_milliseconds) nap_milliseconds = (unsigned int)sec_diff * 1000; } - ossl_sleep(nap_milliseconds); + OSSL_sleep(nap_milliseconds); return 1; } @@ -899,7 +995,7 @@ static int bio_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds) * 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. + * Call ERR_raise(ERR_LIB_BIO, ...) 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) diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h index 749e8f810c30..05954f85bb2f 100644 --- a/crypto/bio/bio_local.h +++ b/crypto/bio/bio_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2021 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 @@ -7,8 +7,9 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "internal/sockets.h" +#include "internal/bio_addr.h" /* BEGIN BIO_ADDRINFO/BIO_ADDR stuff. */ @@ -33,13 +34,6 @@ # error openssl/bio.h included before bio_local.h # endif -/* - * Undefine AF_UNIX on systems that define it but don't support it. - */ -# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VMS) -# undef AF_UNIX -# endif - # ifdef AI_PASSIVE /* @@ -70,17 +64,6 @@ struct bio_addrinfo_st { struct bio_addrinfo_st *bai_next; }; # endif - -union bio_addr_st { - struct sockaddr sa; -# ifdef AF_INET6 - struct sockaddr_in6 s_in6; -# endif - struct sockaddr_in s_in; -# ifdef AF_UNIX - struct sockaddr_un s_un; -# endif -}; #endif /* END BIO_ADDRINFO/BIO_ADDR stuff. */ @@ -133,7 +116,6 @@ struct bio_st { uint64_t num_read; uint64_t num_write; CRYPTO_EX_DATA ex_data; - CRYPTO_RWLOCK *lock; }; #ifndef OPENSSL_NO_SOCK @@ -149,9 +131,15 @@ struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap); socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap); socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai); const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai); + +# if defined(OPENSSL_SYS_WINDOWS) && defined(WSAID_WSARECVMSG) +# define BIO_HAVE_WSAMSG +extern LPFN_WSARECVMSG bio_WSARecvMsg; +extern LPFN_WSASENDMSG bio_WSASendMsg; +# endif #endif -extern CRYPTO_RWLOCK *bio_type_lock; +extern CRYPTO_REF_COUNT bio_type_count; void bio_sock_cleanup_int(void); diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c index 469715ba09eb..b665929b5fef 100644 --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,25 +10,26 @@ #include "bio_local.h" #include "internal/thread_once.h" -CRYPTO_RWLOCK *bio_type_lock = NULL; +CRYPTO_REF_COUNT bio_type_count; static CRYPTO_ONCE bio_type_init = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(do_bio_type_init) { - bio_type_lock = CRYPTO_THREAD_lock_new(); - return bio_type_lock != NULL; + return CRYPTO_NEW_REF(&bio_type_count, BIO_TYPE_START); } int BIO_get_new_index(void) { - static CRYPTO_REF_COUNT bio_count = BIO_TYPE_START; int newval; if (!RUN_ONCE(&bio_type_init, do_bio_type_init)) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + /* Perhaps the error should be raised in do_bio_type_init()? */ + ERR_raise(ERR_LIB_BIO, ERR_R_CRYPTO_LIB); return -1; } - if (!CRYPTO_UP_REF(&bio_count, &newval, bio_type_lock)) + if (!CRYPTO_UP_REF(&bio_type_count, &newval)) + return -1; + if (newval > BIO_TYPE_MASK) return -1; return newval; } @@ -40,7 +41,6 @@ BIO_METHOD *BIO_meth_new(int type, const char *name) if (biom == NULL || (biom->name = OPENSSL_strdup(name)) == NULL) { OPENSSL_free(biom); - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); return NULL; } biom->type = type; @@ -55,6 +55,7 @@ void BIO_meth_free(BIO_METHOD *biom) } } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_write(const BIO_METHOD *biom)) (BIO *, const char *, int) { return biom->bwrite_old; @@ -65,6 +66,7 @@ int (*BIO_meth_get_write_ex(const BIO_METHOD *biom)) (BIO *, const char *, size_ { return biom->bwrite; } +#endif /* Conversion for old style bwrite to new style */ int bwrite_conv(BIO *bio, const char *data, size_t datal, size_t *written) @@ -102,6 +104,7 @@ int BIO_meth_set_write_ex(BIO_METHOD *biom, return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int) { return biom->bread_old; @@ -111,6 +114,7 @@ int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size { return biom->bread; } +#endif /* Conversion for old style bread to new style */ int bread_conv(BIO *bio, char *data, size_t datal, size_t *readbytes) @@ -148,10 +152,12 @@ int BIO_meth_set_read_ex(BIO_METHOD *biom, return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *) { return biom->bputs; } +#endif int BIO_meth_set_puts(BIO_METHOD *biom, int (*bputs) (BIO *, const char *)) @@ -160,10 +166,12 @@ int BIO_meth_set_puts(BIO_METHOD *biom, return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_gets(const BIO_METHOD *biom)) (BIO *, char *, int) { return biom->bgets; } +#endif int BIO_meth_set_gets(BIO_METHOD *biom, int (*bgets) (BIO *, char *, int)) @@ -172,10 +180,12 @@ int BIO_meth_set_gets(BIO_METHOD *biom, return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 long (*BIO_meth_get_ctrl(const BIO_METHOD *biom)) (BIO *, int, long, void *) { return biom->ctrl; } +#endif int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *)) @@ -184,10 +194,12 @@ int BIO_meth_set_ctrl(BIO_METHOD *biom, return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_create(const BIO_METHOD *biom)) (BIO *) { return biom->create; } +#endif int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)) { @@ -195,10 +207,12 @@ int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *)) return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 int (*BIO_meth_get_destroy(const BIO_METHOD *biom)) (BIO *) { return biom->destroy; } +#endif int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)) { @@ -206,10 +220,12 @@ int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *)) return 1; } +#ifndef OPENSSL_NO_DEPRECATED_3_5 long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom)) (BIO *, int, BIO_info_cb *) { return biom->callback_ctrl; } +#endif int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, long (*callback_ctrl) (BIO *, int, @@ -218,3 +234,29 @@ int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, biom->callback_ctrl = callback_ctrl; return 1; } + +int BIO_meth_set_sendmmsg(BIO_METHOD *biom, + int (*bsendmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *)) +{ + biom->bsendmmsg = bsendmmsg; + return 1; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_5 +int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *) { + return biom->bsendmmsg; +} +#endif + +int BIO_meth_set_recvmmsg(BIO_METHOD *biom, + int (*brecvmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *)) +{ + biom->brecvmmsg = brecvmmsg; + return 1; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_5 +int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *) { + return biom->brecvmmsg; +} +#endif diff --git a/crypto/bio/bio_print.c b/crypto/bio/bio_print.c index 4c9c3af7cfd6..5f2543030e54 100644 --- a/crypto/bio/bio_print.c +++ b/crypto/bio/bio_print.c @@ -1,5 +1,5 @@ /* - * 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 @@ -62,7 +62,7 @@ static int _dopr(char **sbuffer, char **buffer, #define DP_F_NUM (1 << 3) /* print leading zeroes */ #define DP_F_ZERO (1 << 4) -/* print HEX in UPPPERcase */ +/* print HEX in UPPERcase */ #define DP_F_UP (1 << 5) /* treat value as unsigned */ #define DP_F_UNSIGNED (1 << 6) @@ -276,7 +276,7 @@ _dopr(char **sbuffer, break; case 'E': flags |= DP_F_UP; - /* fall thru */ + /* fall through */ case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); @@ -288,7 +288,7 @@ _dopr(char **sbuffer, break; case 'G': flags |= DP_F_UP; - /* fall thru */ + /* fall through */ case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); @@ -707,8 +707,6 @@ fmtfp(char **sbuffer, fracpart = (fracpart / 10); } - if (fplace == sizeof(fconvert)) - fplace--; fconvert[fplace] = 0; /* convert exponent part */ @@ -847,10 +845,8 @@ doapr_outch(char **sbuffer, *maxlen += BUFFER_INC; if (*buffer == NULL) { - if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) return 0; - } if (*currlen > 0) { if (!ossl_assert(*sbuffer != NULL)) return 0; @@ -861,10 +857,8 @@ doapr_outch(char **sbuffer, char *tmpbuf; tmpbuf = OPENSSL_realloc(*buffer, *maxlen); - if (tmpbuf == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (tmpbuf == NULL) return 0; - } *buffer = tmpbuf; } } diff --git a/crypto/bio/bio_sock.c b/crypto/bio/bio_sock.c index 84496de6f6bd..be1a74620f69 100644 --- a/crypto/bio/bio_sock.c +++ b/crypto/bio/bio_sock.c @@ -10,6 +10,7 @@ #include #include #include "bio_local.h" + #ifndef OPENSSL_NO_SOCK # define SOCKET_PROTOCOL IPPROTO_TCP # ifdef SO_MAXCONN @@ -26,9 +27,6 @@ static int wsa_init_done = 0; # if defined __TANDEM # include # include /* select */ -# if defined(OPENSSL_TANDEM_FLOSS) -# include -# endif # elif defined _WIN32 # include /* for type fd_set */ # else @@ -41,6 +39,7 @@ static int wsa_init_done = 0; # include # endif # endif +# include "internal/sockets.h" /* for openssl_fdset() */ # ifndef OPENSSL_NO_DEPRECATED_1_1_0 int BIO_get_host_ip(const char *str, unsigned char *ip) @@ -130,6 +129,11 @@ struct hostent *BIO_gethostbyname(const char *name) } # endif +# ifdef BIO_HAVE_WSAMSG +LPFN_WSARECVMSG bio_WSARecvMsg; +LPFN_WSASENDMSG bio_WSASendMsg; +# endif + int BIO_sock_init(void) { # ifdef OPENSSL_SYS_WINDOWS @@ -150,6 +154,39 @@ int BIO_sock_init(void) ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP); return -1; } + + /* + * On Windows, some socket functions are not exposed as a prototype. + * Instead, their function pointers must be loaded via this elaborate + * process... + */ +# ifdef BIO_HAVE_WSAMSG + { + GUID id_WSARecvMsg = WSAID_WSARECVMSG; + GUID id_WSASendMsg = WSAID_WSASENDMSG; + DWORD len_out = 0; + SOCKET s; + + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (s != INVALID_SOCKET) { + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, + &id_WSARecvMsg, sizeof(id_WSARecvMsg), + &bio_WSARecvMsg, sizeof(bio_WSARecvMsg), + &len_out, NULL, NULL) != 0 + || len_out != sizeof(bio_WSARecvMsg)) + bio_WSARecvMsg = NULL; + + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, + &id_WSASendMsg, sizeof(id_WSASendMsg), + &bio_WSASendMsg, sizeof(bio_WSASendMsg), + &len_out, NULL, NULL) != 0 + || len_out != sizeof(bio_WSASendMsg)) + bio_WSASendMsg = NULL; + + closesocket(s); + } + } +# endif } # endif /* OPENSSL_SYS_WINDOWS */ # ifdef WATT32 @@ -267,13 +304,14 @@ int BIO_accept(int sock, char **ip_port) if (ip_port != NULL) { char *host = BIO_ADDR_hostname_string(&res, 1); char *port = BIO_ADDR_service_string(&res, 1); - if (host != NULL && port != NULL) + if (host != NULL && port != NULL) { *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); - else + } else { *ip_port = NULL; + ERR_raise(ERR_LIB_BIO, ERR_R_BIO_LIB); + } if (*ip_port == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); BIO_closesocket(ret); ret = (int)INVALID_SOCKET; } else { @@ -392,15 +430,16 @@ int BIO_sock_info(int sock, */ int BIO_socket_wait(int fd, int for_read, time_t max_time) { +# if defined(OPENSSL_SYS_WINDOWS) || !defined(POLLIN) fd_set confds; struct timeval tv; time_t now; -#ifdef _WIN32 +# ifdef _WIN32 if ((SOCKET)fd == INVALID_SOCKET) -#else +# else if (fd < 0 || fd >= FD_SETSIZE) -#endif +# endif return -1; if (max_time == 0) return 1; @@ -415,5 +454,22 @@ int BIO_socket_wait(int fd, int for_read, time_t max_time) tv.tv_sec = (long)(max_time - now); /* might overflow */ return select(fd + 1, for_read ? &confds : NULL, for_read ? NULL : &confds, NULL, &tv); +# else + struct pollfd confds; + time_t now; + + if (fd < 0) + return -1; + if (max_time == 0) + return 1; + + now = time(NULL); + if (max_time < now) + return 0; + + confds.fd = fd; + confds.events = for_read ? POLLIN : POLLOUT; + return poll(&confds, 1, (int)(max_time - now) * 1000); +# endif } #endif /* !defined(OPENSSL_NO_SOCK) */ diff --git a/crypto/bio/bio_sock2.c b/crypto/bio/bio_sock2.c index 8bdad0c0b6ae..252a9ab0745d 100644 --- a/crypto/bio/bio_sock2.c +++ b/crypto/bio/bio_sock2.c @@ -13,6 +13,7 @@ #include "bio_local.h" #include "internal/ktls.h" +#include "internal/bio_tfo.h" #include @@ -68,6 +69,7 @@ int BIO_socket(int domain, int socktype, int protocol, int options) * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages. * - BIO_SOCK_NONBLOCK: Make the socket non-blocking. * - BIO_SOCK_NODELAY: don't delay small messages. + * - BIO_SOCK_TFO: use TCP Fast Open * * options holds BIO socket options that can be used * You should call this for every address returned by BIO_lookup @@ -107,6 +109,68 @@ int BIO_connect(int sock, const BIO_ADDR *addr, int options) return 0; } } + if (options & BIO_SOCK_TFO) { +# if defined(OSSL_TFO_CLIENT_FLAG) +# if defined(OSSL_TFO_SYSCTL_CLIENT) + int enabled = 0; + size_t enabledlen = sizeof(enabled); + + /* Later FreeBSD */ + if (sysctlbyname(OSSL_TFO_SYSCTL_CLIENT, &enabled, &enabledlen, NULL, 0) < 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT); + return 0; + } + /* Need to check for client flag */ + if (!(enabled & OSSL_TFO_CLIENT_FLAG)) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED); + return 0; + } +# elif defined(OSSL_TFO_SYSCTL) + int enabled = 0; + size_t enabledlen = sizeof(enabled); + + /* macOS */ + if (sysctlbyname(OSSL_TFO_SYSCTL, &enabled, &enabledlen, NULL, 0) < 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT); + return 0; + } + /* Need to check for client flag */ + if (!(enabled & OSSL_TFO_CLIENT_FLAG)) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED); + return 0; + } +# endif +# endif +# if defined(OSSL_TFO_CONNECTX) + sa_endpoints_t sae; + + memset(&sae, 0, sizeof(sae)); + sae.sae_dstaddr = BIO_ADDR_sockaddr(addr); + sae.sae_dstaddrlen = BIO_ADDR_sockaddr_size(addr); + if (connectx(sock, &sae, SAE_ASSOCID_ANY, + CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE, + NULL, 0, NULL, NULL) == -1) { + if (!BIO_sock_should_retry(-1)) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling connectx()"); + ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR); + } + return 0; + } +# endif +# if defined(OSSL_TFO_CLIENT_SOCKOPT) + if (setsockopt(sock, IPPROTO_TCP, OSSL_TFO_CLIENT_SOCKOPT, + (const void *)&on, sizeof(on)) != 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO); + return 0; + } +# endif +# if defined(OSSL_TFO_DO_NOT_CONNECT) + return 1; +# endif + } if (connect(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) == -1) { @@ -199,6 +263,7 @@ int BIO_bind(int sock, const BIO_ADDR *addr, int options) * for a recently closed port. * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only * for IPv6 addresses and not IPv4 addresses mapped to IPv6. + * - BIO_SOCK_TFO: accept TCP fast open (set TCP_FASTOPEN) * * It's recommended that you set up both an IPv6 and IPv4 listen socket, and * then check both for new clients that connect to it. You want to set up @@ -262,7 +327,7 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) } } - /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */ + /* On OpenBSD it is always IPv6 only with IPv6 sockets thus read-only */ # if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) if (BIO_ADDR_family(addr) == AF_INET6) { /* @@ -290,6 +355,54 @@ int BIO_listen(int sock, const BIO_ADDR *addr, int options) return 0; } +# if defined(OSSL_TFO_SERVER_SOCKOPT) + /* + * Must do it explicitly after listen() for macOS, still + * works fine on other OS's + */ + if ((options & BIO_SOCK_TFO) && socktype != SOCK_DGRAM) { + int q = OSSL_TFO_SERVER_SOCKOPT_VALUE; +# if defined(OSSL_TFO_CLIENT_FLAG) +# if defined(OSSL_TFO_SYSCTL_SERVER) + int enabled = 0; + size_t enabledlen = sizeof(enabled); + + /* Later FreeBSD */ + if (sysctlbyname(OSSL_TFO_SYSCTL_SERVER, &enabled, &enabledlen, NULL, 0) < 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT); + return 0; + } + /* Need to check for server flag */ + if (!(enabled & OSSL_TFO_SERVER_FLAG)) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED); + return 0; + } +# elif defined(OSSL_TFO_SYSCTL) + int enabled = 0; + size_t enabledlen = sizeof(enabled); + + /* Early FreeBSD, macOS */ + if (sysctlbyname(OSSL_TFO_SYSCTL, &enabled, &enabledlen, NULL, 0) < 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_NO_KERNEL_SUPPORT); + return 0; + } + /* Need to check for server flag */ + if (!(enabled & OSSL_TFO_SERVER_FLAG)) { + ERR_raise(ERR_LIB_BIO, BIO_R_TFO_DISABLED); + return 0; + } +# endif +# endif + if (setsockopt(sock, IPPROTO_TCP, OSSL_TFO_SERVER_SOCKOPT, + (void *)&q, sizeof(q)) < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_TFO); + return 0; + } + } +# endif + return 1; } diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c index 8870831039e9..24423aa36f73 100644 --- a/crypto/bio/bss_acpt.c +++ b/crypto/bio/bss_acpt.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -92,10 +92,8 @@ 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); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } ret->accept_family = BIO_FAMILY_IPANY; ret->accept_sock = (int)INVALID_SOCKET; return ret; @@ -188,7 +186,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) * at least the "else" part will always be * compiled. */ -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 family = AF_INET6; } else { #endif @@ -358,7 +356,7 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c) BIO_free(bio); else if (s >= 0) BIO_closesocket(s); - end: + end: return ret; } @@ -452,10 +450,14 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) data->bio_chain = (BIO *)ptr; } else if (num == 4) { data->accept_family = *(int *)ptr; + } else if (num == 5) { + data->bind_mode |= BIO_SOCK_TFO; } } else { if (num == 2) { data->bind_mode &= ~BIO_SOCK_NONBLOCK; + } else if (num == 5) { + data->bind_mode &= ~BIO_SOCK_TFO; } } break; @@ -497,7 +499,7 @@ static long acpt_ctrl(BIO *b, int cmd, long num, void *ptr) *pp = data->cache_peer_serv; } else if (num == 4) { switch (BIO_ADDRINFO_family(data->addr_iter)) { -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 case AF_INET6: ret = BIO_FAMILY_IPV6; break; diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c index 7fa8778cae10..3af3b27ea5ab 100644 --- a/crypto/bio/bss_bio.c +++ b/crypto/bio/bss_bio.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,7 +15,7 @@ * See ssl/ssltest.c for some hints on how this can be used. */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include @@ -273,7 +273,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) BIO_clear_retry_flags(bio); - if (!bio->init || buf == NULL || num == 0) + if (!bio->init || buf == NULL || num_ <= 0) return 0; b = bio->ptr; @@ -620,20 +620,16 @@ static int bio_make_pair(BIO *bio1, BIO *bio2) if (b1->buf == NULL) { b1->buf = OPENSSL_malloc(b1->size); - if (b1->buf == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (b1->buf == NULL) return 0; - } b1->len = 0; b1->offset = 0; } if (b2->buf == NULL) { b2->buf = OPENSSL_malloc(b2->size); - if (b2->buf == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (b2->buf == NULL) return 0; - } b2->len = 0; b2->offset = 0; } diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index 0d91f25fe70e..9d00f18297ff 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,6 +11,7 @@ #include #include "bio_local.h" +#include "internal/bio_tfo.h" #include "internal/ktls.h" #ifndef OPENSSL_NO_SOCK @@ -18,12 +19,14 @@ typedef struct bio_connect_st { int state; int connect_family; + int connect_sock_type; char *param_hostname; char *param_service; int connect_mode; # ifndef OPENSSL_NO_KTLS unsigned char record_type; # endif + int tfo_first; BIO_ADDRINFO *addr_first; const BIO_ADDRINFO *addr_iter; @@ -37,20 +40,30 @@ typedef struct bio_connect_st { * ssl info_callback */ BIO_info_cb *info_callback; + /* + * Used when connect_sock_type is SOCK_DGRAM. Owned by us; we forward + * read/write(mmsg) calls to this if present. + */ + BIO *dgram_bio; } BIO_CONNECT; static int conn_write(BIO *h, const char *buf, int num); static int conn_read(BIO *h, char *buf, int size); static int conn_puts(BIO *h, const char *str); +static int conn_gets(BIO *h, char *buf, int size); static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int conn_new(BIO *h); static int conn_free(BIO *data); static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *); +static int conn_sendmmsg(BIO *h, BIO_MSG *m, size_t s, size_t n, + uint64_t f, size_t *mp); +static int conn_recvmmsg(BIO *h, BIO_MSG *m, size_t s, size_t n, + uint64_t f, size_t *mp); static int conn_state(BIO *b, BIO_CONNECT *c); static void conn_close_socket(BIO *data); -BIO_CONNECT *BIO_CONNECT_new(void); -void BIO_CONNECT_free(BIO_CONNECT *a); +static BIO_CONNECT *BIO_CONNECT_new(void); +static void BIO_CONNECT_free(BIO_CONNECT *a); #define BIO_CONN_S_BEFORE 1 #define BIO_CONN_S_GET_ADDR 2 @@ -68,16 +81,36 @@ static const BIO_METHOD methods_connectp = { bread_conv, conn_read, conn_puts, - NULL, /* conn_gets, */ + conn_gets, conn_ctrl, conn_new, conn_free, conn_callback_ctrl, + conn_sendmmsg, + conn_recvmmsg, }; +static int conn_create_dgram_bio(BIO *b, BIO_CONNECT *c) +{ + if (c->connect_sock_type != SOCK_DGRAM) + return 1; + +#ifndef OPENSSL_NO_DGRAM + c->dgram_bio = BIO_new_dgram(b->num, 0); + if (c->dgram_bio == NULL) + goto err; + + return 1; + +err: +#endif + c->state = BIO_CONN_S_CONNECT_ERROR; + return 0; +} + static int conn_state(BIO *b, BIO_CONNECT *c) { - int ret = -1, i; + int ret = -1, i, opts; BIO_info_cb *cb = NULL; if (c->info_callback != NULL) @@ -105,7 +138,7 @@ static int conn_state(BIO *b, BIO_CONNECT *c) * at least the "else" part will always be * compiled. */ -#ifdef AF_INET6 +#if OPENSSL_USE_IPV6 family = AF_INET6; } else { #endif @@ -125,7 +158,8 @@ static int conn_state(BIO *b, BIO_CONNECT *c) } if (BIO_lookup(c->param_hostname, c->param_service, BIO_LOOKUP_CLIENT, - family, SOCK_STREAM, &c->addr_first) == 0) + family, c->connect_sock_type, + &c->addr_first) == 0) goto exit_loop; } if (c->addr_first == NULL) { @@ -154,8 +188,12 @@ static int conn_state(BIO *b, BIO_CONNECT *c) case BIO_CONN_S_CONNECT: BIO_clear_retry_flags(b); ERR_set_mark(); - ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter), - BIO_SOCK_KEEPALIVE | c->connect_mode); + + opts = c->connect_mode; + if (BIO_ADDRINFO_socktype(c->addr_iter) == SOCK_STREAM) + opts |= BIO_SOCK_KEEPALIVE; + + ret = BIO_connect(b->num, BIO_ADDRINFO_address(c->addr_iter), opts); b->retry_reason = 0; if (ret == 0) { if (BIO_sock_should_retry(ret)) { @@ -183,6 +221,8 @@ static int conn_state(BIO *b, BIO_CONNECT *c) goto exit_loop; } else { ERR_clear_last_mark(); + if (!conn_create_dgram_bio(b, c)) + break; c->state = BIO_CONN_S_OK; } break; @@ -209,6 +249,8 @@ static int conn_state(BIO *b, BIO_CONNECT *c) ret = 0; goto exit_loop; } else { + if (!conn_create_dgram_bio(b, c)) + break; c->state = BIO_CONN_S_OK; # ifndef OPENSSL_NO_KTLS /* @@ -249,20 +291,19 @@ static int conn_state(BIO *b, BIO_CONNECT *c) return ret; } -BIO_CONNECT *BIO_CONNECT_new(void) +static BIO_CONNECT *BIO_CONNECT_new(void) { BIO_CONNECT *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } ret->state = BIO_CONN_S_BEFORE; ret->connect_family = BIO_FAMILY_IPANY; + ret->connect_sock_type = SOCK_STREAM; return ret; } -void BIO_CONNECT_free(BIO_CONNECT *a) +static void BIO_CONNECT_free(BIO_CONNECT *a) { if (a == NULL) return; @@ -310,6 +351,8 @@ static int conn_free(BIO *a) return 0; data = (BIO_CONNECT *)a->ptr; + BIO_free(data->dgram_bio); + if (a->shutdown) { conn_close_socket(a); BIO_CONNECT_free(data); @@ -332,6 +375,13 @@ static int conn_read(BIO *b, char *out, int outl) return ret; } + if (data->dgram_bio != NULL) { + BIO_clear_retry_flags(b); + ret = BIO_read(data->dgram_bio, out, outl); + BIO_set_flags(b, BIO_get_retry_flags(data->dgram_bio)); + return ret; + } + if (out != NULL) { clear_socket_error(); # ifndef OPENSSL_NO_KTLS @@ -363,6 +413,13 @@ static int conn_write(BIO *b, const char *in, int inl) return ret; } + if (data->dgram_bio != NULL) { + BIO_clear_retry_flags(b); + ret = BIO_write(data->dgram_bio, in, inl); + BIO_set_flags(b, BIO_get_retry_flags(data->dgram_bio)); + return ret; + } + clear_socket_error(); # ifndef OPENSSL_NO_KTLS if (BIO_should_ktls_ctrl_msg_flag(b)) { @@ -372,6 +429,15 @@ static int conn_write(BIO *b, const char *in, int inl) BIO_clear_ktls_ctrl_msg_flag(b); } } else +# endif +# if defined(OSSL_TFO_SENDTO) + if (data->tfo_first) { + int peerlen = BIO_ADDRINFO_sockaddr_size(data->addr_iter); + + ret = sendto(b->num, in, inl, OSSL_TFO_SENDTO, + BIO_ADDRINFO_sockaddr(data->addr_iter), peerlen); + data->tfo_first = 0; + } else # endif ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); @@ -389,6 +455,7 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) const char **pptr = NULL; long ret = 1; BIO_CONNECT *data; + const BIO_ADDR *dg_addr; # ifndef OPENSSL_NO_KTLS ktls_crypto_info_t *crypto_info; # endif @@ -422,7 +489,7 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) *pptr = (const char *)BIO_ADDRINFO_address(data->addr_iter); } else if (num == 3) { switch (BIO_ADDRINFO_family(data->addr_iter)) { -# ifdef AF_INET6 +# if OPENSSL_USE_IPV6 case AF_INET6: ret = BIO_FAMILY_IPV6; break; @@ -437,6 +504,8 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) ret = -1; break; } + } else if (num == 4) { + ret = data->connect_mode; } else { ret = 0; } @@ -491,14 +560,90 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) } } break; + case BIO_C_SET_SOCK_TYPE: + if ((num != SOCK_STREAM && num != SOCK_DGRAM) + || data->state >= BIO_CONN_S_GET_ADDR) { + ret = 0; + break; + } + + data->connect_sock_type = (int)num; + ret = 1; + break; + case BIO_C_GET_SOCK_TYPE: + ret = data->connect_sock_type; + break; + case BIO_C_GET_DGRAM_BIO: + if (data->dgram_bio != NULL) { + *(BIO **)ptr = data->dgram_bio; + ret = 1; + } else { + ret = 0; + } + break; + case BIO_CTRL_DGRAM_GET_PEER: + case BIO_CTRL_DGRAM_DETECT_PEER_ADDR: + if (data->state != BIO_CONN_S_OK) + conn_state(b, data); /* best effort */ + + if (data->state >= BIO_CONN_S_CREATE_SOCKET + && data->addr_iter != NULL + && (dg_addr = BIO_ADDRINFO_address(data->addr_iter)) != NULL) { + + ret = BIO_ADDR_sockaddr_size(dg_addr); + if (num == 0 || num > ret) + num = ret; + + memcpy(ptr, dg_addr, num); + ret = num; + } else { + ret = 0; + } + + break; + case BIO_CTRL_GET_RPOLL_DESCRIPTOR: + case BIO_CTRL_GET_WPOLL_DESCRIPTOR: + { + BIO_POLL_DESCRIPTOR *pd = ptr; + + if (data->state != BIO_CONN_S_OK) + conn_state(b, data); /* best effort */ + + if (data->state >= BIO_CONN_S_CREATE_SOCKET) { + pd->type = BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD; + pd->value.fd = b->num; + } else { + ret = 0; + } + } + break; case BIO_C_SET_NBIO: if (num != 0) data->connect_mode |= BIO_SOCK_NONBLOCK; else data->connect_mode &= ~BIO_SOCK_NONBLOCK; + + if (data->dgram_bio != NULL) + ret = BIO_set_nbio(data->dgram_bio, num); + break; +#if defined(TCP_FASTOPEN) && !defined(OPENSSL_NO_TFO) + case BIO_C_SET_TFO: + if (num != 0) { + data->connect_mode |= BIO_SOCK_TFO; + data->tfo_first = 1; + } else { + data->connect_mode &= ~BIO_SOCK_TFO; + data->tfo_first = 0; + } + break; +#endif case BIO_C_SET_CONNECT_MODE: data->connect_mode = (int)num; + if (num & BIO_SOCK_TFO) + data->tfo_first = 1; + else + data->tfo_first = 0; break; case BIO_C_GET_FD: if (b->init) { @@ -571,6 +716,11 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_clear_ktls_ctrl_msg_flag(b); ret = 0; break; + case BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE: + ret = ktls_enable_tx_zerocopy_sendfile(b->num); + if (ret) + BIO_set_ktls_zerocopy_sendfile_flag(b); + break; # endif default: ret = 0; @@ -608,6 +758,123 @@ static int conn_puts(BIO *bp, const char *str) return ret; } +int conn_gets(BIO *bio, char *buf, int size) +{ + BIO_CONNECT *data; + char *ptr = buf; + int ret = 0; + + 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 || bio->ptr == NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + data = (BIO_CONNECT *)bio->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(bio, data); + if (ret <= 0) + return ret; + } + + if (data->dgram_bio != NULL) { + ERR_raise(ERR_LIB_BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } + + clear_socket_error(); + while (size-- > 1) { +# ifndef OPENSSL_NO_KTLS + if (BIO_get_ktls_recv(bio)) + ret = ktls_read_record(bio->num, ptr, 1); + else +# endif + ret = readsocket(bio->num, ptr, 1); + BIO_clear_retry_flags(bio); + if (ret <= 0) { + if (BIO_sock_should_retry(ret)) + BIO_set_retry_read(bio); + else if (ret == 0) + bio->flags |= BIO_FLAGS_IN_EOF; + break; + } + if (*ptr++ == '\n') + break; + } + *ptr = '\0'; + return ret > 0 || (bio->flags & BIO_FLAGS_IN_EOF) != 0 ? ptr - buf : ret; +} + +static int conn_sendmmsg(BIO *bio, BIO_MSG *msg, size_t stride, size_t num_msgs, + uint64_t flags, size_t *msgs_processed) +{ + int ret; + BIO_CONNECT *data; + + if (bio == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + data = (BIO_CONNECT *)bio->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(bio, data); + if (ret <= 0) { + *msgs_processed = 0; + return 0; + } + } + + if (data->dgram_bio == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return BIO_sendmmsg(data->dgram_bio, msg, stride, num_msgs, + flags, msgs_processed); +} + +static int conn_recvmmsg(BIO *bio, BIO_MSG *msg, size_t stride, size_t num_msgs, + uint64_t flags, size_t *msgs_processed) +{ + int ret; + BIO_CONNECT *data; + + if (bio == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + data = (BIO_CONNECT *)bio->ptr; + if (data->state != BIO_CONN_S_OK) { + ret = conn_state(bio, data); + if (ret <= 0) { + *msgs_processed = 0; + return 0; + } + } + + if (data->dgram_bio == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return BIO_recvmmsg(data->dgram_bio, msg, stride, num_msgs, + flags, msgs_processed); +} + BIO *BIO_new_connect(const char *str) { BIO *ret; diff --git a/crypto/bio/bss_core.c b/crypto/bio/bss_core.c index 7a84b20460c8..b9a8eff3464a 100644 --- a/crypto/bio/bss_core.c +++ b/crypto/bio/bss_core.c @@ -10,6 +10,7 @@ #include #include "bio_local.h" #include "internal/cryptlib.h" +#include "crypto/context.h" typedef struct { OSSL_FUNC_BIO_read_ex_fn *c_bio_read_ex; @@ -21,26 +22,19 @@ typedef struct { OSSL_FUNC_BIO_free_fn *c_bio_free; } BIO_CORE_GLOBALS; -static void bio_core_globals_free(void *vbcg) +void ossl_bio_core_globals_free(void *vbcg) { OPENSSL_free(vbcg); } -static void *bio_core_globals_new(OSSL_LIB_CTX *ctx) +void *ossl_bio_core_globals_new(OSSL_LIB_CTX *ctx) { return OPENSSL_zalloc(sizeof(BIO_CORE_GLOBALS)); } -static const OSSL_LIB_CTX_METHOD bio_core_globals_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - bio_core_globals_new, - bio_core_globals_free, -}; - static ossl_inline BIO_CORE_GLOBALS *get_globals(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX, - &bio_core_globals_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_BIO_CORE_INDEX); } static int bio_core_read_ex(BIO *bio, char *data, size_t data_len, diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 8ca1cf64ed47..ea2550859ccd 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,6 +14,7 @@ #include #include +#include "internal/time.h" #include "bio_local.h" #ifndef OPENSSL_NO_DGRAM @@ -42,6 +43,102 @@ ((a)->s6_addr32[2] == htonl(0x0000ffff))) # endif +/* Determine what method to use for BIO_sendmmsg and BIO_recvmmsg. */ +# define M_METHOD_NONE 0 +# define M_METHOD_RECVMMSG 1 +# define M_METHOD_RECVMSG 2 +# define M_METHOD_RECVFROM 3 +# define M_METHOD_WSARECVMSG 4 + +# if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +# if !(__GLIBC_PREREQ(2, 14)) +# undef NO_RECVMMSG + /* + * Some old glibc versions may have recvmmsg and MSG_WAITFORONE flag, but + * not sendmmsg. We need both so force this to be disabled on these old + * versions + */ +# define NO_RECVMMSG +# endif +# endif +# if defined(__GNU__) + /* GNU/Hurd does not have IP_PKTINFO yet */ + #undef NO_RECVMSG + #define NO_RECVMSG +# endif +# if (defined(__ANDROID_API__) && __ANDROID_API__ < 21) || defined(_AIX) +# undef NO_RECVMMSG +# define NO_RECVMMSG +# endif +# if !defined(M_METHOD) +# if defined(OPENSSL_SYS_WINDOWS) && defined(BIO_HAVE_WSAMSG) && !defined(NO_WSARECVMSG) +# define M_METHOD M_METHOD_WSARECVMSG +# elif !defined(OPENSSL_SYS_WINDOWS) && defined(MSG_WAITFORONE) && !defined(NO_RECVMMSG) +# define M_METHOD M_METHOD_RECVMMSG +# elif !defined(OPENSSL_SYS_WINDOWS) && defined(CMSG_LEN) && !defined(NO_RECVMSG) +# define M_METHOD M_METHOD_RECVMSG +# elif !defined(NO_RECVFROM) +# define M_METHOD M_METHOD_RECVFROM +# else +# define M_METHOD M_METHOD_NONE +# endif +# endif + +# if defined(OPENSSL_SYS_WINDOWS) +# define BIO_CMSG_SPACE(x) WSA_CMSG_SPACE(x) +# define BIO_CMSG_FIRSTHDR(x) WSA_CMSG_FIRSTHDR(x) +# define BIO_CMSG_NXTHDR(x, y) WSA_CMSG_NXTHDR(x, y) +# define BIO_CMSG_DATA(x) WSA_CMSG_DATA(x) +# define BIO_CMSG_LEN(x) WSA_CMSG_LEN(x) +# define MSGHDR_TYPE WSAMSG +# define CMSGHDR_TYPE WSACMSGHDR +# else +# define MSGHDR_TYPE struct msghdr +# define CMSGHDR_TYPE struct cmsghdr +# define BIO_CMSG_SPACE(x) CMSG_SPACE(x) +# define BIO_CMSG_FIRSTHDR(x) CMSG_FIRSTHDR(x) +# define BIO_CMSG_NXTHDR(x, y) CMSG_NXTHDR(x, y) +# define BIO_CMSG_DATA(x) CMSG_DATA(x) +# define BIO_CMSG_LEN(x) CMSG_LEN(x) +# endif + +# if M_METHOD == M_METHOD_RECVMMSG \ + || M_METHOD == M_METHOD_RECVMSG \ + || M_METHOD == M_METHOD_WSARECVMSG +# if defined(__APPLE__) + /* + * CMSG_SPACE is not a constant expression on OSX even though POSIX + * says it's supposed to be. This should be adequate. + */ +# define BIO_CMSG_ALLOC_LEN 64 +# else +# if defined(IPV6_PKTINFO) +# define BIO_CMSG_ALLOC_LEN_1 BIO_CMSG_SPACE(sizeof(struct in6_pktinfo)) +# else +# define BIO_CMSG_ALLOC_LEN_1 0 +# endif +# if defined(IP_PKTINFO) +# define BIO_CMSG_ALLOC_LEN_2 BIO_CMSG_SPACE(sizeof(struct in_pktinfo)) +# else +# define BIO_CMSG_ALLOC_LEN_2 0 +# endif +# if defined(IP_RECVDSTADDR) +# define BIO_CMSG_ALLOC_LEN_3 BIO_CMSG_SPACE(sizeof(struct in_addr)) +# else +# define BIO_CMSG_ALLOC_LEN_3 0 +# endif +# define BIO_MAX(X,Y) ((X) > (Y) ? (X) : (Y)) +# define BIO_CMSG_ALLOC_LEN \ + BIO_MAX(BIO_CMSG_ALLOC_LEN_1, \ + BIO_MAX(BIO_CMSG_ALLOC_LEN_2, BIO_CMSG_ALLOC_LEN_3)) +# endif +# if (defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)) && defined(IPV6_RECVPKTINFO) +# define SUPPORT_LOCAL_ADDR +# endif +# endif + +# define BIO_MSG_N(array, stride, n) (*(BIO_MSG *)((char *)(array) + (n)*(stride))) + static int dgram_write(BIO *h, const char *buf, int num); static int dgram_read(BIO *h, char *buf, int size); static int dgram_puts(BIO *h, const char *str); @@ -49,6 +146,12 @@ static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int dgram_new(BIO *h); static int dgram_free(BIO *data); static int dgram_clear(BIO *bio); +static int dgram_sendmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, + uint64_t flags, size_t *num_processed); +static int dgram_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, + uint64_t flags, size_t *num_processed); # ifndef OPENSSL_NO_SCTP static int dgram_sctp_write(BIO *h, const char *buf, int num); @@ -67,8 +170,6 @@ static void dgram_sctp_handle_auth_free_key_event(BIO *b, union sctp_notificatio static int BIO_dgram_should_retry(int s); -static void get_current_time(struct timeval *t); - static const BIO_METHOD methods_dgramp = { BIO_TYPE_DGRAM, "datagram socket", @@ -82,6 +183,8 @@ static const BIO_METHOD methods_dgramp = { dgram_new, dgram_free, NULL, /* dgram_callback_ctrl */ + dgram_sendmmsg, + dgram_recvmmsg, }; # ifndef OPENSSL_NO_SCTP @@ -98,17 +201,21 @@ static const BIO_METHOD methods_dgramp_sctp = { dgram_sctp_new, dgram_sctp_free, NULL, /* dgram_callback_ctrl */ + NULL, /* sendmmsg */ + NULL, /* recvmmsg */ }; # endif typedef struct bio_dgram_data_st { BIO_ADDR peer; + BIO_ADDR local_addr; unsigned int connected; unsigned int _errno; unsigned int mtu; - struct timeval next_timeout; - struct timeval socket_timeout; + OSSL_TIME next_timeout; + OSSL_TIME socket_timeout; unsigned int peekmode; + char local_addr_enabled; } bio_dgram_data; # ifndef OPENSSL_NO_SCTP @@ -118,11 +225,13 @@ typedef struct bio_dgram_sctp_save_message_st { int length; } bio_dgram_sctp_save_message; +/* + * Note: bio_dgram_data must be first here + * as we use dgram_ctrl for underlying dgram operations + * which will cast this struct to a bio_dgram_data + */ typedef struct bio_dgram_sctp_data_st { - BIO_ADDR peer; - unsigned int connected; - unsigned int _errno; - unsigned int mtu; + bio_dgram_data dgram; struct bio_dgram_sctp_sndinfo sndinfo; struct bio_dgram_sctp_rcvinfo rcvinfo; struct bio_dgram_sctp_prinfo prinfo; @@ -195,96 +304,102 @@ static void dgram_adjust_rcv_timeout(BIO *b) { # if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; + OSSL_TIME timeleft; /* Is a timer active? */ - if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { - struct timeval timenow, timeleft; - + if (!ossl_time_is_zero(data->next_timeout)) { /* Read current socket timeout */ # ifdef OPENSSL_SYS_WINDOWS int timeout; - int sz = sizeof(timeout); + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz) < 0) { - perror("getsockopt"); - } else { - data->socket_timeout.tv_sec = timeout / 1000; - data->socket_timeout.tv_usec = (timeout % 1000) * 1000; - } + (void *)&timeout, &sz) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); + else + data->socket_timeout = ossl_ms2time(timeout); # else - socklen_t sz = sizeof(data->socket_timeout); - if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - &(data->socket_timeout), &sz) < 0) { - perror("getsockopt"); - } else - OPENSSL_assert(sz <= sizeof(data->socket_timeout)); + struct timeval tv; + socklen_t sz = sizeof(tv); + + if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &tv, &sz) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); + else + data->socket_timeout = ossl_time_from_timeval(tv); # endif - /* Get current time */ - get_current_time(&timenow); - /* Calculate time left until timer expires */ - memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); - if (timeleft.tv_usec < timenow.tv_usec) { - timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec; - timeleft.tv_sec--; - } else { - timeleft.tv_usec -= timenow.tv_usec; - } - if (timeleft.tv_sec < timenow.tv_sec) { - timeleft.tv_sec = 0; - timeleft.tv_usec = 1; - } else { - timeleft.tv_sec -= timenow.tv_sec; - } + timeleft = ossl_time_subtract(data->next_timeout, ossl_time_now()); + if (ossl_time_compare(timeleft, ossl_ticks2time(OSSL_TIME_US)) < 0) + timeleft = ossl_ticks2time(OSSL_TIME_US); /* * Adjust socket timeout if next handshake message timer will expire * earlier. */ - if ((data->socket_timeout.tv_sec == 0 - && data->socket_timeout.tv_usec == 0) - || (data->socket_timeout.tv_sec > timeleft.tv_sec) - || (data->socket_timeout.tv_sec == timeleft.tv_sec - && data->socket_timeout.tv_usec >= timeleft.tv_usec)) { + if (ossl_time_is_zero(data->socket_timeout) + || ossl_time_compare(data->socket_timeout, timeleft) >= 0) { # ifdef OPENSSL_SYS_WINDOWS - timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000; + timeout = (int)ossl_time2ms(timeleft); if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, sizeof(timeout)) < 0) { - perror("setsockopt"); - } + (void *)&timeout, sizeof(timeout)) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # else - if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft, - sizeof(struct timeval)) < 0) { - perror("setsockopt"); - } + tv = ossl_time_to_timeval(timeleft); + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &tv, + sizeof(tv)) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # endif } } # endif } +static void dgram_update_local_addr(BIO *b) +{ + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + socklen_t addr_len = sizeof(data->local_addr); + + if (getsockname(b->num, &data->local_addr.sa, &addr_len) < 0) + /* + * This should not be possible, but zero-initialize and return + * anyway. + */ + BIO_ADDR_clear(&data->local_addr); +} + +# if M_METHOD == M_METHOD_RECVMMSG || M_METHOD == M_METHOD_RECVMSG || M_METHOD == M_METHOD_WSARECVMSG +static int dgram_get_sock_family(BIO *b) +{ + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + return data->local_addr.sa.sa_family; +} +# endif + static void dgram_reset_rcv_timeout(BIO *b) { # if defined(SO_RCVTIMEO) bio_dgram_data *data = (bio_dgram_data *)b->ptr; /* Is a timer active? */ - if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) { + if (!ossl_time_is_zero(data->next_timeout)) { # ifdef OPENSSL_SYS_WINDOWS - int timeout = data->socket_timeout.tv_sec * 1000 + - data->socket_timeout.tv_usec / 1000; + int timeout = (int)ossl_time2ms(data->socket_timeout); + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, sizeof(timeout)) < 0) { - perror("setsockopt"); - } + (void *)&timeout, sizeof(timeout)) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # else - if (setsockopt - (b->num, SOL_SOCKET, SO_RCVTIMEO, &(data->socket_timeout), - sizeof(struct timeval)) < 0) { - perror("setsockopt"); - } + struct timeval tv = ossl_time_to_timeval(data->socket_timeout); + + if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # endif } # endif @@ -301,7 +416,7 @@ static int dgram_read(BIO *b, char *out, int outl) if (out != NULL) { clear_socket_error(); - memset(&peer, 0, sizeof(peer)); + BIO_ADDR_clear(&peer); dgram_adjust_rcv_timeout(b); if (data->peekmode) flags = MSG_PEEK; @@ -388,12 +503,56 @@ static long dgram_get_mtu_overhead(bio_dgram_data *data) return ret; } +/* Enables appropriate destination address reception option on the socket. */ +# if defined(SUPPORT_LOCAL_ADDR) +static int enable_local_addr(BIO *b, int enable) { + int af = dgram_get_sock_family(b); + + if (af == AF_INET) { +# if defined(IP_PKTINFO) + /* IP_PKTINFO is preferred */ + if (setsockopt(b->num, IPPROTO_IP, IP_PKTINFO, + (void *)&enable, sizeof(enable)) < 0) + return 0; + + return 1; + +# elif defined(IP_RECVDSTADDR) + /* Fall back to IP_RECVDSTADDR */ + + if (setsockopt(b->num, IPPROTO_IP, IP_RECVDSTADDR, + &enable, sizeof(enable)) < 0) + return 0; + + return 1; +# endif + } + +# if OPENSSL_USE_IPV6 + if (af == AF_INET6) { +# if defined(IPV6_RECVPKTINFO) + if (setsockopt(b->num, IPPROTO_IPV6, IPV6_RECVPKTINFO, + &enable, sizeof(enable)) < 0) + return 0; + + return 1; +# endif + } +# endif + + return 0; +} +# endif + static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret = 1; int *ip; bio_dgram_data *data = NULL; +# ifndef __DJGPP__ + /* There are currently no cases where this is used on djgpp/watt32. */ int sockopt_val = 0; +# endif int d_errno; # if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU)) socklen_t sockopt_len; /* assume that system supporting IP_MTU is @@ -401,6 +560,8 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) socklen_t addr_len; BIO_ADDR addr; # endif + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); data = (bio_dgram_data *)b->ptr; @@ -417,6 +578,17 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) b->num = *((int *)ptr); b->shutdown = (int)num; b->init = 1; + dgram_update_local_addr(b); + if (getpeername(b->num, (struct sockaddr *)&ss, &ss_len) == 0) { + BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)&ss)); + data->connected = 1; + } +# if defined(SUPPORT_LOCAL_ADDR) + if (data->local_addr_enabled) { + if (enable_local_addr(b, 1) < 1) + data->local_addr_enabled = 0; + } +# endif break; case BIO_C_GET_FD: if (b->init) { @@ -448,7 +620,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_MTU_DISCOVER: # if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) addr_len = (socklen_t) sizeof(addr); - memset(&addr, 0, sizeof(addr)); + BIO_ADDR_clear(&addr); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; @@ -458,14 +630,16 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) sockopt_val = IP_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) - perror("setsockopt"); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); break; # if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) - perror("setsockopt"); + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); break; # endif default: @@ -479,7 +653,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_QUERY_MTU: # if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU) addr_len = (socklen_t) sizeof(addr); - memset(&addr, 0, sizeof(addr)); + BIO_ADDR_clear(&addr); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; @@ -562,7 +736,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr)); } else { data->connected = 0; - memset(&data->peer, 0, sizeof(data->peer)); + BIO_ADDR_clear(&data->peer); } break; case BIO_CTRL_DGRAM_GET_PEER: @@ -576,8 +750,34 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_SET_PEER: BIO_ADDR_make(&data->peer, BIO_ADDR_sockaddr((BIO_ADDR *)ptr)); break; + case BIO_CTRL_DGRAM_DETECT_PEER_ADDR: + { + BIO_ADDR xaddr, *p = &data->peer; + socklen_t xaddr_len = sizeof(xaddr.sa); + + if (BIO_ADDR_family(p) == AF_UNSPEC) { + if (getpeername(b->num, (void *)&xaddr.sa, &xaddr_len) == 0 + && BIO_ADDR_family(&xaddr) != AF_UNSPEC) { + p = &xaddr; + } else { + ret = 0; + break; + } + } + + ret = BIO_ADDR_sockaddr_size(p); + if (num == 0 || num > ret) + num = ret; + + memcpy(ptr, p, (ret = num)); + } + break; + case BIO_C_SET_NBIO: + if (!BIO_socket_nbio(b->num, num != 0)) + ret = 0; + break; case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: - memcpy(&(data->next_timeout), ptr, sizeof(struct timeval)); + data->next_timeout = ossl_time_from_timeval(*(struct timeval *)ptr); break; # if defined(SO_RCVTIMEO) case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: @@ -585,18 +785,17 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) { struct timeval *tv = (struct timeval *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000; - if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, sizeof(timeout)) < 0) { - perror("setsockopt"); - ret = -1; - } + + if ((ret = setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, sizeof(timeout))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); } # else - if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, - sizeof(struct timeval)) < 0) { - perror("setsockopt"); - ret = -1; - } + if ((ret = setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, + sizeof(struct timeval))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: @@ -607,10 +806,10 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) struct timeval *tv = (struct timeval *)ptr; sz = sizeof(timeout); - if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - (void *)&timeout, &sz) < 0) { - perror("getsockopt"); - ret = -1; + if ((ret = getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + (void *)&timeout, &sz)) < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; @@ -618,12 +817,12 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) } # else socklen_t sz = sizeof(struct timeval); - if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, - ptr, &sz) < 0) { - perror("getsockopt"); - ret = -1; + if ((ret = getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, + ptr, &sz)) < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); } else { - OPENSSL_assert(sz <= sizeof(struct timeval)); + OPENSSL_assert((size_t)sz <= sizeof(struct timeval)); ret = (int)sz; } # endif @@ -636,18 +835,17 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) { struct timeval *tv = (struct timeval *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000; - if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - (void *)&timeout, sizeof(timeout)) < 0) { - perror("setsockopt"); - ret = -1; - } + + if ((ret = setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void *)&timeout, sizeof(timeout))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); } # else - if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, - sizeof(struct timeval)) < 0) { - perror("setsockopt"); - ret = -1; - } + if ((ret = setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, + sizeof(struct timeval))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: @@ -658,10 +856,10 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) struct timeval *tv = (struct timeval *)ptr; sz = sizeof(timeout); - if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - (void *)&timeout, &sz) < 0) { - perror("getsockopt"); - ret = -1; + if ((ret = getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + (void *)&timeout, &sz)) < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; @@ -669,12 +867,13 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) } # else socklen_t sz = sizeof(struct timeval); - if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, - ptr, &sz) < 0) { - perror("getsockopt"); - ret = -1; + + if ((ret = getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, + ptr, &sz)) < 0) { + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling getsockopt()"); } else { - OPENSSL_assert(sz <= sizeof(struct timeval)); + OPENSSL_assert((size_t)sz <= sizeof(struct timeval)); ret = (int)sz; } # endif @@ -705,30 +904,27 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) break; # endif case BIO_CTRL_DGRAM_SET_DONT_FRAG: - sockopt_val = num ? 1 : 0; - switch (data->peer.sa.sa_family) { case AF_INET: # if defined(IP_DONTFRAG) + sockopt_val = num ? 1 : 0; if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAG, - &sockopt_val, sizeof(sockopt_val))) < 0) { - perror("setsockopt"); - ret = -1; - } + &sockopt_val, sizeof(sockopt_val))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # elif defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined (IP_PMTUDISC_PROBE) - if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT), - (ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, - &sockopt_val, sizeof(sockopt_val))) < 0) { - perror("setsockopt"); - ret = -1; - } + sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT; + if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # elif defined(OPENSSL_SYS_WINDOWS) && defined(IP_DONTFRAGMENT) + sockopt_val = num ? 1 : 0; if ((ret = setsockopt(b->num, IPPROTO_IP, IP_DONTFRAGMENT, (const char *)&sockopt_val, - sizeof(sockopt_val))) < 0) { - perror("setsockopt"); - ret = -1; - } + sizeof(sockopt_val))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # else ret = -1; # endif @@ -736,19 +932,19 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) # if OPENSSL_USE_IPV6 case AF_INET6: # if defined(IPV6_DONTFRAG) + sockopt_val = num ? 1 : 0; if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_DONTFRAG, (const void *)&sockopt_val, - sizeof(sockopt_val))) < 0) { - perror("setsockopt"); - ret = -1; - } + sizeof(sockopt_val))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); + # elif defined(OPENSSL_SYS_LINUX) && defined(IPV6_MTUDISCOVER) - if ((sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT), - (ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, - &sockopt_val, sizeof(sockopt_val))) < 0) { - perror("setsockopt"); - ret = -1; - } + sockopt_val = num ? IP_PMTUDISC_PROBE : IP_PMTUDISC_DONT; + if ((ret = setsockopt(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, + &sockopt_val, sizeof(sockopt_val))) < 0) + ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), + "calling setsockopt()"); # else ret = -1; # endif @@ -774,10 +970,59 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_DGRAM_SET_PEEK_MODE: data->peekmode = (unsigned int)num; break; + + case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP: +# if defined(SUPPORT_LOCAL_ADDR) + ret = 1; +# else + ret = 0; +# endif + break; + + case BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE: +# if defined(SUPPORT_LOCAL_ADDR) + num = num > 0; + if (num != data->local_addr_enabled) { + if (enable_local_addr(b, num) < 1) { + ret = 0; + break; + } + + data->local_addr_enabled = (char)num; + } +# else + ret = 0; +# endif + break; + + case BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE: + *(int *)ptr = data->local_addr_enabled; + break; + + case BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS: + ret = (long)(BIO_DGRAM_CAP_HANDLES_DST_ADDR + | BIO_DGRAM_CAP_HANDLES_SRC_ADDR + | BIO_DGRAM_CAP_PROVIDES_DST_ADDR + | BIO_DGRAM_CAP_PROVIDES_SRC_ADDR); + break; + + case BIO_CTRL_GET_RPOLL_DESCRIPTOR: + case BIO_CTRL_GET_WPOLL_DESCRIPTOR: + { + BIO_POLL_DESCRIPTOR *pd = ptr; + + pd->type = BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD; + pd->value.fd = b->num; + } + break; + default: ret = 0; break; } + /* Normalize if error */ + if (ret < 0) + ret = -1; return ret; } @@ -790,6 +1035,726 @@ static int dgram_puts(BIO *bp, const char *str) return ret; } +# if M_METHOD == M_METHOD_WSARECVMSG +static void translate_msg_win(BIO *b, WSAMSG *mh, WSABUF *iov, + unsigned char *control, BIO_MSG *msg) +{ + iov->len = msg->data_len; + iov->buf = msg->data; + + /* Windows requires namelen to be set exactly */ + mh->name = msg->peer != NULL ? &msg->peer->sa : NULL; + if (msg->peer != NULL && dgram_get_sock_family(b) == AF_INET) + mh->namelen = sizeof(struct sockaddr_in); +# if OPENSSL_USE_IPV6 + else if (msg->peer != NULL && dgram_get_sock_family(b) == AF_INET6) + mh->namelen = sizeof(struct sockaddr_in6); +# endif + else + mh->namelen = 0; + + /* + * When local address reception (IP_PKTINFO, etc.) is enabled, on Windows + * this causes WSARecvMsg to fail if the control buffer is too small to hold + * the structure, or if no control buffer is passed. So we need to give it + * the control buffer even if we aren't actually going to examine the + * result. + */ + mh->lpBuffers = iov; + mh->dwBufferCount = 1; + mh->Control.len = BIO_CMSG_ALLOC_LEN; + mh->Control.buf = control; + mh->dwFlags = 0; +} +# endif + +# if M_METHOD == M_METHOD_RECVMMSG || M_METHOD == M_METHOD_RECVMSG +/* Translates a BIO_MSG to a msghdr and iovec. */ +static void translate_msg(BIO *b, struct msghdr *mh, struct iovec *iov, + unsigned char *control, BIO_MSG *msg) +{ + bio_dgram_data *data; + + iov->iov_base = msg->data; + iov->iov_len = msg->data_len; + + data = (bio_dgram_data *)b->ptr; + if (data->connected == 0) { + /* macOS requires msg_namelen be 0 if msg_name is NULL */ + mh->msg_name = msg->peer != NULL ? &msg->peer->sa : NULL; + if (msg->peer != NULL && dgram_get_sock_family(b) == AF_INET) + mh->msg_namelen = sizeof(struct sockaddr_in); +# if OPENSSL_USE_IPV6 + else if (msg->peer != NULL && dgram_get_sock_family(b) == AF_INET6) + mh->msg_namelen = sizeof(struct sockaddr_in6); +# endif + else + mh->msg_namelen = 0; + } else { + mh->msg_name = NULL; + mh->msg_namelen = 0; + } + + mh->msg_iov = iov; + mh->msg_iovlen = 1; + mh->msg_control = msg->local != NULL ? control : NULL; + mh->msg_controllen = msg->local != NULL ? BIO_CMSG_ALLOC_LEN : 0; + mh->msg_flags = 0; +} +# endif + +# if M_METHOD == M_METHOD_RECVMMSG || M_METHOD == M_METHOD_RECVMSG || M_METHOD == M_METHOD_WSARECVMSG +/* Extracts destination address from the control buffer. */ +static int extract_local(BIO *b, MSGHDR_TYPE *mh, BIO_ADDR *local) { +# if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO) + CMSGHDR_TYPE *cmsg; + int af = dgram_get_sock_family(b); + + for (cmsg = BIO_CMSG_FIRSTHDR(mh); cmsg != NULL; + cmsg = BIO_CMSG_NXTHDR(mh, cmsg)) { + if (af == AF_INET) { + if (cmsg->cmsg_level != IPPROTO_IP) + continue; + +# if defined(IP_PKTINFO) + if (cmsg->cmsg_type != IP_PKTINFO) + continue; + + local->s_in.sin_addr = + ((struct in_pktinfo *)BIO_CMSG_DATA(cmsg))->ipi_addr; + +# elif defined(IP_RECVDSTADDR) + if (cmsg->cmsg_type != IP_RECVDSTADDR) + continue; + + local->s_in.sin_addr = *(struct in_addr *)BIO_CMSG_DATA(cmsg); +# endif + +# if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) + { + bio_dgram_data *data = b->ptr; + + local->s_in.sin_family = AF_INET; + local->s_in.sin_port = data->local_addr.s_in.sin_port; + } + return 1; +# endif + } +# if OPENSSL_USE_IPV6 + else if (af == AF_INET6) { + if (cmsg->cmsg_level != IPPROTO_IPV6) + continue; + +# if defined(IPV6_RECVPKTINFO) + if (cmsg->cmsg_type != IPV6_PKTINFO) + continue; + + { + bio_dgram_data *data = b->ptr; + + local->s_in6.sin6_addr = + ((struct in6_pktinfo *)BIO_CMSG_DATA(cmsg))->ipi6_addr; + local->s_in6.sin6_family = AF_INET6; + local->s_in6.sin6_port = data->local_addr.s_in6.sin6_port; + local->s_in6.sin6_scope_id = + data->local_addr.s_in6.sin6_scope_id; + local->s_in6.sin6_flowinfo = 0; + } + return 1; +# endif + } +# endif + } +# endif + + return 0; +} + +static int pack_local(BIO *b, MSGHDR_TYPE *mh, const BIO_ADDR *local) { + int af = dgram_get_sock_family(b); +# if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO) + CMSGHDR_TYPE *cmsg; + bio_dgram_data *data = b->ptr; +# endif + + if (af == AF_INET) { +# if defined(IP_PKTINFO) + struct in_pktinfo *info; + +# if defined(OPENSSL_SYS_WINDOWS) + cmsg = (CMSGHDR_TYPE *)mh->Control.buf; +# else + cmsg = (CMSGHDR_TYPE *)mh->msg_control; +# endif + + cmsg->cmsg_len = BIO_CMSG_LEN(sizeof(struct in_pktinfo)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + + info = (struct in_pktinfo *)BIO_CMSG_DATA(cmsg); +# if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_CYGWIN) && !defined(__FreeBSD__) && !defined(__QNX__) + info->ipi_spec_dst = local->s_in.sin_addr; +# endif + info->ipi_addr.s_addr = 0; + info->ipi_ifindex = 0; + + /* + * We cannot override source port using this API, therefore + * ensure the application specified a source port of 0 + * or the one we are bound to. (Better to error than silently + * ignore this.) + */ + if (local->s_in.sin_port != 0 + && data->local_addr.s_in.sin_port != local->s_in.sin_port) { + ERR_raise(ERR_LIB_BIO, BIO_R_PORT_MISMATCH); + return 0; + } + +# if defined(OPENSSL_SYS_WINDOWS) + mh->Control.len = BIO_CMSG_SPACE(sizeof(struct in_pktinfo)); +# else + mh->msg_controllen = BIO_CMSG_SPACE(sizeof(struct in_pktinfo)); +# endif + return 1; + +# elif defined(IP_SENDSRCADDR) + struct in_addr *info; + + /* + * At least FreeBSD is very pedantic about using IP_SENDSRCADDR when we + * are not bound to 0.0.0.0 or ::, even if the address matches what we + * bound to. Support this by not packing the structure if the address + * matches our understanding of our local address. IP_SENDSRCADDR is a + * BSD thing, so we don't need an explicit test for BSD here. + */ + if (local->s_in.sin_addr.s_addr == data->local_addr.s_in.sin_addr.s_addr) { + mh->msg_control = NULL; + mh->msg_controllen = 0; + return 1; + } + + cmsg = (struct cmsghdr *)mh->msg_control; + cmsg->cmsg_len = BIO_CMSG_LEN(sizeof(struct in_addr)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + + info = (struct in_addr *)BIO_CMSG_DATA(cmsg); + *info = local->s_in.sin_addr; + + /* See comment above. */ + if (local->s_in.sin_port != 0 + && data->local_addr.s_in.sin_port != local->s_in.sin_port) { + ERR_raise(ERR_LIB_BIO, BIO_R_PORT_MISMATCH); + return 0; + } + + mh->msg_controllen = BIO_CMSG_SPACE(sizeof(struct in_addr)); + return 1; +# endif + } +# if OPENSSL_USE_IPV6 + else if (af == AF_INET6) { +# if defined(IPV6_PKTINFO) + struct in6_pktinfo *info; + +# if defined(OPENSSL_SYS_WINDOWS) + cmsg = (CMSGHDR_TYPE *)mh->Control.buf; +# else + cmsg = (CMSGHDR_TYPE *)mh->msg_control; +# endif + cmsg->cmsg_len = BIO_CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + + info = (struct in6_pktinfo *)BIO_CMSG_DATA(cmsg); + info->ipi6_addr = local->s_in6.sin6_addr; + info->ipi6_ifindex = 0; + + /* + * See comment above, but also applies to the other fields + * in sockaddr_in6. + */ + if (local->s_in6.sin6_port != 0 + && data->local_addr.s_in6.sin6_port != local->s_in6.sin6_port) { + ERR_raise(ERR_LIB_BIO, BIO_R_PORT_MISMATCH); + return 0; + } + + if (local->s_in6.sin6_scope_id != 0 + && data->local_addr.s_in6.sin6_scope_id != local->s_in6.sin6_scope_id) { + ERR_raise(ERR_LIB_BIO, BIO_R_PORT_MISMATCH); + return 0; + } + +# if defined(OPENSSL_SYS_WINDOWS) + mh->Control.len = BIO_CMSG_SPACE(sizeof(struct in6_pktinfo)); +# else + mh->msg_controllen = BIO_CMSG_SPACE(sizeof(struct in6_pktinfo)); +# endif + return 1; +# endif + } +# endif + + return 0; +} +# endif + +/* + * Converts flags passed to BIO_sendmmsg or BIO_recvmmsg to syscall flags. You + * should mask out any system flags returned by this function you cannot support + * in a particular circumstance. Currently no flags are defined. + */ +# if M_METHOD != M_METHOD_NONE +static int translate_flags(uint64_t flags) { + return 0; +} +# endif + +static int dgram_sendmmsg(BIO *b, BIO_MSG *msg, size_t stride, + size_t num_msg, uint64_t flags, size_t *num_processed) +{ +# if M_METHOD != M_METHOD_NONE && M_METHOD != M_METHOD_RECVMSG + int ret; +# endif +# if M_METHOD == M_METHOD_RECVMMSG +# define BIO_MAX_MSGS_PER_CALL 64 + int sysflags; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + size_t i; + struct mmsghdr mh[BIO_MAX_MSGS_PER_CALL]; + struct iovec iov[BIO_MAX_MSGS_PER_CALL]; + unsigned char control[BIO_MAX_MSGS_PER_CALL][BIO_CMSG_ALLOC_LEN]; + int have_local_enabled = data->local_addr_enabled; +# elif M_METHOD == M_METHOD_RECVMSG + int sysflags; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + ossl_ssize_t l; + struct msghdr mh; + struct iovec iov; + unsigned char control[BIO_CMSG_ALLOC_LEN]; + int have_local_enabled = data->local_addr_enabled; +# elif M_METHOD == M_METHOD_WSARECVMSG + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + int have_local_enabled = data->local_addr_enabled; + WSAMSG wmsg; + WSABUF wbuf; + DWORD num_bytes_sent = 0; + unsigned char control[BIO_CMSG_ALLOC_LEN]; +# endif +# if M_METHOD == M_METHOD_RECVFROM || M_METHOD == M_METHOD_WSARECVMSG + int sysflags; +# endif + + if (num_msg == 0) { + *num_processed = 0; + return 1; + } + + if (num_msg > OSSL_SSIZE_MAX) + num_msg = OSSL_SSIZE_MAX; + +# if M_METHOD != M_METHOD_NONE + sysflags = translate_flags(flags); +# endif + +# if M_METHOD == M_METHOD_RECVMMSG + /* + * In the sendmmsg/recvmmsg case, we need to allocate our translated struct + * msghdr and struct iovec on the stack to support multithreaded use. Thus + * we place a fixed limit on the number of messages per call, in the + * expectation that we will be called again if there were more messages to + * be sent. + */ + if (num_msg > BIO_MAX_MSGS_PER_CALL) + num_msg = BIO_MAX_MSGS_PER_CALL; + + for (i = 0; i < num_msg; ++i) { + translate_msg(b, &mh[i].msg_hdr, &iov[i], + control[i], &BIO_MSG_N(msg, stride, i)); + + /* If local address was requested, it must have been enabled */ + if (BIO_MSG_N(msg, stride, i).local != NULL) { + if (!have_local_enabled) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + if (pack_local(b, &mh[i].msg_hdr, + BIO_MSG_N(msg, stride, i).local) < 1) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + } + } + + /* Do the batch */ + ret = sendmmsg(b->num, mh, num_msg, sysflags); + if (ret < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + for (i = 0; i < (size_t)ret; ++i) { + BIO_MSG_N(msg, stride, i).data_len = mh[i].msg_len; + BIO_MSG_N(msg, stride, i).flags = 0; + } + + *num_processed = (size_t)ret; + return 1; + +# elif M_METHOD == M_METHOD_RECVMSG + /* + * If sendmsg is available, use it. + */ + translate_msg(b, &mh, &iov, control, msg); + + if (msg->local != NULL) { + if (!have_local_enabled) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + if (pack_local(b, &mh, msg->local) < 1) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + } + + l = sendmsg(b->num, &mh, sysflags); + if (l < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + msg->data_len = (size_t)l; + msg->flags = 0; + *num_processed = 1; + return 1; + +# elif M_METHOD == M_METHOD_WSARECVMSG || M_METHOD == M_METHOD_RECVFROM +# if M_METHOD == M_METHOD_WSARECVMSG + if (bio_WSASendMsg != NULL) { + /* WSASendMsg-based implementation for Windows. */ + translate_msg_win(b, &wmsg, &wbuf, control, msg); + + if (msg[0].local != NULL) { + if (!have_local_enabled) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + if (pack_local(b, &wmsg, msg[0].local) < 1) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + } + + ret = WSASendMsg((SOCKET)b->num, &wmsg, 0, &num_bytes_sent, NULL, NULL); + if (ret < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + msg[0].data_len = num_bytes_sent; + msg[0].flags = 0; + *num_processed = 1; + return 1; + } +# endif + + /* + * Fallback to sendto and send a single message. + */ + if (msg[0].local != NULL) { + /* + * We cannot set the local address if using sendto + * so fail in this case + */ + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + ret = sendto(b->num, msg[0].data, +# if defined(OPENSSL_SYS_WINDOWS) + (int)msg[0].data_len, +# else + msg[0].data_len, +# endif + sysflags, + msg[0].peer != NULL ? BIO_ADDR_sockaddr(msg[0].peer) : NULL, + msg[0].peer != NULL ? BIO_ADDR_sockaddr_size(msg[0].peer) : 0); + if (ret <= 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + msg[0].data_len = ret; + msg[0].flags = 0; + *num_processed = 1; + return 1; + +# else + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + *num_processed = 0; + return 0; +# endif +} + +static int dgram_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, + uint64_t flags, size_t *num_processed) +{ +# if M_METHOD != M_METHOD_NONE && M_METHOD != M_METHOD_RECVMSG + int ret; +# endif +# if M_METHOD == M_METHOD_RECVMMSG + int sysflags; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + size_t i; + struct mmsghdr mh[BIO_MAX_MSGS_PER_CALL]; + struct iovec iov[BIO_MAX_MSGS_PER_CALL]; + unsigned char control[BIO_MAX_MSGS_PER_CALL][BIO_CMSG_ALLOC_LEN]; + int have_local_enabled = data->local_addr_enabled; +# elif M_METHOD == M_METHOD_RECVMSG + int sysflags; + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + ossl_ssize_t l; + struct msghdr mh; + struct iovec iov; + unsigned char control[BIO_CMSG_ALLOC_LEN]; + int have_local_enabled = data->local_addr_enabled; +# elif M_METHOD == M_METHOD_WSARECVMSG + bio_dgram_data *data = (bio_dgram_data *)b->ptr; + int have_local_enabled = data->local_addr_enabled; + WSAMSG wmsg; + WSABUF wbuf; + DWORD num_bytes_received = 0; + unsigned char control[BIO_CMSG_ALLOC_LEN]; +# endif +# if M_METHOD == M_METHOD_RECVFROM || M_METHOD == M_METHOD_WSARECVMSG + int sysflags; + socklen_t slen; +# endif + + if (num_msg == 0) { + *num_processed = 0; + return 1; + } + + if (num_msg > OSSL_SSIZE_MAX) + num_msg = OSSL_SSIZE_MAX; + +# if M_METHOD != M_METHOD_NONE + sysflags = translate_flags(flags); +# endif + +# if M_METHOD == M_METHOD_RECVMMSG + /* + * In the sendmmsg/recvmmsg case, we need to allocate our translated struct + * msghdr and struct iovec on the stack to support multithreaded use. Thus + * we place a fixed limit on the number of messages per call, in the + * expectation that we will be called again if there were more messages to + * be sent. + */ + if (num_msg > BIO_MAX_MSGS_PER_CALL) + num_msg = BIO_MAX_MSGS_PER_CALL; + + for (i = 0; i < num_msg; ++i) { + translate_msg(b, &mh[i].msg_hdr, &iov[i], + control[i], &BIO_MSG_N(msg, stride, i)); + + /* If local address was requested, it must have been enabled */ + if (BIO_MSG_N(msg, stride, i).local != NULL && !have_local_enabled) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + } + + /* Do the batch */ + ret = recvmmsg(b->num, mh, num_msg, sysflags, NULL); + if (ret < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + for (i = 0; i < (size_t)ret; ++i) { + BIO_MSG_N(msg, stride, i).data_len = mh[i].msg_len; + BIO_MSG_N(msg, stride, i).flags = 0; + /* + * *(msg->peer) will have been filled in by recvmmsg; + * for msg->local we parse the control data returned + */ + if (BIO_MSG_N(msg, stride, i).local != NULL) + if (extract_local(b, &mh[i].msg_hdr, + BIO_MSG_N(msg, stride, i).local) < 1) + /* + * It appears BSDs do not support local addresses for + * loopback sockets. In this case, just clear the local + * address, as for OS X and Windows in some circumstances + * (see below). + */ + BIO_ADDR_clear(msg->local); + } + + *num_processed = (size_t)ret; + return 1; + +# elif M_METHOD == M_METHOD_RECVMSG + /* + * If recvmsg is available, use it. + */ + translate_msg(b, &mh, &iov, control, msg); + + /* If local address was requested, it must have been enabled */ + if (msg->local != NULL && !have_local_enabled) { + /* + * If we have done at least one message, we must return the + * count; if we haven't done any, we can give an error code + */ + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + l = recvmsg(b->num, &mh, sysflags); + if (l < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + msg->data_len = (size_t)l; + msg->flags = 0; + + if (msg->local != NULL) + if (extract_local(b, &mh, msg->local) < 1) + /* + * OS X exhibits odd behaviour where it appears that if a packet is + * sent before the receiving interface enables IP_PKTINFO, it will + * sometimes not have any control data returned even if the + * receiving interface enables IP_PKTINFO before calling recvmsg(). + * This appears to occur non-deterministically. Presumably, OS X + * handles IP_PKTINFO at the time the packet is enqueued into a + * socket's receive queue, rather than at the time recvmsg() is + * called, unlike most other operating systems. Thus (if this + * hypothesis is correct) there is a race between where IP_PKTINFO + * is enabled by the process and when the kernel's network stack + * queues the incoming message. + * + * We cannot return the local address if we do not have it, but this + * is not a caller error either, so just return a zero address + * structure. This is similar to how we handle Windows loopback + * interfaces (see below). We enable this workaround for all + * platforms, not just Apple, as this kind of quirk in OS networking + * stacks seems to be common enough that failing hard if a local + * address is not provided appears to be too brittle. + */ + BIO_ADDR_clear(msg->local); + + *num_processed = 1; + return 1; + +# elif M_METHOD == M_METHOD_RECVFROM || M_METHOD == M_METHOD_WSARECVMSG +# if M_METHOD == M_METHOD_WSARECVMSG + if (bio_WSARecvMsg != NULL) { + /* WSARecvMsg-based implementation for Windows. */ + translate_msg_win(b, &wmsg, &wbuf, control, msg); + + /* If local address was requested, it must have been enabled */ + if (msg[0].local != NULL && !have_local_enabled) { + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + ret = WSARecvMsg((SOCKET)b->num, &wmsg, &num_bytes_received, NULL, NULL); + if (ret < 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + *num_processed = 0; + return 0; + } + + msg[0].data_len = num_bytes_received; + msg[0].flags = 0; + if (msg[0].local != NULL) + if (extract_local(b, &wmsg, msg[0].local) < 1) + /* + * On Windows, loopback is not a "proper" interface and it works + * differently; packets are essentially short-circuited and + * don't go through all of the normal processing. A consequence + * of this is that packets sent from the local machine to the + * local machine _will not have IP_PKTINFO_ even if the + * IP_PKTINFO socket option is enabled. WSARecvMsg just sets + * Control.len to 0 on returning. + * + * This applies regardless of whether the loopback address, + * 127.0.0.1 is used, or a local interface address (e.g. + * 192.168.1.1); in both cases IP_PKTINFO will not be present. + * + * We report this condition by setting the local BIO_ADDR's + * family to 0. + */ + BIO_ADDR_clear(msg[0].local); + + *num_processed = 1; + return 1; + } +# endif + + /* + * Fallback to recvfrom and receive a single message. + */ + if (msg[0].local != NULL) { + /* + * We cannot determine the local address if using recvfrom + * so fail in this case + */ + ERR_raise(ERR_LIB_BIO, BIO_R_LOCAL_ADDR_NOT_AVAILABLE); + *num_processed = 0; + return 0; + } + + slen = sizeof(*msg[0].peer); + ret = recvfrom(b->num, msg[0].data, +# if defined(OPENSSL_SYS_WINDOWS) + (int)msg[0].data_len, +# else + msg[0].data_len, +# endif + sysflags, + msg[0].peer != NULL ? &msg[0].peer->sa : NULL, + msg[0].peer != NULL ? &slen : NULL); + if (ret <= 0) { + ERR_raise(ERR_LIB_SYS, get_last_socket_error()); + return 0; + } + + msg[0].data_len = ret; + msg[0].flags = 0; + *num_processed = 1; + return 1; + +# else + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + *num_processed = 0; + return 0; +# endif +} + # ifndef OPENSSL_NO_SCTP const BIO_METHOD *BIO_s_datagram_sctp(void) { @@ -938,10 +1903,8 @@ static int dgram_sctp_new(BIO *bi) bi->init = 0; bi->num = 0; - if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) return 0; - } # ifdef SCTP_PR_SCTP_NONE data->prinfo.pr_policy = SCTP_PR_SCTP_NONE; # endif @@ -1163,7 +2126,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) if (ret < 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_read(b); - data->_errno = get_last_socket_error(); + data->dgram._errno = get_last_socket_error(); } } @@ -1176,10 +2139,8 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) optlen = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(optlen); - if (authchunks == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if (authchunks == NULL) return -1; - } memset(authchunks, 0, optlen); ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen); @@ -1317,7 +2278,7 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) if (ret <= 0) { if (BIO_dgram_should_retry(ret)) { BIO_set_retry_write(b); - data->_errno = get_last_socket_error(); + data->dgram._errno = get_last_socket_error(); } } return ret; @@ -1339,16 +2300,16 @@ static long dgram_sctp_ctrl(BIO *b, int cmd, long num, void *ptr) * Set to maximum (2^14) and ignore user input to enable transport * protocol fragmentation. Returns always 2^14. */ - data->mtu = 16384; - ret = data->mtu; + data->dgram.mtu = 16384; + ret = data->dgram.mtu; break; case BIO_CTRL_DGRAM_SET_MTU: /* * Set to maximum (2^14) and ignore input to enable transport * protocol fragmentation. Returns always 2^14. */ - data->mtu = 16384; - ret = data->mtu; + data->dgram.mtu = 16384; + ret = data->dgram.mtu; break; case BIO_CTRL_DGRAM_SET_CONNECTED: case BIO_CTRL_DGRAM_CONNECT: @@ -1896,27 +2857,4 @@ int BIO_dgram_non_fatal_error(int err) return 0; } -static void get_current_time(struct timeval *t) -{ -# if defined(_WIN32) - SYSTEMTIME st; - unsigned __int64 now_ul; - FILETIME now_ft; - - GetSystemTime(&st); - SystemTimeToFileTime(&st, &now_ft); - now_ul = ((unsigned __int64)now_ft.dwHighDateTime << 32) | now_ft.dwLowDateTime; -# ifdef __MINGW32__ - now_ul -= 116444736000000000ULL; -# else - now_ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */ -# endif - t->tv_sec = (long)(now_ul / 10000000); - t->tv_usec = ((int)(now_ul % 10000000)) / 10; -# else - if (gettimeofday(t, NULL) < 0) - perror("gettimeofday"); -# endif -} - #endif diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c index f756225edb21..41514589a5dd 100644 --- a/crypto/bio/bss_fd.c +++ b/crypto/bio/bss_fd.c @@ -149,7 +149,7 @@ static long fd_ctrl(BIO *b, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_RESET: num = 0; - /* fall thru */ + /* fall through */ case BIO_C_FILE_SEEK: ret = (long)UP_lseek(b->num, num, 0); break; diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c index a6143b6abcf6..2743a14417cf 100644 --- a/crypto/bio/bss_file.c +++ b/crypto/bio/bss_file.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ /* * Following definition aliases fopen to fopen64 on above mentioned * platforms. This makes it possible to open and sequentially access files - * larger than 2GB from 32-bit application. It does not allow to traverse + * larger than 2GB from 32-bit application. It does not allow one to traverse * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit * platform permits that, not with fseek/ftell. Not to mention that breaking * 2GB limit for seeking would require surgery to *our* API. But sequential @@ -235,15 +235,6 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) _setmode(fd, _O_TEXT); else _setmode(fd, _O_BINARY); - /* - * Reports show that ftell() isn't trustable in text mode. - * This has been confirmed as a bug in the Universal C RTL, see - * https://developercommunity.visualstudio.com/content/problem/425878/fseek-ftell-fail-in-text-mode-for-unix-style-text.html - * The suggested work-around from Microsoft engineering is to - * turn off buffering until the bug is resolved. - */ - if ((num & BIO_FP_TEXT) != 0) - setvbuf((FILE *)ptr, NULL, _IONBF, 0); # elif defined(OPENSSL_SYS_MSDOS) int fd = fileno((FILE *)ptr); /* Set correct text/binary mode */ diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c index 63b30e300fec..f587cab2f833 100644 --- a/crypto/bio/bss_log.c +++ b/crypto/bio/bss_log.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -24,6 +24,8 @@ #if defined(OPENSSL_SYS_WINCE) #elif defined(OPENSSL_SYS_WIN32) +#elif defined(__wasi__) +# define NO_SYSLOG #elif defined(OPENSSL_SYS_VMS) # include # include @@ -197,10 +199,8 @@ static int slg_write(BIO *b, const char *in, int inl) if (inl < 0) return 0; - if ((buf = OPENSSL_malloc(inl + 1)) == NULL) { - ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(inl + 1)) == NULL) return 0; - } memcpy(buf, in, inl); buf[inl] = '\0'; diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c index 9153c1f1cd81..8cbea38a9021 100644 --- a/crypto/bio/bss_mem.c +++ b/crypto/bio/bss_mem.c @@ -1,5 +1,5 @@ /* - * 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 @@ -76,7 +76,7 @@ const BIO_METHOD *BIO_s_mem(void) const BIO_METHOD *BIO_s_secmem(void) { - return(&secmem_method); + return &secmem_method; } BIO *BIO_new_mem_buf(const void *buf, int len) diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c index f5d88102303a..82f7be85ae0c 100644 --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -1,5 +1,5 @@ /* - * 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 @@ -10,6 +10,7 @@ #include #include #include "bio_local.h" +#include "internal/bio_tfo.h" #include "internal/cryptlib.h" #include "internal/ktls.h" @@ -27,6 +28,14 @@ # define sock_puts SockPuts # endif +struct bss_sock_st { + BIO_ADDR tfo_peer; + int tfo_first; +#ifndef OPENSSL_NO_KTLS + unsigned char ktls_record_type; +#endif +}; + static int sock_write(BIO *h, const char *buf, int num); static int sock_read(BIO *h, char *buf, int size); static int sock_puts(BIO *h, const char *str); @@ -81,8 +90,10 @@ static int sock_new(BIO *bi) { bi->init = 0; bi->num = 0; - bi->ptr = NULL; bi->flags = 0; + bi->ptr = OPENSSL_zalloc(sizeof(struct bss_sock_st)); + if (bi->ptr == NULL) + return 0; return 1; } @@ -97,6 +108,8 @@ static int sock_free(BIO *a) a->init = 0; a->flags = 0; } + OPENSSL_free(a->ptr); + a->ptr = NULL; return 1; } @@ -126,17 +139,30 @@ static int sock_read(BIO *b, char *out, int outl) static int sock_write(BIO *b, const char *in, int inl) { int ret = 0; +# if !defined(OPENSSL_NO_KTLS) || defined(OSSL_TFO_SENDTO) + struct bss_sock_st *data = (struct bss_sock_st *)b->ptr; +# endif clear_socket_error(); # ifndef OPENSSL_NO_KTLS if (BIO_should_ktls_ctrl_msg_flag(b)) { - unsigned char record_type = (intptr_t)b->ptr; + unsigned char record_type = data->ktls_record_type; ret = ktls_send_ctrl_message(b->num, record_type, in, inl); if (ret >= 0) { ret = inl; BIO_clear_ktls_ctrl_msg_flag(b); } } else +# endif +# if defined(OSSL_TFO_SENDTO) + if (data->tfo_first) { + struct bss_sock_st *data = (struct bss_sock_st *)b->ptr; + socklen_t peerlen = BIO_ADDR_sockaddr_size(&data->tfo_peer); + + ret = sendto(b->num, in, inl, OSSL_TFO_SENDTO, + BIO_ADDR_sockaddr(&data->tfo_peer), peerlen); + data->tfo_first = 0; + } else # endif ret = writesocket(b->num, in, inl); BIO_clear_retry_flags(b); @@ -151,16 +177,24 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret = 1; int *ip; + struct bss_sock_st *data = (struct bss_sock_st *)b->ptr; # ifndef OPENSSL_NO_KTLS ktls_crypto_info_t *crypto_info; # endif switch (cmd) { case BIO_C_SET_FD: - sock_free(b); + /* minimal sock_free() */ + if (b->shutdown) { + if (b->init) + BIO_closesocket(b->num); + b->flags = 0; + } b->num = *((int *)ptr); b->shutdown = (int)num; b->init = 1; + data->tfo_first = 0; + memset(&data->tfo_peer, 0, sizeof(data->tfo_peer)); break; case BIO_C_GET_FD: if (b->init) { @@ -181,6 +215,20 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = 1; break; + case BIO_CTRL_GET_RPOLL_DESCRIPTOR: + case BIO_CTRL_GET_WPOLL_DESCRIPTOR: + { + BIO_POLL_DESCRIPTOR *pd = ptr; + + if (!b->init) { + ret = 0; + break; + } + + pd->type = BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD; + pd->value.fd = b->num; + } + break; # ifndef OPENSSL_NO_KTLS case BIO_CTRL_SET_KTLS: crypto_info = (ktls_crypto_info_t *)ptr; @@ -194,17 +242,41 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) return BIO_should_ktls_flag(b, 0) != 0; case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG: BIO_set_ktls_ctrl_msg_flag(b); - b->ptr = (void *)num; + data->ktls_record_type = (unsigned char)num; ret = 0; break; case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG: BIO_clear_ktls_ctrl_msg_flag(b); ret = 0; break; + case BIO_CTRL_SET_KTLS_TX_ZEROCOPY_SENDFILE: + ret = ktls_enable_tx_zerocopy_sendfile(b->num); + if (ret) + BIO_set_ktls_zerocopy_sendfile_flag(b); + break; # endif case BIO_CTRL_EOF: ret = (b->flags & BIO_FLAGS_IN_EOF) != 0; break; + case BIO_C_GET_CONNECT: + if (ptr != NULL && num == 2) { + const char **pptr = (const char **)ptr; + + *pptr = (const char *)&data->tfo_peer; + } else { + ret = 0; + } + break; + case BIO_C_SET_CONNECT: + if (ptr != NULL && num == 2) { + ret = BIO_ADDR_make(&data->tfo_peer, + BIO_ADDR_sockaddr((const BIO_ADDR *)ptr)); + if (ret) + data->tfo_first = 1; + } else { + ret = 0; + } + break; default: ret = 0; break; diff --git a/crypto/bio/build.info b/crypto/bio/build.info index b203ed5e63fe..2102038c74d9 100644 --- a/crypto/bio/build.info +++ b/crypto/bio/build.info @@ -11,7 +11,7 @@ SOURCE[../../libcrypto]=\ SOURCE[../../libcrypto]=\ bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \ bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \ - bss_log.c bss_core.c + bss_log.c bss_core.c bss_dgram_pair.c # Filters SOURCE[../../libcrypto]=\ diff --git a/crypto/bio/ossl_core_bio.c b/crypto/bio/ossl_core_bio.c index 328302ea34e6..8d21115b652d 100644 --- a/crypto/bio/ossl_core_bio.c +++ b/crypto/bio/ossl_core_bio.c @@ -1,5 +1,5 @@ /* - * Copyright 2021 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 @@ -17,7 +17,6 @@ */ struct ossl_core_bio_st { CRYPTO_REF_COUNT ref_cnt; - CRYPTO_RWLOCK *ref_lock; BIO *bio; }; @@ -25,11 +24,10 @@ static OSSL_CORE_BIO *core_bio_new(void) { OSSL_CORE_BIO *cb = OPENSSL_malloc(sizeof(*cb)); - if (cb == NULL || (cb->ref_lock = CRYPTO_THREAD_lock_new()) == NULL) { + if (cb == NULL || !CRYPTO_NEW_REF(&cb->ref_cnt, 1)) { OPENSSL_free(cb); return NULL; } - cb->ref_cnt = 1; return cb; } @@ -37,7 +35,7 @@ int ossl_core_bio_up_ref(OSSL_CORE_BIO *cb) { int ref = 0; - return CRYPTO_UP_REF(&cb->ref_cnt, &ref, cb->ref_lock); + return CRYPTO_UP_REF(&cb->ref_cnt, &ref); } int ossl_core_bio_free(OSSL_CORE_BIO *cb) @@ -45,10 +43,10 @@ int ossl_core_bio_free(OSSL_CORE_BIO *cb) int ref = 0, res = 1; if (cb != NULL) { - CRYPTO_DOWN_REF(&cb->ref_cnt, &ref, cb->ref_lock); + CRYPTO_DOWN_REF(&cb->ref_cnt, &ref); if (ref <= 0) { res = BIO_free(cb->bio); - CRYPTO_THREAD_lock_free(cb->ref_lock); + CRYPTO_FREE_REF(&cb->ref_cnt); OPENSSL_free(cb); } } diff --git a/crypto/bn/README.pod b/crypto/bn/README.pod deleted file mode 100644 index 1286fc0d4132..000000000000 --- a/crypto/bn/README.pod +++ /dev/null @@ -1,241 +0,0 @@ -=pod - -=head1 NAME - -bn_mul_words, bn_mul_add_words, bn_sqr_words, bn_div_words, -bn_add_words, bn_sub_words, bn_mul_comba4, bn_mul_comba8, -bn_sqr_comba4, bn_sqr_comba8, bn_cmp_words, bn_mul_normal, -bn_mul_low_normal, bn_mul_recursive, bn_mul_part_recursive, -bn_mul_low_recursive, bn_sqr_normal, bn_sqr_recursive, -bn_expand, bn_wexpand, bn_expand2, bn_fix_top, bn_check_top, -bn_print, bn_dump, bn_set_max, bn_set_high, bn_set_low - BIGNUM -library internal functions - -=head1 SYNOPSIS - - #include - - BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w); - BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, - BN_ULONG w); - void bn_sqr_words(BN_ULONG *rp, 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, BN_ULONG *ap, BN_ULONG *bp, - int num); - BN_ULONG bn_sub_words(BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp, - int num); - - void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); - void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b); - void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a); - void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a); - - int bn_cmp_words(BN_ULONG *a, BN_ULONG *b, int n); - - void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, - int nb); - void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n); - void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2, - int dna, int dnb, BN_ULONG *tmp); - void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, - int n, int tna, int tnb, BN_ULONG *tmp); - void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, - int n2, BN_ULONG *tmp); - - void bn_sqr_normal(BN_ULONG *r, BN_ULONG *a, int n, BN_ULONG *tmp); - void bn_sqr_recursive(BN_ULONG *r, BN_ULONG *a, int n2, BN_ULONG *tmp); - - void mul(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c); - void mul_add(BN_ULONG r, BN_ULONG a, BN_ULONG w, BN_ULONG c); - void sqr(BN_ULONG r0, BN_ULONG r1, BN_ULONG a); - - BIGNUM *bn_expand(BIGNUM *a, int bits); - BIGNUM *bn_wexpand(BIGNUM *a, int n); - BIGNUM *bn_expand2(BIGNUM *a, int n); - void bn_fix_top(BIGNUM *a); - - void bn_check_top(BIGNUM *a); - void bn_print(BIGNUM *a); - void bn_dump(BN_ULONG *d, int n); - void bn_set_max(BIGNUM *a); - void bn_set_high(BIGNUM *r, BIGNUM *a, int n); - void bn_set_low(BIGNUM *r, BIGNUM *a, int n); - -=head1 DESCRIPTION - -This page documents the internal functions used by the OpenSSL -B implementation. They are described here to facilitate -debugging and extending the library. They are I to be used by -applications. - -=head2 The BIGNUM structure - - typedef struct bignum_st BIGNUM; - - 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; - }; - - -The integer value is stored in B, a malloc()ed array of words (B), -least significant word first. A B can be either 16, 32 or 64 bits -in size, depending on the 'number of bits' (B) specified in -C. - -B is the size of the B array that has been allocated. B -is the number of words being used, so for a value of 4, bn.d[0]=4 and -bn.top=1. B is 1 if the number is negative. When a B is -B<0>, the B field can be B and B == B<0>. - -B is a bit field of flags which are defined in C. The -flags begin with B. The macros BN_set_flags(b, n) and -BN_get_flags(b, n) exist to enable or fetch flag(s) B from B -structure B. - -Various routines in this library require the use of temporary -B variables during their execution. Since dynamic memory -allocation to create Bs is rather expensive when used in -conjunction with repeated subroutine calls, the B structure is -used. This structure contains B Bs, see -L. - -=head2 Low-level arithmetic operations - -These functions are implemented in C and for several platforms in -assembly language: - -bn_mul_words(B, B, B, B) operates on the B word -arrays B and B. It computes B * B, places the result -in B, and returns the high word (carry). - -bn_mul_add_words(B, B, B, B) operates on the B -word arrays B and B. It computes B * B + B, places -the result in B, and returns the high word (carry). - -bn_sqr_words(B, B, B) operates on the B word array -B and the 2*B word array B. It computes B * B -word-wise, and places the low and high bytes of the result in B. - -bn_div_words(B, B, B) divides the two word number (B, B) -by B and returns the result. - -bn_add_words(B, B, B, B) operates on the B word -arrays B, B and B. It computes B + B, places the -result in B, and returns the high word (carry). - -bn_sub_words(B, B, B, B) operates on the B word -arrays B, B and B. It computes B - B, places the -result in B, and returns the carry (1 if B E B, 0 -otherwise). - -bn_mul_comba4(B, B, B) operates on the 4 word arrays B and -B and the 8 word array B. It computes B*B and places the -result in B. - -bn_mul_comba8(B, B, B) operates on the 8 word arrays B and -B and the 16 word array B. It computes B*B and places the -result in B. - -bn_sqr_comba4(B, B, B) operates on the 4 word arrays B and -B and the 8 word array B. - -bn_sqr_comba8(B, B, B) operates on the 8 word arrays B and -B and the 16 word array B. - -The following functions are implemented in C: - -bn_cmp_words(B, B, B) operates on the B word arrays B -and B. It returns 1, 0 and -1 if B is greater than, equal and -less than B. - -bn_mul_normal(B, B, B, B, B) operates on the B -word array B, the B word array B and the B+B word -array B. It computes B*B and places the result in B. - -bn_mul_low_normal(B, B, B, B) operates on the B word -arrays B, B and B. It computes the B low words of -B*B and places the result in B. - -bn_mul_recursive(B, B, B, B, B, B, B) operates -on the word arrays B and B of length B+B and B+B -(B and B are currently allowed to be 0 or negative) and the 2*B -word arrays B and B. B must be a power of 2. It computes -B*B and places the result in B. - -bn_mul_part_recursive(B, B, B, B, B, B, B) -operates on the word arrays B and B of length B+B and -B+B and the 4*B word arrays B and B. - -bn_mul_low_recursive(B, B, B, B, B) operates on the -B word arrays B and B and the B/2 word arrays B -and B. - -BN_mul() calls bn_mul_normal(), or an optimized implementation if the -factors have the same size: bn_mul_comba8() is used if they are 8 -words long, bn_mul_recursive() if they are larger than -B and the size is an exact multiple of the word -size, and bn_mul_part_recursive() for others that are larger than -B. - -bn_sqr_normal(B, B, B, B) operates on the B word array -B and the 2*B word arrays B and B. - -The implementations use the following macros which, depending on the -architecture, may use "long long" C operations or inline assembler. -They are defined in C. - -mul(B, B, B, B) computes B*B+B and places the -low word of the result in B and the high word in B. - -mul_add(B, B, B, B) computes B*B+B+B and -places the low word of the result in B and the high word in B. - -sqr(B, B, B) computes B*B and places the low word -of the result in B and the high word in B. - -=head2 Size changes - -bn_expand() ensures that B has enough space for a B bit -number. bn_wexpand() ensures that B has enough space for an -B word number. If the number has to be expanded, both macros -call bn_expand2(), which allocates a new B array and copies the -data. They return B on error, B otherwise. - -The bn_fix_top() macro reduces Btop> to point to the most -significant non-zero word plus one when B has shrunk. - -=head2 Debugging - -bn_check_top() verifies that C<((a)-Etop E= 0 && (a)-Etop -E= (a)-Edmax)>. A violation will cause the program to abort. - -bn_print() prints B to stderr. bn_dump() prints B words at B -(in reverse order, i.e. most significant word first) to stderr. - -bn_set_max() makes B a static number with a B of its current size. -This is used by bn_set_low() and bn_set_high() to make B a read-only -B that contains the B low or high words of B. - -If B is not defined, bn_check_top(), bn_print(), bn_dump() -and bn_set_max() are defined as empty macros. - -=head1 SEE ALSO - -L - -=head1 COPYRIGHT - -Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not 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. - -=cut diff --git a/crypto/bn/asm/armv4-gf2m.pl b/crypto/bn/asm/armv4-gf2m.pl index d380c89f1f2b..5733a0174660 100644 --- a/crypto/bn/asm/armv4-gf2m.pl +++ b/crypto/bn/asm/armv4-gf2m.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2020 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 @@ -325,7 +325,8 @@ $code.=<<___; .align 5 #if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/bn/asm/armv4-mont.pl b/crypto/bn/asm/armv4-mont.pl index c26df751a5eb..6e839d845ca8 100644 --- a/crypto/bn/asm/armv4-mont.pl +++ b/crypto/bn/asm/armv4-mont.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# 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 @@ -749,7 +749,8 @@ $code.=<<___; .asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by " .align 2 #if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/bn/asm/armv8-mont.pl b/crypto/bn/asm/armv8-mont.pl index 3192eab3092a..83129d6a2d6c 100755 --- a/crypto/bn/asm/armv8-mont.pl +++ b/crypto/bn/asm/armv8-mont.pl @@ -67,8 +67,8 @@ $n0="x4"; # const BN_ULONG *n0, $num="x5"; # int num); $code.=<<___; +#include "arm_arch.h" #ifndef __KERNEL__ -# include "arm_arch.h" .extern OPENSSL_armv8_rsa_neonized .hidden OPENSSL_armv8_rsa_neonized #endif @@ -78,6 +78,7 @@ $code.=<<___; .type bn_mul_mont,%function .align 5 bn_mul_mont: + AARCH64_SIGN_LINK_REGISTER .Lbn_mul_mont: tst $num,#3 b.ne .Lmul_mont @@ -290,6 +291,7 @@ bn_mul_mont: mov x0,#1 ldp x23,x24,[x29,#48] ldr x29,[sp],#64 + AARCH64_VALIDATE_LINK_REGISTER ret .size bn_mul_mont,.-bn_mul_mont ___ @@ -311,6 +313,8 @@ $code.=<<___; .type bn_mul8x_mont_neon,%function .align 5 bn_mul8x_mont_neon: + // Not adding AARCH64_SIGN_LINK_REGISTER here because bn_mul8x_mont_neon is jumped to + // only from bn_mul_mont which has already signed the return address. stp x29,x30,[sp,#-80]! mov x16,sp stp d8,d9,[sp,#16] @@ -651,6 +655,7 @@ $code.=<<___; ldp d10,d11,[sp,#32] ldp d8,d9,[sp,#16] ldr x29,[sp],#80 + AARCH64_VALIDATE_LINK_REGISTER ret // bx lr .size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon @@ -673,7 +678,8 @@ __bn_sqr8x_mont: cmp $ap,$bp b.ne __bn_mul4x_mont .Lsqr8x_mont: - .inst 0xd503233f // paciasp + // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_sqr8x_mont is jumped to + // only from bn_mul_mont which has already signed the return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -1427,7 +1433,8 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldr x29,[sp],#128 - .inst 0xd50323bf // autiasp + // x30 is loaded earlier + AARCH64_VALIDATE_LINK_REGISTER ret .size __bn_sqr8x_mont,.-__bn_sqr8x_mont ___ @@ -1451,7 +1458,8 @@ $code.=<<___; .type __bn_mul4x_mont,%function .align 5 __bn_mul4x_mont: - .inst 0xd503233f // paciasp + // Not adding AARCH64_SIGN_LINK_REGISTER here because __bn_mul4x_mont is jumped to + // only from bn_mul_mont (or __bn_sqr8x_mont from bn_mul_mont) which has already signed the return address. stp x29,x30,[sp,#-128]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -1885,12 +1893,14 @@ __bn_mul4x_mont: ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldr x29,[sp],#128 - .inst 0xd50323bf // autiasp + // x30 loaded earlier + AARCH64_VALIDATE_LINK_REGISTER ret .size __bn_mul4x_mont,.-__bn_mul4x_mont ___ } $code.=<<___; +.rodata .asciz "Montgomery Multiplication for ARMv8, CRYPTOGAMS by " .align 4 ___ diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl index bc18826d08f8..44a6f10d4dbd 100644 --- a/crypto/bn/asm/mips.pl +++ b/crypto/bn/asm/mips.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -802,7 +802,7 @@ $code.=<<___; #if 0 /* - * The bn_div_3_words entry point is re-used for constant-time interface. + * The bn_div_3_words entry point is reused for constant-time interface. * Implementation is retained as historical reference. */ .align 5 diff --git a/crypto/bn/asm/ppc64-mont-fixed.pl b/crypto/bn/asm/ppc64-mont-fixed.pl index e69de29bb2d1..e27d0ad93d85 100755 --- a/crypto/bn/asm/ppc64-mont-fixed.pl +++ b/crypto/bn/asm/ppc64-mont-fixed.pl @@ -0,0 +1,583 @@ +#! /usr/bin/env perl +# Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +# ==================================================================== +# Written by Amitay Isaacs , Martin Schwenke +# & Alastair D'Silva for +# the OpenSSL project. +# ==================================================================== + +# +# Fixed length (n=6), unrolled PPC Montgomery Multiplication +# + +# 2021 +# +# Although this is a generic implementation for unrolling Montgomery +# Multiplication for arbitrary values of n, this is currently only +# used for n = 6 to improve the performance of ECC p384. +# +# Unrolling allows intermediate results to be stored in registers, +# rather than on the stack, improving performance by ~7% compared to +# the existing PPC assembly code. +# +# The ISA 3.0 implementation uses combination multiply/add +# instructions (maddld, maddhdu) to improve performance by an +# additional ~10% on Power 9. +# +# Finally, saving non-volatile registers into volatile vector +# registers instead of onto the stack saves a little more. +# +# On a Power 9 machine we see an overall improvement of ~18%. +# + +use strict; +use warnings; + +my ($flavour, $output, $dir, $xlate); + +# $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}ppc-xlate.pl" and -f $xlate ) or +( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or +die "can't locate ppc-xlate.pl"; + +open STDOUT,"| $^X $xlate $flavour \"$output\"" + or die "can't call $xlate: $!"; + +if ($flavour !~ /64/) { + die "bad flavour ($flavour) - only ppc64 permitted"; +} + +my $SIZE_T= 8; + +# Registers are global so the code is remotely readable + +# Parameters for Montgomery multiplication +my $ze = "r0"; +my $sp = "r1"; +my $toc = "r2"; +my $rp = "r3"; +my $ap = "r4"; +my $bp = "r5"; +my $np = "r6"; +my $n0 = "r7"; +my $num = "r8"; + +my $i = "r9"; +my $c0 = "r10"; +my $bp0 = "r11"; +my $bpi = "r11"; +my $bpj = "r11"; +my $tj = "r12"; +my $apj = "r12"; +my $npj = "r12"; +my $lo = "r14"; +my $c1 = "r14"; + +# Non-volatile registers used for tp[i] +# +# 12 registers are available but the limit on unrolling is 10, +# since registers from $tp[0] to $tp[$n+1] are used. +my @tp = ("r20" .. "r31"); + +# volatile VSRs for saving non-volatile GPRs - faster than stack +my @vsrs = ("v32" .. "v46"); + +package Mont; + +sub new($$) +{ + my ($class, $n) = @_; + + if ($n > 10) { + die "Can't unroll for BN length ${n} (maximum 10)" + } + + my $self = { + code => "", + n => $n, + }; + bless $self, $class; + + return $self; +} + +sub add_code($$) +{ + my ($self, $c) = @_; + + $self->{code} .= $c; +} + +sub get_code($) +{ + my ($self) = @_; + + return $self->{code}; +} + +sub get_function_name($) +{ + my ($self) = @_; + + return "bn_mul_mont_fixed_n" . $self->{n}; +} + +sub get_label($$) +{ + my ($self, $l) = @_; + + return "L" . $l . "_" . $self->{n}; +} + +sub get_labels($@) +{ + my ($self, @labels) = @_; + + my %out = (); + + foreach my $l (@labels) { + $out{"$l"} = $self->get_label("$l"); + } + + return \%out; +} + +sub nl($) +{ + my ($self) = @_; + + $self->add_code("\n"); +} + +sub copy_result($) +{ + my ($self) = @_; + + my ($n) = $self->{n}; + + for (my $j = 0; $j < $n; $j++) { + $self->add_code(<<___); + std $tp[$j],`$j*$SIZE_T`($rp) +___ + } + +} + +sub mul_mont_fixed($) +{ + my ($self) = @_; + + my ($n) = $self->{n}; + my $fname = $self->get_function_name(); + my $label = $self->get_labels("outer", "enter", "sub", "copy", "end"); + + $self->add_code(<<___); + +.globl .${fname} +.align 5 +.${fname}: + +___ + + $self->save_registers(); + + $self->add_code(<<___); + li $ze,0 + ld $n0,0($n0) + + ld $bp0,0($bp) + + ld $apj,0($ap) +___ + + $self->mul_c_0($tp[0], $apj, $bp0, $c0); + + for (my $j = 1; $j < $n - 1; $j++) { + $self->add_code(<<___); + ld $apj,`$j*$SIZE_T`($ap) +___ + $self->mul($tp[$j], $apj, $bp0, $c0); + } + + $self->add_code(<<___); + ld $apj,`($n-1)*$SIZE_T`($ap) +___ + + $self->mul_last($tp[$n-1], $tp[$n], $apj, $bp0, $c0); + + $self->add_code(<<___); + li $tp[$n+1],0 + +___ + + $self->add_code(<<___); + li $i,0 + mtctr $num + b $label->{"enter"} + +.align 4 +$label->{"outer"}: + ldx $bpi,$bp,$i + + ld $apj,0($ap) +___ + + $self->mul_add_c_0($tp[0], $tp[0], $apj, $bpi, $c0); + + for (my $j = 1; $j < $n; $j++) { + $self->add_code(<<___); + ld $apj,`$j*$SIZE_T`($ap) +___ + $self->mul_add($tp[$j], $tp[$j], $apj, $bpi, $c0); + } + + $self->add_code(<<___); + addc $tp[$n],$tp[$n],$c0 + addze $tp[$n+1],$ze +___ + + $self->add_code(<<___); +.align 4 +$label->{"enter"}: + mulld $bpi,$tp[0],$n0 + + ld $npj,0($np) +___ + + $self->mul_add_c_0($lo, $tp[0], $bpi, $npj, $c0); + + for (my $j = 1; $j < $n; $j++) { + $self->add_code(<<___); + ld $npj,`$j*$SIZE_T`($np) +___ + $self->mul_add($tp[$j-1], $tp[$j], $npj, $bpi, $c0); + } + + $self->add_code(<<___); + addc $tp[$n-1],$tp[$n],$c0 + addze $tp[$n],$tp[$n+1] + + addi $i,$i,$SIZE_T + bdnz $label->{"outer"} + + and. $tp[$n],$tp[$n],$tp[$n] + bne $label->{"sub"} + + cmpld $tp[$n-1],$npj + blt $label->{"copy"} + +$label->{"sub"}: +___ + + # + # Reduction + # + + $self->add_code(<<___); + ld $bpj,`0*$SIZE_T`($np) + subfc $c1,$bpj,$tp[0] + std $c1,`0*$SIZE_T`($rp) + +___ + for (my $j = 1; $j < $n - 1; $j++) { + $self->add_code(<<___); + ld $bpj,`$j*$SIZE_T`($np) + subfe $c1,$bpj,$tp[$j] + std $c1,`$j*$SIZE_T`($rp) + +___ + } + + $self->add_code(<<___); + subfe $c1,$npj,$tp[$n-1] + std $c1,`($n-1)*$SIZE_T`($rp) + +___ + + $self->add_code(<<___); + addme. $tp[$n],$tp[$n] + beq $label->{"end"} + +$label->{"copy"}: +___ + + $self->copy_result(); + + $self->add_code(<<___); + +$label->{"end"}: +___ + + $self->restore_registers(); + + $self->add_code(<<___); + li r3,1 + blr +.size .${fname},.-.${fname} +___ + +} + +package Mont::GPR; + +our @ISA = ('Mont'); + +sub new($$) +{ + my ($class, $n) = @_; + + return $class->SUPER::new($n); +} + +sub save_registers($) +{ + my ($self) = @_; + + my $n = $self->{n}; + + $self->add_code(<<___); + std $lo,-8($sp) +___ + + for (my $j = 0; $j <= $n+1; $j++) { + $self->{code}.=<<___; + std $tp[$j],-`($j+2)*8`($sp) +___ + } + + $self->add_code(<<___); + +___ +} + +sub restore_registers($) +{ + my ($self) = @_; + + my $n = $self->{n}; + + $self->add_code(<<___); + ld $lo,-8($sp) +___ + + for (my $j = 0; $j <= $n+1; $j++) { + $self->{code}.=<<___; + ld $tp[$j],-`($j+2)*8`($sp) +___ + } + + $self->{code} .=<<___; + +___ +} + +# Direct translation of C mul() +sub mul($$$$$) +{ + my ($self, $r, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $lo,$a,$w + addc $r,$lo,$c + mulhdu $c,$a,$w + addze $c,$c + +___ +} + +# Like mul() but $c is ignored as an input - an optimisation to save a +# preliminary instruction that would set input $c to 0 +sub mul_c_0($$$$$) +{ + my ($self, $r, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $r,$a,$w + mulhdu $c,$a,$w + +___ +} + +# Like mul() but does not to the final addition of CA into $c - an +# optimisation to save an instruction +sub mul_last($$$$$$) +{ + my ($self, $r1, $r2, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $lo,$a,$w + addc $r1,$lo,$c + mulhdu $c,$a,$w + + addze $r2,$c +___ +} + +# Like C mul_add() but allow $r_out and $r_in to be different +sub mul_add($$$$$$) +{ + my ($self, $r_out, $r_in, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $lo,$a,$w + addc $lo,$lo,$c + mulhdu $c,$a,$w + addze $c,$c + addc $r_out,$r_in,$lo + addze $c,$c + +___ +} + +# Like mul_add() but $c is ignored as an input - an optimisation to save a +# preliminary instruction that would set input $c to 0 +sub mul_add_c_0($$$$$$) +{ + my ($self, $r_out, $r_in, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $lo,$a,$w + addc $r_out,$r_in,$lo + mulhdu $c,$a,$w + addze $c,$c + +___ +} + +package Mont::GPR_300; + +our @ISA = ('Mont::GPR'); + +sub new($$) +{ + my ($class, $n) = @_; + + my $mont = $class->SUPER::new($n); + + return $mont; +} + +sub get_function_name($) +{ + my ($self) = @_; + + return "bn_mul_mont_300_fixed_n" . $self->{n}; +} + +sub get_label($$) +{ + my ($self, $l) = @_; + + return "L" . $l . "_300_" . $self->{n}; +} + +# Direct translation of C mul() +sub mul($$$$$) +{ + my ($self, $r, $a, $w, $c, $last) = @_; + + $self->add_code(<<___); + maddld $r,$a,$w,$c + maddhdu $c,$a,$w,$c + +___ +} + +# Save the last carry as the final entry +sub mul_last($$$$$) +{ + my ($self, $r1, $r2, $a, $w, $c) = @_; + + $self->add_code(<<___); + maddld $r1,$a,$w,$c + maddhdu $r2,$a,$w,$c + +___ +} + +# Like mul() but $c is ignored as an input - an optimisation to save a +# preliminary instruction that would set input $c to 0 +sub mul_c_0($$$$$) +{ + my ($self, $r, $a, $w, $c) = @_; + + $self->add_code(<<___); + mulld $r,$a,$w + mulhdu $c,$a,$w + +___ +} + +# Like C mul_add() but allow $r_out and $r_in to be different +sub mul_add($$$$$$) +{ + my ($self, $r_out, $r_in, $a, $w, $c) = @_; + + $self->add_code(<<___); + maddld $lo,$a,$w,$c + maddhdu $c,$a,$w,$c + addc $r_out,$r_in,$lo + addze $c,$c + +___ +} + +# Like mul_add() but $c is ignored as an input - an optimisation to save a +# preliminary instruction that would set input $c to 0 +sub mul_add_c_0($$$$$$) +{ + my ($self, $r_out, $r_in, $a, $w, $c) = @_; + + $self->add_code(<<___); + maddld $lo,$a,$w,$r_in + maddhdu $c,$a,$w,$r_in +___ + + if ($r_out ne $lo) { + $self->add_code(<<___); + mr $r_out,$lo +___ + } + + $self->nl(); +} + + +package main; + +my $code; + +$code.=<<___; +.machine "any" +.text +___ + +my $mont; + +$mont = new Mont::GPR(6); +$mont->mul_mont_fixed(); +$code .= $mont->get_code(); + +$mont = new Mont::GPR_300(6); +$mont->mul_mont_fixed(); +$code .= $mont->get_code(); + +$code =~ s/\`([^\`]*)\`/eval $1/gem; + +$code.=<<___; +.asciz "Montgomery Multiplication for PPC by , " +___ + +print $code; +close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/bn/asm/rsaz-avx2.pl b/crypto/bn/asm/rsaz-avx2.pl index 3d0e342a6b8c..59b9c89b5be2 100755 --- a/crypto/bn/asm/rsaz-avx2.pl +++ b/crypto/bn/asm/rsaz-avx2.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use @@ -1779,6 +1779,7 @@ $code.=<<___; ret .size rsaz_avx2_eligible,.-rsaz_avx2_eligible +.section .rodata align=64 .align 64 .Land_mask: .quad 0x1fffffff,0x1fffffff,0x1fffffff,0x1fffffff @@ -1790,6 +1791,7 @@ $code.=<<___; .long 0,0,0,0, 1,1,1,1 .long 2,2,2,2, 3,3,3,3 .long 4,4,4,4, 4,4,4,4 +.previous .align 64 ___ diff --git a/crypto/bn/asm/rsaz-avx512.pl b/crypto/bn/asm/rsaz-avx512.pl deleted file mode 100644 index 8d1d19f6c728..000000000000 --- a/crypto/bn/asm/rsaz-avx512.pl +++ /dev/null @@ -1,754 +0,0 @@ -# Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. -# Copyright (c) 2020, Intel Corporation. All Rights Reserved. -# -# Licensed under the Apache License 2.0 (the "License"). You may not use -# this file except in compliance with the License. You can obtain a copy -# in the file LICENSE in the source distribution or at -# https://www.openssl.org/source/license.html -# -# -# Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov -# Intel Corporation -# -# December 2020 -# -# Initial release. -# -# Implementation utilizes 256-bit (ymm) registers to avoid frequency scaling issues. -# -# IceLake-Client @ 1.3GHz -# |---------+----------------------+--------------+-------------| -# | | OpenSSL 3.0.0-alpha9 | this | Unit | -# |---------+----------------------+--------------+-------------| -# | rsa2048 | 2 127 659 | 1 015 625 | cycles/sign | -# | | 611 | 1280 / +109% | sign/s | -# |---------+----------------------+--------------+-------------| -# - -# $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; - -$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); -$avx512ifma=0; - -$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; -( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or -( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or -die "can't locate x86_64-xlate.pl"; - -if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1` - =~ /GNU assembler version ([2-9]\.[0-9]+)/) { - $avx512ifma = ($1>=2.26); -} - -if (!$avx512 && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) && - `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) { - $avx512ifma = ($1==2.11 && $2>=8) + ($1>=2.12); -} - -if (!$avx512 && `$ENV{CC} -v 2>&1` - =~ /(Apple)?\s*((?:clang|LLVM) version|.*based on LLVM) ([0-9]+)\.([0-9]+)\.([0-9]+)?/) { - my $ver = $3 + $4/100.0 + $5/10000.0; # 3.1.0->3.01, 3.10.1->3.1001 - if ($1) { - # Apple conditions, they use a different version series, see - # https://en.wikipedia.org/wiki/Xcode#Xcode_7.0_-_10.x_(since_Free_On-Device_Development)_2 - # clang 7.0.0 is Apple clang 10.0.1 - $avx512ifma = ($ver>=10.0001) - } else { - $avx512ifma = ($3>=7.0); - } -} - -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" - or die "can't call $xlate: $!"; -*STDOUT=*OUT; - -if ($avx512ifma>0) {{{ -@_6_args_universal_ABI = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9"); - -$code.=<<___; -.extern OPENSSL_ia32cap_P -.globl ossl_rsaz_avx512ifma_eligible -.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent -.align 32 -ossl_rsaz_avx512ifma_eligible: - mov OPENSSL_ia32cap_P+8(%rip), %ecx - xor %eax,%eax - and \$`1<<31|1<<21|1<<17|1<<16`, %ecx # avx512vl + avx512ifma + avx512dq + avx512f - cmp \$`1<<31|1<<21|1<<17|1<<16`, %ecx - cmove %ecx,%eax - ret -.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible -___ - -############################################################################### -# Almost Montgomery Multiplication (AMM) for 20-digit number in radix 2^52. -# -# AMM is defined as presented in the paper -# "Efficient Software Implementations of Modular Exponentiation" by Shay Gueron. -# -# The input and output are presented in 2^52 radix domain, i.e. -# |res|, |a|, |b|, |m| are arrays of 20 64-bit qwords with 12 high bits zeroed. -# |k0| is a Montgomery coefficient, which is here k0 = -1/m mod 2^64 -# (note, the implementation counts only 52 bits from it). -# -# NB: the AMM implementation does not perform "conditional" subtraction step as -# specified in the original algorithm as according to the paper "Enhanced Montgomery -# Multiplication" by Shay Gueron (see Lemma 1), the result will be always < 2*2^1024 -# and can be used as a direct input to the next AMM iteration. -# This post-condition is true, provided the correct parameter |s| is choosen, i.e. -# s >= n + 2 * k, which matches our case: 1040 > 1024 + 2 * 1. -# -# void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, -# const BN_ULONG *a, -# const BN_ULONG *b, -# const BN_ULONG *m, -# BN_ULONG k0); -############################################################################### -{ -# input parameters ("%rdi","%rsi","%rdx","%rcx","%r8") -my ($res,$a,$b,$m,$k0) = @_6_args_universal_ABI; - -my $mask52 = "%rax"; -my $acc0_0 = "%r9"; -my $acc0_0_low = "%r9d"; -my $acc0_1 = "%r15"; -my $acc0_1_low = "%r15d"; -my $b_ptr = "%r11"; - -my $iter = "%ebx"; - -my $zero = "%ymm0"; -my ($R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0) = ("%ymm1", map("%ymm$_",(16..19))); -my ($R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1) = ("%ymm2", map("%ymm$_",(20..23))); -my $Bi = "%ymm3"; -my $Yi = "%ymm4"; - -# Registers mapping for normalization. -# We can reuse Bi, Yi registers here. -my $TMP = $Bi; -my $mask52x4 = $Yi; -my ($T0,$T0h,$T1,$T1h,$T2) = map("%ymm$_", (24..28)); - -sub amm52x20_x1() { -# _data_offset - offset in the |a| or |m| arrays pointing to the beginning -# of data for corresponding AMM operation; -# _b_offset - offset in the |b| array pointing to the next qword digit; -my ($_data_offset,$_b_offset,$_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2,$_k0) = @_; -my $_R0_xmm = $_R0; -$_R0_xmm =~ s/%y/%x/; -$code.=<<___; - movq $_b_offset($b_ptr), %r13 # b[i] - - vpbroadcastq %r13, $Bi # broadcast b[i] - movq $_data_offset($a), %rdx - mulx %r13, %r13, %r12 # a[0]*b[i] = (t0,t2) - addq %r13, $_acc # acc += t0 - movq %r12, %r10 - adcq \$0, %r10 # t2 += CF - - movq $_k0, %r13 - imulq $_acc, %r13 # acc * k0 - andq $mask52, %r13 # yi = (acc * k0) & mask52 - - vpbroadcastq %r13, $Yi # broadcast y[i] - movq $_data_offset($m), %rdx - mulx %r13, %r13, %r12 # yi * m[0] = (t0,t1) - addq %r13, $_acc # acc += t0 - adcq %r12, %r10 # t2 += (t1 + CF) - - shrq \$52, $_acc - salq \$12, %r10 - or %r10, $_acc # acc = ((acc >> 52) | (t2 << 12)) - - vpmadd52luq `$_data_offset+64*0`($a), $Bi, $_R0 - vpmadd52luq `$_data_offset+64*0+32`($a), $Bi, $_R0h - vpmadd52luq `$_data_offset+64*1`($a), $Bi, $_R1 - vpmadd52luq `$_data_offset+64*1+32`($a), $Bi, $_R1h - vpmadd52luq `$_data_offset+64*2`($a), $Bi, $_R2 - - vpmadd52luq `$_data_offset+64*0`($m), $Yi, $_R0 - vpmadd52luq `$_data_offset+64*0+32`($m), $Yi, $_R0h - vpmadd52luq `$_data_offset+64*1`($m), $Yi, $_R1 - vpmadd52luq `$_data_offset+64*1+32`($m), $Yi, $_R1h - vpmadd52luq `$_data_offset+64*2`($m), $Yi, $_R2 - - # Shift accumulators right by 1 qword, zero extending the highest one - valignq \$1, $_R0, $_R0h, $_R0 - valignq \$1, $_R0h, $_R1, $_R0h - valignq \$1, $_R1, $_R1h, $_R1 - valignq \$1, $_R1h, $_R2, $_R1h - valignq \$1, $_R2, $zero, $_R2 - - vmovq $_R0_xmm, %r13 - addq %r13, $_acc # acc += R0[0] - - vpmadd52huq `$_data_offset+64*0`($a), $Bi, $_R0 - vpmadd52huq `$_data_offset+64*0+32`($a), $Bi, $_R0h - vpmadd52huq `$_data_offset+64*1`($a), $Bi, $_R1 - vpmadd52huq `$_data_offset+64*1+32`($a), $Bi, $_R1h - vpmadd52huq `$_data_offset+64*2`($a), $Bi, $_R2 - - vpmadd52huq `$_data_offset+64*0`($m), $Yi, $_R0 - vpmadd52huq `$_data_offset+64*0+32`($m), $Yi, $_R0h - vpmadd52huq `$_data_offset+64*1`($m), $Yi, $_R1 - vpmadd52huq `$_data_offset+64*1+32`($m), $Yi, $_R1h - vpmadd52huq `$_data_offset+64*2`($m), $Yi, $_R2 -___ -} - -# Normalization routine: handles carry bits in R0..R2 QWs and -# gets R0..R2 back to normalized 2^52 representation. -# -# Uses %r8-14,%e[bcd]x -sub amm52x20_x1_norm { -my ($_acc,$_R0,$_R0h,$_R1,$_R1h,$_R2) = @_; -$code.=<<___; - # Put accumulator to low qword in R0 - vpbroadcastq $_acc, $TMP - vpblendd \$3, $TMP, $_R0, $_R0 - - # Extract "carries" (12 high bits) from each QW of R0..R2 - # Save them to LSB of QWs in T0..T2 - vpsrlq \$52, $_R0, $T0 - vpsrlq \$52, $_R0h, $T0h - vpsrlq \$52, $_R1, $T1 - vpsrlq \$52, $_R1h, $T1h - vpsrlq \$52, $_R2, $T2 - - # "Shift left" T0..T2 by 1 QW - valignq \$3, $T1h, $T2, $T2 - valignq \$3, $T1, $T1h, $T1h - valignq \$3, $T0h, $T1, $T1 - valignq \$3, $T0, $T0h, $T0h - valignq \$3, $zero, $T0, $T0 - - # Drop "carries" from R0..R2 QWs - vpandq $mask52x4, $_R0, $_R0 - vpandq $mask52x4, $_R0h, $_R0h - vpandq $mask52x4, $_R1, $_R1 - vpandq $mask52x4, $_R1h, $_R1h - vpandq $mask52x4, $_R2, $_R2 - - # Sum R0..R2 with corresponding adjusted carries - vpaddq $T0, $_R0, $_R0 - vpaddq $T0h, $_R0h, $_R0h - vpaddq $T1, $_R1, $_R1 - vpaddq $T1h, $_R1h, $_R1h - vpaddq $T2, $_R2, $_R2 - - # Now handle carry bits from this addition - # Get mask of QWs which 52-bit parts overflow... - vpcmpuq \$1, $_R0, $mask52x4, %k1 # OP=lt - vpcmpuq \$1, $_R0h, $mask52x4, %k2 - vpcmpuq \$1, $_R1, $mask52x4, %k3 - vpcmpuq \$1, $_R1h, $mask52x4, %k4 - vpcmpuq \$1, $_R2, $mask52x4, %k5 - kmovb %k1, %r14d # k1 - kmovb %k2, %r13d # k1h - kmovb %k3, %r12d # k2 - kmovb %k4, %r11d # k2h - kmovb %k5, %r10d # k3 - - # ...or saturated - vpcmpuq \$0, $_R0, $mask52x4, %k1 # OP=eq - vpcmpuq \$0, $_R0h, $mask52x4, %k2 - vpcmpuq \$0, $_R1, $mask52x4, %k3 - vpcmpuq \$0, $_R1h, $mask52x4, %k4 - vpcmpuq \$0, $_R2, $mask52x4, %k5 - kmovb %k1, %r9d # k4 - kmovb %k2, %r8d # k4h - kmovb %k3, %ebx # k5 - kmovb %k4, %ecx # k5h - kmovb %k5, %edx # k6 - - # Get mask of QWs where carries shall be propagated to. - # Merge 4-bit masks to 8-bit values to use add with carry. - shl \$4, %r13b - or %r13b, %r14b - shl \$4, %r11b - or %r11b, %r12b - - add %r14b, %r14b - adc %r12b, %r12b - adc %r10b, %r10b - - shl \$4, %r8b - or %r8b,%r9b - shl \$4, %cl - or %cl, %bl - - add %r9b, %r14b - adc %bl, %r12b - adc %dl, %r10b - - xor %r9b, %r14b - xor %bl, %r12b - xor %dl, %r10b - - kmovb %r14d, %k1 - shr \$4, %r14b - kmovb %r14d, %k2 - kmovb %r12d, %k3 - shr \$4, %r12b - kmovb %r12d, %k4 - kmovb %r10d, %k5 - - # Add carries according to the obtained mask - vpsubq $mask52x4, $_R0, ${_R0}{%k1} - vpsubq $mask52x4, $_R0h, ${_R0h}{%k2} - vpsubq $mask52x4, $_R1, ${_R1}{%k3} - vpsubq $mask52x4, $_R1h, ${_R1h}{%k4} - vpsubq $mask52x4, $_R2, ${_R2}{%k5} - - vpandq $mask52x4, $_R0, $_R0 - vpandq $mask52x4, $_R0h, $_R0h - vpandq $mask52x4, $_R1, $_R1 - vpandq $mask52x4, $_R1h, $_R1h - vpandq $mask52x4, $_R2, $_R2 -___ -} - -$code.=<<___; -.text - -.globl ossl_rsaz_amm52x20_x1_256 -.type ossl_rsaz_amm52x20_x1_256,\@function,5 -.align 32 -ossl_rsaz_amm52x20_x1_256: -.cfi_startproc - endbranch - push %rbx -.cfi_push %rbx - push %rbp -.cfi_push %rbp - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -.Lrsaz_amm52x20_x1_256_body: - - # Zeroing accumulators - vpxord $zero, $zero, $zero - vmovdqa64 $zero, $R0_0 - vmovdqa64 $zero, $R0_0h - vmovdqa64 $zero, $R1_0 - vmovdqa64 $zero, $R1_0h - vmovdqa64 $zero, $R2_0 - - xorl $acc0_0_low, $acc0_0_low - - movq $b, $b_ptr # backup address of b - movq \$0xfffffffffffff, $mask52 # 52-bit mask - - # Loop over 20 digits unrolled by 4 - mov \$5, $iter - -.align 32 -.Lloop5: -___ - foreach my $idx (0..3) { - &amm52x20_x1(0,8*$idx,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,$k0); - } -$code.=<<___; - lea `4*8`($b_ptr), $b_ptr - dec $iter - jne .Lloop5 - - vmovdqa64 .Lmask52x4(%rip), $mask52x4 -___ - &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0); -$code.=<<___; - - vmovdqu64 $R0_0, ($res) - vmovdqu64 $R0_0h, 32($res) - vmovdqu64 $R1_0, 64($res) - vmovdqu64 $R1_0h, 96($res) - vmovdqu64 $R2_0, 128($res) - - vzeroupper - mov 0(%rsp),%r15 -.cfi_restore %r15 - mov 8(%rsp),%r14 -.cfi_restore %r14 - mov 16(%rsp),%r13 -.cfi_restore %r13 - mov 24(%rsp),%r12 -.cfi_restore %r12 - mov 32(%rsp),%rbp -.cfi_restore %rbp - mov 40(%rsp),%rbx -.cfi_restore %rbx - lea 48(%rsp),%rsp -.cfi_adjust_cfa_offset -48 -.Lrsaz_amm52x20_x1_256_epilogue: - ret -.cfi_endproc -.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256 -___ - -$code.=<<___; -.data -.align 32 -.Lmask52x4: - .quad 0xfffffffffffff - .quad 0xfffffffffffff - .quad 0xfffffffffffff - .quad 0xfffffffffffff -___ - -############################################################################### -# Dual Almost Montgomery Multiplication for 20-digit number in radix 2^52 -# -# See description of ossl_rsaz_amm52x20_x1_256() above for details about Almost -# Montgomery Multiplication algorithm and function input parameters description. -# -# This function does two AMMs for two independent inputs, hence dual. -# -# void ossl_rsaz_amm52x20_x2_256(BN_ULONG out[2][20], -# const BN_ULONG a[2][20], -# const BN_ULONG b[2][20], -# const BN_ULONG m[2][20], -# const BN_ULONG k0[2]); -############################################################################### - -$code.=<<___; -.text - -.globl ossl_rsaz_amm52x20_x2_256 -.type ossl_rsaz_amm52x20_x2_256,\@function,5 -.align 32 -ossl_rsaz_amm52x20_x2_256: -.cfi_startproc - endbranch - push %rbx -.cfi_push %rbx - push %rbp -.cfi_push %rbp - push %r12 -.cfi_push %r12 - push %r13 -.cfi_push %r13 - push %r14 -.cfi_push %r14 - push %r15 -.cfi_push %r15 -.Lrsaz_amm52x20_x2_256_body: - - # Zeroing accumulators - vpxord $zero, $zero, $zero - vmovdqa64 $zero, $R0_0 - vmovdqa64 $zero, $R0_0h - vmovdqa64 $zero, $R1_0 - vmovdqa64 $zero, $R1_0h - vmovdqa64 $zero, $R2_0 - vmovdqa64 $zero, $R0_1 - vmovdqa64 $zero, $R0_1h - vmovdqa64 $zero, $R1_1 - vmovdqa64 $zero, $R1_1h - vmovdqa64 $zero, $R2_1 - - xorl $acc0_0_low, $acc0_0_low - xorl $acc0_1_low, $acc0_1_low - - movq $b, $b_ptr # backup address of b - movq \$0xfffffffffffff, $mask52 # 52-bit mask - - mov \$20, $iter - -.align 32 -.Lloop20: -___ - &amm52x20_x1( 0, 0,$acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0,"($k0)"); - # 20*8 = offset of the next dimension in two-dimension array - &amm52x20_x1(20*8,20*8,$acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1,"8($k0)"); -$code.=<<___; - lea 8($b_ptr), $b_ptr - dec $iter - jne .Lloop20 - - vmovdqa64 .Lmask52x4(%rip), $mask52x4 -___ - &amm52x20_x1_norm($acc0_0,$R0_0,$R0_0h,$R1_0,$R1_0h,$R2_0); - &amm52x20_x1_norm($acc0_1,$R0_1,$R0_1h,$R1_1,$R1_1h,$R2_1); -$code.=<<___; - - vmovdqu64 $R0_0, ($res) - vmovdqu64 $R0_0h, 32($res) - vmovdqu64 $R1_0, 64($res) - vmovdqu64 $R1_0h, 96($res) - vmovdqu64 $R2_0, 128($res) - - vmovdqu64 $R0_1, 160($res) - vmovdqu64 $R0_1h, 192($res) - vmovdqu64 $R1_1, 224($res) - vmovdqu64 $R1_1h, 256($res) - vmovdqu64 $R2_1, 288($res) - - vzeroupper - mov 0(%rsp),%r15 -.cfi_restore %r15 - mov 8(%rsp),%r14 -.cfi_restore %r14 - mov 16(%rsp),%r13 -.cfi_restore %r13 - mov 24(%rsp),%r12 -.cfi_restore %r12 - mov 32(%rsp),%rbp -.cfi_restore %rbp - mov 40(%rsp),%rbx -.cfi_restore %rbx - lea 48(%rsp),%rsp -.cfi_adjust_cfa_offset -48 -.Lrsaz_amm52x20_x2_256_epilogue: - ret -.cfi_endproc -.size ossl_rsaz_amm52x20_x2_256, .-ossl_rsaz_amm52x20_x2_256 -___ -} - -############################################################################### -# Constant time extraction from the precomputed table of powers base^i, where -# i = 0..2^EXP_WIN_SIZE-1 -# -# The input |red_table| contains precomputations for two independent base values, -# so the |tbl_idx| indicates for which base shall we extract the value. -# |red_table_idx| is a power index. -# -# Extracted value (output) is 20 digit number in 2^52 radix. -# -# void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y, -# const BN_ULONG red_table[1 << EXP_WIN_SIZE][2][20], -# int red_table_idx, -# int tbl_idx); # 0 or 1 -# -# EXP_WIN_SIZE = 5 -############################################################################### -{ -# input parameters -my ($out,$red_tbl,$red_tbl_idx,$tbl_idx) = @_6_args_universal_ABI; - -my ($t0,$t1,$t2,$t3,$t4) = map("%ymm$_", (0..4)); -my $t4xmm = $t4; -$t4xmm =~ s/%y/%x/; -my ($tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = map("%ymm$_", (16..20)); -my ($cur_idx,$idx,$ones) = map("%ymm$_", (21..23)); - -$code.=<<___; -.text - -.align 32 -.globl ossl_extract_multiplier_2x20_win5 -.type ossl_extract_multiplier_2x20_win5,\@function,4 -ossl_extract_multiplier_2x20_win5: -.cfi_startproc - endbranch - leaq ($tbl_idx,$tbl_idx,4), %rax - salq \$5, %rax - addq %rax, $red_tbl - - vmovdqa64 .Lones(%rip), $ones # broadcast ones - vpbroadcastq $red_tbl_idx, $idx - leaq `(1<<5)*2*20*8`($red_tbl), %rax # holds end of the tbl - - vpxor $t4xmm, $t4xmm, $t4xmm - vmovdqa64 $t4, $t3 # zeroing t0..4, cur_idx - vmovdqa64 $t4, $t2 - vmovdqa64 $t4, $t1 - vmovdqa64 $t4, $t0 - vmovdqa64 $t4, $cur_idx - -.align 32 -.Lloop: - vpcmpq \$0, $cur_idx, $idx, %k1 # mask of (idx == cur_idx) - addq \$320, $red_tbl # 320 = 2 * 20 digits * 8 bytes - vpaddq $ones, $cur_idx, $cur_idx # increment cur_idx - vmovdqu64 -320($red_tbl), $tmp0 # load data from red_tbl - vmovdqu64 -288($red_tbl), $tmp1 - vmovdqu64 -256($red_tbl), $tmp2 - vmovdqu64 -224($red_tbl), $tmp3 - vmovdqu64 -192($red_tbl), $tmp4 - vpblendmq $tmp0, $t0, ${t0}{%k1} # extract data when mask is not zero - vpblendmq $tmp1, $t1, ${t1}{%k1} - vpblendmq $tmp2, $t2, ${t2}{%k1} - vpblendmq $tmp3, $t3, ${t3}{%k1} - vpblendmq $tmp4, $t4, ${t4}{%k1} - cmpq $red_tbl, %rax - jne .Lloop - - vmovdqu64 $t0, ($out) # store t0..4 - vmovdqu64 $t1, 32($out) - vmovdqu64 $t2, 64($out) - vmovdqu64 $t3, 96($out) - vmovdqu64 $t4, 128($out) - - ret -.cfi_endproc -.size ossl_extract_multiplier_2x20_win5, .-ossl_extract_multiplier_2x20_win5 -___ -$code.=<<___; -.data -.align 32 -.Lones: - .quad 1,1,1,1 -___ -} - -if ($win64) { -$rec="%rcx"; -$frame="%rdx"; -$context="%r8"; -$disp="%r9"; - -$code.=<<___ -.extern __imp_RtlVirtualUnwind -.type rsaz_def_handler,\@abi-omnipotent -.align 16 -rsaz_def_handler: - push %rsi - push %rdi - push %rbx - push %rbp - push %r12 - push %r13 - push %r14 - push %r15 - pushfq - sub \$64,%rsp - - mov 120($context),%rax # pull context->Rax - mov 248($context),%rbx # pull context->Rip - - mov 8($disp),%rsi # disp->ImageBase - mov 56($disp),%r11 # disp->HandlerData - - mov 0(%r11),%r10d # HandlerData[0] - lea (%rsi,%r10),%r10 # prologue label - cmp %r10,%rbx # context->Rip<.Lprologue - jb .Lcommon_seh_tail - - mov 152($context),%rax # pull context->Rsp - - mov 4(%r11),%r10d # HandlerData[1] - lea (%rsi,%r10),%r10 # epilogue label - cmp %r10,%rbx # context->Rip>=.Lepilogue - jae .Lcommon_seh_tail - - lea 48(%rax),%rax - - mov -8(%rax),%rbx - mov -16(%rax),%rbp - mov -24(%rax),%r12 - mov -32(%rax),%r13 - mov -40(%rax),%r14 - mov -48(%rax),%r15 - mov %rbx,144($context) # restore context->Rbx - mov %rbp,160($context) # restore context->Rbp - mov %r12,216($context) # restore context->R12 - mov %r13,224($context) # restore context->R13 - mov %r14,232($context) # restore context->R14 - mov %r15,240($context) # restore context->R14 - -.Lcommon_seh_tail: - mov 8(%rax),%rdi - mov 16(%rax),%rsi - mov %rax,152($context) # restore context->Rsp - mov %rsi,168($context) # restore context->Rsi - mov %rdi,176($context) # restore context->Rdi - - mov 40($disp),%rdi # disp->ContextRecord - mov $context,%rsi # context - mov \$154,%ecx # sizeof(CONTEXT) - .long 0xa548f3fc # cld; rep movsq - - mov $disp,%rsi - xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER - mov 8(%rsi),%rdx # arg2, disp->ImageBase - mov 0(%rsi),%r8 # arg3, disp->ControlPc - mov 16(%rsi),%r9 # arg4, disp->FunctionEntry - mov 40(%rsi),%r10 # disp->ContextRecord - lea 56(%rsi),%r11 # &disp->HandlerData - lea 24(%rsi),%r12 # &disp->EstablisherFrame - mov %r10,32(%rsp) # arg5 - mov %r11,40(%rsp) # arg6 - mov %r12,48(%rsp) # arg7 - mov %rcx,56(%rsp) # arg8, (NULL) - call *__imp_RtlVirtualUnwind(%rip) - - mov \$1,%eax # ExceptionContinueSearch - add \$64,%rsp - popfq - pop %r15 - pop %r14 - pop %r13 - pop %r12 - pop %rbp - pop %rbx - pop %rdi - pop %rsi - ret -.size rsaz_def_handler,.-rsaz_def_handler - -.section .pdata -.align 4 - .rva .LSEH_begin_ossl_rsaz_amm52x20_x1_256 - .rva .LSEH_end_ossl_rsaz_amm52x20_x1_256 - .rva .LSEH_info_ossl_rsaz_amm52x20_x1_256 - - .rva .LSEH_begin_ossl_rsaz_amm52x20_x2_256 - .rva .LSEH_end_ossl_rsaz_amm52x20_x2_256 - .rva .LSEH_info_ossl_rsaz_amm52x20_x2_256 - - .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5 - .rva .LSEH_end_ossl_extract_multiplier_2x20_win5 - .rva .LSEH_info_ossl_extract_multiplier_2x20_win5 - -.section .xdata -.align 8 -.LSEH_info_ossl_rsaz_amm52x20_x1_256: - .byte 9,0,0,0 - .rva rsaz_def_handler - .rva .Lrsaz_amm52x20_x1_256_body,.Lrsaz_amm52x20_x1_256_epilogue -.LSEH_info_ossl_rsaz_amm52x20_x2_256: - .byte 9,0,0,0 - .rva rsaz_def_handler - .rva .Lrsaz_amm52x20_x2_256_body,.Lrsaz_amm52x20_x2_256_epilogue -.LSEH_info_ossl_extract_multiplier_2x20_win5: - .byte 9,0,0,0 - .rva rsaz_def_handler - .rva .LSEH_begin_ossl_extract_multiplier_2x20_win5,.LSEH_begin_ossl_extract_multiplier_2x20_win5 -___ -} -}}} else {{{ # fallback for old assembler -$code.=<<___; -.text - -.globl ossl_rsaz_avx512ifma_eligible -.type ossl_rsaz_avx512ifma_eligible,\@abi-omnipotent -ossl_rsaz_avx512ifma_eligible: - xor %eax,%eax - ret -.size ossl_rsaz_avx512ifma_eligible, .-ossl_rsaz_avx512ifma_eligible - -.globl ossl_rsaz_amm52x20_x1_256 -.globl ossl_rsaz_amm52x20_x2_256 -.globl ossl_extract_multiplier_2x20_win5 -.type ossl_rsaz_amm52x20_x1_256,\@abi-omnipotent -ossl_rsaz_amm52x20_x1_256: -ossl_rsaz_amm52x20_x2_256: -ossl_extract_multiplier_2x20_win5: - .byte 0x0f,0x0b # ud2 - ret -.size ossl_rsaz_amm52x20_x1_256, .-ossl_rsaz_amm52x20_x1_256 -___ -}}} - -$code =~ s/\`([^\`]*)\`/eval $1/gem; -print $code; -close STDOUT or die "error closing STDOUT: $!"; diff --git a/crypto/bn/asm/rsaz-x86_64.pl b/crypto/bn/asm/rsaz-x86_64.pl index 5c7d526fa37a..36bf229477aa 100755 --- a/crypto/bn/asm/rsaz-x86_64.pl +++ b/crypto/bn/asm/rsaz-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2012, Intel Corporation. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use @@ -2248,10 +2248,12 @@ $code.=<<___; .cfi_endproc .size rsaz_512_gather4,.-rsaz_512_gather4 +.section .rodata align=64 .align 64 .Linc: .long 0,0, 1,1 .long 2,2, 2,2 +.previous ___ } diff --git a/crypto/bn/asm/sparcv8.S b/crypto/bn/asm/sparcv8.S index 94487008443e..e5402cc4e26f 100644 --- a/crypto/bn/asm/sparcv8.S +++ b/crypto/bn/asm/sparcv8.S @@ -381,7 +381,7 @@ bn_add_words: inc 16,%o1 addxcc %g3,%g4,%g3 st %g3,[%o0+4] - + ld [%o1-4],%g3 ld [%o2+12],%g4 inc 16,%o2 @@ -469,7 +469,7 @@ bn_sub_words: inc 16,%o1 subxcc %g3,%g4,%g4 st %g4,[%o0+4] - + ld [%o1-4],%g3 ld [%o2+12],%g4 inc 16,%o2 @@ -1040,7 +1040,7 @@ bn_mul_comba4: addxcc c_2,t_2,c_2 != st c_1,rp(6) !r[6]=c1; st c_2,rp(7) !r[7]=c2; - + ret restore %g0,%g0,%o0 @@ -1448,7 +1448,7 @@ bn_sqr_comba4: addxcc c_2,t_2,c_2 != st c_1,rp(6) !r[6]=c1; st c_2,rp(7) !r[7]=c2; - + ret restore %g0,%g0,%o0 diff --git a/crypto/bn/asm/sparcv8plus.S b/crypto/bn/asm/sparcv8plus.S index 696dc7b5fe09..8a936f1c72e4 100644 --- a/crypto/bn/asm/sparcv8plus.S +++ b/crypto/bn/asm/sparcv8plus.S @@ -496,7 +496,7 @@ bn_add_words: inc 16,%o1 addccc %g1,%g2,%g1 stuw %g1,[%o0+4] - + inc 16,%o2 addccc %g3,%g4,%g3 stuw %g3,[%o0+8] @@ -1126,7 +1126,7 @@ bn_mul_comba4: srlx t_1,32,c_12 != stuw t_1,rp(6) !r[6]=c1; stuw c_12,rp(7) !r[7]=c2; - + ret restore %g0,%g0,%o0 @@ -1548,7 +1548,7 @@ bn_sqr_comba4: srlx t_1,32,c_12 stuw t_1,rp(6) !r[6]=c1; stuw c_12,rp(7) !r[7]=c2; - + ret restore %g0,%g0,%o0 diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl index 185d9e76ce23..07dd40d9228c 100755 --- a/crypto/bn/asm/x86_64-mont5.pl +++ b/crypto/bn/asm/x86_64-mont5.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -3577,11 +3577,13 @@ $code.=<<___; ___ } $code.=<<___; +.section .rodata align=64 .align 64 .Linc: .long 0,0, 1,1 .long 2,2, 2,2 .asciz "Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by " +.previous ___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c index 4ffe443066cc..c39907a7dfd3 100644 --- a/crypto/bn/bn_asm.c +++ b/crypto/bn/bn_asm.c @@ -432,11 +432,6 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, #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) */ @@ -960,8 +955,6 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, #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]; diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index 7e5a1c52e27d..6c6de1a30f54 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -33,14 +33,12 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) bn_check_top(mod); - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_CRYPTO_LIB); OPENSSL_free(ret); return NULL; } diff --git a/crypto/bn/bn_const.c b/crypto/bn/bn_const.c index a36e0ac792dd..190a36391206 100644 --- a/crypto/bn/bn_const.c +++ b/crypto/bn/bn_const.c @@ -19,7 +19,7 @@ * The prime is: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } * * RFC2409 specifies a generator of 2. - * RFC2412 specifies a generator of of 22. + * RFC2412 specifies a generator of 22. */ BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) diff --git a/crypto/bn/bn_conv.c b/crypto/bn/bn_conv.c index 75054f5d6a6c..57dda04b0d78 100644 --- a/crypto/bn/bn_conv.c +++ b/crypto/bn/bn_conv.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,8 +11,6 @@ #include "crypto/ctype.h" #include "bn_local.h" -static const char Hex[] = "0123456789ABCDEF"; - /* Must 'OPENSSL_free' the returned data */ char *BN_bn2hex(const BIGNUM *a) { @@ -23,10 +21,8 @@ char *BN_bn2hex(const BIGNUM *a) if (BN_is_zero(a)) return OPENSSL_strdup("0"); buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); - if (buf == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (buf == NULL) goto err; - } p = buf; if (a->neg) *p++ = '-'; @@ -35,8 +31,7 @@ char *BN_bn2hex(const BIGNUM *a) /* strip leading zeros */ v = (int)((a->d[i] >> j) & 0xff); if (z || v != 0) { - *p++ = Hex[v >> 4]; - *p++ = Hex[v & 0x0f]; + p += ossl_to_hex(p, v); z = 1; } } @@ -70,10 +65,8 @@ char *BN_bn2dec(const BIGNUM *a) bn_data_num = num / BN_DEC_NUM + 1; bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); buf = OPENSSL_malloc(tbytes); - if (buf == NULL || bn_data == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (buf == NULL || bn_data == NULL) goto err; - } if ((t = BN_dup(a)) == NULL) goto err; diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c index 35a7ddbab737..aa70ca7a3fd9 100644 --- a/crypto/bn/bn_ctx.c +++ b/crypto/bn/bn_ctx.c @@ -119,10 +119,8 @@ BN_CTX *BN_CTX_new_ex(OSSL_LIB_CTX *ctx) { BN_CTX *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } /* Initialise the structure */ BN_POOL_init(&ret->pool); BN_STACK_init(&ret->stack); @@ -268,10 +266,8 @@ static int BN_STACK_push(BN_STACK *st, unsigned int idx) st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES; unsigned int *newitems; - if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) return 0; - } if (st->depth) memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth); OPENSSL_free(st->indexes); @@ -322,10 +318,8 @@ static BIGNUM *BN_POOL_get(BN_POOL *p, int flag) if (p->used == p->size) { BN_POOL_ITEM *item; - if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) return NULL; - } for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) { bn_init(bn); if ((flag & BN_FLG_SECURE) != 0) diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c index 0e563ad823c7..1dda2e017f1b 100644 --- a/crypto/bn/bn_exp.c +++ b/crypto/bn/bn_exp.c @@ -169,7 +169,7 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { - int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int i, j, bits, ret = 0, wstart, wend, window; int start = 1; BIGNUM *aa; /* Table of variables obtained from 'ctx' */ @@ -239,7 +239,6 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, start = 1; /* This is used to avoid multiplication etc * when there is only the value '1' in the * buffer. */ - wvalue = 0; /* The 'value' of the window */ wstart = bits - 1; /* The top bit of the window */ wend = 0; /* The bottom bit of the window */ @@ -255,6 +254,8 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, goto err; for (;;) { + int wvalue; /* The 'value' of the window */ + if (BN_is_bit_set(p, wstart) == 0) { if (!start) if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) @@ -296,7 +297,6 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, /* move the 'window' down further */ wstart -= wend + 1; - wvalue = 0; start = 0; if (wstart < 0) break; @@ -312,7 +312,7 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) { - int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int i, j, bits, ret = 0, wstart, wend, window; int start = 1; BIGNUM *d, *r; const BIGNUM *aa; @@ -392,7 +392,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, start = 1; /* This is used to avoid multiplication etc * when there is only the value '1' in the * buffer. */ - wvalue = 0; /* The 'value' of the window */ wstart = bits - 1; /* The top bit of the window */ wend = 0; /* The bottom bit of the window */ @@ -412,6 +411,8 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx)) goto err; for (;;) { + int wvalue; /* The 'value' of the window */ + if (BN_is_bit_set(p, wstart) == 0) { if (!start) { if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx)) @@ -454,7 +455,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, /* move the 'window' down further */ wstart -= wend + 1; - wvalue = 0; start = 0; if (wstart < 0) break; @@ -1320,7 +1320,7 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx) { - int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int i, j, bits, ret = 0, wstart, wend, window; int start = 1; BIGNUM *d; /* Table of variables obtained from 'ctx' */ @@ -1380,7 +1380,6 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, start = 1; /* This is used to avoid multiplication etc * when there is only the value '1' in the * buffer. */ - wvalue = 0; /* The 'value' of the window */ wstart = bits - 1; /* The top bit of the window */ wend = 0; /* The bottom bit of the window */ @@ -1396,6 +1395,8 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, goto err; for (;;) { + int wvalue; /* The 'value' of the window */ + if (BN_is_bit_set(p, wstart) == 0) { if (!start) if (!BN_mod_mul(r, r, r, m, ctx)) @@ -1437,7 +1438,6 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, /* move the 'window' down further */ wstart -= wend + 1; - wvalue = 0; start = 0; if (wstart < 0) break; @@ -1452,7 +1452,7 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, /* * This is a variant of modular exponentiation optimization that does * parallel 2-primes exponentiation using 256-bit (AVX512VL) AVX512_IFMA ISA - * in 52-bit binary redundant representation. + * or AVX_IFMA ISA in 52-bit binary redundant representation. * If such instructions are not available, or input data size is not supported, * it falls back to two BN_mod_exp_mont_consttime() calls. */ @@ -1468,13 +1468,21 @@ int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1 BN_MONT_CTX *mont1 = NULL; BN_MONT_CTX *mont2 = NULL; - if (ossl_rsaz_avx512ifma_eligible() && - ((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) && - (a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024))) { + if ((ossl_rsaz_avx512ifma_eligible() || ossl_rsaz_avxifma_eligible()) && + (((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) && + (a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024)) || + ((a1->top == 24) && (p1->top == 24) && (BN_num_bits(m1) == 1536) && + (a2->top == 24) && (p2->top == 24) && (BN_num_bits(m2) == 1536)) || + ((a1->top == 32) && (p1->top == 32) && (BN_num_bits(m1) == 2048) && + (a2->top == 32) && (p2->top == 32) && (BN_num_bits(m2) == 2048)))) { - if (bn_wexpand(rr1, 16) == NULL) + int topn = a1->top; + /* Modulus bits of |m1| and |m2| are equal */ + int mod_bits = BN_num_bits(m1); + + if (bn_wexpand(rr1, topn) == NULL) goto err; - if (bn_wexpand(rr2, 16) == NULL) + if (bn_wexpand(rr2, topn) == NULL) goto err; /* Ensure that montgomery contexts are initialized */ @@ -1499,14 +1507,14 @@ int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1 mont1->RR.d, mont1->n0[0], rr2->d, a2->d, p2->d, m2->d, mont2->RR.d, mont2->n0[0], - 1024 /* factor bit size */); + mod_bits); - rr1->top = 16; + rr1->top = topn; rr1->neg = 0; bn_correct_top(rr1); bn_check_top(rr1); - rr2->top = 16; + rr2->top = topn; rr2->neg = 0; bn_correct_top(rr2); bn_check_top(rr2); diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c index cd0b0151ec7e..13de70eb0d50 100644 --- a/crypto/bn/bn_gcd.c +++ b/crypto/bn/bn_gcd.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,7 @@ #include "internal/cryptlib.h" #include "bn_local.h" +#include "internal/constant_time.h" /* * bn_mod_inverse_no_branch is a special version of BN_mod_inverse. It does @@ -522,7 +523,7 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, if (ctx == NULL) { ctx = new_ctx = BN_CTX_new_ex(NULL); if (ctx == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_BN_LIB); return NULL; } } @@ -534,6 +535,37 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, return rv; } +/* + * The numbers a and b are coprime if the only positive integer that is a + * divisor of both of them is 1. + * i.e. gcd(a,b) = 1. + * + * Coprimes have the property: b has a multiplicative inverse modulo a + * i.e there is some value x such that bx = 1 (mod a). + * + * Testing the modulo inverse is currently much faster than the constant + * time version of BN_gcd(). + */ +int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *tmp; + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) + goto end; + + ERR_set_mark(); + BN_set_flags(a, BN_FLG_CONSTTIME); + ret = (BN_mod_inverse(tmp, a, b, ctx) != NULL); + /* Clear any errors (an error is returned if there is no inverse) */ + ERR_pop_to_mark(); +end: + BN_CTX_end(ctx); + return ret; +} + /*- * This function is based on the constant-time GCD work by Bernstein and Yang: * https://eprint.iacr.org/2019/266 @@ -549,8 +581,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *in, int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) { BIGNUM *g, *temp = NULL; - BN_ULONG mask = 0; - int i, j, top, rlen, glen, m, bit = 1, delta = 1, cond = 0, shifts = 0, ret = 0; + BN_ULONG pow2_numbits, pow2_numbits_temp, pow2_condition_mask, pow2_flag; + int i, j, top, rlen, glen, m, delta = 1, cond = 0, pow2_shifts, ret = 0; /* Note 2: zero input corner cases are not constant-time since they are * handled immediately. An attacker can run an attack under this @@ -580,18 +612,29 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) goto err; /* find shared powers of two, i.e. "shifts" >= 1 */ + pow2_flag = 1; + pow2_shifts = 0; + pow2_numbits = 0; for (i = 0; i < r->dmax && i < g->dmax; i++) { - mask = ~(r->d[i] | g->d[i]); - for (j = 0; j < BN_BITS2; j++) { - bit &= mask; - shifts += bit; - mask >>= 1; - } + pow2_numbits_temp = r->d[i] | g->d[i]; + pow2_condition_mask = constant_time_is_zero_bn(pow2_flag); + pow2_flag &= constant_time_is_zero_bn(pow2_numbits_temp); + pow2_shifts += pow2_flag; + pow2_numbits = constant_time_select_bn(pow2_condition_mask, + pow2_numbits, pow2_numbits_temp); + } + pow2_numbits = ~pow2_numbits; + pow2_shifts *= BN_BITS2; + pow2_flag = 1; + for (j = 0; j < BN_BITS2; j++) { + pow2_flag &= pow2_numbits; + pow2_shifts += pow2_flag; + pow2_numbits >>= 1; } /* subtract shared powers of two; shifts >= 1 */ - if (!BN_rshift(r, r, shifts) - || !BN_rshift(g, g, shifts)) + if (!BN_rshift(r, r, pow2_shifts) + || !BN_rshift(g, g, pow2_shifts)) goto err; /* expand to biggest nword, with room for a possible extra word */ @@ -634,7 +677,7 @@ int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx) /* remove possible negative sign */ r->neg = 0; /* add powers of 2 removed, then correct the artificial shift */ - if (!BN_lshift(r, r, shifts) + if (!BN_lshift(r, r, pow2_shifts) || !BN_rshift1(r, r)) goto err; diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c index bcc66613cc14..ae7e9d751c29 100644 --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -475,10 +475,8 @@ int BN_GF2m_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, bn_check_top(p); arr = OPENSSL_malloc(sizeof(*arr) * max); - if (arr == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (arr == NULL) return 0; - } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); @@ -537,10 +535,8 @@ int BN_GF2m_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) bn_check_top(p); arr = OPENSSL_malloc(sizeof(*arr) * max); - if (arr == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (arr == NULL) return 0; - } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); @@ -922,10 +918,8 @@ int BN_GF2m_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, bn_check_top(p); arr = OPENSSL_malloc(sizeof(*arr) * max); - if (arr == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (arr == NULL) return 0; - } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); @@ -986,10 +980,8 @@ int BN_GF2m_mod_sqrt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) bn_check_top(p); arr = OPENSSL_malloc(sizeof(*arr) * max); - if (arr == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (arr == NULL) return 0; - } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); @@ -1122,10 +1114,8 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, bn_check_top(p); arr = OPENSSL_malloc(sizeof(*arr) * max); - if (arr == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (arr == NULL) goto err; - } ret = BN_GF2m_poly2arr(p, arr, max); if (!ret || ret > max) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_LENGTH); diff --git a/crypto/bn/bn_intern.c b/crypto/bn/bn_intern.c index c0f7f5fea604..505a9dfcc391 100644 --- a/crypto/bn/bn_intern.c +++ b/crypto/bn/bn_intern.c @@ -29,10 +29,8 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) if (BN_is_zero(scalar)) { r = OPENSSL_malloc(1); - if (r == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (r == NULL) goto err; - } r[0] = 0; *ret_len = 1; return r; @@ -62,10 +60,8 @@ signed char *bn_compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) * (*ret_len will be set to the actual length, i.e. at most * BN_num_bits(scalar) + 1) */ - if (r == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (r == NULL) goto err; - } window_val = scalar->d[0] & mask; j = 0; while ((window_val != 0) || (j + w + 1 < len)) { /* if j+w+1 >= len, @@ -188,7 +184,7 @@ void bn_set_static_words(BIGNUM *a, const BN_ULONG *words, int size) int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words) { if (bn_wexpand(a, num_words) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BN, ERR_R_BN_LIB); return 0; } diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 9677a603cb2d..470592731fa8 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -82,8 +82,9 @@ int BN_get_params(int which) 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 }; + static const BIGNUM const_one = { + (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA + }; return &const_one; } @@ -244,22 +245,21 @@ BIGNUM *BN_new(void) { BIGNUM *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) 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; - } +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 */ @@ -279,10 +279,8 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) 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); + if (a == NULL) return NULL; - } assert(b->top <= words); if (b->top > 0) @@ -430,42 +428,102 @@ int BN_set_word(BIGNUM *a, BN_ULONG w) return 1; } -BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +typedef enum {BIG, LITTLE} endianness_t; +typedef enum {SIGNED, UNSIGNED} signedness_t; + +static BIGNUM *bin2bn(const unsigned char *s, int len, BIGNUM *ret, + endianness_t endianness, signedness_t signedness) { - unsigned int i, m; + int inc; + const unsigned char *s2; + int inc2; + int neg = 0, xor = 0, carry = 0; + unsigned int i; unsigned int n; - BN_ULONG l; BIGNUM *bn = NULL; + /* Negative length is not acceptable */ + if (len < 0) + return 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--) + + /* + * If the input has no bits, the number is considered zero. + * This makes calls with s==NULL and len==0 safe. + */ + if (len == 0) { + BN_clear(ret); + return ret; + } + + /* + * The loop that does the work iterates from least to most + * significant BIGNUM chunk, so we adapt parameters to transfer + * input bytes accordingly. + */ + if (endianness == LITTLE) { + s2 = s + len - 1; + inc2 = -1; + inc = 1; + } else { + s2 = s; + inc2 = 1; + inc = -1; + s += len - 1; + } + + /* Take note of the signedness of the input bytes*/ + if (signedness == SIGNED) { + neg = !!(*s2 & 0x80); + xor = neg ? 0xff : 0x00; + carry = neg; + } + + /* + * Skip leading sign extensions (the value of |xor|). + * This is the only spot where |s2| and |inc2| are used. + */ + for ( ; len > 0 && *s2 == xor; s2 += inc2, len--) continue; - n = len; - if (n == 0) { + + /* + * If there was a set of 0xff, we backtrack one byte unless the next + * one has a sign bit, as the last 0xff is then part of the actual + * number, rather then a mere sign extension. + */ + if (xor == 0xff) { + if (len == 0 || !(*s2 & 0x80)) + len++; + } + /* If it was all zeros, we're done */ + if (len == 0) { ret->top = 0; return ret; } - i = ((n - 1) / BN_BYTES) + 1; - m = ((n - 1) % (BN_BYTES)); - if (bn_wexpand(ret, (int)i) == NULL) { + n = ((len - 1) / BN_BYTES) + 1; /* Number of resulting bignum chunks */ + if (bn_wexpand(ret, (int)n) == 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; + ret->top = n; + ret->neg = neg; + for (i = 0; n-- > 0; i++) { + BN_ULONG l = 0; /* Accumulator */ + unsigned int m = 0; /* Offset in a bignum chunk, in bits */ + + for (; len > 0 && m < BN_BYTES * 8; len--, s += inc, m += 8) { + BN_ULONG byte_xored = *s ^ xor; + BN_ULONG byte = (byte_xored + carry) & 0xff; + + carry = byte_xored > byte; /* Implicit 1 or 0 */ + l |= (byte << m); } + ret->d[i] = l; } /* * need to call this due to clear byte at top if avoiding having the top @@ -475,30 +533,58 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *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) +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) { - int n; + return bin2bn(s, len, ret, BIG, UNSIGNED); +} + +BIGNUM *BN_signed_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + return bin2bn(s, len, ret, BIG, SIGNED); +} + +static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, + endianness_t endianness, signedness_t signedness) +{ + int inc; + int n, n8; + int xor = 0, carry = 0, ext = 0; size_t i, lasti, j, atop, mask; BN_ULONG l; /* - * In case |a| is fixed-top, BN_num_bytes can return bogus length, + * In case |a| is fixed-top, BN_num_bits 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); + n8 = BN_num_bits(a); + n = (n8 + 7) / 8; /* This is what BN_num_bytes() does */ + + /* Take note of the signedness of the bignum */ + if (signedness == SIGNED) { + xor = a->neg ? 0xff : 0x00; + carry = a->neg; + + /* + * if |n * 8 == n|, then the MSbit is set, otherwise unset. + * We must compensate with one extra byte if that doesn't + * correspond to the signedness of the bignum with regards + * to 2's complement. + */ + ext = (n * 8 == n8) + ? !a->neg /* MSbit set on nonnegative bignum */ + : a->neg; /* MSbit unset on negative bignum */ + } + if (tolen == -1) { - tolen = n; - } else if (tolen < n) { /* uncommon/unlike case */ + tolen = n + ext; + } else if (tolen < n + ext) { /* uncommon/unlike case */ BIGNUM temp = *a; bn_correct_top(&temp); - n = BN_num_bytes(&temp); - if (tolen < n) + n8 = BN_num_bits(&temp); + n = (n8 + 7) / 8; /* This is what BN_num_bytes() does */ + if (tolen < n + ext) return -1; } @@ -510,19 +596,30 @@ int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianess_t endiane return tolen; } + /* + * The loop that does the work iterates from least significant + * to most significant BIGNUM limb, so we adapt parameters to + * transfer output bytes accordingly. + */ + if (endianness == LITTLE) { + inc = 1; + } else { + inc = -1; + to += tolen - 1; /* Move to the last byte, not beyond */ + } + 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; + unsigned char byte, byte_xored; + 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; + byte = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask); + byte_xored = byte ^ xor; + *to = (unsigned char)(byte_xored + carry); + carry = byte_xored > *to; /* Implicit 1 or 0 */ + to += inc; i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */ } @@ -533,66 +630,43 @@ int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { if (tolen < 0) return -1; - return bn2binpad(a, to, tolen, big); + return bn2binpad(a, to, tolen, BIG, UNSIGNED); +} + +int BN_signed_bn2bin(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen, BIG, SIGNED); } int BN_bn2bin(const BIGNUM *a, unsigned char *to) { - return bn2binpad(a, to, -1, big); + return bn2binpad(a, to, -1, BIG, UNSIGNED); } BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) { - unsigned int i, m; - unsigned int n; - BN_ULONG l; - BIGNUM *bn = NULL; + return bin2bn(s, len, ret, LITTLE, UNSIGNED); +} - 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; +BIGNUM *BN_signed_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + return bin2bn(s, len, ret, LITTLE, SIGNED); } int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) { if (tolen < 0) return -1; - return bn2binpad(a, to, tolen, little); + return bn2binpad(a, to, tolen, LITTLE, UNSIGNED); +} + +int BN_signed_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen, LITTLE, SIGNED); } BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret) @@ -604,6 +678,15 @@ BIGNUM *BN_native2bn(const unsigned char *s, int len, BIGNUM *ret) return BN_bin2bn(s, len, ret); } +BIGNUM *BN_signed_native2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + DECLARE_IS_ENDIAN; + + if (IS_LITTLE_ENDIAN) + return BN_signed_lebin2bn(s, len, ret); + return BN_signed_bin2bn(s, len, ret); +} + int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen) { DECLARE_IS_ENDIAN; @@ -613,6 +696,15 @@ int BN_bn2nativepad(const BIGNUM *a, unsigned char *to, int tolen) return BN_bn2binpad(a, to, tolen); } +int BN_signed_bn2native(const BIGNUM *a, unsigned char *to, int tolen) +{ + DECLARE_IS_ENDIAN; + + if (IS_LITTLE_ENDIAN) + return BN_signed_bn2lebin(a, to, tolen); + return BN_signed_bn2bin(a, to, tolen); +} + int BN_ucmp(const BIGNUM *a, const BIGNUM *b) { int i; @@ -854,9 +946,6 @@ 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); @@ -960,7 +1049,7 @@ int BN_is_word(const BIGNUM *a, const BN_ULONG w) return BN_abs_is_word(a, w) && (!w || !a->neg); } -int ossl_bn_is_word_fixed_top(const BIGNUM *a, BN_ULONG w) +int ossl_bn_is_word_fixed_top(const BIGNUM *a, const BN_ULONG w) { int res, i; const BN_ULONG *ap = a->d; @@ -1007,10 +1096,8 @@ 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); + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) return NULL; - } return ret; } diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h index 50e9d26e215b..b5be37ba973e 100644 --- a/crypto/bn/bn_local.h +++ b/crypto/bn/bn_local.h @@ -243,8 +243,11 @@ 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. */ + BN_ULONG *d; /* + * Pointer to an array of 'BN_BITS2' bit + * chunks. These chunks are organised in + * a least significant chunk first order. + */ int top; /* Index of last used d +1. */ /* The next are internal book keeping for bn_expand. */ int dmax; /* Size of the d array. */ diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c index 2dda2e3442ed..5f08bfa4a534 100644 --- a/crypto/bn/bn_mod.c +++ b/crypto/bn/bn_mod.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,6 +8,7 @@ */ #include "internal/cryptlib.h" +#include "internal/nelem.h" #include "bn_local.h" int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) @@ -61,12 +62,10 @@ int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, if (bn_wexpand(r, mtop) == NULL) return 0; - if (mtop > sizeof(storage) / sizeof(storage[0])) { + if (mtop > OSSL_NELEM(storage)) { tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG)); - if (tp == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (tp == NULL) return 0; - } } ap = a->d != NULL ? a->d : tp; diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index 1c5d66bbf863..4f08394d7f0a 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -229,10 +229,8 @@ BN_MONT_CTX *BN_MONT_CTX_new(void) { BN_MONT_CTX *ret; - if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) return NULL; - } BN_MONT_CTX_init(ret); ret->flags = BN_FLG_MALLOCED; @@ -467,3 +465,45 @@ BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_RWLOCK *lock, CRYPTO_THREAD_unlock(lock); return ret; } + +int ossl_bn_mont_ctx_set(BN_MONT_CTX *ctx, const BIGNUM *modulus, int ri, const unsigned char *rr, + size_t rrlen, uint32_t nlo, uint32_t nhi) +{ + if (BN_copy(&ctx->N, modulus) == NULL) + return 0; + if (BN_bin2bn(rr, rrlen, &ctx->RR) == NULL) + return 0; + ctx->ri = ri; +#if (BN_BITS2 <= 32) && defined(OPENSSL_BN_ASM_MONT) + ctx->n0[0] = nlo; + ctx->n0[1] = nhi; +#elif BN_BITS2 <= 32 + ctx->n0[0] = nlo; + ctx->n0[1] = 0; +#else + ctx->n0[0] = ((BN_ULONG)nhi << 32)| nlo; + ctx->n0[1] = 0; +#endif + + return 1; +} + +int ossl_bn_mont_ctx_eq(const BN_MONT_CTX *m1, const BN_MONT_CTX *m2) +{ + if (m1->ri != m2->ri) + return 0; + if (BN_cmp(&m1->RR, &m2->RR) != 0) + return 0; + if (m1->flags != m2->flags) + return 0; +#ifdef MONT_WORD + if (m1->n0[0] != m2->n0[0]) + return 0; + if (m1->n0[1] != m2->n0[1]) + return 0; +#else + if (BN_cmp(&m1->Ni, &m2->Ni) != 0) + return 0; +#endif + return 1; +} diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c index dc6b6f5a1215..c3864b8c691a 100644 --- a/crypto/bn/bn_mul.c +++ b/crypto/bn/bn_mul.c @@ -115,12 +115,12 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, r[1] = a[1]; if (--dl <= 0) break; - /* fall thru */ + /* fall through */ case 2: r[2] = a[2]; if (--dl <= 0) break; - /* fall thru */ + /* fall through */ case 3: r[3] = a[3]; if (--dl <= 0) diff --git a/crypto/bn/bn_nist.c b/crypto/bn/bn_nist.c index d761e5702da2..527ecb34d854 100644 --- a/crypto/bn/bn_nist.c +++ b/crypto/bn/bn_nist.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -84,8 +84,8 @@ static const BN_ULONG _nist_p_384_sqr[] = { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL }; -static const BN_ULONG _nist_p_521[] = - { 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, +static const BN_ULONG _nist_p_521[] = { + 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, @@ -251,7 +251,7 @@ const BIGNUM *BN_get0_nist_prime_521(void) /* * To avoid more recent compilers (specifically clang-14) from treating this - * code as a violation of the strict aliasing conditions and omiting it, this + * code as a violation of the strict aliasing conditions and omitting 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 diff --git a/crypto/bn/bn_ppc.c b/crypto/bn/bn_ppc.c index 3ee76ea96574..80f705eddee9 100644 --- a/crypto/bn/bn_ppc.c +++ b/crypto/bn/bn_ppc.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2009-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,12 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num); int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np, const BN_ULONG *n0, int num); + int bn_mul_mont_fixed_n6(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); + int bn_mul_mont_300_fixed_n6(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); if (num < 4) return 0; @@ -34,5 +40,17 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, * no opportunity to figure it out... */ +#if defined(_ARCH_PPC64) && !defined(__ILP32__) + /* Minerva side-channel fix danny */ +# if defined(USE_FIXED_N6) + if (num == 6) { + if (OPENSSL_ppccap_P & PPC_MADD300) + return bn_mul_mont_300_fixed_n6(rp, ap, bp, np, n0, num); + else + return bn_mul_mont_fixed_n6(rp, ap, bp, np, n0, num); + } +# endif +#endif + return bn_mul_mont_int(rp, ap, bp, np, n0, num); } diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c index ddd31a025254..96eb1b3c347f 100644 --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -145,10 +145,8 @@ int BN_generate_prime_ex2(BIGNUM *ret, int bits, int safe, } mods = OPENSSL_zalloc(sizeof(*mods) * NUMPRIMES); - if (mods == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (mods == NULL) return 0; - } BN_CTX_start(ctx); t = BN_CTX_get(ctx); @@ -252,6 +250,17 @@ int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx, return bn_is_prime_int(w, checks, ctx, do_trial_division, cb); } +/* + * Use this only for key generation. + * It always uses trial division. The number of checks + * (MR rounds) passed in is used without being clamped to a minimum value. + */ +int ossl_bn_check_generated_prime(const BIGNUM *w, int checks, BN_CTX *ctx, + BN_GENCB *cb) +{ + return bn_is_prime_int(w, checks, ctx, 1, cb); +} + int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb) { return ossl_bn_check_prime(p, 0, ctx, 1, cb); diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c index ba0970b1f87d..da537a07a914 100644 --- a/crypto/bn/bn_rand.c +++ b/crypto/bn/bn_rand.c @@ -41,10 +41,8 @@ static int bnrand(BNRAND_FLAG flag, BIGNUM *rnd, int bits, int top, int bottom, mask = 0xff << (bit + 1); buf = OPENSSL_malloc(bytes); - if (buf == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if (buf == NULL) goto err; - } /* make a random number and set the top and bottom bits */ b = flag == NORMAL ? RAND_bytes_ex(libctx, buf, bytes, strength) diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c index 3a2c812ac666..83fd175c437f 100644 --- a/crypto/bn/bn_recp.c +++ b/crypto/bn/bn_recp.c @@ -21,10 +21,8 @@ BN_RECP_CTX *BN_RECP_CTX_new(void) { BN_RECP_CTX *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_BN, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } bn_init(&(ret->N)); bn_init(&(ret->Nr)); diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c index 62d8685d03e0..c967ca962978 100644 --- a/crypto/bn/bn_rsa_fips186_4.c +++ b/crypto/bn/bn_rsa_fips186_4.c @@ -48,6 +48,34 @@ const BIGNUM ossl_bn_inv_sqrt_2 = { BN_FLG_STATIC_DATA }; +/* + * Refer to FIPS 186-5 Table B.1 for minimum rounds of Miller Rabin + * required for generation of RSA aux primes (p1, p2, q1 and q2). + */ +static int bn_rsa_fips186_5_aux_prime_MR_rounds(int nbits) +{ + if (nbits >= 4096) + return 44; + if (nbits >= 3072) + return 41; + if (nbits >= 2048) + return 38; + return 0; /* Error */ +} + +/* + * Refer to FIPS 186-5 Table B.1 for minimum rounds of Miller Rabin + * required for generation of RSA primes (p and q) + */ +static int bn_rsa_fips186_5_prime_MR_rounds(int nbits) +{ + if (nbits >= 3072) + return 4; + if (nbits >= 2048) + return 5; + return 0; /* Error */ +} + /* * FIPS 186-5 Table A.1. "Min length of auxiliary primes p1, p2, q1, q2". * (FIPS 186-5 has an entry for >= 4096 bits). @@ -97,11 +125,13 @@ static int bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(int nbits) * 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. + * rounds The number of Miller Rabin rounds * 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, + int rounds, BN_GENCB *cb) { int ret = 0; @@ -113,11 +143,11 @@ static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1, BN_set_flags(p1, BN_FLG_CONSTTIME); /* Find the first odd number >= Xp1 that is probably prime */ - for(;;) { + for (;;) { i++; BN_GENCB_call(cb, 0, i); /* MR test with trial division */ - tmp = BN_check_prime(p1, ctx, cb); + tmp = ossl_bn_check_generated_prime(p1, rounds, ctx, cb); if (tmp > 0) break; if (tmp < 0) @@ -160,7 +190,7 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout, { int ret = 0; BIGNUM *p1i = NULL, *p2i = NULL, *Xp1i = NULL, *Xp2i = NULL; - int bitlen; + int bitlen, rounds; if (p == NULL || Xpout == NULL) return 0; @@ -177,6 +207,7 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout, bitlen = bn_rsa_fips186_5_aux_prime_min_size(nlen); if (bitlen == 0) goto err; + rounds = bn_rsa_fips186_5_aux_prime_MR_rounds(nlen); /* (Steps 4.1/5.1): Randomly generate Xp1 if it is not passed in */ if (Xp1 == NULL) { @@ -194,8 +225,8 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout, } /* (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)) + if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, rounds, cb) + || !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, rounds, cb)) goto err; /* (Table B.1) auxiliary prime Max length check */ if ((BN_num_bits(p1i) + BN_num_bits(p2i)) >= @@ -243,11 +274,11 @@ err: */ 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 nlen, const BIGNUM *e, + BN_CTX *ctx, BN_GENCB *cb) { int ret = 0; - int i, imax; + int i, imax, rounds; int bits = nlen >> 1; BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2; BIGNUM *base, *range; @@ -286,14 +317,20 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin, goto err; } + /* + * (Step 1) GCD(2r1, r2) = 1. + * Note: This algorithm was doing a gcd(2r1, r2)=1 test before doing an + * mod_inverse(2r1, r2) which are effectively the same operation. + * (The algorithm assumed that the gcd test would be faster). Since the + * mod_inverse is currently faster than calling the constant time + * BN_gcd(), the call to BN_gcd() has been omitted. The inverse result + * is used further down. + */ if (!(BN_lshift1(r1x2, r1) - /* (Step 1) GCD(2r1, r2) = 1 */ - && BN_gcd(tmp, r1x2, r2, ctx) - && BN_is_one(tmp) + && (BN_mod_inverse(tmp, r1x2, r2, ctx) != NULL) /* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */ - && BN_mod_inverse(R, r2, r1x2, ctx) + && (BN_mod_inverse(R, r2, r1x2, ctx) != NULL) && 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 */ @@ -305,11 +342,13 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin, /* * 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 + * 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. */ + rounds = bn_rsa_fips186_5_prime_MR_rounds(nlen); imax = 20 * bits; /* max = 20/2 * nbits */ for (;;) { if (Xin == NULL) { @@ -337,11 +376,11 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin, /* (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)) + || !BN_sub_word(y1, 1)) goto err; - if (BN_is_one(tmp)) { - int rv = BN_check_prime(Y, ctx, cb); + + if (BN_are_coprime(y1, e, ctx)) { + int rv = ossl_bn_check_generated_prime(Y, rounds, ctx, cb); if (rv > 0) goto end; diff --git a/crypto/bn/build.info b/crypto/bn/build.info index c4ba51b26552..a82271136cba 100644 --- a/crypto/bn/build.info +++ b/crypto/bn/build.info @@ -24,7 +24,8 @@ IF[{- !$disabled{asm} -}] $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 + rsaz-avx2.s rsaz_exp_x2.c rsaz-2k-avx512.s rsaz-3k-avx512.s rsaz-4k-avx512.s \ + rsaz-2k-avxifma.s rsaz-3k-avxifma.s rsaz-4k-avxifma.s IF[{- $config{target} !~ /^VC/ -}] $BNASM_x86_64=asm/x86_64-gcc.c $BNASM_x86_64 ELSE @@ -58,7 +59,7 @@ IF[{- !$disabled{asm} -}] IF[{- ($target{perlasm_scheme} // '') eq '31' -}] $BNASM_s390x=bn_asm.c s390x-mont.S ELSE - $BNASM_s390x=asm/s390x.S s390x-mont.S + $BNASM_s390x=asm/s390x.S s390x-mont.S bn_s390x.c ENDIF $BNDEF_s390x=OPENSSL_BN_ASM_MONT $BNASM_s390x_ec2m=s390x-gf2m.s @@ -79,7 +80,7 @@ IF[{- !$disabled{asm} -}] $BNASM_ppc32=bn_ppc.c bn-ppc.s ppc-mont.s $BNDEF_ppc32=OPENSSL_BN_ASM_MONT - $BNASM_ppc64=$BNASM_ppc32 + $BNASM_ppc64=$BNASM_ppc32 ppc64-mont-fixed.s $BNDEF_ppc64=$BNDEF_ppc32 $BNASM_c64xplus=asm/bn-c64xplus.asm @@ -155,7 +156,12 @@ 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[rsaz-2k-avx512.s]=asm/rsaz-2k-avx512.pl +GENERATE[rsaz-3k-avx512.s]=asm/rsaz-3k-avx512.pl +GENERATE[rsaz-4k-avx512.s]=asm/rsaz-4k-avx512.pl +GENERATE[rsaz-2k-avxifma.s]=asm/rsaz-2k-avxifma.pl +GENERATE[rsaz-3k-avxifma.s]=asm/rsaz-3k-avxifma.pl +GENERATE[rsaz-4k-avxifma.s]=asm/rsaz-4k-avxifma.pl GENERATE[bn-ia64.s]=asm/ia64.S GENERATE[ia64-mont.s]=asm/ia64-mont.pl @@ -166,6 +172,7 @@ GENERATE[parisc-mont.s]=asm/parisc-mont.pl GENERATE[bn-ppc.s]=asm/ppc.pl GENERATE[ppc-mont.s]=asm/ppc-mont.pl GENERATE[ppc64-mont.s]=asm/ppc64-mont.pl +GENERATE[ppc64-mont-fixed.s]=asm/ppc64-mont-fixed.pl GENERATE[alpha-mont.S]=asm/alpha-mont.pl diff --git a/crypto/bn/rsaz_exp.c b/crypto/bn/rsaz_exp.c index 2a1ff09eefc9..80b583f35ae8 100644 --- a/crypto/bn/rsaz_exp.c +++ b/crypto/bn/rsaz_exp.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2013-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2012, Intel Corporation. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -13,6 +13,7 @@ */ #include +#include "internal/common.h" #include "rsaz_exp.h" #ifndef RSAZ_ENABLED @@ -31,16 +32,8 @@ void rsaz_1024_scatter5_avx2(void *tbl, const void *val, int i); void rsaz_1024_gather5_avx2(void *val, const void *tbl, int i); void rsaz_1024_red2norm_avx2(void *norm, const void *red); -#if defined(__GNUC__) -# define ALIGN64 __attribute__((aligned(64))) -#elif defined(_MSC_VER) -# define ALIGN64 __declspec(align(64)) -#elif defined(__SUNPRO_C) -# define ALIGN64 +#if defined(__SUNPRO_C) # pragma align 64(one,two80) -#else -/* not fatal, might hurt performance a little */ -# define ALIGN64 #endif ALIGN64 static const BN_ULONG one[40] = { diff --git a/crypto/bn/rsaz_exp.h b/crypto/bn/rsaz_exp.h index e27e9f047138..49a0bf3bf199 100644 --- a/crypto/bn/rsaz_exp.h +++ b/crypto/bn/rsaz_exp.h @@ -1,5 +1,5 @@ /* - * Copyright 2013-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2013-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2020, Intel Corporation. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -40,6 +40,8 @@ void RSAZ_512_mod_exp(BN_ULONG result[8], int ossl_rsaz_avx512ifma_eligible(void); +int ossl_rsaz_avxifma_eligible(void); + int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, const BN_ULONG *base1, const BN_ULONG *exponent1, diff --git a/crypto/bn/rsaz_exp_x2.c b/crypto/bn/rsaz_exp_x2.c index 4a2a6752f672..e33546208735 100644 --- a/crypto/bn/rsaz_exp_x2.c +++ b/crypto/bn/rsaz_exp_x2.c @@ -1,6 +1,6 @@ /* * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2020, Intel Corporation. All Rights Reserved. + * Copyright (c) 2020-2021, Intel Corporation. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,7 +8,8 @@ * https://www.openssl.org/source/license.html * * - * Originally written by Ilya Albrekht, Sergey Kirillov and Andrey Matyukov + * Originally written by Sergey Kirillov and Andrey Matyukov. + * Special thanks to Ilya Albrekht for his valuable hints. * Intel Corporation * */ @@ -23,14 +24,6 @@ NON_EMPTY_TRANSLATION_UNIT # include # include -# if defined(__GNUC__) -# define ALIGN64 __attribute__((aligned(64))) -# elif defined(_MSC_VER) -# define ALIGN64 __declspec(align(64)) -# else -# define ALIGN64 -# endif - # define ALIGN_OF(ptr, boundary) \ ((unsigned char *)(ptr) + (boundary - (((size_t)(ptr)) & (boundary - 1)))) @@ -42,8 +35,12 @@ NON_EMPTY_TRANSLATION_UNIT # define BITS2WORD8_SIZE(x) (((x) + 7) >> 3) # define BITS2WORD64_SIZE(x) (((x) + 63) >> 6) -static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len); -static ossl_inline void put_digit52(uint8_t *out, int out_len, uint64_t digit); +/* Number of registers required to hold |digits_num| amount of qword digits */ +# define NUMBER_OF_REGISTERS(digits_num, register_size) \ + (((digits_num) * 64 + (register_size) - 1) / (register_size)) + +static ossl_inline uint64_t get_digit(const uint8_t *in, int in_len); +static ossl_inline void put_digit(uint8_t *out, int out_len, uint64_t digit); static void to_words52(BN_ULONG *out, int out_len, const BN_ULONG *in, int in_bitsize); static void from_words52(BN_ULONG *bn_out, int out_bitsize, const BN_ULONG *in); @@ -55,41 +52,117 @@ static ossl_inline int number_of_digits(int bitsize, int digit_size) return (bitsize + digit_size - 1) / digit_size; } -typedef void (*AMM52)(BN_ULONG *res, const BN_ULONG *base, - const BN_ULONG *exp, const BN_ULONG *m, BN_ULONG k0); -typedef void (*EXP52_x2)(BN_ULONG *res, const BN_ULONG *base, - const BN_ULONG *exp[2], const BN_ULONG *m, - const BN_ULONG *rr, const BN_ULONG k0[2]); - /* * For details of the methods declared below please refer to * crypto/bn/asm/rsaz-avx512.pl * - * Naming notes: + * Naming conventions: * amm = Almost Montgomery Multiplication * ams = Almost Montgomery Squaring - * 52x20 - data represented as array of 20 digits in 52-bit radix + * 52xZZ - data represented as array of ZZ digits in 52-bit radix * _x1_/_x2_ - 1 or 2 independent inputs/outputs - * _256 suffix - uses 256-bit (AVX512VL) registers + * _ifma256 - uses 256-bit wide IFMA ISA (AVX512_IFMA256) + * _avxifma256 - uses 256-bit wide AVXIFMA ISA (AVX_IFMA256) */ -/*AMM = Almost Montgomery Multiplication. */ -void ossl_rsaz_amm52x20_x1_256(BN_ULONG *res, const BN_ULONG *base, - const BN_ULONG *exp, const BN_ULONG *m, - BN_ULONG k0); -static void RSAZ_exp52x20_x2_256(BN_ULONG *res, const BN_ULONG *base, - const BN_ULONG *exp[2], const BN_ULONG *m, - const BN_ULONG *rr, const BN_ULONG k0[2]); -void ossl_rsaz_amm52x20_x2_256(BN_ULONG *out, const BN_ULONG *a, - const BN_ULONG *b, const BN_ULONG *m, - const BN_ULONG k0[2]); +void ossl_rsaz_amm52x20_x1_ifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x20_x2_ifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y, const BN_ULONG *red_table, - int red_table_idx, int tbl_idx); + int red_table_idx1, int red_table_idx2); + +void ossl_rsaz_amm52x30_x1_ifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x30_x2_ifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x30_win5(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx1, int red_table_idx2); + +void ossl_rsaz_amm52x40_x1_ifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x40_x2_ifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x40_win5(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx1, int red_table_idx2); + +void ossl_rsaz_amm52x20_x1_avxifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x20_x2_avxifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x20_win5_avx(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx1, + int red_table_idx2); + +void ossl_rsaz_amm52x30_x1_avxifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x30_x2_avxifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x30_win5_avx(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx1, + int red_table_idx2); + +void ossl_rsaz_amm52x40_x1_avxifma256(BN_ULONG *res, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + BN_ULONG k0); +void ossl_rsaz_amm52x40_x2_avxifma256(BN_ULONG *out, const BN_ULONG *a, + const BN_ULONG *b, const BN_ULONG *m, + const BN_ULONG k0[2]); +void ossl_extract_multiplier_2x40_win5_avx(BN_ULONG *red_Y, + const BN_ULONG *red_table, + int red_table_idx1, + int red_table_idx2); + +typedef void (*AMM)(BN_ULONG *res, const BN_ULONG *a, const BN_ULONG *b, + const BN_ULONG *m, BN_ULONG k0); + +static AMM ossl_rsaz_amm52_x1[] = { + ossl_rsaz_amm52x20_x1_avxifma256, ossl_rsaz_amm52x20_x1_ifma256, + ossl_rsaz_amm52x30_x1_avxifma256, ossl_rsaz_amm52x30_x1_ifma256, + ossl_rsaz_amm52x40_x1_avxifma256, ossl_rsaz_amm52x40_x1_ifma256, +}; + +typedef void (*DAMM)(BN_ULONG *res, const BN_ULONG *a, const BN_ULONG *b, + const BN_ULONG *m, const BN_ULONG k0[2]); + +static DAMM ossl_rsaz_amm52_x2[] = { + ossl_rsaz_amm52x20_x2_avxifma256, ossl_rsaz_amm52x20_x2_ifma256, + ossl_rsaz_amm52x30_x2_avxifma256, ossl_rsaz_amm52x30_x2_ifma256, + ossl_rsaz_amm52x40_x2_avxifma256, ossl_rsaz_amm52x40_x2_ifma256, +}; + +typedef void (*DEXTRACT)(BN_ULONG *res, const BN_ULONG *red_table, + int red_table_idx, int tbl_idx); + +static DEXTRACT ossl_extract_multiplier_win5[] = { + ossl_extract_multiplier_2x20_win5_avx, ossl_extract_multiplier_2x20_win5, + ossl_extract_multiplier_2x30_win5_avx, ossl_extract_multiplier_2x30_win5, + ossl_extract_multiplier_2x40_win5_avx, ossl_extract_multiplier_2x40_win5, +}; + +static int RSAZ_mod_exp_x2_ifma256(BN_ULONG *res, const BN_ULONG *base, + const BN_ULONG *exp[2], const BN_ULONG *m, + const BN_ULONG *rr, const BN_ULONG k0[2], + int modulus_bitsize); /* * Dual Montgomery modular exponentiation using prime moduli of the - * same bit size, optimized with AVX512 ISA. + * same bit size, optimized with AVX512 ISA or AVXIFMA ISA. * * Input and output parameters for each exponentiation are independent and * denoted here by index |i|, i = 1..2. @@ -98,7 +171,10 @@ void ossl_extract_multiplier_2x20_win5(BN_ULONG *red_Y, * * Each moduli shall be |factor_size| bit size. * - * NOTE: currently only 2x1024 case is supported. + * Supported cases: + * - 2x1024 + * - 2x1536 + * - 2x2048 * * [out] res|i| - result of modular exponentiation: array of qword values * in regular (2^64) radix. Size of array shall be enough @@ -135,52 +211,52 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, */ int exp_digits = number_of_digits(factor_size + 2, DIGIT_SIZE); int coeff_pow = 4 * (DIGIT_SIZE * exp_digits - factor_size); + + /* Number of YMM registers required to store exponent's digits */ + int ymm_regs_num = NUMBER_OF_REGISTERS(exp_digits, 256 /* ymm bit size */); + /* Capacity of the register set (in qwords) to store exponent */ + int regs_capacity = ymm_regs_num * 4; + BN_ULONG *base1_red, *m1_red, *rr1_red; BN_ULONG *base2_red, *m2_red, *rr2_red; BN_ULONG *coeff_red; BN_ULONG *storage = NULL; BN_ULONG *storage_aligned = NULL; - BN_ULONG storage_len_bytes = 7 * exp_digits * sizeof(BN_ULONG); - - /* AMM = Almost Montgomery Multiplication */ - AMM52 amm = NULL; - /* Dual (2-exps in parallel) exponentiation */ - EXP52_x2 exp_x2 = NULL; + int storage_len_bytes = 7 * regs_capacity * sizeof(BN_ULONG) + + 64 /* alignment */; const BN_ULONG *exp[2] = {0}; BN_ULONG k0[2] = {0}; + /* AMM = Almost Montgomery Multiplication */ + AMM amm = NULL; + int avx512ifma = !!ossl_rsaz_avx512ifma_eligible(); - /* Only 1024-bit factor size is supported now */ - switch (factor_size) { - case 1024: - amm = ossl_rsaz_amm52x20_x1_256; - exp_x2 = RSAZ_exp52x20_x2_256; - break; - default: + if (factor_size != 1024 && factor_size != 1536 && factor_size != 2048) goto err; - } - storage = (BN_ULONG *)OPENSSL_malloc(storage_len_bytes + 64); + amm = ossl_rsaz_amm52_x1[(factor_size / 512 - 2) * 2 + avx512ifma]; + + storage = (BN_ULONG *)OPENSSL_malloc(storage_len_bytes); if (storage == NULL) goto err; storage_aligned = (BN_ULONG *)ALIGN_OF(storage, 64); /* Memory layout for red(undant) representations */ base1_red = storage_aligned; - base2_red = storage_aligned + 1 * exp_digits; - m1_red = storage_aligned + 2 * exp_digits; - m2_red = storage_aligned + 3 * exp_digits; - rr1_red = storage_aligned + 4 * exp_digits; - rr2_red = storage_aligned + 5 * exp_digits; - coeff_red = storage_aligned + 6 * exp_digits; + base2_red = storage_aligned + 1 * regs_capacity; + m1_red = storage_aligned + 2 * regs_capacity; + m2_red = storage_aligned + 3 * regs_capacity; + rr1_red = storage_aligned + 4 * regs_capacity; + rr2_red = storage_aligned + 5 * regs_capacity; + coeff_red = storage_aligned + 6 * regs_capacity; /* Convert base_i, m_i, rr_i, from regular to 52-bit radix */ - to_words52(base1_red, exp_digits, base1, factor_size); - to_words52(base2_red, exp_digits, base2, factor_size); - to_words52(m1_red, exp_digits, m1, factor_size); - to_words52(m2_red, exp_digits, m2, factor_size); - to_words52(rr1_red, exp_digits, rr1, factor_size); - to_words52(rr2_red, exp_digits, rr2, factor_size); + to_words52(base1_red, regs_capacity, base1, factor_size); + to_words52(base2_red, regs_capacity, base2, factor_size); + to_words52(m1_red, regs_capacity, m1, factor_size); + to_words52(m2_red, regs_capacity, m2, factor_size); + to_words52(rr1_red, regs_capacity, rr1, factor_size); + to_words52(rr2_red, regs_capacity, rr2, factor_size); /* * Compute target domain Montgomery converters RR' for each modulus @@ -193,10 +269,10 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, * where * k = 4 * (52 * digits52 - modlen) * R = 2^(64 * ceil(modlen/64)) mod m - * RR = R^2 mod M + * RR = R^2 mod m * R' = 2^(52 * ceil(modlen/52)) mod m * - * modlen = 1024: k = 64, RR = 2^2048 mod m, RR' = 2^2080 mod m + * EX/ modlen = 1024: k = 64, RR = 2^2048 mod m, RR' = 2^2080 mod m */ memset(coeff_red, 0, exp_digits * sizeof(BN_ULONG)); /* (1) in reduced domain representation */ @@ -214,7 +290,11 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, k0[0] = k0_1; k0[1] = k0_2; - exp_x2(rr1_red, base1_red, exp, m1_red, rr1_red, k0); + /* Dual (2-exps in parallel) exponentiation */ + ret = RSAZ_mod_exp_x2_ifma256(rr1_red, base1_red, exp, m1_red, rr1_red, + k0, factor_size); + if (!ret) + goto err; /* Convert rr_i back to regular radix */ from_words52(res1, factor_size, rr1_red); @@ -226,7 +306,6 @@ int ossl_rsaz_mod_exp_avx512_x2(BN_ULONG *res1, bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size); bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size); - ret = 1; err: if (storage != NULL) { OPENSSL_cleanse(storage, storage_len_bytes); @@ -236,91 +315,144 @@ err: } /* - * Dual 1024-bit w-ary modular exponentiation using prime moduli of the same - * bit size using Almost Montgomery Multiplication, optimized with AVX512_IFMA - * ISA. + * Dual {1024,1536,2048}-bit w-ary modular exponentiation using prime moduli of + * the same bit size using Almost Montgomery Multiplication, optimized with + * AVX512_IFMA256 ISA. * * The parameter w (window size) = 5. * - * [out] res - result of modular exponentiation: 2x20 qword + * [out] res - result of modular exponentiation: 2x{20,30,40} qword * values in 2^52 radix. - * [in] base - base (2x20 qword values in 2^52 radix) - * [in] exp - array of 2 pointers to 16 qword values in 2^64 radix. + * [in] base - base (2x{20,30,40} qword values in 2^52 radix) + * [in] exp - array of 2 pointers to {16,24,32} qword values in 2^64 radix. * Exponent is not converted to redundant representation. - * [in] m - moduli (2x20 qword values in 2^52 radix) - * [in] rr - Montgomery parameter for 2 moduli: RR = 2^2080 mod m. - * (2x20 qword values in 2^52 radix) + * [in] m - moduli (2x{20,30,40} qword values in 2^52 radix) + * [in] rr - Montgomery parameter for 2 moduli: + * RR(1024) = 2^2080 mod m. + * RR(1536) = 2^3120 mod m. + * RR(2048) = 2^4160 mod m. + * (2x{20,30,40} qword values in 2^52 radix) * [in] k0 - Montgomery parameter for 2 moduli: k0 = -1/m mod 2^64 * * \return (void). */ -static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */ - const BN_ULONG *base, /* [2][20] */ - const BN_ULONG *exp[2], /* 2x16 */ - const BN_ULONG *m, /* [2][20] */ - const BN_ULONG *rr, /* [2][20] */ - const BN_ULONG k0[2]) +int RSAZ_mod_exp_x2_ifma256(BN_ULONG *out, + const BN_ULONG *base, + const BN_ULONG *exp[2], + const BN_ULONG *m, + const BN_ULONG *rr, + const BN_ULONG k0[2], + int modulus_bitsize) { -# define BITSIZE_MODULUS (1024) -# define EXP_WIN_SIZE (5) -# define EXP_WIN_MASK ((1U << EXP_WIN_SIZE) - 1) -/* - * Number of digits (64-bit words) in redundant representation to handle - * modulus bits - */ -# define RED_DIGITS (20) -# define EXP_DIGITS (16) -# define DAMM ossl_rsaz_amm52x20_x2_256 + int ret = 0; + int idx; + + /* Exponent window size */ + int exp_win_size = 5; + int exp_win_mask = (1U << exp_win_size) - 1; + + /* + * Number of digits (64-bit words) in redundant representation to handle + * modulus bits + */ + int red_digits = 0; + int exp_digits = 0; + + BN_ULONG *storage = NULL; + BN_ULONG *storage_aligned = NULL; + int storage_len_bytes = 0; + + /* Red(undant) result Y and multiplier X */ + BN_ULONG *red_Y = NULL; /* [2][red_digits] */ + BN_ULONG *red_X = NULL; /* [2][red_digits] */ + /* Pre-computed table of base powers */ + BN_ULONG *red_table = NULL; /* [1U << exp_win_size][2][red_digits] */ + /* Expanded exponent */ + BN_ULONG *expz = NULL; /* [2][exp_digits + 1] */ + + /* Dual AMM */ + DAMM damm = NULL; + /* Extractor from red_table */ + DEXTRACT extract = NULL; + int avx512ifma = !!ossl_rsaz_avx512ifma_eligible(); + /* * Squaring is done using multiplication now. That can be a subject of * optimization in future. */ -# define DAMS(r,a,m,k0) \ - ossl_rsaz_amm52x20_x2_256((r),(a),(a),(m),(k0)) +# define DAMS(r,a,m,k0) damm((r),(a),(a),(m),(k0)) - /* Allocate stack for red(undant) result Y and multiplier X */ - ALIGN64 BN_ULONG red_Y[2][RED_DIGITS]; - ALIGN64 BN_ULONG red_X[2][RED_DIGITS]; + if (modulus_bitsize != 1024 && modulus_bitsize != 1536 && modulus_bitsize != 2048) + goto err; - /* Allocate expanded exponent */ - ALIGN64 BN_ULONG expz[2][EXP_DIGITS + 1]; + damm = ossl_rsaz_amm52_x2[(modulus_bitsize / 512 - 2) * 2 + avx512ifma]; + extract = ossl_extract_multiplier_win5[(modulus_bitsize / 512 - 2) * 2 + avx512ifma]; - /* Pre-computed table of base powers */ - ALIGN64 BN_ULONG red_table[1U << EXP_WIN_SIZE][2][RED_DIGITS]; + switch (modulus_bitsize) { + case 1024: + red_digits = 20; + exp_digits = 16; + break; + case 1536: + /* Extended with 2 digits padding to avoid mask ops in high YMM register */ + red_digits = 30 + 2; + exp_digits = 24; + break; + case 2048: + red_digits = 40; + exp_digits = 32; + break; + default: + goto err; + } - int idx; + storage_len_bytes = (2 * red_digits /* red_Y */ + + 2 * red_digits /* red_X */ + + 2 * red_digits * (1U << exp_win_size) /* red_table */ + + 2 * (exp_digits + 1)) /* expz */ + * sizeof(BN_ULONG) + + 64; /* alignment */ - memset(red_Y, 0, sizeof(red_Y)); - memset(red_table, 0, sizeof(red_table)); - memset(red_X, 0, sizeof(red_X)); + storage = (BN_ULONG *)OPENSSL_zalloc(storage_len_bytes); + if (storage == NULL) + goto err; + storage_aligned = (BN_ULONG *)ALIGN_OF(storage, 64); + + red_Y = storage_aligned; + red_X = red_Y + 2 * red_digits; + red_table = red_X + 2 * red_digits; + expz = red_table + 2 * red_digits * (1U << exp_win_size); /* * Compute table of powers base^i, i = 0, ..., (2^EXP_WIN_SIZE) - 1 * table[0] = mont(x^0) = mont(1) * table[1] = mont(x^1) = mont(x) */ - red_X[0][0] = 1; - red_X[1][0] = 1; - DAMM(red_table[0][0], (const BN_ULONG*)red_X, rr, m, k0); - DAMM(red_table[1][0], base, rr, m, k0); + red_X[0 * red_digits] = 1; + red_X[1 * red_digits] = 1; + damm(&red_table[0 * 2 * red_digits], (const BN_ULONG*)red_X, rr, m, k0); + damm(&red_table[1 * 2 * red_digits], base, rr, m, k0); - for (idx = 1; idx < (int)((1U << EXP_WIN_SIZE) / 2); idx++) { - DAMS(red_table[2 * idx + 0][0], red_table[1 * idx][0], m, k0); - DAMM(red_table[2 * idx + 1][0], red_table[2 * idx][0], red_table[1][0], m, k0); + for (idx = 1; idx < (int)((1U << exp_win_size) / 2); idx++) { + DAMS(&red_table[(2 * idx + 0) * 2 * red_digits], + &red_table[(1 * idx) * 2 * red_digits], m, k0); + damm(&red_table[(2 * idx + 1) * 2 * red_digits], + &red_table[(2 * idx) * 2 * red_digits], + &red_table[1 * 2 * red_digits], m, k0); } /* Copy and expand exponents */ - memcpy(expz[0], exp[0], EXP_DIGITS * sizeof(BN_ULONG)); - expz[0][EXP_DIGITS] = 0; - memcpy(expz[1], exp[1], EXP_DIGITS * sizeof(BN_ULONG)); - expz[1][EXP_DIGITS] = 0; + memcpy(&expz[0 * (exp_digits + 1)], exp[0], exp_digits * sizeof(BN_ULONG)); + expz[1 * (exp_digits + 1) - 1] = 0; + memcpy(&expz[1 * (exp_digits + 1)], exp[1], exp_digits * sizeof(BN_ULONG)); + expz[2 * (exp_digits + 1) - 1] = 0; /* Exponentiation */ { - const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; - BN_ULONG table_idx_mask = EXP_WIN_MASK; + const int rem = modulus_bitsize % exp_win_size; + const BN_ULONG table_idx_mask = exp_win_mask; - int exp_bit_no = BITSIZE_MODULUS - rem; + int exp_bit_no = modulus_bitsize - rem; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; @@ -337,8 +469,9 @@ static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */ OPENSSL_assert(rem != 0); /* Process 1-st exp window - just init result */ - red_table_idx_0 = expz[0][exp_chunk_no]; - red_table_idx_1 = expz[1][exp_chunk_no]; + red_table_idx_0 = expz[exp_chunk_no + 0 * (exp_digits + 1)]; + red_table_idx_1 = expz[exp_chunk_no + 1 * (exp_digits + 1)]; + /* * The function operates with fixed moduli sizes divisible by 64, * thus table index here is always in supported range [0, EXP_WIN_SIZE). @@ -346,13 +479,10 @@ static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */ red_table_idx_0 >>= exp_chunk_shift; red_table_idx_1 >>= exp_chunk_shift; - ossl_extract_multiplier_2x20_win5(red_Y[0], (const BN_ULONG*)red_table, - (int)red_table_idx_0, 0); - ossl_extract_multiplier_2x20_win5(red_Y[1], (const BN_ULONG*)red_table, - (int)red_table_idx_1, 1); + extract(&red_Y[0 * red_digits], (const BN_ULONG*)red_table, (int)red_table_idx_0, (int)red_table_idx_1); /* Process other exp windows */ - for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { + for (exp_bit_no -= exp_win_size; exp_bit_no >= 0; exp_bit_no -= exp_win_size) { /* Extract pre-computed multiplier from the table */ { BN_ULONG T; @@ -360,43 +490,37 @@ static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */ exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; { - red_table_idx_0 = expz[0][exp_chunk_no]; - T = expz[0][exp_chunk_no + 1]; + red_table_idx_0 = expz[exp_chunk_no + 0 * (exp_digits + 1)]; + T = expz[exp_chunk_no + 1 + 0 * (exp_digits + 1)]; red_table_idx_0 >>= exp_chunk_shift; /* * Get additional bits from then next quadword * when 64-bit boundaries are crossed. */ - if (exp_chunk_shift > 64 - EXP_WIN_SIZE) { + if (exp_chunk_shift > 64 - exp_win_size) { T <<= (64 - exp_chunk_shift); red_table_idx_0 ^= T; } red_table_idx_0 &= table_idx_mask; - - ossl_extract_multiplier_2x20_win5(red_X[0], - (const BN_ULONG*)red_table, - (int)red_table_idx_0, 0); } { - red_table_idx_1 = expz[1][exp_chunk_no]; - T = expz[1][exp_chunk_no + 1]; + red_table_idx_1 = expz[exp_chunk_no + 1 * (exp_digits + 1)]; + T = expz[exp_chunk_no + 1 + 1 * (exp_digits + 1)]; red_table_idx_1 >>= exp_chunk_shift; /* * Get additional bits from then next quadword * when 64-bit boundaries are crossed. */ - if (exp_chunk_shift > 64 - EXP_WIN_SIZE) { + if (exp_chunk_shift > 64 - exp_win_size) { T <<= (64 - exp_chunk_shift); red_table_idx_1 ^= T; } red_table_idx_1 &= table_idx_mask; - - ossl_extract_multiplier_2x20_win5(red_X[1], - (const BN_ULONG*)red_table, - (int)red_table_idx_1, 1); } + + extract(&red_X[0 * red_digits], (const BN_ULONG*)red_table, (int)red_table_idx_0, (int)red_table_idx_1); } /* Series of squaring */ @@ -406,43 +530,46 @@ static void RSAZ_exp52x20_x2_256(BN_ULONG *out, /* [2][20] */ DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0); DAMS((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, m, k0); - DAMM((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0); + damm((BN_ULONG*)red_Y, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0); } } /* * * NB: After the last AMM of exponentiation in Montgomery domain, the result - * may be 1025-bit, but the conversion out of Montgomery domain performs an - * AMM(x,1) which guarantees that the final result is less than |m|, so no - * conditional subtraction is needed here. See "Efficient Software - * Implementations of Modular Exponentiation" (by Shay Gueron) paper for details. + * may be (modulus_bitsize + 1), but the conversion out of Montgomery domain + * performs an AMM(x,1) which guarantees that the final result is less than + * |m|, so no conditional subtraction is needed here. See [1] for details. + * + * [1] Gueron, S. Efficient software implementations of modular exponentiation. + * DOI: 10.1007/s13389-012-0031-5 */ /* Convert result back in regular 2^52 domain */ - memset(red_X, 0, sizeof(red_X)); - red_X[0][0] = 1; - red_X[1][0] = 1; - DAMM(out, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0); + memset(red_X, 0, 2 * red_digits * sizeof(BN_ULONG)); + red_X[0 * red_digits] = 1; + red_X[1 * red_digits] = 1; + damm(out, (const BN_ULONG*)red_Y, (const BN_ULONG*)red_X, m, k0); - /* Clear exponents */ - OPENSSL_cleanse(expz, sizeof(expz)); - OPENSSL_cleanse(red_Y, sizeof(red_Y)); + ret = 1; -# undef DAMS -# undef DAMM -# undef EXP_DIGITS -# undef RED_DIGITS -# undef EXP_WIN_MASK -# undef EXP_WIN_SIZE -# undef BITSIZE_MODULUS +err: + if (storage != NULL) { + /* Clear whole storage */ + OPENSSL_cleanse(storage, storage_len_bytes); + OPENSSL_free(storage); + } + +#undef DAMS + return ret; } -static ossl_inline uint64_t get_digit52(const uint8_t *in, int in_len) +static ossl_inline uint64_t get_digit(const uint8_t *in, int in_len) { uint64_t digit = 0; assert(in != NULL); + assert(in_len <= 8); for (; in_len > 0; in_len--) { digit <<= 8; @@ -480,17 +607,17 @@ static void to_words52(BN_ULONG *out, int out_len, } if (in_bitsize > DIGIT_SIZE) { - uint64_t digit = get_digit52(in_str, 7); + uint64_t digit = get_digit(in_str, 7); out[0] = digit & DIGIT_MASK; in_str += 6; in_bitsize -= DIGIT_SIZE; - digit = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize)); + digit = get_digit(in_str, BITS2WORD8_SIZE(in_bitsize)); out[1] = digit >> 4; out += 2; out_len -= 2; } else if (in_bitsize > 0) { - out[0] = get_digit52(in_str, BITS2WORD8_SIZE(in_bitsize)); + out[0] = get_digit(in_str, BITS2WORD8_SIZE(in_bitsize)); out++; out_len--; } @@ -498,12 +625,13 @@ static void to_words52(BN_ULONG *out, int out_len, memset(out, 0, out_len * sizeof(BN_ULONG)); } -static ossl_inline void put_digit52(uint8_t *pStr, int strLen, uint64_t digit) +static ossl_inline void put_digit(uint8_t *out, int out_len, uint64_t digit) { - assert(pStr != NULL); + assert(out != NULL); + assert(out_len <= 8); - for (; strLen > 0; strLen--) { - *pStr++ = (uint8_t)(digit & 0xFF); + for (; out_len > 0; out_len--) { + *out++ = (uint8_t)(digit & 0xFF); digit >>= 8; } } @@ -539,13 +667,13 @@ static void from_words52(BN_ULONG *out, int out_bitsize, const BN_ULONG *in) } if (out_bitsize > DIGIT_SIZE) { - put_digit52(out_str, 7, in[0]); + put_digit(out_str, 7, in[0]); out_str += 6; out_bitsize -= DIGIT_SIZE; - put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize), + put_digit(out_str, BITS2WORD8_SIZE(out_bitsize), (in[1] << 4 | in[0] >> 48)); } else if (out_bitsize) { - put_digit52(out_str, BITS2WORD8_SIZE(out_bitsize), in[0]); + put_digit(out_str, BITS2WORD8_SIZE(out_bitsize), in[0]); } } } diff --git a/crypto/buffer/buffer.c b/crypto/buffer/buffer.c index db1ea38b195a..3394342986f6 100644 --- a/crypto/buffer/buffer.c +++ b/crypto/buffer/buffer.c @@ -33,10 +33,8 @@ BUF_MEM *BUF_MEM_new(void) BUF_MEM *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } return ret; } @@ -87,7 +85,7 @@ size_t BUF_MEM_grow(BUF_MEM *str, size_t len) } /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ if (len > LIMIT_BEFORE_EXPANSION) { - ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BUF, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } n = (len + 3) / 3 * 4; @@ -96,7 +94,6 @@ size_t BUF_MEM_grow(BUF_MEM *str, size_t len) else ret = OPENSSL_realloc(str->data, n); if (ret == NULL) { - ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); len = 0; } else { str->data = ret; @@ -125,7 +122,7 @@ size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) } /* This limit is sufficient to ensure (len+3)/3*4 < 2**31 */ if (len > LIMIT_BEFORE_EXPANSION) { - ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_BUF, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } n = (len + 3) / 3 * 4; @@ -134,7 +131,6 @@ size_t BUF_MEM_grow_clean(BUF_MEM *str, size_t len) else ret = OPENSSL_clear_realloc(str->data, str->max, n); if (ret == NULL) { - ERR_raise(ERR_LIB_BUF, ERR_R_MALLOC_FAILURE); len = 0; } else { str->data = ret; diff --git a/crypto/build.info b/crypto/build.info index a45bf8deefd5..aee5c467668a 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -1,12 +1,12 @@ # 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 \ +SUBDIRS=objects buffer bio stack lhash hashtable rand evp asn1 pem x509 conf \ txt_db pkcs7 pkcs12 ui kdf store property \ - md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \ + md2 md4 md5 sha mdc2 ml_kem 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 + ffc hpke thread ml_dsa slh_dsa LIBS=../libcrypto @@ -51,6 +51,10 @@ IF[{- !$disabled{asm} && $config{processor} ne '386' -}] $CPUIDASM_c64xplus=c64xpluscpuid.s + $CPUIDASM_riscv64=riscvcap.c riscv64cpuid.s + $CPUIDASM_riscv32=riscvcap.c riscv32cpuid.s + + $CPUIDASM_loongarch64=loongarchcap.c loongarch64cpuid.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} -}] @@ -87,7 +91,7 @@ DEFINE[../providers/libdefault.a]=$CPUIDDEF $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[../libcrypto]=$CORE_COMMON provider_conf.c indicator_core.c SOURCE[../providers/libfips.a]=$CORE_COMMON # Central utilities @@ -95,13 +99,15 @@ $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 + param_build_set.c der_writer.c threads_lib.c params_dup.c \ + time.c params_idx.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 + comp_methods.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 sleep.c deterministic_nonce.c \ + quic_vlint.c time.c defaults.c ssl_err.c SOURCE[../providers/libfips.a]=$UTIL_COMMON SOURCE[../libcrypto]=$UPLINKSRC @@ -130,7 +136,10 @@ GENERATE[armv4cpuid.S]=armv4cpuid.pl INCLUDE[armv4cpuid.o]=. GENERATE[s390xcpuid.S]=s390xcpuid.pl INCLUDE[s390xcpuid.o]=. +GENERATE[riscv64cpuid.s]=riscv64cpuid.pl +GENERATE[riscv32cpuid.s]=riscv32cpuid.pl +GENERATE[loongarch64cpuid.s]=loongarch64cpuid.pl IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] SHARED_SOURCE[../libcrypto]=dllmain.c ENDIF diff --git a/crypto/camellia/asm/cmll-x86_64.pl b/crypto/camellia/asm/cmll-x86_64.pl index 7e069614d915..43023a6986b5 100644 --- a/crypto/camellia/asm/cmll-x86_64.pl +++ b/crypto/camellia/asm/cmll-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -657,6 +657,7 @@ sub S0222 { my $i=shift; $i=@SBOX[$i]; $i=($i<<1|$i>>7)&0xff; $i=$i<<16|$i<<8|$i sub S3033 { my $i=shift; $i=@SBOX[$i]; $i=($i>>1|$i<<7)&0xff; $i=$i<<24|$i<<8|$i; sprintf("0x%08x",$i); } $code.=<<___; +.section .rodata align=64 .align 64 .LCamellia_SIGMA: .long 0x3bcc908b, 0xa09e667f, 0x4caa73b2, 0xb67ae858 @@ -682,6 +683,7 @@ $_ivp="40(%rsp)"; $_rsp="48(%rsp)"; $code.=<<___; +.text .globl Camellia_cbc_encrypt .type Camellia_cbc_encrypt,\@function,6 .align 16 diff --git a/crypto/cast/cast_local.h b/crypto/cast/cast_local.h index 4434a342002a..e99fe0882ae7 100644 --- a/crypto/cast/cast_local.h +++ b/crypto/cast/cast_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2017 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 @@ -11,70 +11,25 @@ # include #endif -#undef c2l -#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ - l|=((unsigned long)(*((c)++)))<< 8L, \ - l|=((unsigned long)(*((c)++)))<<16L, \ - l|=((unsigned long)(*((c)++)))<<24L) - -/* NOTE - c is not incremented as per c2l */ -#undef c2ln -#define c2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ - case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ - case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ - case 5: l2|=((unsigned long)(*(--(c)))); \ - case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ - case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ - case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ - case 1: l1|=((unsigned long)(*(--(c)))); \ - } \ - } - -#undef l2c -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24L)&0xff)) - -/* NOTE - c is not incremented as per l2c */ -#undef l2cn -#define l2cn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ - } \ - } - /* NOTE - c is not incremented as per n2l */ #define n2ln(c,l1,l2,n) { \ c+=n; \ l1=l2=0; \ switch (n) { \ case 8: l2 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((unsigned long)(*(--(c))))<<24; \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((unsigned long)(*(--(c))))<<24; \ } \ } @@ -84,19 +39,19 @@ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ } \ } diff --git a/crypto/chacha/asm/chacha-armv4.pl b/crypto/chacha/asm/chacha-armv4.pl index 0aa13519eb83..bb48b6eeb99e 100755 --- a/crypto/chacha/asm/chacha-armv4.pl +++ b/crypto/chacha/asm/chacha-armv4.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2020 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 @@ -1154,7 +1154,8 @@ $code.=<<___; add sp,sp,#4*(16+3) ldmia sp!,{r4-r11,pc} .size ChaCha20_neon,.-ChaCha20_neon -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ }}} diff --git a/crypto/chacha/asm/chacha-armv8.pl b/crypto/chacha/asm/chacha-armv8.pl index dcdc4a04e367..8ed2a1a32649 100755 --- a/crypto/chacha/asm/chacha-armv8.pl +++ b/crypto/chacha/asm/chacha-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -132,13 +132,15 @@ my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2)); } $code.=<<___; +#include "arm_arch.h" #ifndef __KERNEL__ -# include "arm_arch.h" .extern OPENSSL_armcap_P .hidden OPENSSL_armcap_P + +.extern ChaCha20_ctr32_sve #endif -.text +.rodata .align 5 .Lsigma: @@ -149,27 +151,29 @@ $code.=<<___; .long 0x02010003,0x06050407,0x0a09080b,0x0e0d0c0f .asciz "ChaCha20 for ARMv8, CRYPTOGAMS by \@dot-asm" -.globl ChaCha20_ctr32 -.type ChaCha20_ctr32,%function +.text + +.globl ChaCha20_ctr32_dflt +.type ChaCha20_ctr32_dflt,%function .align 5 -ChaCha20_ctr32: - cbz $len,.Labort +ChaCha20_ctr32_dflt: + AARCH64_SIGN_LINK_REGISTER cmp $len,#192 b.lo .Lshort - #ifndef __KERNEL__ adrp x17,OPENSSL_armcap_P ldr w17,[x17,#:lo12:OPENSSL_armcap_P] +.Lcheck_neon: tst w17,#ARMV7_NEON b.ne .LChaCha20_neon #endif .Lshort: - .inst 0xd503233f // paciasp stp x29,x30,[sp,#-96]! add x29,sp,#0 - adr @x[0],.Lsigma + adrp @x[0],.Lsigma + add @x[0],@x[0],:lo12:.Lsigma stp x19,x20,[sp,#16] stp x21,x22,[sp,#32] stp x23,x24,[sp,#48] @@ -285,8 +289,8 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp .Labort: + AARCH64_VALIDATE_LINK_REGISTER ret .align 4 @@ -342,8 +346,43 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret +.size ChaCha20_ctr32_dflt,.-ChaCha20_ctr32_dflt + +.globl ChaCha20_ctr32 +.type ChaCha20_ctr32,%function +.align 5 +ChaCha20_ctr32: + AARCH64_SIGN_LINK_REGISTER + cbz $len,.Labort + cmp $len,#192 + b.lo .Lshort +#ifndef __KERNEL__ + adrp x17,OPENSSL_armcap_P + ldr w17,[x17,#:lo12:OPENSSL_armcap_P] + tst w17,#ARMV8_SVE + b.eq .Lcheck_neon + stp x29,x30,[sp,#-16]! + sub sp,sp,#16 + // SVE handling will inevitably increment the counter + // Neon/Scalar code that follows to process tail data needs to + // use new counter, unfortunately the input counter buffer + // pointed to by ctr is meant to be read-only per API contract + // we have to copy the buffer to stack to be writable by SVE + ldp x5,x6,[$ctr] + stp x5,x6,[sp] + mov $ctr,sp + bl ChaCha20_ctr32_sve + cbz $len,1f + bl ChaCha20_ctr32_dflt +1: + add sp,sp,#16 + ldp x29,x30,[sp],#16 + AARCH64_VALIDATE_LINK_REGISTER + ret +#endif + b .Lshort .size ChaCha20_ctr32,.-ChaCha20_ctr32 ___ @@ -432,12 +471,13 @@ $code.=<<___; .type ChaCha20_neon,%function .align 5 ChaCha20_neon: + AARCH64_SIGN_LINK_REGISTER .LChaCha20_neon: - .inst 0xd503233f // paciasp stp x29,x30,[sp,#-96]! add x29,sp,#0 - adr @x[0],.Lsigma + adrp @x[0],.Lsigma + add @x[0],@x[0],:lo12:.Lsigma stp x19,x20,[sp,#16] stp x21,x22,[sp,#32] stp x23,x24,[sp,#48] @@ -667,7 +707,7 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .align 4 @@ -799,7 +839,7 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ChaCha20_neon,.-ChaCha20_neon ___ @@ -844,11 +884,12 @@ $code.=<<___; .type ChaCha20_512_neon,%function .align 5 ChaCha20_512_neon: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-96]! add x29,sp,#0 - adr @x[0],.Lsigma + adrp @x[0],.Lsigma + add @x[0],@x[0],:lo12:.Lsigma stp x19,x20,[sp,#16] stp x21,x22,[sp,#32] stp x23,x24,[sp,#48] @@ -1268,7 +1309,7 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ChaCha20_512_neon,.-ChaCha20_512_neon ___ diff --git a/crypto/chacha/asm/chacha-x86_64.pl b/crypto/chacha/asm/chacha-x86_64.pl index cdb900c037fd..5506e33fa2d0 100755 --- a/crypto/chacha/asm/chacha-x86_64.pl +++ b/crypto/chacha/asm/chacha-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -102,6 +102,7 @@ $code.=<<___; .extern OPENSSL_ia32cap_P +.section .rodata align=64 .align 64 .Lzero: .long 0,0,0,0 @@ -133,6 +134,7 @@ $code.=<<___; .Lsigma: .asciz "expand 32-byte k" .asciz "ChaCha20 for x86_64, CRYPTOGAMS by " +.previous ___ sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm diff --git a/crypto/chacha/build.info b/crypto/chacha/build.info index e7159dc066dc..c151e190429d 100644 --- a/crypto/chacha/build.info +++ b/crypto/chacha/build.info @@ -10,31 +10,48 @@ IF[{- !$disabled{asm} -}] $CHACHAASM_s390x=chacha-s390x.S $CHACHAASM_armv4=chacha-armv4.S - $CHACHAASM_aarch64=chacha-armv8.S + $CHACHAASM_aarch64=chacha-armv8.S chacha-armv8-sve.S + + $CHACHAASM_loongarch64=chacha-loongarch64.S $CHACHAASM_ppc32=chacha_ppc.c chacha-ppc.s + IF[{- $target{sys_id} ne "AIX" && $target{sys_id} ne "MACOSX" -}] + $CHACHAASM_ppc32=chacha_ppc.c chacha-ppc.s chachap10-ppc.s + ENDIF $CHACHAASM_ppc64=$CHACHAASM_ppc32 $CHACHAASM_c64xplus=chacha-c64xplus.s + $CHACHAASM_riscv64=chacha_riscv.c chacha_enc.c chacha-riscv64-v-zbb.s chacha-riscv64-v-zbb-zvkb.s + $CHACHADEF_riscv64=INCLUDE_C_CHACHA20 + # Now that we have defined all the arch specific variables, use the # appropriate one IF[$CHACHAASM_{- $target{asm_arch} -}] $CHACHAASM=$CHACHAASM_{- $target{asm_arch} -} + $CHACHADEF=$CHACHADEF_{- $target{asm_arch} -} ENDIF ENDIF SOURCE[../../libcrypto]=$CHACHAASM +DEFINE[../../libcrypto]=$CHACHADEF GENERATE[chacha-x86.S]=asm/chacha-x86.pl GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl GENERATE[chacha-ppc.s]=asm/chacha-ppc.pl +GENERATE[chachap10-ppc.s]=asm/chachap10-ppc.pl GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl INCLUDE[chacha-armv4.o]=.. GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl +GENERATE[chacha-armv8-sve.S]=asm/chacha-armv8-sve.pl INCLUDE[chacha-armv8.o]=.. +INCLUDE[chacha-armv8-sve.o]=.. +INCLUDE[chacha-loongarch64.o]=.. INCLUDE[chacha-s390x.o]=.. GENERATE[chacha-c64xplus.S]=asm/chacha-c64xplus.pl GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl GENERATE[chacha-ia64.S]=asm/chacha-ia64.pl GENERATE[chacha-ia64.s]=chacha-ia64.S +GENERATE[chacha-loongarch64.S]=asm/chacha-loongarch64.pl +GENERATE[chacha-riscv64-v-zbb.s]=asm/chacha-riscv64-v-zbb.pl +GENERATE[chacha-riscv64-v-zbb-zvkb.s]=asm/chacha-riscv64-v-zbb.pl zvkb diff --git a/crypto/chacha/chacha_enc.c b/crypto/chacha/chacha_enc.c index c5d1d63d8027..f6fbc119885a 100644 --- a/crypto/chacha/chacha_enc.c +++ b/crypto/chacha/chacha_enc.c @@ -24,6 +24,28 @@ typedef union { # define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) +# ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && \ + !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if defined(__riscv_zbb) || defined(__riscv_zbkb) +# if __riscv_xlen == 64 +# undef ROTATE +# define ROTATE(x, n) ({ u32 ret; \ + asm ("roriw %0, %1, %2" \ + : "=r"(ret) \ + : "r"(x), "i"(32 - (n))); ret;}) +# endif +# if __riscv_xlen == 32 +# undef ROTATE +# define ROTATE(x, n) ({ u32 ret; \ + asm ("rori %0, %1, %2" \ + : "=r"(ret) \ + : "r"(x), "i"(32 - (n))); ret;}) +# endif +# endif +# endif +# endif + # define U32TO8_LITTLE(p, v) do { \ (p)[0] = (u8)(v >> 0); \ (p)[1] = (u8)(v >> 8); \ @@ -68,9 +90,13 @@ static void chacha20_core(chacha_buf *output, const u32 input[16]) } } -void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, - size_t len, const unsigned int key[8], - const unsigned int counter[4]) +#ifdef INCLUDE_C_CHACHA20 +void ChaCha20_ctr32_c(unsigned char *out, const unsigned char *inp, size_t len, + const unsigned int key[8], const unsigned int counter[4]) +#else +void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len, + const unsigned int key[8], const unsigned int counter[4]) +#endif { u32 input[16]; chacha_buf buf; diff --git a/crypto/chacha/chacha_ppc.c b/crypto/chacha/chacha_ppc.c index 5319040cc167..91ed85eaf02b 100644 --- a/crypto/chacha/chacha_ppc.c +++ b/crypto/chacha/chacha_ppc.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved. + * 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 @@ -23,13 +23,20 @@ void ChaCha20_ctr32_vmx(unsigned char *out, const unsigned char *inp, void ChaCha20_ctr32_vsx(unsigned char *out, const unsigned char *inp, size_t len, const unsigned int key[8], const unsigned int counter[4]); +void ChaCha20_ctr32_vsx_p10(unsigned char *out, const unsigned char *inp, + size_t len, const unsigned int key[8], + const unsigned int counter[4]); void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len, const unsigned int key[8], const unsigned int counter[4]) { - OPENSSL_ppccap_P & PPC_CRYPTO207 - ? ChaCha20_ctr32_vsx(out, inp, len, key, counter) - : OPENSSL_ppccap_P & PPC_ALTIVEC - ? ChaCha20_ctr32_vmx(out, inp, len, key, counter) - : ChaCha20_ctr32_int(out, inp, len, key, counter); +#if !defined(OPENSSL_SYS_AIX) && !defined(OPENSSL_SYS_MACOSX) + OPENSSL_ppccap_P & PPC_BRD31 + ? ChaCha20_ctr32_vsx_p10(out, inp, len, key, counter) : +#endif + OPENSSL_ppccap_P & PPC_CRYPTO207 + ? ChaCha20_ctr32_vsx(out, inp, len, key, counter) + : OPENSSL_ppccap_P & PPC_ALTIVEC + ? ChaCha20_ctr32_vmx(out, inp, len, key, counter) + : ChaCha20_ctr32_int(out, inp, len, key, counter); } diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c index 7f94727085e5..16f4b904ad85 100644 --- a/crypto/cmac/cmac.c +++ b/crypto/cmac/cmac.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,7 +19,9 @@ #include "internal/cryptlib.h" #include #include +#include "crypto/cmac.h" +#define LOCAL_BUF_SIZE 2048 struct CMAC_CTX_st { /* Cipher context to use */ EVP_CIPHER_CTX *cctx; @@ -53,10 +55,8 @@ CMAC_CTX *CMAC_CTX_new(void) { CMAC_CTX *ctx; - if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL) return NULL; - } ctx->cctx = EVP_CIPHER_CTX_new(); if (ctx->cctx == NULL) { OPENSSL_free(ctx); @@ -96,7 +96,7 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) if (in->nlast_block == -1) return 0; - if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) < 0) + if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) == 0) return 0; if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx)) return 0; @@ -108,19 +108,24 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in) return 1; } -int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, - const EVP_CIPHER *cipher, ENGINE *impl) +int ossl_cmac_init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl, + const OSSL_PARAM param[]) { static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 }; + int block_len; /* All zeros means restart */ if (!key && !cipher && !impl && keylen == 0) { /* Not initialised */ if (ctx->nlast_block == -1) return 0; - if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) + if (!EVP_EncryptInit_ex2(ctx->cctx, NULL, NULL, zero_iv, param)) return 0; - memset(ctx->tbl, 0, EVP_CIPHER_CTX_get_block_size(ctx->cctx)); + block_len = EVP_CIPHER_CTX_get_block_size(ctx->cctx); + if (block_len == 0) + return 0; + memset(ctx->tbl, 0, block_len); ctx->nlast_block = 0; return 1; } @@ -128,8 +133,13 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, if (cipher != NULL) { /* Ensure we can't use this ctx until we also have a key */ ctx->nlast_block = -1; - if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL)) - return 0; + if (impl != NULL) { + if (!EVP_EncryptInit_ex(ctx->cctx, cipher, impl, NULL, NULL)) + return 0; + } else { + if (!EVP_EncryptInit_ex2(ctx->cctx, cipher, NULL, NULL, param)) + return 0; + } } /* Non-NULL key means initialisation complete */ if (key != NULL) { @@ -141,7 +151,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, return 0; if (EVP_CIPHER_CTX_set_key_length(ctx->cctx, keylen) <= 0) return 0; - if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, key, zero_iv)) + if (!EVP_EncryptInit_ex2(ctx->cctx, NULL, key, zero_iv, param)) return 0; if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) return 0; @@ -151,7 +161,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, make_kn(ctx->k2, ctx->k1, bl); OPENSSL_cleanse(ctx->tbl, bl); /* Reset context again ready for first data block */ - if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv)) + if (!EVP_EncryptInit_ex2(ctx->cctx, NULL, NULL, zero_iv, param)) return 0; /* Zero tbl so resume works */ memset(ctx->tbl, 0, bl); @@ -160,16 +170,24 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, return 1; } +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl) +{ + return ossl_cmac_init(ctx, key, keylen, cipher, impl, NULL); +} + int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) { const unsigned char *data = in; int bl; + size_t max_burst_blocks, cipher_blocks; + unsigned char buf[LOCAL_BUF_SIZE]; if (ctx->nlast_block == -1) return 0; if (dlen == 0) return 1; - if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) + if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0) return 0; /* Copy into partial block if we need to */ if (ctx->nlast_block > 0) { @@ -190,11 +208,35 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen) return 0; } /* Encrypt all but one of the complete blocks left */ - while (dlen > (size_t)bl) { - if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0) - return 0; - dlen -= bl; - data += bl; + + max_burst_blocks = LOCAL_BUF_SIZE / bl; + cipher_blocks = (dlen - 1) / bl; + if (max_burst_blocks == 0) { + /* + * When block length is greater than local buffer size, + * use ctx->tbl as cipher output. + */ + while (dlen > (size_t)bl) { + if (EVP_Cipher(ctx->cctx, ctx->tbl, data, bl) <= 0) + return 0; + dlen -= bl; + data += bl; + } + } else { + while (cipher_blocks > max_burst_blocks) { + if (EVP_Cipher(ctx->cctx, buf, data, max_burst_blocks * bl) <= 0) + return 0; + dlen -= max_burst_blocks * bl; + data += max_burst_blocks * bl; + cipher_blocks -= max_burst_blocks; + } + if (cipher_blocks > 0) { + if (EVP_Cipher(ctx->cctx, buf, data, cipher_blocks * bl) <= 0) + return 0; + dlen -= cipher_blocks * bl; + data += cipher_blocks * bl; + memcpy(ctx->tbl, &buf[(cipher_blocks - 1) * bl], bl); + } } /* Copy any data left to last block buffer */ memcpy(ctx->last_block, data, dlen); @@ -209,7 +251,7 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen) if (ctx->nlast_block == -1) return 0; - if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0) + if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0) return 0; if (poutlen != NULL) *poutlen = (size_t)bl; diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info index a2a57c14ec10..907d78d25ffb 100644 --- a/crypto/cmp/build.info +++ b/crypto/cmp/build.info @@ -1,4 +1,11 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \ +$OPENSSLSRC=\ + cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \ cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \ - cmp_server.c cmp_client.c cmp_http.c + cmp_server.c cmp_client.c cmp_genm.c + +IF[{- !$disabled{'http'} -}] + $OPENSSLSRC=$OPENSSLSRC cmp_http.c +ENDIF + +SOURCE[../../libcrypto]=$OPENSSLSRC diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c index a8de73ad979b..a32632026743 100644 --- a/crypto/cmp/cmp_asn.c +++ b/crypto/cmp/cmp_asn.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -12,6 +12,7 @@ #include #include "cmp_local.h" +#include "internal/crmf.h" /* explicit #includes not strictly needed since implied by the above: */ #include @@ -28,7 +29,6 @@ ASN1_SEQUENCE(OSSL_CMP_REVANNCONTENT) = { } ASN1_SEQUENCE_END(OSSL_CMP_REVANNCONTENT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT) - ASN1_SEQUENCE(OSSL_CMP_CHALLENGE) = { ASN1_OPT(OSSL_CMP_CHALLENGE, owf, X509_ALGOR), ASN1_SIMPLE(OSSL_CMP_CHALLENGE, witness, ASN1_OCTET_STRING), @@ -36,19 +36,16 @@ ASN1_SEQUENCE(OSSL_CMP_CHALLENGE) = { } ASN1_SEQUENCE_END(OSSL_CMP_CHALLENGE) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE) - ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYCHALLCONTENT) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_POPODECKEYCHALLCONTENT, OSSL_CMP_CHALLENGE) ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYCHALLCONTENT) - ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYRESPCONTENT) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_POPODECKEYRESPCONTENT, ASN1_INTEGER) ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYRESPCONTENT) - ASN1_SEQUENCE(OSSL_CMP_CAKEYUPDANNCONTENT) = { /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */ ASN1_SIMPLE(OSSL_CMP_CAKEYUPDANNCONTENT, oldWithNew, X509), @@ -59,15 +56,10 @@ ASN1_SEQUENCE(OSSL_CMP_CAKEYUPDANNCONTENT) = { } ASN1_SEQUENCE_END(OSSL_CMP_CAKEYUPDANNCONTENT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT) - ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = { ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI), ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - * - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails, ASN1_UTF8STRING) } ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT) @@ -119,10 +111,27 @@ ASN1_ADB(OSSL_CMP_ITAV) = { ADB_ENTRY(NID_id_it_suppLangTags, ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.suppLangTagsValue, ASN1_UTF8STRING)), + ADB_ENTRY(NID_id_it_caCerts, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.caCerts, X509)), + ADB_ENTRY(NID_id_it_rootCaCert, + ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaCert, X509)), + ADB_ENTRY(NID_id_it_rootCaKeyUpdate, + ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate, + OSSL_CMP_ROOTCAKEYUPDATE)), + ADB_ENTRY(NID_id_it_certReqTemplate, + ASN1_OPT(OSSL_CMP_ITAV, infoValue.certReqTemplate, + OSSL_CMP_CERTREQTEMPLATE)), + ADB_ENTRY(NID_id_it_certProfile, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile, + ASN1_UTF8STRING)), + ADB_ENTRY(NID_id_it_crlStatusList, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crlStatusList, + OSSL_CMP_CRLSTATUS)), + ADB_ENTRY(NID_id_it_crls, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crls, X509_CRL)) } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0, &infotypeandvalue_default_tt, NULL); - ASN1_SEQUENCE(OSSL_CMP_ITAV) = { ASN1_SIMPLE(OSSL_CMP_ITAV, infoType, ASN1_OBJECT), ASN1_ADB_OBJECT(OSSL_CMP_ITAV) @@ -130,6 +139,41 @@ ASN1_SEQUENCE(OSSL_CMP_ITAV) = { IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ITAV) IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV) +ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = { + /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */ + ASN1_SIMPLE(OSSL_CMP_ROOTCAKEYUPDATE, newWithNew, X509), + ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, newWithOld, X509, 0), + ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, oldWithNew, X509, 1) +} ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE) + +ASN1_ITEM_TEMPLATE(OSSL_CMP_ATAVS) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, + OSSL_CMP_ATAVS, OSSL_CRMF_ATTRIBUTETYPEANDVALUE) +ASN1_ITEM_TEMPLATE_END(OSSL_CMP_ATAVS) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ATAVS) + +ASN1_SEQUENCE(OSSL_CMP_CERTREQTEMPLATE) = { + ASN1_SIMPLE(OSSL_CMP_CERTREQTEMPLATE, certTemplate, OSSL_CRMF_CERTTEMPLATE), + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_CERTREQTEMPLATE, keySpec, + OSSL_CRMF_ATTRIBUTETYPEANDVALUE) +} ASN1_SEQUENCE_END(OSSL_CMP_CERTREQTEMPLATE) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE) + +ASN1_CHOICE(OSSL_CMP_CRLSOURCE) = { + ASN1_EXP(OSSL_CMP_CRLSOURCE, value.dpn, DIST_POINT_NAME, 0), + ASN1_EXP(OSSL_CMP_CRLSOURCE, value.issuer, GENERAL_NAMES, 1), +} ASN1_CHOICE_END(OSSL_CMP_CRLSOURCE) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE) +#define OSSL_CMP_CRLSOURCE_DPN 0 +#define OSSL_CMP_CRLSOURCE_ISSUER 1 + +ASN1_SEQUENCE(OSSL_CMP_CRLSTATUS) = { + ASN1_SIMPLE(OSSL_CMP_CRLSTATUS, source, OSSL_CMP_CRLSOURCE), + ASN1_OPT(OSSL_CMP_CRLSTATUS, thisUpdate, ASN1_TIME) +} ASN1_SEQUENCE_END(OSSL_CMP_CRLSTATUS) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS) + OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value) { OSSL_CMP_ITAV *itav; @@ -181,13 +225,609 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, return 1; err: - if (created != 0) { + if (created) { sk_OSSL_CMP_ITAV_free(*itav_sk_p); *itav_sk_p = NULL; } return 0; } +OSSL_CMP_ITAV +*OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile) +{ + OSSL_CMP_ITAV *itav; + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + itav->infoType = OBJ_nid2obj(NID_id_it_certProfile); + itav->infoValue.certProfile = certProfile; + return itav; +} + +int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_certProfile) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.certProfile; + return 1; +} + +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts) +{ + OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new(); + + if (itav == NULL) + return NULL; + if (sk_X509_num(caCerts) > 0 + && (itav->infoValue.caCerts = + sk_X509_deep_copy(caCerts, X509_dup, X509_free)) == NULL) { + OSSL_CMP_ITAV_free(itav); + return NULL; + } + itav->infoType = OBJ_nid2obj(NID_id_it_caCerts); + return itav; +} + +int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_caCerts) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = sk_X509_num(itav->infoValue.caCerts) > 0 + ? itav->infoValue.caCerts : NULL; + return 1; +} + +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaCert(const X509 *rootCaCert) +{ + OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new(); + + if (itav == NULL) + return NULL; + if (rootCaCert != NULL + && (itav->infoValue.rootCaCert = X509_dup(rootCaCert)) == NULL) { + OSSL_CMP_ITAV_free(itav); + return NULL; + } + itav->infoType = OBJ_nid2obj(NID_id_it_rootCaCert); + return itav; +} + +int OSSL_CMP_ITAV_get0_rootCaCert(const OSSL_CMP_ITAV *itav, X509 **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaCert) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.rootCaCert; + return 1; +} +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew, + const X509 *newWithOld, + const X509 *oldWithNew) +{ + OSSL_CMP_ITAV *itav; + OSSL_CMP_ROOTCAKEYUPDATE *upd = NULL; + + if (newWithNew != NULL) { + upd = OSSL_CMP_ROOTCAKEYUPDATE_new(); + if (upd == NULL) + return NULL; + + if ((upd->newWithNew = X509_dup(newWithNew)) == NULL) + goto err; + if (newWithOld != NULL + && (upd->newWithOld = X509_dup(newWithOld)) == NULL) + goto err; + if (oldWithNew != NULL + && (upd->oldWithNew = X509_dup(oldWithNew)) == NULL) + goto err; + } + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + goto err; + itav->infoType = OBJ_nid2obj(NID_id_it_rootCaKeyUpdate); + itav->infoValue.rootCaKeyUpdate = upd; + return itav; + + err: + OSSL_CMP_ROOTCAKEYUPDATE_free(upd); + return NULL; +} + +int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav, + X509 **newWithNew, + X509 **newWithOld, + X509 **oldWithNew) +{ + OSSL_CMP_ROOTCAKEYUPDATE *upd; + + if (itav == NULL || newWithNew == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaKeyUpdate) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + upd = itav->infoValue.rootCaKeyUpdate; + *newWithNew = upd != NULL ? upd->newWithNew : NULL; + if (newWithOld != NULL) + *newWithOld = upd != NULL ? upd->newWithOld : NULL; + if (oldWithNew != NULL) + *oldWithNew = upd != NULL ? upd->oldWithNew : NULL; + return 1; +} + +OSSL_CMP_ITAV +*OSSL_CMP_ITAV_new0_certReqTemplate(OSSL_CRMF_CERTTEMPLATE *certTemplate, + OSSL_CMP_ATAVS *keySpec) +{ + OSSL_CMP_ITAV *itav; + OSSL_CMP_CERTREQTEMPLATE *tmpl; + + if (certTemplate == NULL && keySpec != NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + itav->infoType = OBJ_nid2obj(NID_id_it_certReqTemplate); + if (certTemplate == NULL) + return itav; + + if ((tmpl = OSSL_CMP_CERTREQTEMPLATE_new()) == NULL) { + OSSL_CMP_ITAV_free(itav); + return NULL; + } + itav->infoValue.certReqTemplate = tmpl; + tmpl->certTemplate = certTemplate; + tmpl->keySpec = keySpec; + return itav; +} + +int OSSL_CMP_ITAV_get1_certReqTemplate(const OSSL_CMP_ITAV *itav, + OSSL_CRMF_CERTTEMPLATE **certTemplate, + OSSL_CMP_ATAVS **keySpec) +{ + OSSL_CMP_CERTREQTEMPLATE *tpl; + + if (itav == NULL || certTemplate == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + + *certTemplate = NULL; + if (keySpec != NULL) + *keySpec = NULL; + + if (OBJ_obj2nid(itav->infoType) != NID_id_it_certReqTemplate) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + tpl = itav->infoValue.certReqTemplate; + if (tpl == NULL) /* no requirements available */ + return 1; + + if ((*certTemplate = OSSL_CRMF_CERTTEMPLATE_dup(tpl->certTemplate)) == NULL) + return 0; + if (keySpec != NULL && tpl->keySpec != NULL) { + int i, n = sk_OSSL_CMP_ATAV_num(tpl->keySpec); + + *keySpec = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_reserve(NULL, n); + if (*keySpec == NULL) + goto err; + for (i = 0; i < n; i++) { + OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(tpl->keySpec, i); + ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */); + int nid; + const char *name; + + if (type == NULL) { + ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC, + "keySpec with index %d in certReqTemplate does not exist", + i); + goto err; + } + nid = OBJ_obj2nid(type); + + if (nid != NID_id_regCtrl_algId + && nid != NID_id_regCtrl_rsaKeyLen) { + name = OBJ_nid2ln(nid); + if (name == NULL) + name = OBJ_nid2sn(nid); + if (name == NULL) + name = ""; + ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC, + "keySpec with index %d in certReqTemplate has invalid type %s", + i, name); + goto err; + } + OSSL_CMP_ATAV_push1(keySpec, atav); + } + } + return 1; + + err: + OSSL_CRMF_CERTTEMPLATE_free(*certTemplate); + *certTemplate = NULL; + sk_OSSL_CMP_ATAV_pop_free(*keySpec, OSSL_CMP_ATAV_free); + if (keySpec != NULL) + *keySpec = NULL; + return 0; +} + +OSSL_CMP_ATAV *OSSL_CMP_ATAV_create(ASN1_OBJECT *type, ASN1_TYPE *value) +{ + OSSL_CMP_ATAV *atav; + + if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL) + return NULL; + OSSL_CMP_ATAV_set0(atav, type, value); + return atav; +} + +void OSSL_CMP_ATAV_set0(OSSL_CMP_ATAV *atav, ASN1_OBJECT *type, + ASN1_TYPE *value) +{ + atav->type = type; + atav->value.other = value; +} + +ASN1_OBJECT *OSSL_CMP_ATAV_get0_type(const OSSL_CMP_ATAV *atav) +{ + if (atav == NULL) + return NULL; + return atav->type; +} + +OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_algId(const X509_ALGOR *alg) +{ + X509_ALGOR *dup; + OSSL_CMP_ATAV *res; + + if (alg == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + if ((dup = X509_ALGOR_dup(alg)) == NULL) + return NULL; + res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_algId), + (ASN1_TYPE *)dup); + if (res == NULL) + X509_ALGOR_free(dup); + return res; +} + +X509_ALGOR *OSSL_CMP_ATAV_get0_algId(const OSSL_CMP_ATAV *atav) +{ + if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_algId) + return NULL; + return atav->value.algId; +} + +OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_rsaKeyLen(int len) +{ + ASN1_INTEGER *aint; + OSSL_CMP_ATAV *res = NULL; + + if (len <= 0) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + if ((aint = ASN1_INTEGER_new()) == NULL) + return NULL; + if (!ASN1_INTEGER_set(aint, len) + || (res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_rsaKeyLen), + (ASN1_TYPE *)aint)) == NULL) + ASN1_INTEGER_free(aint); + return res; +} + +int OSSL_CMP_ATAV_get_rsaKeyLen(const OSSL_CMP_ATAV *atav) +{ + int64_t val; + + if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_rsaKeyLen + || !ASN1_INTEGER_get_int64(&val, atav->value.rsaKeyLen)) + return -1; + if (val <= 0 || val > INT_MAX) + return -2; + return (int)val; +} + +ASN1_TYPE *OSSL_CMP_ATAV_get0_value(const OSSL_CMP_ATAV *atav) +{ + if (atav == NULL) + return NULL; + return atav->value.other; +} + +int OSSL_CMP_ATAV_push1(OSSL_CMP_ATAVS **sk_p, const OSSL_CMP_ATAV *atav) +{ + int created = 0; + OSSL_CMP_ATAV *dup; + + if (sk_p == NULL || atav == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + goto err; + } + + if (*sk_p == NULL) { + if ((*sk_p = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null()) == NULL) + goto err; + created = 1; + } + + if ((dup = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)atav)) == NULL) + goto err; + if (sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(*sk_p, dup)) + return 1; + OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(dup); + + err: + if (created) { + sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(*sk_p); + *sk_p = NULL; + } + return 0; +} + +OSSL_CMP_ITAV +*OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList) +{ + OSSL_CMP_ITAV *itav; + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + itav->infoType = OBJ_nid2obj(NID_id_it_crlStatusList); + itav->infoValue.crlStatusList = crlStatusList; + return itav; +} + +int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav, + STACK_OF(OSSL_CMP_CRLSTATUS) **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_crlStatusList) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.crlStatusList; + return 1; +} + +OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn, + const GENERAL_NAMES *issuer, + const ASN1_TIME *thisUpdate) +{ + OSSL_CMP_CRLSOURCE *crlsource; + OSSL_CMP_CRLSTATUS *crlstatus; + + if (dpn == NULL && issuer == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (dpn != NULL && issuer != NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + + if ((crlstatus = OSSL_CMP_CRLSTATUS_new()) == NULL) + return NULL; + crlsource = crlstatus->source; + + if (dpn != NULL) { + crlsource->type = OSSL_CMP_CRLSOURCE_DPN; + if ((crlsource->value.dpn = DIST_POINT_NAME_dup(dpn)) == NULL) + goto err; + } else { + crlsource->type = OSSL_CMP_CRLSOURCE_ISSUER; + if ((crlsource->value.issuer = + sk_GENERAL_NAME_deep_copy(issuer, GENERAL_NAME_dup, + GENERAL_NAME_free)) == NULL) + goto err; + } + + if (thisUpdate != NULL + && (crlstatus->thisUpdate = ASN1_TIME_dup(thisUpdate)) == NULL) + goto err; + return crlstatus; + + err: + OSSL_CMP_CRLSTATUS_free(crlstatus); + return NULL; +} + +static GENERAL_NAMES *gennames_new(const X509_NAME *nm) +{ + GENERAL_NAMES *names; + GENERAL_NAME *name = NULL; + + if ((names = sk_GENERAL_NAME_new_reserve(NULL, 1)) == NULL) + return NULL; + if (!GENERAL_NAME_set1_X509_NAME(&name, nm)) { + sk_GENERAL_NAME_free(names); + return NULL; + } + (void)sk_GENERAL_NAME_push(names, name); /* cannot fail */ + return names; +} + +static int gennames_allowed(GENERAL_NAMES *names, int only_DN) +{ + if (names == NULL) + return 0; + if (!only_DN) + return 1; + return sk_GENERAL_NAME_num(names) == 1 + && sk_GENERAL_NAME_value(names, 0)->type == GEN_DIRNAME; +} + +OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl, + const X509 *cert, int only_DN) +{ + STACK_OF(DIST_POINT) *crldps = NULL; + ISSUING_DIST_POINT *idp = NULL; + DIST_POINT_NAME *dpn = NULL; + AUTHORITY_KEYID *akid = NULL; + GENERAL_NAMES *issuers = NULL; + const GENERAL_NAMES *CRLissuer = NULL; + const ASN1_TIME *last = crl == NULL ? NULL : X509_CRL_get0_lastUpdate(crl); + OSSL_CMP_CRLSTATUS *status = NULL; + int i, NID_akid = NID_authority_key_identifier; + + /* + * Note: + * X509{,_CRL}_get_ext_d2i(..., NID, ..., NULL) return the 1st extension with + * given NID that is available, if any. If there are more, this is an error. + */ + if (cert != NULL) { + crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL); + /* if available, take the first suitable element */ + for (i = 0; i < sk_DIST_POINT_num(crldps); i++) { + DIST_POINT *dp = sk_DIST_POINT_value(crldps, i); + + if (dp == NULL) + continue; + if ((dpn = dp->distpoint) != NULL) { + CRLissuer = NULL; + break; + } + if (gennames_allowed(dp->CRLissuer, only_DN) && CRLissuer == NULL) + /* don't break because any dp->distpoint in list is preferred */ + CRLissuer = dp->CRLissuer; + } + } else { + if (crl == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + idp = X509_CRL_get_ext_d2i(crl, + NID_issuing_distribution_point, NULL, NULL); + if (idp != NULL && idp->distpoint != NULL) + dpn = idp->distpoint; + } + + if (dpn == NULL && CRLissuer == NULL) { + if (cert != NULL) { + akid = X509_get_ext_d2i(cert, NID_akid, NULL, NULL); + if (akid != NULL && gennames_allowed(akid->issuer, only_DN)) + CRLissuer = akid->issuer; + else + CRLissuer = issuers = gennames_new(X509_get_issuer_name(cert)); + } + if (CRLissuer == NULL && crl != NULL) { + akid = X509_CRL_get_ext_d2i(crl, NID_akid, NULL, NULL); + if (akid != NULL && gennames_allowed(akid->issuer, only_DN)) + CRLissuer = akid->issuer; + else + CRLissuer = issuers = gennames_new(X509_CRL_get_issuer(crl)); + } + if (CRLissuer == NULL) + goto end; + } + + status = OSSL_CMP_CRLSTATUS_new1(dpn, CRLissuer, last); + end: + sk_DIST_POINT_pop_free(crldps, DIST_POINT_free); + ISSUING_DIST_POINT_free(idp); + AUTHORITY_KEYID_free(akid); + sk_GENERAL_NAME_pop_free(issuers, GENERAL_NAME_free); + return status; +} + +int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus, + DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer, + ASN1_TIME **thisUpdate) +{ + OSSL_CMP_CRLSOURCE *crlsource; + + if (crlstatus == NULL || dpn == NULL || issuer == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + if ((crlsource = crlstatus->source) == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + if (crlsource->type == OSSL_CMP_CRLSOURCE_DPN) { + *dpn = crlsource->value.dpn; + *issuer = NULL; + } else if (crlsource->type == OSSL_CMP_CRLSOURCE_ISSUER) { + *dpn = NULL; + *issuer = crlsource->value.issuer; + } else { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + if (thisUpdate != NULL) + *thisUpdate = crlstatus->thisUpdate; + return 1; +} + +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl) +{ + OSSL_CMP_ITAV *itav; + X509_CRL *crl_copy = NULL; + STACK_OF(X509_CRL) *crls = NULL; + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + + if (crl != NULL) { + if ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL + || (crl_copy = X509_CRL_dup(crl)) == NULL + || !sk_X509_CRL_push(crls, crl_copy)) + goto err; + crl_copy = NULL; /* ownership transferred to crls */ + } + + itav->infoType = OBJ_nid2obj(NID_id_it_crls); + itav->infoValue.crls = crls; + return itav; + + err: + OPENSSL_free(crl_copy); + sk_X509_CRL_free(crls); + OSSL_CMP_ITAV_free(itav); + return NULL; +} + +int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_crls) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.crls; + return 1; +} + /* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a) { @@ -209,7 +849,7 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a) } static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval, - const ASN1_ITEM *it, void *exarg) + ossl_unused const ASN1_ITEM *it, void *exarg) { OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval; @@ -251,35 +891,31 @@ ASN1_CHOICE(OSSL_CMP_CERTORENCCERT) = { /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */ ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.certificate, X509, 0), ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.encryptedCert, - OSSL_CRMF_ENCRYPTEDVALUE, 1), + OSSL_CRMF_ENCRYPTEDKEY, 1), } ASN1_CHOICE_END(OSSL_CMP_CERTORENCCERT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT) - ASN1_SEQUENCE(OSSL_CMP_CERTIFIEDKEYPAIR) = { ASN1_SIMPLE(OSSL_CMP_CERTIFIEDKEYPAIR, certOrEncCert, OSSL_CMP_CERTORENCCERT), ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, privateKey, - OSSL_CRMF_ENCRYPTEDVALUE, 0), + OSSL_CRMF_ENCRYPTEDKEY, 0), ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, publicationInfo, OSSL_CRMF_PKIPUBLICATIONINFO, 1) } ASN1_SEQUENCE_END(OSSL_CMP_CERTIFIEDKEYPAIR) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR) - ASN1_SEQUENCE(OSSL_CMP_REVDETAILS) = { ASN1_SIMPLE(OSSL_CMP_REVDETAILS, certDetails, OSSL_CRMF_CERTTEMPLATE), ASN1_OPT(OSSL_CMP_REVDETAILS, crlEntryDetails, X509_EXTENSIONS) } ASN1_SEQUENCE_END(OSSL_CMP_REVDETAILS) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS) - ASN1_ITEM_TEMPLATE(OSSL_CMP_REVREQCONTENT) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_REVREQCONTENT, OSSL_CMP_REVDETAILS) ASN1_ITEM_TEMPLATE_END(OSSL_CMP_REVREQCONTENT) - ASN1_SEQUENCE(OSSL_CMP_REVREPCONTENT) = { ASN1_SEQUENCE_OF(OSSL_CMP_REVREPCONTENT, status, OSSL_CMP_PKISI), ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_REVREPCONTENT, revCerts, OSSL_CRMF_CERTID, @@ -288,7 +924,6 @@ ASN1_SEQUENCE(OSSL_CMP_REVREPCONTENT) = { } ASN1_SEQUENCE_END(OSSL_CMP_REVREPCONTENT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT) - ASN1_SEQUENCE(OSSL_CMP_KEYRECREPCONTENT) = { ASN1_SIMPLE(OSSL_CMP_KEYRECREPCONTENT, status, OSSL_CMP_PKISI), ASN1_EXP_OPT(OSSL_CMP_KEYRECREPCONTENT, newSigCert, X509, 0), @@ -298,21 +933,15 @@ ASN1_SEQUENCE(OSSL_CMP_KEYRECREPCONTENT) = { } ASN1_SEQUENCE_END(OSSL_CMP_KEYRECREPCONTENT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT) - ASN1_ITEM_TEMPLATE(OSSL_CMP_PKISTATUS) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_UNIVERSAL, 0, status, ASN1_INTEGER) ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS) ASN1_SEQUENCE(OSSL_CMP_PKISI) = { ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS), - /* - * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING), - /* - * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly - */ + /* OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING, used directly */ ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(OSSL_CMP_PKISI) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI) @@ -321,7 +950,8 @@ IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI) ASN1_SEQUENCE(OSSL_CMP_CERTSTATUS) = { ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certHash, ASN1_OCTET_STRING), ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certReqId, ASN1_INTEGER), - ASN1_OPT(OSSL_CMP_CERTSTATUS, statusInfo, OSSL_CMP_PKISI) + ASN1_OPT(OSSL_CMP_CERTSTATUS, statusInfo, OSSL_CMP_PKISI), + ASN1_EXP_OPT(OSSL_CMP_CERTSTATUS, hashAlg, X509_ALGOR, 0) } ASN1_SEQUENCE_END(OSSL_CMP_CERTSTATUS) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS) @@ -428,10 +1058,7 @@ ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = { ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7), ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo, OSSL_CMP_ITAV, 8) diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c index 4c8dbfdcd739..e129705e0e63 100644 --- a/crypto/cmp/cmp_client.c +++ b/crypto/cmp/cmp_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -11,7 +11,6 @@ #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 @@ -32,7 +31,7 @@ static int unprotected_exception(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *rep, int invalid_protection, - int expected_type /* ignored here */) + ossl_unused int expected_type) { int rcvd_type = OSSL_CMP_MSG_get_bodytype(rep /* may be NULL */); const char *msg_type = NULL; @@ -117,6 +116,23 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si) return 1; } +static int is_crep_with_waiting(const OSSL_CMP_MSG *resp, int rid) +{ + OSSL_CMP_CERTREPMESSAGE *crepmsg; + OSSL_CMP_CERTRESPONSE *crep; + int bt = OSSL_CMP_MSG_get_bodytype(resp); + + if (!IS_CREP(bt)) + return 0; + + crepmsg = resp->body->value.ip; /* same for cp and kup */ + crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); + + return (crep != NULL + && ossl_cmp_pkisi_get_status(crep->status) + == OSSL_CMP_PKISTATUS_waiting); +} + /*- * Perform the generic aspects of sending a request and receiving a response. * Returns 1 on success and provides the received PKIMESSAGE in *rep. @@ -138,8 +154,10 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, int time_left; OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb; +#ifndef OPENSSL_NO_HTTP if (transfer_cb == NULL) transfer_cb = OSSL_CMP_MSG_http_perform; +#endif *rep = NULL; if (ctx->total_timeout != 0 /* not waiting indefinitely */) { @@ -162,7 +180,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, /* 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); + if (ctx->server != NULL) + ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str); *rep = (*transfer_cb)(ctx, req); ctx->msg_timeout = bak_msg_timeout; @@ -182,7 +201,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, * 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)); + ossl_cmp_log2(INFO, ctx, "received %s%s", ossl_cmp_bodytype_to_string(bt), + ossl_cmp_is_error_with_waiting(*rep) ? " (waiting)" : ""); /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */ if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF @@ -193,9 +213,17 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, expected_type)) return 0; + /* + * rep can have the expected response type, which during polling is pollRep. + * When polling, also any other non-error response (the final response) + * is fine here. When not yet polling, delayed delivery may be initiated + * by the server returning an error message with 'waiting' status (or a + * response message of expected type ip/cp/kup with 'waiting' status). + */ if (bt == expected_type - /* as an answer to polling, there could be IP/CP/KUP: */ - || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP)) + || (expected_type == OSSL_CMP_PKIBODY_POLLREP + ? bt != OSSL_CMP_PKIBODY_ERROR + : ossl_cmp_is_error_with_waiting(*rep))) return 1; /* received message type is not one of the expected ones (e.g., error) */ @@ -237,7 +265,7 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, /*- * 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. + * poll, which should yield a pollRep or the final response. * 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. * @@ -248,7 +276,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, * 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). + * Returns 0 on error (which includes the cases that timeout has been reached + * or a response with 'waiting' status has been received). */ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, OSSL_CMP_MSG **rep, int *checkAfter) @@ -314,7 +343,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, str, check_after); if (ctx->total_timeout != 0) { /* timeout is not infinite */ - const int exp = 5; /* expected max time per msg round trip */ + const int exp = OSSL_CMP_EXPECTED_RESP_TIME; int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL)); if (time_left <= 0) { @@ -331,15 +360,25 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, OSSL_CMP_MSG_free(prep); prep = NULL; if (sleep) { - ossl_sleep((unsigned long)(1000 * check_after)); + OSSL_sleep((unsigned long)(1000 * check_after)); } else { if (checkAfter != NULL) *checkAfter = (int)check_after; return -1; /* exits the loop */ } + } else if (is_crep_with_waiting(prep, rid) + || ossl_cmp_is_error_with_waiting(prep)) { + /* received status must not be 'waiting' */ + (void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, + OSSL_CMP_CTX_FAILINFO_badRequest, + "polling already started", + 0 /* errorCode */, NULL); + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS); + goto err; } else { - ossl_cmp_info(ctx, "received ip/cp/kup after polling"); - /* any other body type has been rejected by send_receive_check() */ + ossl_cmp_info(ctx, "received final response after polling"); + if (!ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL)) + return 0; break; } } @@ -351,11 +390,63 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, return 1; err: + (void)ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL); OSSL_CMP_MSG_free(preq); OSSL_CMP_MSG_free(prep); return 0; } +static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx, + const OSSL_CMP_MSG *rep, int rid) +{ + /* + * Lightweight CMP Profile section 4.4 states: the senderNonce of the + * preceding request message because this value will be needed for checking + * the recipNonce of the final response to be received after polling. + */ + if ((is_crep_with_waiting(rep, rid) + || ossl_cmp_is_error_with_waiting(rep)) + && !ossl_cmp_ctx_set1_first_senderNonce(ctx, ctx->senderNonce)) + return 0; + + return 1; +} + +/* + * Send request and get response possibly with polling initiated by error msg. + * Polling for ip/cp/kup/ with 'waiting' status is handled by cert_response(). + */ +static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, + OSSL_CMP_MSG **rep, int expected_type) +{ + + if (!send_receive_check(ctx, req, rep, expected_type)) + return 0; + + if (ossl_cmp_is_error_with_waiting(*rep)) { + if (!save_senderNonce_if_waiting(ctx, *rep, OSSL_CMP_CERTREQID_NONE)) + return 0; + /* not modifying ctx->status during certConf and error exchanges */ + if (expected_type != OSSL_CMP_PKIBODY_PKICONF + && !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo)) + return 0; + + OSSL_CMP_MSG_free(*rep); + *rep = NULL; + + if (poll_for_response(ctx, 1 /* can sleep */, OSSL_CMP_CERTREQID_NONE, + rep, NULL /* checkAfter */) <= 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); + return 0; + } + } + if (OSSL_CMP_MSG_get_bodytype(*rep) != expected_type) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; + } + + return 1; +} /* * Send certConf for IR, CR or KUR sequences and check response, * not modifying ctx->status during the certConf exchange @@ -372,7 +463,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId, if (certConf == NULL) goto err; - res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + res = send_receive_also_delayed(ctx, certConf, &PKIconf, + OSSL_CMP_PKIBODY_PKICONF); err: OSSL_CMP_MSG_free(certConf); @@ -396,7 +488,8 @@ int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, 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); + res = send_receive_also_delayed(ctx, error, + &PKIconf, OSSL_CMP_PKIBODY_PKICONF); err: OSSL_CMP_MSG_free(error); @@ -490,6 +583,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, { 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 */ @@ -516,7 +610,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, if (X509_verify_cert(csc) <= 0) goto err; - if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc), + 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); @@ -544,7 +638,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, "success building approximate chain for newly enrolled cert"); } (void)ossl_cmp_ctx_set1_newChain(ctx, chain); - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); return fail_info; } @@ -559,70 +653,104 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, */ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, OSSL_CMP_MSG **resp, int *checkAfter, - int req_type, int expected_type) + ossl_unused int req_type, + ossl_unused int expected_type) { - EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx); + EVP_PKEY *rkey = NULL; int fail_info = 0; /* no failure */ const char *txt = NULL; - OSSL_CMP_CERTREPMESSAGE *crepmsg; - OSSL_CMP_CERTRESPONSE *crep; + OSSL_CMP_CERTREPMESSAGE *crepmsg = NULL; + OSSL_CMP_CERTRESPONSE *crep = NULL; OSSL_CMP_certConf_cb_t cb; X509 *cert; char *subj = NULL; int ret = 1; + int rcvd_type; + OSSL_CMP_PKISI *si; if (!ossl_assert(ctx != NULL)) return 0; retry: - crepmsg = (*resp)->body->value.ip; /* same for cp and kup */ - if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) { - ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); - return 0; - } - crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); - if (crep == NULL) - return 0; - if (!save_statusInfo(ctx, crep->status)) - return 0; - if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */ - rid = ossl_cmp_asn1_get_int(crep->certReqId); - if (rid < OSSL_CMP_CERTREQID_NONE) { - ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); + rcvd_type = OSSL_CMP_MSG_get_bodytype(*resp); + if (IS_CREP(rcvd_type)) { + 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; + si = crep->status; + + if (rid == OSSL_CMP_CERTREQID_NONE) { + /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */ + rid = ossl_cmp_asn1_get_int(crep->certReqId); + if (rid < OSSL_CMP_CERTREQID_NONE) { + ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); + return 0; + } + } + } else if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) { + si = (*resp)->body->value.error->pKIStatusInfo; + } else { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; } - if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) { + if (!save_statusInfo(ctx, si)) + return 0; + + if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) { + /* + * Here we allow both and error message with waiting indication + * as well as a certificate response with waiting indication, where + * its flavor (ip, cp, or kup) may not strictly match ir/cr/p10cr/kur. + */ 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' */ + goto retry; /* got some response other than pollRep */ } else { ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); return 0; } } + /* at this point, we have received ip/cp/kup/error without waiting */ + if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) { + ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR); + return 0; + } + /* here we are strict on the flavor of ip/cp/kup: must match request */ + if (rcvd_type != expected_type) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + 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)) + if (!ossl_cmp_ctx_set0_newCert(ctx, cert)) { + X509_free(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 + if (crepmsg != NULL && crepmsg->caPubs != NULL && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs)) return 0; subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + rkey = ossl_cmp_ctx_get0_newPubkey(ctx); if (rkey != NULL /* X509_check_private_key() also works if rkey is just public key */ && !(X509_check_private_key(ctx->newCert, rkey))) { @@ -649,6 +777,10 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, if (fail_info != 0) /* immediately log error before any certConf exchange */ ossl_cmp_log1(ERROR, ctx, "rejecting newly enrolled cert with subject: %s", subj); + /* + * certConf exchange should better be moved to do_certreq_seq() such that + * also more low-level errors with CertReqMessages get reported to server + */ if (!ctx->disableConfirm && !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) { if (!ossl_cmp_exchange_certConf(ctx, rid, fail_info, txt)) @@ -705,6 +837,9 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */ if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) goto err; + + if (!save_senderNonce_if_waiting(ctx, rep, rid)) + return 0; } else { if (req_type < 0) return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, @@ -732,7 +867,6 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, const OSSL_CRMF_MSG *crm) { - OSSL_CMP_MSG *rep = NULL; int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR; int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID; @@ -747,6 +881,9 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) goto err; + if (!save_senderNonce_if_waiting(ctx, rep, rid)) + return 0; + if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type) <= 0) goto err; @@ -773,7 +910,8 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) return 0; } ctx->status = OSSL_CMP_PKISTATUS_request; - if (ctx->oldCert == NULL && ctx->p10CSR == NULL) { + if (ctx->oldCert == NULL && ctx->p10CSR == NULL + && (ctx->serialNumber == NULL || ctx->issuer == NULL)) { ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT); return 0; } @@ -783,7 +921,7 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) goto end; ctx->status = OSSL_CMP_PKISTATUS_trans; - if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) + if (!send_receive_also_delayed(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) goto end; rrep = rp->body->value.rp; @@ -840,7 +978,8 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) 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); + 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); @@ -903,7 +1042,7 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx) goto err; ctx->status = OSSL_CMP_PKISTATUS_trans; - if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) + if (!send_receive_also_delayed(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) goto err; ctx->status = OSSL_CMP_PKISTATUS_accepted; diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 9d9bd357daf7..7b78ab16036b 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -20,16 +20,35 @@ #include #include +#define DEFINE_OSSL_CMP_CTX_get0(FIELD, TYPE) \ + DEFINE_OSSL_CMP_CTX_get0_NAME(FIELD, FIELD, TYPE) +#define DEFINE_OSSL_CMP_CTX_get0_NAME(NAME, FIELD, TYPE) \ +TYPE *OSSL_CMP_CTX_get0_##NAME(const OSSL_CMP_CTX *ctx) \ +{ \ + if (ctx == NULL) { \ + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ + return NULL; \ + } \ + return ctx->FIELD; \ +} + /* * 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; +DEFINE_OSSL_CMP_CTX_get0_NAME(trusted, trusted, X509_STORE) + +#define DEFINE_OSSL_set0(PREFIX, FIELD, TYPE) \ + DEFINE_OSSL_set0_NAME(PREFIX, FIELD, FIELD, TYPE) +#define DEFINE_OSSL_set0_NAME(PREFIX, NAME, FIELD, TYPE) \ +int PREFIX##_set0##_##NAME(OSSL_CMP_CTX *ctx, TYPE *val) \ +{ \ + if (ctx == NULL) { \ + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ + return 0; \ + } \ + TYPE##_free(ctx->FIELD); \ + ctx->FIELD = val; \ + return 1; \ } /* @@ -37,26 +56,13 @@ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx) * 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; -} +DEFINE_OSSL_set0_NAME(OSSL_CMP_CTX, trusted, trusted, X509_STORE) + +DEFINE_OSSL_CMP_CTX_get0(libctx, OSSL_LIB_CTX) +DEFINE_OSSL_CMP_CTX_get0(propq, const char) /* 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; -} +DEFINE_OSSL_CMP_CTX_get0(untrusted, STACK_OF(X509)) /* * Set untrusted certificates for path construction in authentication of @@ -73,11 +79,11 @@ int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs) 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); + OSSL_STACK_OF_X509_free(ctx->untrusted); ctx->untrusted = untrusted; return 1; err: - sk_X509_pop_free(untrusted, X509_free); + OSSL_STACK_OF_X509_free(untrusted); return 0; } @@ -108,7 +114,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) ctx->libctx = libctx; if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) - goto oom; + goto err; ctx->log_verbosity = OSSL_CMP_LOG_INFO; @@ -117,9 +123,12 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) ctx->keep_alive = 1; ctx->msg_timeout = -1; + ctx->tls_used = -1; /* default for backward compatibility */ - if ((ctx->untrusted = sk_X509_new_null()) == NULL) - goto oom; + if ((ctx->untrusted = sk_X509_new_null()) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); + goto err; + } ctx->pbm_slen = 16; if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, NID_sha256)) @@ -135,8 +144,6 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) /* 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; @@ -157,11 +164,13 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx) return 0; } +#ifndef OPENSSL_NO_HTTP 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; } +#endif ctx->status = OSSL_CMP_PKISTATUS_unspecified; ctx->failInfoCode = -1; @@ -173,7 +182,8 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx) && 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_validatedSrvCert(ctx, NULL) + && ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL) && OSSL_CMP_CTX_set1_transactionID(ctx, NULL) && OSSL_CMP_CTX_set1_senderNonce(ctx, NULL) && ossl_cmp_ctx_set1_recipNonce(ctx, NULL); @@ -185,10 +195,12 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx) if (ctx == NULL) return; +#ifndef OPENSSL_NO_HTTP if (ctx->http_ctx != NULL) { (void)OSSL_HTTP_close(ctx->http_ctx, 1); ossl_cmp_debug(ctx, "disconnected from CMP server"); } +#endif OPENSSL_free(ctx->propq); OPENSSL_free(ctx->serverPath); OPENSSL_free(ctx->server); @@ -199,10 +211,10 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx) X509_free(ctx->validatedSrvCert); X509_NAME_free(ctx->expected_sender); X509_STORE_free(ctx->trusted); - sk_X509_pop_free(ctx->untrusted, X509_free); + OSSL_STACK_OF_X509_free(ctx->untrusted); X509_free(ctx->cert); - sk_X509_pop_free(ctx->chain, X509_free); + OSSL_STACK_OF_X509_free(ctx->chain); EVP_PKEY_free(ctx->pkey); ASN1_OCTET_STRING_free(ctx->referenceValue); if (ctx->secretValue != NULL) @@ -215,120 +227,83 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx) 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); + ASN1_OCTET_STRING_free(ctx->first_senderNonce); + OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs); + OSSL_STACK_OF_X509_free(ctx->extraCertsOut); EVP_PKEY_free(ctx->newPkey); X509_NAME_free(ctx->issuer); + ASN1_INTEGER_free(ctx->serialNumber); 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); + X509_EXTENSIONS_free(ctx->reqExtensions); 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); + OSSL_CMP_ITAVs_free(ctx->genm_ITAVs); - sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free); + OSSL_CMP_PKIFREETEXT_free(ctx->statusString); 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); + OSSL_STACK_OF_X509_free(ctx->newChain); + OSSL_STACK_OF_X509_free(ctx->caPubs); + OSSL_STACK_OF_X509_free(ctx->extraCertsIn); 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; +#define DEFINE_OSSL_set(PREFIX, FIELD, TYPE) \ +int PREFIX##_set_##FIELD(OSSL_CMP_CTX *ctx, TYPE val) \ +{ \ + if (ctx == NULL) { \ + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ + return 0; \ + } \ + ctx->FIELD = val; \ + return 1; \ +} + +DEFINE_OSSL_set(ossl_cmp_ctx, status, int) + +#define DEFINE_OSSL_get(PREFIX, FIELD, TYPE, ERR_RET) \ +TYPE PREFIX##_get_##FIELD(const OSSL_CMP_CTX *ctx) \ +{ \ + if (ctx == NULL) { \ + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ + return ERR_RET; \ + } \ + return ctx->FIELD; \ } /* * 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; -} +DEFINE_OSSL_get(OSSL_CMP_CTX, status, int, -1) /* * 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; -} +DEFINE_OSSL_CMP_CTX_get0(statusString, OSSL_CMP_PKIFREETEXT) -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; -} +DEFINE_OSSL_set0(ossl_cmp_ctx, statusString, OSSL_CMP_PKIFREETEXT) /* 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, certConf_cb, OSSL_CMP_certConf_cb_t) /* * 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, certConf_cb_arg, void *) /* * 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; -} +DEFINE_OSSL_get(OSSL_CMP_CTX, certConf_cb_arg, void *, NULL) #ifndef OPENSSL_NO_TRACE static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt, @@ -452,8 +427,8 @@ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx, ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } - return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref, - len); + 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 */ @@ -461,6 +436,7 @@ 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; @@ -475,74 +451,51 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, return 1; } +#define DEFINE_OSSL_CMP_CTX_get1_certs(FIELD) \ +STACK_OF(X509) *OSSL_CMP_CTX_get1_##FIELD(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->FIELD); \ +} + /* 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); +DEFINE_OSSL_CMP_CTX_get1_certs(newChain) + +#define DEFINE_OSSL_set1_certs(PREFIX, FIELD) \ +int PREFIX##_set1_##FIELD(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs) \ +{ \ + if (ctx == NULL) { \ + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ + return 0; \ + } \ + OSSL_STACK_OF_X509_free(ctx->FIELD); \ + ctx->FIELD = NULL; \ + return certs == NULL || (ctx->FIELD = X509_chain_up_ref(certs)) != NULL; \ } /* * 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; -} +DEFINE_OSSL_set1_certs(ossl_cmp_ctx, newChain) /* 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); -} +DEFINE_OSSL_CMP_CTX_get1_certs(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; -} +DEFINE_OSSL_set1_certs(ossl_cmp_ctx, extraCertsIn) /* * 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; -} +DEFINE_OSSL_set1_certs(OSSL_CMP_CTX, extraCertsOut) /* * Add the given policy info object @@ -583,6 +536,8 @@ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx) return 1; } +DEFINE_OSSL_CMP_CTX_get0(geninfo_ITAVs, STACK_OF(OSSL_CMP_ITAV)) + /* 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) { @@ -598,28 +553,13 @@ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) * 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); -} +DEFINE_OSSL_CMP_CTX_get1_certs(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_OSSL_set1_certs(ossl_cmp_ctx, caPubs) #define char_dup OPENSSL_strdup #define char_free OPENSSL_free @@ -642,8 +582,9 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \ #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) \ + +#define DEFINE_OSSL_set1_up_ref(PREFIX, FIELD, TYPE) \ +int PREFIX##_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \ { \ if (ctx == NULL) { \ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \ @@ -662,12 +603,14 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \ return 1; \ } +DEFINE_OSSL_set1_up_ref(ossl_cmp_ctx, validatedSrvCert, X509) + /* * 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) +DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, srvCert, X509) /* Set the X509 name of the recipient to be placed in the PKIHeader */ DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME) @@ -678,6 +621,8 @@ DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME) /* Set the X509 name of the issuer to be placed in the certTemplate */ DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME) +/* Set the ASN1_INTEGER serial to be placed in the certTemplate for rr */ +DEFINE_OSSL_CMP_CTX_set1(serialNumber, ASN1_INTEGER) /* * Set the subject name that will be placed in the certificate * request. This will be the subject name on the received certificate. @@ -697,7 +642,7 @@ int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts) ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES); return 0; } - sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free); + X509_EXTENSIONS_free(ctx->reqExtensions); ctx->reqExtensions = exts; return 1; } @@ -750,7 +695,7 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx, * 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) +DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, cert, X509) int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted, STACK_OF(X509) *candidates) @@ -784,7 +729,7 @@ int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted, * 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) +DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, oldCert, X509) /* Set the PKCS#10 CSR to be sent in P10CR */ DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ) @@ -793,31 +738,19 @@ 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; +DEFINE_OSSL_set0(ossl_cmp_ctx, newCert, X509) - X509_free(ctx->newCert); - ctx->newCert = cert; - return 1; -} +/* Get successfully validated server cert, if any, of current transaction */ +DEFINE_OSSL_CMP_CTX_get0(validatedSrvCert, X509) /* * 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; -} +DEFINE_OSSL_CMP_CTX_get0(newCert, X509) /* Set the client's current private key */ -DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY) +DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, 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) @@ -864,151 +797,77 @@ EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx) 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); +#define DEFINE_set1_ASN1_OCTET_STRING(PREFIX, FIELD) \ +int PREFIX##_set1_##FIELD(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->FIELD, id); \ } +/* Set the given transactionID to the context */ +DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, transactionID) + /* 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); -} +DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, recipNonce) /* 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); -} +DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, senderNonce) + +/* store the first req sender nonce for verifying delayed delivery */ +DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, first_senderNonce) /* 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 */ +/* Set the (HTTP) hostname 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) +#ifndef OPENSSL_NO_HTTP /* 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, http_cb, OSSL_HTTP_bio_cb_t) /* 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, http_cb_arg, void *) /* * 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; -} +DEFINE_OSSL_get(OSSL_CMP_CTX, http_cb_arg, void *, NULL) +#endif /* 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, transfer_cb, OSSL_CMP_transfer_cb_t) /* 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, transfer_cb_arg, void *) /* * 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; -} +DEFINE_OSSL_get(OSSL_CMP_CTX, transfer_cb_arg, void *, NULL) /** 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; -} +DEFINE_OSSL_set(OSSL_CMP_CTX, serverPort, int) /* 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; -} +DEFINE_OSSL_set(ossl_cmp_ctx, failInfoCode, int) /* * 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; -} +DEFINE_OSSL_get(OSSL_CMP_CTX, failInfoCode, int, -1) /* 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) @@ -1056,6 +915,9 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_UNPROTECTED_ERRORS: ctx->unprotectedErrors = val; break; + case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS: + ctx->noCacheExtraCerts = val; + break; case OSSL_CMP_OPT_VALIDITY_DAYS: ctx->days = val; break; @@ -1098,6 +960,9 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val) case OSSL_CMP_OPT_TOTAL_TIMEOUT: ctx->total_timeout = val; break; + case OSSL_CMP_OPT_USE_TLS: + ctx->tls_used = val; + break; case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: ctx->permitTAInExtraCertsForIR = val; break; @@ -1138,6 +1003,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) return ctx->unprotectedSend; case OSSL_CMP_OPT_UNPROTECTED_ERRORS: return ctx->unprotectedErrors; + case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS: + return ctx->noCacheExtraCerts; case OSSL_CMP_OPT_VALIDITY_DAYS: return ctx->days; case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT: @@ -1162,6 +1029,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt) return ctx->msg_timeout; case OSSL_CMP_OPT_TOTAL_TIMEOUT: return ctx->total_timeout; + case OSSL_CMP_OPT_USE_TLS: + return ctx->tls_used; case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR: return ctx->permitTAInExtraCertsForIR; case OSSL_CMP_OPT_REVOCATION_REASON: diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index dfc6dfbedee9..6d87d7b463dd 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -76,16 +76,31 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "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_EXPECTED_POLLREQ), "expected pollreq"}, {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_CENTRAL_GEN_KEY), + "failed extracting central gen key"}, {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_GENERATE_CERTREQTEMPLATE), + "generate certreqtemplate"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CRLSTATUS), + "error creating crlstatus"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GET_ITAV), "get itav"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_KEYSPEC), "invalid keyspec"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE), + "invalid rootcakeyupdate"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CENTRAL_GEN_KEY), + "missing central gen key"}, {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"}, @@ -139,18 +154,30 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {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_UNCLEAN_CTX), "unclean ctx"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY), + "unexpected central gen key"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE), + "unexpected certprofile"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST), + "unexpected crlstatuslist"}, {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_POLLREQ), "unexpected pollreq"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_SENDER), "unexpected sender"}, {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_CRL_ISSUER), "unknown crl issuer"}, {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_PKIBODY), + "unsupported pkibody"}, {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"}, diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c index 8c553af61a53..d00c9f76bb42 100644 --- a/crypto/cmp/cmp_hdr.c +++ b/crypto/cmp/cmp_hdr.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -72,6 +72,16 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) return hdr->recipNonce; } +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr) +{ + if (hdr == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + return hdr->generalInfo; +} + /* a NULL-DN as an empty sequence of RDNs */ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) { @@ -79,34 +89,6 @@ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) || (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName)); } -/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */ -static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src) -{ - GENERAL_NAME *name; - - if (!ossl_assert(tgt != NULL)) - return 0; - if ((name = GENERAL_NAME_new()) == NULL) - goto err; - name->type = GEN_DIRNAME; - - if (src == NULL) { /* NULL-DN */ - if ((name->d.directoryName = X509_NAME_new()) == NULL) - goto err; - } else if (!X509_NAME_set(&name->d.directoryName, src)) { - goto err; - } - - GENERAL_NAME_free(*tgt); - *tgt = name; - - return 1; - - err: - GENERAL_NAME_free(name); - return 0; -} - /* * Set the sender name in PKIHeader. * when nm is NULL, sender is set to an empty string @@ -116,14 +98,14 @@ int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) { if (!ossl_assert(hdr != NULL)) return 0; - return set1_general_name(&hdr->sender, nm); + return GENERAL_NAME_set1_X509_NAME(&hdr->sender, nm); } int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm) { if (!ossl_assert(hdr != NULL)) return 0; - return set1_general_name(&hdr->recipient, nm); + return GENERAL_NAME_set1_X509_NAME(&hdr->recipient, nm); } int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr) @@ -276,8 +258,7 @@ int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) if (!set_random(&ctx->transactionID, ctx, OSSL_CMP_TRANSACTIONID_LENGTH)) return 0; - tid = OPENSSL_buf2hexstr(ctx->transactionID->data, - ctx->transactionID->length); + tid = i2s_ASN1_OCTET_STRING(NULL, ctx->transactionID); if (tid != NULL) ossl_cmp_log1(DEBUG, ctx, "Starting new transaction with ID=%s", tid); @@ -302,11 +283,12 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr) return 0; /* - * If neither protection cert nor oldCert nor subject are given, + * If no protection cert nor oldCert nor CSR nor subject is given, * sender name is not known to the client and thus set to NULL-DN */ sender = ctx->cert != NULL ? X509_get_subject_name(ctx->cert) : ctx->oldCert != NULL ? X509_get_subject_name(ctx->oldCert) : + ctx->p10CSR != NULL ? X509_REQ_get_subject_name(ctx->p10CSR) : ctx->subjectName; if (!ossl_cmp_hdr_set1_sender(hdr, sender)) return 0; diff --git a/crypto/cmp/cmp_http.c b/crypto/cmp/cmp_http.c index d29bfa8674ad..c0226e562a32 100644 --- a/crypto/cmp/cmp_http.c +++ b/crypto/cmp/cmp_http.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -14,7 +14,6 @@ #include #include -#include "internal/sockets.h" #include #include "cmp_local.h" @@ -25,12 +24,11 @@ #include #include #include -#include #include -static int keep_alive(int keep_alive, int body_type) +static int keep_alive(int keep_alive, int body_type, BIO **bios) { - if (keep_alive != 0 + if (keep_alive != 0 && bios == NULL /* * Ask for persistent connection only if may need more round trips. * Do so even with disableConfirm because polling might be needed. @@ -46,7 +44,6 @@ static int keep_alive(int keep_alive, int body_type) /* * Send the PKIMessage req and on success return the response, else NULL. - * Any previous error queue entries will likely be removed by ERR_clear_error(). */ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req) @@ -57,6 +54,7 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, int tls_used; const ASN1_ITEM *it = ASN1_ITEM_rptr(OSSL_CMP_MSG); BIO *req_mem, *rsp; + BIO **bios; /* optionally used as bio and rbio */ OSSL_CMP_MSG *res = NULL; if (ctx == NULL || req == NULL) { @@ -69,24 +67,40 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, if ((req_mem = ASN1_item_i2d_mem_bio(it, (const ASN1_VALUE *)req)) == NULL) goto err; + bios = OSSL_CMP_CTX_get_transfer_cb_arg(ctx); if (ctx->serverPort != 0) BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort); - tls_used = OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL; - if (ctx->http_ctx == NULL) - ossl_cmp_log3(DEBUG, ctx, "connecting to CMP server %s:%s%s", - ctx->server, server_port, tls_used ? " using TLS" : ""); + tls_used = ctx->tls_used >= 0 ? ctx->tls_used != 0 + : OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL; /* backward compat */ + if (ctx->http_ctx == NULL) { /* using existing connection or yet not set up own connection */ + const char *path = ctx->serverPath; + + if (path == NULL) + path = ""; + if (*path == '/') + path++; + if (bios == NULL) + ossl_cmp_log4(DEBUG, ctx, + "connecting to CMP server via http%s://%s:%s%s/%s", + tls_used ? "s" : "", ctx->server, server_port, path); + else + ossl_cmp_log3(DEBUG, ctx, + "using existing connection with CMP server %s%s and HTTP path /%s", + ctx->server, server_port, path); + } rsp = OSSL_HTTP_transfer(&ctx->http_ctx, ctx->server, server_port, ctx->serverPath, tls_used, ctx->proxy, ctx->no_proxy, - NULL /* bio */, NULL /* rbio */, + bios == NULL ? NULL : bios[0] /* bio */, + bios == NULL ? NULL : bios[1] /* rbio */, ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx), 0 /* buf_size */, headers, content_type_pkix, req_mem, content_type_pkix, 1 /* expect_asn1 */, OSSL_HTTP_DEFAULT_MAX_RESP_LEN, ctx->msg_timeout, - keep_alive(ctx->keep_alive, req->body->type)); + keep_alive(ctx->keep_alive, req->body->type, bios)); BIO_free(req_mem); res = (OSSL_CMP_MSG *)ASN1_item_d2i_bio(it, rsp, NULL); BIO_free(rsp); @@ -94,9 +108,11 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx, if (ctx->http_ctx == NULL) ossl_cmp_debug(ctx, "disconnected from CMP server"); /* - * Note that on normal successful end of the transaction the connection - * is not closed at this level, but this will be done by the CMP client - * application via OSSL_CMP_CTX_free() or OSSL_CMP_CTX_reinit(). + * Note that on normal successful end of the transaction the + * HTTP connection is not closed at this level if keep_alive(...) != 0. + * It should be closed by the CMP client application + * using OSSL_CMP_CTX_free() or OSSL_CMP_CTX_reinit(). + * Any pre-existing bio (== ctx->transfer_cb_arg) is not freed. */ if (res != NULL) ossl_cmp_debug(ctx, "finished reading response from CMP server"); diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index 8eeb56d4e0f0..bbca4e0ac565 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -25,7 +25,7 @@ # include # include "crypto/x509.h" -#define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL) +# define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL) /* * this structure is used to store the context for CMP sessions @@ -49,10 +49,13 @@ struct ossl_cmp_ctx_st { 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. */ + int tls_used; /* whether to use TLS for client-side HTTP connections */ /* attempts polling for a response if a 'waiting' PKIStatus is received */ time_t end_time; /* session start time + totaltimeout */ +# ifndef OPENSSL_NO_HTTP OSSL_HTTP_bio_cb_t http_cb; void *http_cb_arg; /* allows to store optional argument to cb */ +# endif /* server authentication */ /* @@ -61,6 +64,7 @@ struct ossl_cmp_ctx_st { * certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf */ int unprotectedErrors; + int noCacheExtraCerts; 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 */ @@ -78,7 +82,7 @@ struct ossl_cmp_ctx_st { 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 *referenceValue; /* optional username 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 */ @@ -92,6 +96,7 @@ struct ossl_cmp_ctx_st { ASN1_OCTET_STRING *transactionID; /* the current transaction ID */ ASN1_OCTET_STRING *senderNonce; /* last nonce sent */ ASN1_OCTET_STRING *recipNonce; /* last nonce received */ + ASN1_OCTET_STRING *first_senderNonce; /* sender nonce when starting to poll */ 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 */ @@ -101,7 +106,8 @@ struct ossl_cmp_ctx_st { /* 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 */ + X509_NAME *issuer; /* issuer name to used in cert template, also in rr */ + ASN1_INTEGER *serialNumber; /* certificate serial number to use in rr */ 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 */ @@ -118,7 +124,7 @@ struct ossl_cmp_ctx_st { 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 */ + /* result returned in responses, so far supporting only one certResponse */ 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 */ @@ -202,6 +208,39 @@ typedef struct ossl_cmp_cakeyupdanncontent_st { } OSSL_CMP_CAKEYUPDANNCONTENT; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT) +typedef struct ossl_cmp_rootcakeyupdate_st OSSL_CMP_ROOTCAKEYUPDATE; +DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE) + +typedef struct ossl_cmp_certreqtemplate_st OSSL_CMP_CERTREQTEMPLATE; +DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE) + +/*- + * CRLSource ::= CHOICE { + * dpn [0] DistributionPointName, + * issuer [1] GeneralNames } + */ + +typedef struct ossl_cmp_crlsource_st { + int type; + union { + DIST_POINT_NAME *dpn; + GENERAL_NAMES *issuer; + } value; +} OSSL_CMP_CRLSOURCE; +DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE) + +/* + * CRLStatus ::= SEQUENCE { + * source CRLSource, + * thisUpdate Time OPTIONAL } + */ + +struct ossl_cmp_crlstatus_st { + OSSL_CMP_CRLSOURCE *source; + ASN1_TIME *thisUpdate; +}; /* OSSL_CMP_CRLSTATUS */ +DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS) + /*- * declared already here as it will be used in OSSL_CMP_MSG (nested) and * infoType and infoValue @@ -247,6 +286,21 @@ struct ossl_cmp_itav_st { OSSL_CMP_MSGS *origPKIMessage; /* NID_id_it_suppLangTags - Supported Language Tags */ STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue; + /* NID_id_it_certProfile - Certificate Profile */ + STACK_OF(ASN1_UTF8STRING) *certProfile; + /* NID_id_it_caCerts - CA Certificates */ + STACK_OF(X509) *caCerts; + /* NID_id_it_rootCaCert - Root CA Certificate */ + X509 *rootCaCert; + /* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */ + OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate; + /* NID_id_it_certReqTemplate - Certificate Request Template */ + OSSL_CMP_CERTREQTEMPLATE *certReqTemplate; + /* NID_id_it_crlStatusList - CRL Update Retrieval */ + STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList; + /* NID_id_it_crls - Certificate Status Lists */ + STACK_OF(X509_CRL) *crls; + /* this is to be used for so far undeclared objects */ ASN1_TYPE *other; } infoValue; @@ -257,7 +311,7 @@ typedef struct ossl_cmp_certorenccert_st { int type; union { X509 *certificate; - OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert; + OSSL_CRMF_ENCRYPTEDKEY *encryptedCert; } value; } OSSL_CMP_CERTORENCCERT; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT) @@ -272,7 +326,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT) */ typedef struct ossl_cmp_certifiedkeypair_st { OSSL_CMP_CERTORENCCERT *certOrEncCert; - OSSL_CRMF_ENCRYPTEDVALUE *privateKey; + OSSL_CRMF_ENCRYPTEDKEY *privateKey; OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo; } OSSL_CMP_CERTIFIEDKEYPAIR; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR) @@ -369,13 +423,15 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT) * -- as is used to create and verify the certificate signature * certReqId INTEGER, * -- to match this confirmation with the corresponding req/rep - * statusInfo PKIStatusInfo OPTIONAL + * statusInfo PKIStatusInfo OPTIONAL, + * hashAlg [0] AlgorithmIdentifier OPTIONAL * } */ struct ossl_cmp_certstatus_st { ASN1_OCTET_STRING *certHash; ASN1_INTEGER *certReqId; OSSL_CMP_PKISI *statusInfo; + X509_ALGOR *hashAlg; /* 0 */ } /* OSSL_CMP_CERTSTATUS */; DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS) typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT; @@ -446,7 +502,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREPCONTENT) /*- * PKIHeader ::= SEQUENCE { - * pvno INTEGER { cmp1999(1), cmp2000(2) }, + * pvno INTEGER { cmp1999(1), cmp2000(2), cmp2021(3) }, * sender GeneralName, * -- identifies the sender * recipient GeneralName, @@ -708,6 +764,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART) * } -- or HMAC [RFC2104, RFC2202]) */ /*- + * Not supported: * id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30} * DHBMParameter ::= SEQUENCE { * owf AlgorithmIdentifier, @@ -730,6 +787,32 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART) * } */ +/* + * RootCaKeyUpdateContent ::= SEQUENCE { + * newWithNew CMPCertificate, + * newWithOld [0] CMPCertificate OPTIONAL, + * oldWithNew [1] CMPCertificate OPTIONAL + * } + */ + +struct ossl_cmp_rootcakeyupdate_st { + X509 *newWithNew; + X509 *newWithOld; + X509 *oldWithNew; +} /* OSSL_CMP_ROOTCAKEYUPDATE */; +DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE) + +/*- + * CertReqTemplateContent ::= SEQUENCE { + * certTemplate CertTemplate, + * keySpec Controls OPTIONAL + * } + */ +struct ossl_cmp_certreqtemplate_st { + OSSL_CRMF_CERTTEMPLATE *certTemplate; + OSSL_CMP_ATAVS *keySpec; +} /* OSSL_CMP_CERTREQTEMPLATE */; + /* from cmp_asn.c */ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a); @@ -777,7 +860,7 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx, # 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_set1_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); @@ -790,6 +873,8 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx, 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); +int ossl_cmp_ctx_set1_first_senderNonce(OSSL_CMP_CTX *ctx, + const ASN1_OCTET_STRING *nonce); /* from cmp_status.c */ int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si); @@ -867,7 +952,8 @@ 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, + X509 *cert, const EVP_PKEY *pkey, + 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); @@ -906,8 +992,10 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm, 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); +int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg); /* from cmp_protect.c */ +void ossl_cmp_set_own_chain(OSSL_CMP_CTX *ctx); 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); @@ -925,6 +1013,8 @@ int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, int accept_RAVerified); /* from cmp_client.c */ +/* expected max time per msg round trip, used for last try during polling: */ +# define OSSL_CMP_EXPECTED_RESP_TIME 2 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, diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index c8e467f3c21f..055f14c8f861 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq) { @@ -59,7 +62,6 @@ int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx, return 1; } - OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg) { if (msg == NULL) { @@ -101,6 +103,34 @@ int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg) return msg->body->type; } +X509_PUBKEY *OSSL_CMP_MSG_get0_certreq_publickey(const OSSL_CMP_MSG *msg) +{ + const OSSL_CRMF_MSGS *reqs; + const OSSL_CRMF_MSG *crm; + const OSSL_CRMF_CERTTEMPLATE *tmpl; + X509_PUBKEY *pubkey; + + switch (OSSL_CMP_MSG_get_bodytype(msg)) { + case OSSL_CMP_PKIBODY_IR: + case OSSL_CMP_PKIBODY_CR: + case OSSL_CMP_PKIBODY_KUR: + reqs = msg->body->value.ir; /* value.ir is same for cr and kur */ + if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND); + return NULL; + } + if ((tmpl = OSSL_CRMF_MSG_get0_tmpl(crm)) == NULL + || (pubkey = OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl)) == NULL) { + ERR_raise(ERR_LIB_CMP, CRMF_R_POPO_MISSING_PUBLIC_KEY); + return NULL; + } + return pubkey; + default: + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return NULL; + } +} + /* 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) { @@ -118,34 +148,6 @@ static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex) 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) { @@ -272,6 +274,8 @@ static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR, OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) { OSSL_CRMF_MSG *crm = NULL; + int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD) + == OSSL_CRMF_POPO_NONE; X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert; /* refcert defaults to current client cert */ EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx); @@ -284,9 +288,10 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) : X509_get_issuer_name(refcert); int crit = ctx->setSubjectAltNameCritical || subject == NULL; /* RFC5280: subjectAltName MUST be critical if subject is null */ + OSSL_CRMF_CERTTEMPLATE *tmpl; X509_EXTENSIONS *exts = NULL; - if (rkey == NULL) { + if (rkey == NULL && !central_keygen) { #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY); return NULL; @@ -298,6 +303,7 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) } if ((crm = OSSL_CRMF_MSG_new()) == NULL) return NULL; + tmpl = OSSL_CRMF_MSG_get0_tmpl(crm); if (!OSSL_CRMF_MSG_set_certReqId(crm, rid) /* * fill certTemplate, corresponding to CertificationRequestInfo @@ -307,6 +313,10 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey, subject, issuer, NULL /* serial */)) goto err; + if (rkey != NULL && central_keygen) + X509_PUBKEY_set0_public_key(OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl), + NULL, 0); + if (ctx->days != 0) { time_t now = time(NULL); ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0); @@ -326,13 +336,13 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) && (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 + && (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)) + if (sk_X509_EXTENSION_num(ctx->reqExtensions) > 0 /* augment/override existing ones */ + && X509v3_add_extensions(&exts, ctx->reqExtensions) == NULL) goto err; if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0 && !add1_extension(&exts, NID_subject_alt_name, @@ -442,9 +452,47 @@ OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type, return NULL; } +#ifndef OPENSSL_NO_CMS +static OSSL_CRMF_ENCRYPTEDKEY *enc_privkey(OSSL_CMP_CTX *ctx, const EVP_PKEY *pkey) +{ + OSSL_CRMF_ENCRYPTEDKEY *ek = NULL; + CMS_EnvelopedData *envData = NULL; + BIO *privbio = NULL; + EVP_CIPHER *cipher = NULL; + X509 *recip = ctx->validatedSrvCert; /* this is the client cert */ + STACK_OF(X509) *encryption_recips = sk_X509_new_reserve(NULL, 1); + + if (encryption_recips == NULL + || !X509_add_cert(encryption_recips, recip, X509_ADD_FLAG_UP_REF)) + goto err; + + privbio = BIO_new(BIO_s_mem()); + if (privbio == NULL || i2d_PrivateKey_bio(privbio, pkey) <= 0) + goto err; + ossl_cmp_set_own_chain(ctx); + cipher = EVP_CIPHER_fetch(ctx->libctx, SN_aes_256_cbc, ctx->propq); + envData = ossl_cms_sign_encrypt(privbio, ctx->cert, ctx->chain, ctx->pkey, CMS_BINARY, + encryption_recips, cipher, CMS_BINARY, + ctx->libctx, ctx->propq); + EVP_CIPHER_free(cipher); + if (envData == NULL) + goto err; + ek = OSSL_CRMF_ENCRYPTEDKEY_init_envdata(envData); + + err: + sk_X509_pop_free(encryption_recips, X509_free); + BIO_free(privbio); + if (ek == NULL) + M_ASN1_free_of(envData, CMS_EnvelopedData); + + return ek; +} +#endif + 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, + X509 *cert, const EVP_PKEY *pkey, + const X509 *encryption_recip, STACK_OF(X509) *chain, STACK_OF(X509) *caPubs, int unprotectedErrors) { @@ -488,6 +536,16 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype, if (!X509_up_ref(cert)) goto err; resp->certifiedKeyPair->certOrEncCert->value.certificate = cert; + + if (pkey != NULL) { +#ifndef OPENSSL_NO_CMS + if ((resp->certifiedKeyPair->privateKey = enc_privkey(ctx, pkey)) == NULL) + goto err; +#else + ERR_raise(ERR_LIB_CMP, ERR_R_UNSUPPORTED); + goto err; +#endif + } } if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp)) @@ -519,27 +577,37 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype, OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx) { OSSL_CMP_MSG *msg = NULL; + const X509_NAME *issuer = NULL; + const X509_NAME *subject = NULL; + const ASN1_INTEGER *serialNumber = NULL; + EVP_PKEY *pubkey = NULL; OSSL_CMP_REVDETAILS *rd; int ret; - if (!ossl_assert(ctx != NULL && (ctx->oldCert != NULL - || ctx->p10CSR != NULL))) + if (!ossl_assert(ctx != NULL + && (ctx->oldCert != NULL || ctx->p10CSR != NULL + || (ctx->serialNumber != NULL && ctx->issuer != NULL)))) return NULL; if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL) goto err; + if (ctx->serialNumber != NULL && ctx->issuer != NULL) { + issuer = ctx->issuer; + serialNumber = ctx->serialNumber; + } else if (ctx->oldCert != NULL) { + issuer = X509_get_issuer_name(ctx->oldCert); + serialNumber = X509_get0_serialNumber(ctx->oldCert); + } else if (ctx->p10CSR != NULL) { + pubkey = X509_REQ_get0_pubkey(ctx->p10CSR); + subject = X509_REQ_get_subject_name(ctx->p10CSR); + } else { + 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); + ret = OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails, pubkey, subject, + issuer, serialNumber); if (!ret) goto err; @@ -584,23 +652,20 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si, goto err; rep = msg->body->value.rp; - if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL) + if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL + || !sk_OSSL_CMP_PKISI_push(rep->status, si1)) goto err; - if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) { - OSSL_CMP_PKISI_free(si1); - goto err; - } + si1 = NULL; /* ownership transferred to rep->status */ if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL) goto err; if (cid != NULL) { - if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL) + if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL + || !sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) goto err; - if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) { - OSSL_CRMF_CERTID_free(cid_copy); - goto err; - } + + cid_copy = NULL; /* ownership transferred to rep->revCerts */ } if (!unprotectedErrors @@ -612,6 +677,8 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si, err: ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP); + OSSL_CMP_PKISI_free(si1); + OSSL_CRMF_CERTID_free(cid_copy); OSSL_CMP_MSG_free(msg); return NULL; } @@ -673,7 +740,7 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg, } /* - * Creates a new General Message/Response with an empty itav stack + * Creates a new General Message/Response with a copy of the given itav stack * returns a pointer to the PKIMessage on success, NULL on error */ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, @@ -787,6 +854,8 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId, { OSSL_CMP_MSG *msg = NULL; OSSL_CMP_CERTSTATUS *certStatus = NULL; + EVP_MD *md; + int is_fallback; ASN1_OCTET_STRING *certHash = NULL; OSSL_CMP_PKISI *sinfo; @@ -814,13 +883,23 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId, /* set the ID of the certReq */ if (!ASN1_INTEGER_set(certStatus->certReqId, certReqId)) goto err; + + certStatus->hashAlg = NULL; /* * 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 not available, a fallback hash algorithm is used. */ - if ((certHash = X509_digest_sig(ctx->newCert, NULL, NULL)) == NULL) + if ((certHash = X509_digest_sig(ctx->newCert, &md, &is_fallback)) == NULL) goto err; + if (is_fallback) { + if (!ossl_cmp_hdr_set_pvno(msg->header, OSSL_CMP_PVNO_3)) + goto err; + if ((certStatus->hashAlg = X509_ALGOR_new()) == NULL) + goto err; + X509_ALGOR_set_md(certStatus->hashAlg, md); + } + EVP_MD_free(md); if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash)) goto err; @@ -962,8 +1041,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid) return 1; trid = ossl_cmp_asn1_get_int(certReqId); - - if (trid == OSSL_CMP_CERTREQID_NONE) { + if (trid <= OSSL_CMP_CERTREQID_INVALID) { ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); return 0; } @@ -1023,22 +1101,51 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm, } /*- - * Retrieve the newly enrolled certificate from the given certResponse crep. - * Uses libctx and propq from ctx, in case of indirect POPO also private key. + * Retrieve newly enrolled certificate and key from the given certResponse crep. + * Stores any centrally generated key in ctx->newPkey. + * In case of indirect POPO uses ctx->newPkey to decrypt the new certificate. * Returns a pointer to a copy of the found certificate, or NULL if not found. */ -X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx, - const OSSL_CMP_CERTRESPONSE *crep) +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; + OSSL_CRMF_ENCRYPTEDKEY *encr_key; + EVP_PKEY *pkey = NULL; + int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD) + == OSSL_CRMF_POPO_NONE; + + if (crep->certifiedKeyPair == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND); + return NULL; + } + encr_key = crep->certifiedKeyPair->privateKey; + if (encr_key == NULL && central_keygen) { + ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CENTRAL_GEN_KEY); + return NULL; + } + if (encr_key != NULL) { + if (!central_keygen) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY); + return NULL; + } + /* found encrypted private key, try to extract */ + pkey = OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(encr_key, ctx->trusted, + ctx->untrusted, + ctx->pkey, ctx->cert, + ctx->secretValue, + ctx->libctx, ctx->propq); + if (pkey == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY); + return NULL; + } + OSSL_CMP_CTX_set0_newPkey((OSSL_CMP_CTX *)ctx, 1, pkey); + } if (!ossl_assert(crep != NULL && ctx != NULL)) return NULL; - if (crep->certifiedKeyPair - && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) { + if ((coec = crep->certifiedKeyPair->certOrEncCert) != NULL) { switch (coec->type) { case OSSL_CMP_CERTORENCCERT_CERTIFICATE: crt = X509_dup(coec->value.certificate); @@ -1051,10 +1158,8 @@ X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx, 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); + crt = OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(coec->value.encryptedCert, + ctx->libctx, ctx->propq, pkey, 0); break; default: ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE); @@ -1106,8 +1211,8 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx, } msg = OSSL_CMP_MSG_new(libctx, propq); - if (msg == NULL){ - ERR_raise(ERR_LIB_CMP, ERR_R_MALLOC_FAILURE); + if (msg == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_CMP_LIB); return NULL; } @@ -1178,3 +1283,13 @@ 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); } + +int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg) +{ + if (!ossl_assert(msg != NULL)) + return 0; + + return (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_ERROR + && ossl_cmp_pkisi_get_status(msg->body->value.error->pKIStatusInfo) + == OSSL_CMP_PKISTATUS_waiting); +} diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c index 539f6534cd01..e4f3bffed720 100644 --- a/crypto/cmp/cmp_protect.c +++ b/crypto/cmp/cmp_protect.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -10,6 +10,7 @@ */ #include "cmp_local.h" +#include "crypto/asn1.h" /* explicit #includes not strictly needed since implied by the above: */ #include @@ -21,9 +22,11 @@ /* * 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 + * Calculate protection for |msg| according to |msg->header->protectionAlg| * using the credentials, library context, and property criteria in the ctx. + * Unless |msg->header->protectionAlg| is PasswordBasedMAC, + * its value is completed according to |ctx->pkey| and |ctx->digest|, + * where the latter irrelevant in the case of Edwards curves. * * returns ASN1_BIT_STRING representing the protection on success, else NULL */ @@ -91,9 +94,8 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, 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; + /* OpenSSL by default encodes all bit strings as ASN.1 NamedBitList */ + ossl_asn1_string_set_bits_left(prot, 0); if (!ASN1_BIT_STRING_set(prot, protection, sig_len)) { ASN1_BIT_STRING_free(prot); prot = NULL; @@ -104,23 +106,22 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, OPENSSL_free(prot_part_der); return prot; } else { - int md_nid; - const EVP_MD *md = NULL; + const EVP_MD *md = ctx->digest; + char name[80] = ""; 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 (EVP_PKEY_get_default_digest_name(ctx->pkey, name, sizeof(name)) > 0 + && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */ + md = NULL; if ((prot = ASN1_BIT_STRING_new()) == NULL) return NULL; - if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART), NULL, + if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART), + msg->header->protectionAlg, /* sets X509_ALGOR */ NULL, prot, &prot_part, NULL, ctx->pkey, md, ctx->libctx, ctx->propq)) return prot; @@ -129,6 +130,25 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx, } } +void ossl_cmp_set_own_chain(OSSL_CMP_CTX *ctx) +{ + if (!ossl_assert(ctx != NULL)) + return; + /* 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"); + } + } +} + /* 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) { @@ -141,22 +161,7 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) 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"); - } - } + ossl_cmp_set_own_chain(ctx); if (ctx->chain != NULL) { if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->chain, prepend)) return 0; @@ -185,15 +190,16 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) * 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) +static X509_ALGOR *pbmac_algor(const OSSL_CMP_CTX *ctx) { OSSL_CRMF_PBMPARAMETER *pbm = NULL; unsigned char *pbm_der = NULL; int pbm_der_len; ASN1_STRING *pbm_str = NULL; + X509_ALGOR *alg = NULL; if (!ossl_assert(ctx != NULL)) - return 0; + return NULL; pbm = OSSL_CRMF_pbmp_new(ctx->libctx, ctx->pbm_slen, EVP_MD_get_type(ctx->pbm_owf), ctx->pbm_itercnt, @@ -201,47 +207,18 @@ static int set_pbmac_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg) 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; - + alg = ossl_X509_ALGOR_from_nid(NID_id_PasswordBasedMAC, + V_ASN1_SEQUENCE, pbm_str); err: - ASN1_STRING_free(pbm_str); + if (alg == NULL) + 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; + return alg; } static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg, @@ -260,6 +237,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) /* * For the case of re-protection remove pre-existing protection. + * Does not remove any pre-existing extraCerts. */ X509_ALGOR_free(msg->header->protectionAlg); msg->header->protectionAlg = NULL; @@ -271,7 +249,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) 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)) + if ((msg->header->protectionAlg = pbmac_algor(ctx)) == NULL) goto err; if (!set_senderKID(ctx, msg, NULL)) goto err; @@ -290,7 +268,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) goto err; } - if (!set_sig_algor(ctx, &msg->header->protectionAlg)) + if ((msg->header->protectionAlg = X509_ALGOR_new()) == NULL) 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))) @@ -306,6 +284,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg) goto err; } if (!ctx->unprotectedSend + /* protect according to msg->header->protectionAlg partly set above */ && ((msg->protection = ossl_cmp_calc_protection(ctx, msg)) == NULL)) goto err; diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c index 96f977636ca2..6a833f83c538 100644 --- a/crypto/cmp/cmp_server.c +++ b/crypto/cmp/cmp_server.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -20,11 +20,11 @@ #include /* the context for the generic CMP server */ -struct ossl_cmp_srv_ctx_st -{ - 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 */ +struct ossl_cmp_srv_ctx_st { + OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */ + void *custom_ctx; /* application-specific server context */ + int certReqId; /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */ + int polling; /* current transaction is in polling mode */ OSSL_CMP_SRV_cert_request_cb_t process_cert_request; OSSL_CMP_SRV_rr_cb_t process_rr; @@ -32,6 +32,8 @@ struct ossl_cmp_srv_ctx_st 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_SRV_delayed_delivery_cb_t delayed_delivery; + OSSL_CMP_SRV_clean_transaction_cb_t clean_transaction; int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */ int acceptUnprotected; /* Accept requests with no/invalid prot. */ @@ -59,6 +61,7 @@ OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL) goto err; ctx->certReqId = OSSL_CMP_CERTREQID_INVALID; + ctx->polling = 0; /* all other elements are initialized to 0 or NULL, respectively */ return ctx; @@ -89,6 +92,19 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, return 1; } +int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_delayed_delivery_cb_t delay, + OSSL_CMP_SRV_clean_transaction_cb_t clean) +{ + if (srv_ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->delayed_delivery = delay; + srv_ctx->clean_transaction = clean; + return 1; +} + OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx) { if (srv_ctx == NULL) { @@ -149,6 +165,46 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx, return 1; } +/* return error msg with waiting status if polling is initiated, else NULL */ +static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + int ret; + unsigned long err; + int status = OSSL_CMP_PKISTATUS_waiting, + fail_info = 0, errorCode = 0; + const char *txt = NULL, *details = NULL; + OSSL_CMP_PKISI *si; + OSSL_CMP_MSG *msg; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL + && srv_ctx->delayed_delivery != NULL)) + return NULL; + + ret = srv_ctx->delayed_delivery(srv_ctx, req); + if (ret == 0) + return NULL; + if (ret == 1) { + srv_ctx->polling = 1; + } else { + status = OSSL_CMP_PKISTATUS_rejection; + fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_systemFailure; + txt = "server application error"; + err = ERR_peek_error(); + errorCode = ERR_GET_REASON(err); + details = ERR_reason_error_string(err); + } + + si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt); + if (si == NULL) + return NULL; + + msg = ossl_cmp_error_new(srv_ctx->ctx, si, errorCode, details, + srv_ctx->sendUnprotectedErrors); + OSSL_CMP_PKISI_free(si); + return msg; +} + /* * Processes an ir/cr/p10cr/kur and returns a certification response. * Only handles the first certification request contained in req @@ -160,11 +216,12 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, OSSL_CMP_MSG *msg = NULL; OSSL_CMP_PKISI *si = NULL; X509 *certOut = NULL; + EVP_PKEY *keyOut = NULL; STACK_OF(X509) *chainOut = NULL, *caPubs = NULL; const OSSL_CRMF_MSG *crm = NULL; const X509_REQ *p10cr = NULL; int bodytype; - int certReqId; + int certReqId, central_keygen; if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) return NULL; @@ -195,20 +252,23 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, 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) { + if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == 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) { + if (certReqId != OSSL_CMP_CERTREQID) { /* so far, only possible value */ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); - return 0; + return NULL; } } srv_ctx->certReqId = certReqId; - if (!ossl_cmp_verify_popo(srv_ctx->ctx, req, srv_ctx->acceptRAVerified)) { + central_keygen = OSSL_CRMF_MSG_centralkeygen_requested(crm, p10cr); + if (central_keygen < 0) + return NULL; + if (central_keygen == 0 + && !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, @@ -222,6 +282,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, &certOut, &chainOut, &caPubs); if (si == NULL) goto err; + if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) + srv_ctx->polling = 1; /* 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, @@ -230,19 +292,24 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, /* do not set if polling starts: */ && certOut != NULL)) goto err; + if (central_keygen == 1 + && srv_ctx->ctx->newPkey_priv && srv_ctx->ctx->newPkey != NULL) + keyOut = srv_ctx->ctx->newPkey; } msg = ossl_cmp_certrep_new(srv_ctx->ctx, bodytype, certReqId, si, - certOut, NULL /* enc */, chainOut, caPubs, + certOut, keyOut, NULL /* enc */, chainOut, caPubs, srv_ctx->sendUnprotectedErrors); + /* When supporting OSSL_CRMF_POPO_KEYENC, "enc" will need to be set */ 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); + OSSL_CMP_CTX_set0_newPkey(srv_ctx->ctx, 0, NULL); + OSSL_STACK_OF_X509_free(chainOut); + OSSL_STACK_OF_X509_free(caPubs); return msg; } @@ -264,9 +331,8 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, 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) { + details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, 0); + if (details == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return NULL; } @@ -355,7 +421,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, } 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); + status = sk_OSSL_CMP_CERTSTATUS_value(ccc, 0); } if (status != NULL) { @@ -386,38 +452,96 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return msg; } +/* pollReq is handled separately, to avoid recursive call */ +static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *rsp = NULL; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL + && req->body != NULL)) + return NULL; + + switch (OSSL_CMP_MSG_get_bodytype(req)) { + 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_UNSUPPORTED_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_UNSUPPORTED_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_UNSUPPORTED_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_UNSUPPORTED_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_UNSUPPORTED_PKIBODY); + else + rsp = process_certConf(srv_ctx, req); + break; + + case OSSL_CMP_PKIBODY_POLLREQ: + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + break; + default: + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); + break; + } + + return rsp; +} + 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; + OSSL_CMP_MSG *orig_req; int64_t check_after = 0; OSSL_CMP_MSG *msg = NULL; if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) return NULL; + if (!srv_ctx->polling) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + 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, OSSL_CMP_CERTREQID); + pr = sk_OSSL_CMP_POLLREQ_value(prc, 0); 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)) + &orig_req, &check_after)) return NULL; - if (certReq != NULL) { - msg = process_cert_request(srv_ctx, certReq); - OSSL_CMP_MSG_free(certReq); + if (orig_req != NULL) { + srv_ctx->polling = 0; + msg = process_non_polling_request(srv_ctx, orig_req); + OSSL_CMP_MSG_free(orig_req); } else { if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId, check_after)) == NULL) @@ -487,6 +611,12 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName)) goto err; + if (srv_ctx->polling && req_type != OSSL_CMP_PKIBODY_POLLREQ + && req_type != OSSL_CMP_PKIBODY_ERROR) { + ERR_raise(ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ); + goto err; + } + switch (req_type) { case OSSL_CMP_PKIBODY_IR: case OSSL_CMP_PKIBODY_CR: @@ -496,10 +626,8 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, case OSSL_CMP_PKIBODY_GENM: case OSSL_CMP_PKIBODY_ERROR: if (ctx->transactionID != NULL) { - char *tid; + char *tid = i2s_ASN1_OCTET_STRING(NULL, ctx->transactionID); - 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", @@ -510,6 +638,13 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL) || !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)) goto err; + + if (srv_ctx->clean_transaction != NULL + && !srv_ctx->clean_transaction(srv_ctx, NULL)) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + goto err; + } + break; default: /* transactionID should be already initialized */ @@ -529,49 +664,17 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, 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 (req_type == OSSL_CMP_PKIBODY_POLLREQ) { if (srv_ctx->process_pollReq == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_pollReq(srv_ctx, req); - break; - default: - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - break; + } else { + if (srv_ctx->delayed_delivery != NULL + && (rsp = delayed_delivery(srv_ctx, req)) != NULL) { + goto err; + } + rsp = process_non_polling_request(srv_ctx, req); } err: @@ -581,6 +684,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, int flags = 0; unsigned long err = ERR_peek_error_data(&data, &flags); int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest; + /* fail_info is not very specific */ OSSL_CMP_PKISI *si = NULL; if (!req_verified) { @@ -626,10 +730,19 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, break; /* fall through */ + case OSSL_CMP_PKIBODY_ERROR: + if (rsp != NULL && ossl_cmp_is_error_with_waiting(rsp)) + break; + /* fall through */ + case OSSL_CMP_PKIBODY_RP: case OSSL_CMP_PKIBODY_PKICONF: case OSSL_CMP_PKIBODY_GENP: - case OSSL_CMP_PKIBODY_ERROR: + /* Other terminating response message types are not supported */ + srv_ctx->certReqId = OSSL_CMP_CERTREQID_INVALID; + /* Prepare for next transaction, ignoring any errors here: */ + if (srv_ctx->clean_transaction != NULL) + (void)srv_ctx->clean_transaction(srv_ctx, ctx->transactionID); (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL); ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */ diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c index 68144aa4fed8..b9086d84f846 100644 --- a/crypto/cmp/cmp_status.c +++ b/crypto/cmp/cmp_status.c @@ -184,11 +184,11 @@ char *snprint_PKIStatusInfo_parts(int status, int fail_info, || (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL) return NULL; -#define ADVANCE_BUFFER \ - if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \ - return NULL; \ - write_ptr += printed_chars; \ - bufsize -= printed_chars; +#define ADVANCE_BUFFER \ + if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \ + return NULL; \ + write_ptr += printed_chars; \ + bufsize -= printed_chars; printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string); ADVANCE_BUFFER; diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index 7cf27cc9d4b4..f3c21c5d914c 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -53,8 +53,7 @@ static OSSL_CMP_severity parse_level(const char *level) if (end_level == NULL) return -1; - if (strncmp(level, OSSL_CMP_LOG_PREFIX, - strlen(OSSL_CMP_LOG_PREFIX)) == 0) + if (HAS_PREFIX(level, OSSL_CMP_LOG_PREFIX)) level += strlen(OSSL_CMP_LOG_PREFIX); len = end_level - level; if (len > max_level_len) @@ -190,7 +189,7 @@ void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn) BIO_free(bio); } #else - /* ERR_raise(ERR_LIB_CMP, CMP_R_NO_STDIO) makes no sense during error printing */ + /* ERR_raise(..., CMP_R_NO_STDIO) would make no sense here */ #endif } else { if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0) @@ -244,6 +243,7 @@ int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt, const ASN1_OCTET_STRING *src) { ASN1_OCTET_STRING *new; + if (tgt == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index b9951045c2e8..47bf38b2af5d 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -34,7 +34,8 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx, return 0; bio = BIO_new(BIO_s_mem()); /* may be NULL */ - + if (bio == NULL) + return 0; /* verify that keyUsage, if present, contains digitalSignature */ if (!cmp_ctx->ignore_keyusage && (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) { @@ -138,6 +139,24 @@ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx, return valid; } +static int verify_cb_cert(X509_STORE *ts, X509 *cert, int err) +{ + X509_STORE_CTX_verify_cb verify_cb; + X509_STORE_CTX *csc; + int ok = 0; + + if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL) + return ok; + if ((csc = X509_STORE_CTX_new()) != NULL + && X509_STORE_CTX_init(csc, ts, cert, NULL)) { + X509_STORE_CTX_set_error(csc, err); + X509_STORE_CTX_set_current_cert(csc, cert); + ok = (*verify_cb)(0, csc); + } + X509_STORE_CTX_free(csc); + return ok; +} + /* 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, @@ -156,8 +175,8 @@ static int check_name(const OSSL_CMP_CTX *ctx, int log_success, 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); + ossl_cmp_log3(INFO, ctx, " %s matches %s: %s", + actual_desc, expect_desc, str); OPENSSL_free(str); return 1; } @@ -186,7 +205,7 @@ static int check_kid(const OSSL_CMP_CTX *ctx, ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate"); return 0; } - str = OPENSSL_buf2hexstr(ckid->data, ckid->length); + str = i2s_ASN1_OCTET_STRING(NULL, ckid); if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0) { if (str != NULL) ossl_cmp_log1(INFO, ctx, " subjectKID matches senderKID: %s", str); @@ -197,7 +216,7 @@ static int check_kid(const OSSL_CMP_CTX *ctx, 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) + if ((str = i2s_ASN1_OCTET_STRING(NULL, skid)) != NULL) ossl_cmp_log1(INFO, ctx, " does not match senderKID = %s", str); OPENSSL_free(str); return 0; @@ -255,9 +274,14 @@ static int cert_acceptable(const OSSL_CMP_CTX *ctx, time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert), X509_get0_notAfter(cert)); if (time_cmp != 0) { + int err = time_cmp > 0 ? X509_V_ERR_CERT_HAS_EXPIRED + : X509_V_ERR_CERT_NOT_YET_VALID; + ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired" : "cert is not yet valid"); - return 0; + if (ctx->log_cb != NULL /* logging not temporarily disabled */ + && verify_cb_cert(ts, cert, err) <= 0) + return 0; } if (!check_name(ctx, 1, @@ -353,7 +377,7 @@ static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *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(). + * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert(). */ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs, const char *desc, @@ -382,13 +406,7 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *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; + return ossl_cmp_ctx_set1_validatedSrvCert(ctx, cert); } } if (in_extraCerts && n_acceptable_certs == 0) @@ -399,21 +417,21 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs, /*- * 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(). + * On success cache the found cert using ossl_cmp_ctx_set1_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))) + if (ctx->permitTAInExtraCertsForIR + && OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP) + ossl_cmp_info(ctx, mode_3gpp ? + "normal mode failed; trying now 3GPP mode trusting extraCerts" + : "trying first normal mode using trust store"); + else if (mode_3gpp) 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; @@ -426,25 +444,20 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, : "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); + OSSL_STACK_OF_X509_free(trusted); } 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(). + * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert(). */ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) { @@ -459,6 +472,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) if (sender == NULL || msg->body == NULL) return 0; /* other NULL cases already have been checked */ if (sender->type != GEN_DIRNAME) { + /* So far, only X509_NAME is supported */ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED); return 0; } @@ -468,7 +482,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) /* enable clearing irrelevant errors in attempts to validate sender certs */ (void)ERR_set_mark(); - ctx->log_cb = no_log_cb; /* temporarily disable logging */ + ctx->log_cb = NULL; /* temporarily disable logging */ /* * try first cached scrt, used successfully earlier in same transaction, @@ -481,7 +495,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) return 1; } /* cached sender cert has shown to be no more successfully usable */ - (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL); + (void)ossl_cmp_ctx_set1_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"); @@ -500,8 +514,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) (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); + skid_str = skid == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, skid); if (ctx->log_cb != NULL) { ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that.."); if (sname != NULL) @@ -537,7 +550,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) * 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(). + * On success cache the found cert using ossl_cmp_ctx_set1_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 @@ -599,7 +612,7 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) break; } ossl_cmp_debug(ctx, - "sucessfully validated PBM-based CMP message protection"); + "successfully validated PBM-based CMP message protection"); return 1; } ossl_cmp_warn(ctx, "verifying PBM-based CMP message protection failed"); @@ -624,15 +637,17 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR); return 0; } - if (check_msg_find_cert(ctx, msg)) + if (check_msg_find_cert(ctx, msg)) { + ossl_cmp_debug(ctx, + "successfully validated signature-based CMP message protection using trust store"); 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; + "successfully validated signature-based CMP message protection using pinned server cert"); + return ossl_cmp_ctx_set1_validatedSrvCert(ctx, scrt); } ossl_cmp_warn(ctx, "CMP message signature verification failed"); ERR_raise(ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG); @@ -642,12 +657,35 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) return 0; } +static int check_transactionID_or_nonce(ASN1_OCTET_STRING *expected, + ASN1_OCTET_STRING *actual, int reason) +{ + if (expected != NULL + && (actual == NULL || ASN1_OCTET_STRING_cmp(expected, actual) != 0)) { +#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + char *expected_str, *actual_str; + + expected_str = i2s_ASN1_OCTET_STRING(NULL, expected); + actual_str = actual == NULL ? NULL: i2s_ASN1_OCTET_STRING(NULL, actual); + ERR_raise_data(ERR_LIB_CMP, reason, + "expected = %s, actual = %s", + expected_str == NULL ? "?" : expected_str, + actual == NULL ? "(none)" : + actual_str == NULL ? "?" : actual_str); + OPENSSL_free(expected_str); + OPENSSL_free(actual_str); + return 0; +#endif + } + return 1; +} + /*- * 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 + * its sender is of appropriate type (currently 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 @@ -667,68 +705,94 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, { OSSL_CMP_PKIHEADER *hdr; const X509_NAME *expected_sender; + int num_untrusted, num_added, res; 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. - */ + /* If expected_sender is given, validate sender name of received msg */ 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; + if (expected_sender != NULL) { + const X509_NAME *actual_sender; + char *str; + + if (hdr->sender->type != GEN_DIRNAME) { + ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED); + return 0; + } + actual_sender = hdr->sender->d.directoryName; + /* + * Compare actual sender name of response with expected sender name. + * Mitigates risk of accepting misused PBM secret or + * misused certificate of an unauthorized entity of a trusted hierarchy. + */ + if (!check_name(ctx, 0, "sender DN field", actual_sender, + "expected sender", expected_sender)) { + str = X509_NAME_oneline(actual_sender, NULL, 0); + ERR_raise_data(ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER, + str != NULL ? str : ""); + OPENSSL_free(str); + 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"); + num_added = sk_X509_num(msg->extraCerts); + if (num_added > 10) + ossl_cmp_log1(WARN, ctx, "received CMP message contains %d extraCerts", + num_added); /* * 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. + * The extraCerts are prepended. Allows simple removal if they shall not be + * cached. Also they get used first, which is likely good for efficiency. */ - 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)) + num_untrusted = ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted); + res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts, + /* this allows self-signed certs */ + X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP + | X509_ADD_FLAG_PREPEND); + num_added = (ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted)) + - num_untrusted; + if (!res) { + while (num_added-- > 0) + X509_free(sk_X509_shift(ctx->untrusted)); 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 + if (hdr->protectionAlg != NULL) + res = OSSL_CMP_validate_msg(ctx, msg) + /* explicitly permitted exceptions for invalid protection: */ + || (cb != NULL && (*cb)(ctx, msg, 1, cb_arg) > 0); + else + /* explicitly permitted exceptions for missing protection: */ + res = cb != NULL && (*cb)(ctx, msg, 0, cb_arg) > 0; +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + res = 1; /* support more aggressive fuzzing by letting invalid msg pass */ +#endif + + /* remove extraCerts again if not caching */ + if (ctx->noCacheExtraCerts) + while (num_added-- > 0) + X509_free(sk_X509_shift(ctx->untrusted)); + + if (!res) { + if (hdr->protectionAlg != NULL) 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 + else ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION); - return 0; -#endif - } + return 0; } /* check CMP version number in header */ - if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO) { + if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_2 + && ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_3) { #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO); return 0; @@ -743,26 +807,30 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, } /* 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); + if (!check_transactionID_or_nonce(ctx->transactionID, hdr->transactionID, + CMP_R_TRANSACTIONID_UNMATCHED)) return 0; -#endif - } + /* + * enable clearing irrelevant errors + * in attempts to validate recipient nonce in case of delayed delivery. + */ + (void)ERR_set_mark(); /* 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 (!check_transactionID_or_nonce(ctx->senderNonce, hdr->recipNonce, + CMP_R_RECIPNONCE_UNMATCHED)) { + /* check if we are polling and received final response */ + if (ctx->first_senderNonce == NULL + || OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_POLLREP + /* compare received nonce with our sender nonce at poll start */ + || !check_transactionID_or_nonce(ctx->first_senderNonce, + hdr->recipNonce, + CMP_R_RECIPNONCE_UNMATCHED)) { + (void)ERR_clear_last_mark(); + return 0; + } } + (void)ERR_pop_to_mark(); /* if not yet present, learn transactionID */ if (ctx->transactionID == NULL @@ -777,18 +845,6 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce)) return 0; - /* - * 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 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 diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index 950952015923..1ed239961775 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -84,6 +84,7 @@ ASN1_NDEF_SEQUENCE(CMS_SignedData) = { ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1), ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo) } ASN1_NDEF_SEQUENCE_END(CMS_SignedData) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_SignedData) ASN1_SEQUENCE(CMS_OriginatorInfo) = { ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, certificates, CMS_CertificateChoices, 0), @@ -242,6 +243,7 @@ ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = { ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo), ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1) } ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData) +IMPLEMENT_ASN1_DUP_FUNCTION(CMS_EnvelopedData) ASN1_NDEF_SEQUENCE(CMS_DigestedData) = { ASN1_EMBED(CMS_DigestedData, version, INT32), @@ -315,7 +317,7 @@ static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, case ASN1_OP_STREAM_PRE: if (CMS_stream(&sarg->boundary, cms) <= 0) return 0; - /* fall thru */ + /* fall through */ case ASN1_OP_DETACHED_PRE: sarg->ndef_bio = CMS_dataInit(cms, sarg->out); if (!sarg->ndef_bio) diff --git a/crypto/cms/cms_cd.c b/crypto/cms/cms_cd.c index 6de6d55e58d8..3000268480f4 100644 --- a/crypto/cms/cms_cd.c +++ b/crypto/cms/cms_cd.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,7 +17,7 @@ #include #include "cms_local.h" -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB /* CMS CompressedData Utilities */ @@ -50,8 +50,9 @@ CMS_ContentInfo *ossl_cms_CompressedData_create(int comp_nid, cd->version = 0; - X509_ALGOR_set0(cd->compressionAlgorithm, - OBJ_nid2obj(NID_zlib_compression), V_ASN1_UNDEF, NULL); + (void)X509_ALGOR_set0(cd->compressionAlgorithm, + OBJ_nid2obj(NID_zlib_compression), + V_ASN1_UNDEF, NULL); /* cannot fail */ cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data); diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c index 6a7c049ef316..40b20249a3ad 100644 --- a/crypto/cms/cms_dd.c +++ b/crypto/cms/cms_dd.c @@ -66,7 +66,7 @@ int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, CMS_DigestedData *dd; if (mctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c index 3f931d6e6fef..b49e5f7f5366 100644 --- a/crypto/cms/cms_dh.c +++ b/crypto/cms/cms_dh.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,6 +13,7 @@ #include #include #include "internal/sizes.h" +#include "crypto/asn1.h" #include "crypto/evp.h" #include "cms_local.h" @@ -64,7 +65,7 @@ static int dh_cms_set_peerkey(EVP_PKEY_CTX *pctx, pkpeer = EVP_PKEY_new(); if (pkpeer == NULL || !EVP_PKEY_copy_parameters(pkpeer, pk) - || !EVP_PKEY_set1_encoded_public_key(pkpeer, buf, plen)) + || EVP_PKEY_set1_encoded_public_key(pkpeer, buf, plen) <= 0) goto err; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) @@ -122,7 +123,7 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri) goto err; kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, pctx->propquery); - if (kekcipher == NULL + if (kekcipher == NULL || EVP_CIPHER_get_mode(kekcipher) != EVP_CIPH_WRAP_MODE) goto err; if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL)) @@ -234,12 +235,11 @@ static int dh_cms_encrypt(CMS_RecipientInfo *ri) 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; + ossl_asn1_string_set_bits_left(pubkey, 0); penc = NULL; - X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber), - V_ASN1_UNDEF, NULL); + (void)X509_ALGOR_set0(talg, OBJ_nid2obj(NID_dhpublicnumber), + V_ASN1_UNDEF, NULL); /* cannot fail */ } /* See if custom parameters set */ diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c index d5ebe1ced0a6..6e9962ed6e8f 100644 --- a/crypto/cms/cms_ec.c +++ b/crypto/cms/cms_ec.c @@ -13,6 +13,7 @@ #include #include #include "internal/sizes.h" +#include "crypto/asn1.h" #include "crypto/evp.h" #include "cms_local.h" @@ -110,7 +111,7 @@ static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, if (p == NULL || plen == 0) goto err; - if (!EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen)) + if (EVP_PKEY_set1_encoded_public_key(pkpeer, p, plen) <= 0) goto err; if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0) @@ -281,8 +282,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) 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; + ossl_asn1_string_set_bits_left(pubkey, 0); penc = NULL; (void)X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), @@ -369,9 +369,9 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri) 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; + rv = X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str); + if (!rv) + ASN1_STRING_free(wrap_str); err: OPENSSL_free(penc); @@ -392,26 +392,3 @@ int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt) 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_enc.c b/crypto/cms/cms_enc.c index ae88df33a7f0..ea8f07e1affc 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -45,7 +45,7 @@ BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, b = BIO_new(BIO_f_cipher()); if (b == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB); return NULL; } @@ -121,10 +121,8 @@ BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, /* Generate random session key */ if (!enc || !ec->key) { tkey = OPENSSL_malloc(tkeylen); - if (tkey == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (tkey == NULL) goto err; - } if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0) goto err; } @@ -168,7 +166,7 @@ BIO *ossl_cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec, if (enc) { calg->parameter = ASN1_TYPE_new(); if (calg->parameter == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); goto err; } if ((EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)) { @@ -211,10 +209,8 @@ int ossl_cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, { ec->cipher = cipher; if (key) { - if ((ec->key = OPENSSL_malloc(keylen)) == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if ((ec->key = OPENSSL_malloc(keylen)) == NULL) return 0; - } memcpy(ec->key, key, keylen); } ec->keylen = keylen; @@ -235,7 +231,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, if (ciph) { cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData); if (!cms->d.encryptedData) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return 0; } cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted); diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index 445a16fb771f..375239c78db3 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -74,7 +74,7 @@ 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); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return NULL; } cms->d.envelopedData->version = 0; @@ -93,7 +93,7 @@ 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); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return NULL; } /* Defined in RFC 5083 - Section 2.1. "AuthEnvelopedData Type" */ @@ -232,18 +232,18 @@ CMS_ContentInfo *CMS_EnvelopedData_create_ex(const EVP_CIPHER *cipher, cms = CMS_ContentInfo_new_ex(libctx, propq); if (cms == NULL) - goto merr; + goto err; env = cms_enveloped_data_init(cms); if (env == NULL) - goto merr; + goto err; if (!ossl_cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL, 0, ossl_cms_get0_cmsctx(cms))) - goto merr; + goto err; return cms; - merr: + err: CMS_ContentInfo_free(cms); - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); return NULL; } @@ -252,6 +252,46 @@ CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher) return CMS_EnvelopedData_create_ex(cipher, NULL, NULL); } +BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data, + EVP_PKEY *pkey, X509 *cert, + ASN1_OCTET_STRING *secret, unsigned int flags, + OSSL_LIB_CTX *libctx, const char *propq) +{ + CMS_ContentInfo *ci; + BIO *bio = NULL; + int res = 0; + + if (env == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((ci = CMS_ContentInfo_new_ex(libctx, propq)) == NULL + || (bio = BIO_new(BIO_s_mem())) == NULL) + goto end; + ci->contentType = OBJ_nid2obj(NID_pkcs7_enveloped); + ci->d.envelopedData = env; + if (secret != NULL + && CMS_decrypt_set1_password(ci, (unsigned char *) + ASN1_STRING_get0_data(secret), + ASN1_STRING_length(secret)) != 1) + goto end; + res = CMS_decrypt(ci, secret == NULL ? pkey : NULL, + secret == NULL ? cert : NULL, detached_data, bio, flags); + + end: + if (ci != NULL) { + ci->d.envelopedData = NULL; /* do not indirectly free |env| */ + ci->contentType = NULL; + } + CMS_ContentInfo_free(ci); + if (!res) { + BIO_free(bio); + bio = NULL; + } + return bio; +} + CMS_ContentInfo * CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx, const char *propq) @@ -272,7 +312,7 @@ CMS_AuthEnvelopedData_create_ex(const EVP_CIPHER *cipher, OSSL_LIB_CTX *libctx, return cms; merr: CMS_ContentInfo_free(cms); - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); return NULL; } @@ -317,8 +357,12 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip, if (!ossl_cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx)) return 0; - X509_up_ref(recip); - EVP_PKEY_up_ref(pk); + if (!X509_up_ref(recip)) + return 0; + if (!EVP_PKEY_up_ref(pk)) { + X509_free(recip); + return 0; + } ktri->pkey = pk; ktri->recip = recip; @@ -355,8 +399,10 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip, /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); - if (ri == NULL) - goto merr; + if (ri == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } pk = X509_get0_pubkey(recip); if (pk == NULL) { @@ -383,13 +429,13 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip, } - if (!sk_CMS_RecipientInfo_push(ris, ri)) - goto merr; + if (!sk_CMS_RecipientInfo_push(ris, ri)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; + } return ri; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); err: M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; @@ -500,11 +546,8 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms, goto err; ek = OPENSSL_malloc(eklen); - - if (ek == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (ek == NULL) goto err; - } if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0) goto err; @@ -581,25 +624,17 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, 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; + if (EVP_PKEY_is_a(pkey, "RSA")) + /* upper layer CMS code incorrectly assumes that a successful RSA + * decryption means that the key matches ciphertext (which never + * was the case, implicit rejection or not), so to make it work + * disable implicit rejection for RSA keys */ + EVP_PKEY_CTX_ctrl_str(ktri->pctx, "rsa_pkcs1_implicit_rejection", "0"); - ek = OPENSSL_malloc(eklen); - if (ek == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (evp_pkey_decrypt_alloc(ktri->pctx, &ek, &eklen, fixlen, + ktri->encryptedKey->data, + ktri->encryptedKey->length) <= 0) 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; @@ -705,24 +740,32 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); - if (!ri) - goto merr; + if (!ri) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo); - if (!ri->d.kekri) - goto merr; + if (!ri->d.kekri) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } 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 (kekri->kekid->other == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } } - if (!sk_CMS_RecipientInfo_push(ris, ri)) - goto merr; + if (!sk_CMS_RecipientInfo_push(ris, ri)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; + } /* After this point no calls can fail */ @@ -740,13 +783,11 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, kekri->kekid->other->keyAttr = otherType; } - X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, - OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); + (void)X509_ALGOR_set0(kekri->keyEncryptionAlgorithm, OBJ_nid2obj(nid), + V_ASN1_UNDEF, NULL); /* cannot fail */ return ri; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); err: M_ASN1_free_of(ri, CMS_RecipientInfo); return NULL; @@ -805,7 +846,7 @@ static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx) { const char *alg = NULL; - switch(keylen) { + switch (keylen) { case 16: alg = "AES-128-WRAP"; break; @@ -857,14 +898,12 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms, /* 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); + if (wkey == NULL) goto err; - } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } @@ -940,14 +979,12 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, } ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); - if (ukey == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (ukey == NULL) goto err; - } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } @@ -1245,7 +1282,7 @@ int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain) env->unprotectedAttrs = sk_X509_ATTRIBUTE_new_null(); if (env->unprotectedAttrs == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); return 0; } @@ -1268,7 +1305,7 @@ int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio) BIO_get_cipher_ctx(cmsbio, &ctx); - /* + /* * The tag is set only for encryption. There is nothing to do for * decryption. */ diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index e67d783be290..98d6bea5f028 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -111,6 +111,8 @@ static const ERR_STRING_DATA CMS_str_reasons[] = { {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_PUBLIC_KEY), "no public key"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_RECEIPT_REQUEST), "no receipt request"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_SIGNERS), "no signers"}, + {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_OPERATION_UNSUPPORTED), + "operation unsupported"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PEER_KEY_ERROR), "peer key error"}, {ERR_PACK(ERR_LIB_CMS, 0, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), "private key does not match certificate"}, diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c index 6c43dd102a91..0885a682161c 100644 --- a/crypto/cms/cms_ess.c +++ b/crypto/cms/cms_ess.c @@ -121,13 +121,17 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex( CMS_ReceiptRequest *rr; rr = CMS_ReceiptRequest_new(); - if (rr == NULL) - goto merr; + if (rr == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } if (id) ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen); else { - if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32)) - goto merr; + if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32)) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } if (RAND_bytes_ex(libctx, rr->signedContentIdentifier->data, 32, 0) <= 0) goto err; @@ -146,9 +150,6 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_ex( return rr; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); - err: CMS_ReceiptRequest_free(rr); return NULL; @@ -169,19 +170,20 @@ int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr) int rrderlen, r = 0; rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder); - if (rrderlen < 0) - goto merr; + if (rrderlen < 0) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest, - V_ASN1_SEQUENCE, rrder, rrderlen)) - goto merr; + V_ASN1_SEQUENCE, rrder, rrderlen)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } r = 1; - merr: - if (!r) - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); - + err: OPENSSL_free(rrder); return r; @@ -241,7 +243,7 @@ int ossl_cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) } if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest, V_ASN1_OCTET_STRING, dig, diglen)) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); return 0; } return 1; diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c index dab70af73c33..f5d70e84cec7 100644 --- a/crypto/cms/cms_io.c +++ b/crypto/cms/cms_io.c @@ -18,6 +18,7 @@ int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms) { ASN1_OCTET_STRING **pos; + pos = CMS_get0_content(cms); if (pos == NULL) return 0; @@ -29,7 +30,7 @@ int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms) *boundary = &(*pos)->data; return 1; } - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); return 0; } diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c index 8e9e6a5d148c..ba7579f9f230 100644 --- a/crypto/cms/cms_kari.c +++ b/crypto/cms/cms_kari.c @@ -405,7 +405,9 @@ int ossl_cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, return 0; } - EVP_PKEY_up_ref(recipPubKey); + if (!EVP_PKEY_up_ref(recipPubKey)) + return 0; + rek->pkey = recipPubKey; return 1; } diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index 67b35627ba5e..2bf043103078 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,10 +14,12 @@ #include #include #include -#include +#include #include "internal/sizes.h" +#include "internal/cryptlib.h" #include "crypto/x509.h" #include "cms_local.h" +#include "internal/cms.h" static STACK_OF(CMS_CertificateChoices) **cms_get0_certificate_choices(CMS_ContentInfo *cms); @@ -62,7 +64,6 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq) if (ci->ctx.propq == NULL) { CMS_ContentInfo_free(ci); ci = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); } } } @@ -164,7 +165,7 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont) case NID_pkcs7_digest: cmsbio = ossl_cms_DigestedData_init_bio(cms); break; -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB case NID_id_smime_ct_compressedData: cmsbio = ossl_cms_CompressedData_init_bio(cms); break; @@ -198,6 +199,13 @@ err: /* unfortunately cannot constify SMIME_write_ASN1() due to this function */ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) +{ + return ossl_cms_DataFinal(cms, cmsbio, NULL, 0); +} + +int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio, + const unsigned char *precomp_md, + unsigned int precomp_mdlen) { ASN1_OCTET_STRING **pos = CMS_get0_content(cms); @@ -236,7 +244,7 @@ int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio) return ossl_cms_AuthEnvelopedData_final(cms, cmsbio); case NID_pkcs7_signed: - return ossl_cms_SignedData_final(cms, cmsbio); + return ossl_cms_SignedData_final(cms, cmsbio, precomp_md, precomp_mdlen); case NID_pkcs7_digest: return ossl_cms_DigestedData_do_final(cms, cmsbio, 0); @@ -386,7 +394,7 @@ int CMS_set_detached(CMS_ContentInfo *cms, int detached) (*pos)->flags |= ASN1_STRING_FLAG_CONT; return 1; } - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return 0; } @@ -400,6 +408,7 @@ BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm, const EVP_MD *digest = NULL; EVP_MD *fetched_digest = NULL; char alg[OSSL_MAX_NAME_SIZE]; + size_t xof_len = 0; X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm); OBJ_obj2txt(alg, sizeof(alg), digestoid, 0); @@ -424,6 +433,24 @@ BIO *ossl_cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm, ERR_raise(ERR_LIB_CMS, CMS_R_MD_BIO_INIT_ERROR); goto err; } + if (EVP_MD_xof(digest)) { + if (EVP_MD_is_a(digest, SN_shake128)) + xof_len = 32; + else if (EVP_MD_is_a(digest, SN_shake256)) + xof_len = 64; + if (xof_len > 0) { + EVP_MD_CTX *mdctx; + OSSL_PARAM params[2]; + + if (BIO_get_md_ctx(mdbio, &mdctx) <= 0 || mdctx == NULL) + goto err; + params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, + &xof_len); + params[1] = OSSL_PARAM_construct_end(); + if (!EVP_MD_CTX_set_params(mdctx, params)) + goto err; + } + } EVP_MD_free(fetched_digest); return mdbio; err: @@ -520,9 +547,9 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 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; + if (X509_cmp(cch->d.certificate, cert) == 0) { + X509_free(cert); + return 1; /* cert already present */ } } } @@ -536,11 +563,12 @@ int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert) 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; + if (!X509_up_ref(cert)) + return 0; + if (CMS_add0_cert(cms, cert)) + return 1; + X509_free(cert); + return 0; } static STACK_OF(CMS_RevocationInfoChoice) @@ -592,9 +620,9 @@ CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms) int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl) { - CMS_RevocationInfoChoice *rch; - rch = CMS_add0_RevocationInfoChoice(cms); - if (!rch) + CMS_RevocationInfoChoice *rch = CMS_add0_RevocationInfoChoice(cms); + + if (rch == NULL) return 0; rch->type = CMS_REVCHOICE_CRL; rch->d.crl = crl; @@ -614,55 +642,94 @@ int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl) STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms) { STACK_OF(X509) *certs = NULL; + + if (!ossl_cms_get1_certs_ex(cms, &certs)) + return NULL; + if (sk_X509_num(certs) == 0) { + sk_X509_free(certs); + return NULL; + } + return certs; +} + +int ossl_cms_get1_certs_ex(CMS_ContentInfo *cms, STACK_OF(X509) **certs) +{ CMS_CertificateChoices *cch; STACK_OF(CMS_CertificateChoices) **pcerts; - int i; + int i, n; + if (certs == NULL) + return 0; + *certs = NULL; pcerts = cms_get0_certificate_choices(cms); if (pcerts == NULL) - return NULL; - for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) { + return 0; + + /* make sure to return NULL *certs only on error */ + n = sk_CMS_CertificateChoices_num(*pcerts); + if ((*certs = sk_X509_new_reserve(NULL, n)) == NULL) + return 0; + + for (i = 0; i < n; 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; + if (!X509_add_cert(*certs, cch->d.certificate, + X509_ADD_FLAG_UP_REF)) { + OSSL_STACK_OF_X509_free(*certs); + *certs = NULL; + return 0; } } } - return certs; - + return 1; } 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) + if (!ossl_cms_get1_crls_ex(cms, &crls)) + return NULL; + if (sk_X509_CRL_num(crls) == 0) { + sk_X509_CRL_free(crls); 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_get1_crls_ex(CMS_ContentInfo *cms, STACK_OF(X509_CRL) **crls) +{ + STACK_OF(CMS_RevocationInfoChoice) **pcrls; + CMS_RevocationInfoChoice *rch; + int i, n; + + if (crls == NULL) + return 0; + *crls = NULL; + pcrls = cms_get0_revocation_choices(cms); + if (pcrls == NULL) + return 0; + + /* make sure to return NULL *crls only on error */ + n = sk_CMS_RevocationInfoChoice_num(*pcrls); + if ((*crls = sk_X509_CRL_new_reserve(NULL, n)) == NULL) + return 0; + + for (i = 0; i < n; i++) { + rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i); + if (rch->type == 0) { + if (!X509_CRL_up_ref(rch->d.crl) + || !ossl_assert(sk_X509_CRL_push(*crls, rch->d.crl))) { + /* push cannot fail on reserved stack */ + sk_X509_CRL_pop_free(*crls, X509_CRL_free); + *crls = NULL; + return 0; + } + } + } + return 1; +} + int ossl_cms_ias_cert_cmp(CMS_IssuerAndSerialNumber *ias, X509 *cert) { int ret; @@ -685,18 +752,23 @@ int ossl_cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert) { CMS_IssuerAndSerialNumber *ias; ias = M_ASN1_new_of(CMS_IssuerAndSerialNumber); - if (!ias) + if (!ias) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); goto err; - if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) + } + if (!X509_NAME_set(&ias->issuer, X509_get_issuer_name(cert))) { + ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB); goto err; - if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert))) + } + if (!ASN1_STRING_copy(ias->serialNumber, X509_get0_serialNumber(cert))) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); 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; } @@ -711,10 +783,47 @@ int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert) } keyid = ASN1_STRING_dup(cert_keyid); if (!keyid) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return 0; } ASN1_OCTET_STRING_free(*pkeyid); *pkeyid = keyid; return 1; } + +CMS_EnvelopedData *ossl_cms_sign_encrypt(BIO *data, X509 *sign_cert, STACK_OF(X509) *certs, + EVP_PKEY *sign_key, unsigned int sign_flags, + STACK_OF(X509) *enc_recip, const EVP_CIPHER *cipher, + unsigned int enc_flags, OSSL_LIB_CTX *libctx, + const char *propq) +{ + CMS_EnvelopedData *evd = NULL; + BIO *privbio = NULL, *signbio = NULL; + CMS_ContentInfo *signcms = NULL, *evpcms = NULL; + + if (data == NULL || sign_key == NULL || sign_cert == NULL || enc_recip == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + signcms = CMS_sign_ex(sign_cert, sign_key, certs, data, sign_flags, libctx, propq); + if (signcms == NULL) + goto err; + + signbio = BIO_new(BIO_s_mem()); + if (signbio == NULL + || ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_SignedData), signbio, signcms->d.signedData) <= 0) + goto err; + + evpcms = CMS_encrypt_ex(enc_recip, signbio, cipher, enc_flags, libctx, propq); + if (evpcms == NULL) + goto err; + evd = CMS_EnvelopedData_dup(evpcms->d.envelopedData); + + err: + BIO_free(privbio); + BIO_free(signbio); + CMS_ContentInfo_free(signcms); + CMS_ContentInfo_free(evpcms); + + return evd; +} diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index 1e0e0910d1d1..8ed67f5c19f4 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,11 +21,9 @@ typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber; typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo; typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier; -typedef struct CMS_SignedData_st CMS_SignedData; typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat; typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo; typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo; -typedef struct CMS_EnvelopedData_st CMS_EnvelopedData; typedef struct CMS_DigestedData_st CMS_DigestedData; typedef struct CMS_EncryptedData_st CMS_EncryptedData; typedef struct CMS_AuthenticatedData_st CMS_AuthenticatedData; @@ -102,6 +100,8 @@ struct CMS_SignerInfo_st { EVP_MD_CTX *mctx; EVP_PKEY_CTX *pctx; const CMS_CTX *cms_ctx; + /* Set to 1 if signing time attribute is to be omitted */ + int omit_signing_time; }; struct CMS_SignerIdentifier_st { @@ -396,6 +396,9 @@ const char *ossl_cms_ctx_get0_propq(const CMS_CTX *ctx); void ossl_cms_resolve_libctx(CMS_ContentInfo *ci); CMS_ContentInfo *ossl_cms_Data_create(OSSL_LIB_CTX *ctx, const char *propq); +int ossl_cms_DataFinal(CMS_ContentInfo *cms, BIO *cmsbio, + const unsigned char *precomp_md, + unsigned int precomp_mdlen); CMS_ContentInfo *ossl_cms_DigestedData_create(const EVP_MD *md, OSSL_LIB_CTX *libctx, @@ -405,7 +408,9 @@ int ossl_cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, int verify); BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms); -int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain); +int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain, + const unsigned char *precomp_md, + unsigned int precomp_mdlen); int ossl_cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type, const CMS_CTX *ctx); int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, @@ -480,9 +485,11 @@ int ossl_cms_check_signing_certs(const CMS_SignerInfo *si, int ossl_cms_dh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_ecdh_envelope(CMS_RecipientInfo *ri, int decrypt); int ossl_cms_rsa_envelope(CMS_RecipientInfo *ri, int decrypt); -int ossl_cms_ecdsa_dsa_sign(CMS_SignerInfo *si, int verify); int ossl_cms_rsa_sign(CMS_SignerInfo *si, int verify); +int ossl_cms_get1_certs_ex(CMS_ContentInfo *cms, STACK_OF(X509) **certs); +int ossl_cms_get1_crls_ex(CMS_ContentInfo *cms, STACK_OF(X509_CRL) **crls); + DECLARE_ASN1_ITEM(CMS_CertificateChoices) DECLARE_ASN1_ITEM(CMS_DigestedData) DECLARE_ASN1_ITEM(CMS_EncryptedData) diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c index 2373092bed55..a7d609f83791 100644 --- a/crypto/cms/cms_pwri.c +++ b/crypto/cms/cms_pwri.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2009-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -82,11 +82,12 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, /* Setup algorithm identifier for cipher */ encalg = X509_ALGOR_new(); if (encalg == NULL) { - goto merr; + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } @@ -110,7 +111,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, } encalg->parameter = ASN1_TYPE_new(); if (!encalg->parameter) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); goto err; } if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) { @@ -126,12 +127,16 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, /* Initialize recipient info */ ri = M_ASN1_new_of(CMS_RecipientInfo); - if (ri == NULL) - goto merr; + if (ri == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } ri->d.pwri = M_ASN1_new_of(CMS_PasswordRecipientInfo); - if (ri->d.pwri == NULL) - goto merr; + if (ri->d.pwri == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } ri->type = CMS_RECIPINFO_PASS; pwri = ri->d.pwri; @@ -139,17 +144,23 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, /* Since this is overwritten, free up empty structure already there */ X509_ALGOR_free(pwri->keyEncryptionAlgorithm); pwri->keyEncryptionAlgorithm = X509_ALGOR_new(); - if (pwri->keyEncryptionAlgorithm == NULL) - goto merr; + if (pwri->keyEncryptionAlgorithm == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid); pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new(); - if (pwri->keyEncryptionAlgorithm->parameter == NULL) - goto merr; + if (pwri->keyEncryptionAlgorithm->parameter == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } if (!ASN1_item_pack(encalg, ASN1_ITEM_rptr(X509_ALGOR), &pwri->keyEncryptionAlgorithm->parameter-> - value.sequence)) - goto merr; + value.sequence)) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE; X509_ALGOR_free(encalg); @@ -157,7 +168,8 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, /* Setup PBE algorithm */ - pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1); + pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set_ex(iter, NULL, 0, -1, -1, + cms_ctx->libctx); if (pwri->keyDerivationAlgorithm == NULL) goto err; @@ -165,13 +177,13 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, CMS_RecipientInfo_set0_password(ri, pass, passlen); pwri->version = 0; - if (!sk_CMS_RecipientInfo_push(ris, ri)) - goto merr; + if (!sk_CMS_RecipientInfo_push(ris, ri)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; + } return ri; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); err: EVP_CIPHER_CTX_free(ctx); if (ri) @@ -193,6 +205,10 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); unsigned char *tmp; int outl, rv = 0; + + if (blocklen == 0) + return 0; + if (inlen < 2 * blocklen) { /* too small */ return 0; @@ -201,10 +217,8 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, /* Invalid size */ return 0; } - if ((tmp = OPENSSL_malloc(inlen)) == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if ((tmp = OPENSSL_malloc(inlen)) == NULL) return 0; - } /* setup IV by decrypting last two blocks */ if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, in + inlen - 2 * blocklen, blocklen * 2) @@ -248,6 +262,10 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen, size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx); size_t olen; int dummy; + + if (blocklen == 0) + return 0; + /* * First decide length of output buffer: need header and round up to * multiple of block length. @@ -335,7 +353,7 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, kekctx = EVP_CIPHER_CTX_new(); if (kekctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } /* Fixup cipher based on AlgorithmIdentifier to set IV etc */ @@ -351,9 +369,10 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, /* Finish password based key derivation to setup key in "ctx" */ - if (EVP_PBE_CipherInit(algtmp->algorithm, - (char *)pwri->pass, pwri->passlen, - algtmp->parameter, kekctx, en_de) < 0) { + if (EVP_PBE_CipherInit_ex(algtmp->algorithm, + (char *)pwri->pass, pwri->passlen, + algtmp->parameter, kekctx, en_de, + cms_ctx->libctx, cms_ctx->propq) < 0) { ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } @@ -376,11 +395,8 @@ int ossl_cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, pwri->encryptedKey->length = keylen; } else { key = OPENSSL_malloc(pwri->encryptedKey->length); - - if (key == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (key == NULL) goto err; - } if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data, pwri->encryptedKey->length, kekctx)) { diff --git a/crypto/cms/cms_rsa.c b/crypto/cms/cms_rsa.c index 5e26e89d5012..f132df5c8a0f 100644 --- a/crypto/cms/cms_rsa.c +++ b/crypto/cms/cms_rsa.c @@ -150,17 +150,16 @@ static int rsa_cms_encrypt(CMS_RecipientInfo *ri) if (!ossl_x509_algor_md_to_mgf1(&oaep->maskGenFunc, mgf1md)) goto err; if (labellen > 0) { - oaep->pSourceFunc = X509_ALGOR_new(); - if (oaep->pSourceFunc == NULL) - goto err; los = ASN1_OCTET_STRING_new(); + if (los == NULL) goto err; if (!ASN1_OCTET_STRING_set(los, label, labellen)) goto err; - if (!X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified), - V_ASN1_OCTET_STRING, los)) + oaep->pSourceFunc = ossl_X509_ALGOR_from_nid(NID_pSpecified, + V_ASN1_OCTET_STRING, los); + if (oaep->pSourceFunc == NULL) goto err; los = NULL; @@ -208,10 +207,10 @@ static int rsa_cms_sign(CMS_SignerInfo *si) if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0) return 0; } - if (pad_mode == RSA_PKCS1_PADDING) { - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); - return 1; - } + if (pad_mode == RSA_PKCS1_PADDING) + return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, NULL); + /* We don't support it */ if (pad_mode != RSA_PKCS1_PSS_PADDING) return 0; diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 4758d048386e..9d5b8607de0e 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -38,7 +38,7 @@ static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) if (cms->d.other == NULL) { cms->d.signedData = M_ASN1_new_of(CMS_SignedData); if (!cms->d.signedData) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); return NULL; } cms->d.signedData->version = 1; @@ -53,7 +53,6 @@ static CMS_SignedData *cms_signed_data_init(CMS_ContentInfo *cms) } /* Just initialise SignedData e.g. for certs only structure */ - int CMS_SignedData_init(CMS_ContentInfo *cms) { if (cms_signed_data_init(cms)) @@ -62,9 +61,7 @@ int CMS_SignedData_init(CMS_ContentInfo *cms) return 0; } - /* Check structures and fixup version numbers (if necessary) */ - static void cms_sd_set_version(CMS_SignedData *sd) { int i; @@ -105,8 +102,9 @@ static void cms_sd_set_version(CMS_SignedData *sd) si->version = 3; if (sd->version < 3) sd->version = 3; - } else if (si->version < 1) + } else if (si->version < 1) { si->version = 1; + } } if (sd->version < 1) @@ -136,7 +134,6 @@ static int cms_set_si_contentType_attr(CMS_ContentInfo *cms, CMS_SignerInfo *si) } /* Copy an existing messageDigest value */ - static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si) { STACK_OF(CMS_SignerInfo) *sinfos; @@ -212,8 +209,9 @@ int ossl_cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid, } else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) { if (keyid) *keyid = sid->d.subjectKeyIdentifier; - } else + } else { return 0; + } return 1; } @@ -227,19 +225,60 @@ int ossl_cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert) return -1; } +static int cms_signature_nomd(EVP_PKEY *pkey) +{ + char def_md[80]; + + return EVP_PKEY_get_default_digest_name(pkey, def_md, sizeof(def_md)) == 2 + && strcmp(def_md, "UNDEF") == 0 ? 1 : 0; +} + +/* Method to map any, incl. provider-implemented PKEY types to OIDs */ +/* (EC)DSA and all provider-delivered signatures implementation is the same */ +static int cms_generic_sign(CMS_SignerInfo *si, int verify) +{ + if (!ossl_assert(verify == 0 || verify == 1)) + return -1; + + if (!verify) { + EVP_PKEY *pkey = si->pkey; + int snid, hnid, pknid = EVP_PKEY_get_id(pkey); + X509_ALGOR *alg1, *alg2; + + 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 (pknid <= 0) { /* check whether a provider registered a NID */ + const char *typename = EVP_PKEY_get0_type_name(pkey); + + if (typename != NULL) + pknid = OBJ_txt2nid(typename); + } + if (pknid > 0 && cms_signature_nomd(pkey)) + snid = pknid; + else if (!OBJ_find_sigid_by_algs(&snid, hnid, pknid)) + return -1; + return X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); + } + return 1; +} + static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd) { EVP_PKEY *pkey = si->pkey; int i; if (EVP_PKEY_is_a(pkey, "DSA") || EVP_PKEY_is_a(pkey, "EC")) - return ossl_cms_ecdsa_dsa_sign(si, cmd) > 0; + return cms_generic_sign(si, cmd) > 0; else if (EVP_PKEY_is_a(pkey, "RSA") || EVP_PKEY_is_a(pkey, "RSA-PSS")) return ossl_cms_rsa_sign(si, cmd) > 0; - /* Something else? We'll give engines etc a chance to handle this */ + /* Now give engines, providers, etc a chance to handle this */ if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) - return 1; + return cms_generic_sign(si, cmd) > 0; i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si); if (i == -2) { ERR_raise(ERR_LIB_CMS, CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); @@ -320,22 +359,29 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); - if (!si) - goto merr; + if (!si) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } /* Call for side-effect of computing hash and caching extensions */ X509_check_purpose(signer, -1, -1); - X509_up_ref(signer); - EVP_PKEY_up_ref(pk); + if (!X509_up_ref(signer)) + goto err; + if (!EVP_PKEY_up_ref(pk)) { + X509_free(signer); + goto err; + } si->cms_ctx = ctx; si->pkey = pk; si->signer = signer; si->mctx = EVP_MD_CTX_new(); si->pctx = NULL; + si->omit_signing_time = 0; if (si->mctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } @@ -368,16 +414,6 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, } } - if (!md) { - ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET); - goto err; - } - - if (md == NULL) { - ERR_raise(ERR_LIB_CMS, CMS_R_NO_DIGEST_SET); - goto err; - } - X509_ALGOR_set_md(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ @@ -393,13 +429,15 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { - alg = X509_ALGOR_new(); - if (alg == NULL) - goto merr; + if ((alg = X509_ALGOR_new()) == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_ASN1_LIB); + goto err; + } X509_ALGOR_set_md(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); - goto merr; + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; } } @@ -415,18 +453,31 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); - if (!si->signedAttrs) - goto merr; + if (!si->signedAttrs) { + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; + } } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; + i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); - if (!i) - goto merr; + if (!i) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } + } + if ((flags & CMS_NO_SIGNING_TIME) != 0) { + /* + * The signing-time signed attribute (NID_pkcs9_signingTime) + * would normally be added later, in CMS_SignerInfo_sign(), + * unless we set this flag here + */ + si->omit_signing_time = 1; } if (flags & CMS_CADES) { ESS_SIGNING_CERT *sc = NULL; @@ -462,8 +513,10 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ - if (!CMS_add1_cert(cms, signer)) - goto merr; + if (!CMS_add1_cert(cms, signer)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } } if (flags & CMS_KEY_PARAM) { @@ -490,15 +543,15 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, } } - if (!sd->signerInfos) + if (sd->signerInfos == NULL) sd->signerInfos = sk_CMS_SignerInfo_new_null(); - if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) - goto merr; + if (sd->signerInfos == NULL || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CRYPTO_LIB); + goto err; + } return si; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); err: M_ASN1_free_of(si, CMS_SignerInfo); return NULL; @@ -533,21 +586,22 @@ static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t) else tt = X509_gmtime_adj(NULL, 0); - if (tt == NULL) - goto merr; + if (tt == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB); + goto err; + } if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime, - tt->type, tt, -1) <= 0) - goto merr; + tt->type, tt, -1) <= 0) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } r = 1; - merr: + err: if (t == NULL) ASN1_TIME_free(tt); - if (!r) - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); - return r; } @@ -593,7 +647,8 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms) void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer) { if (signer != NULL) { - X509_up_ref(signer); + if (!X509_up_ref(signer)) + return; EVP_PKEY_free(si->pkey); si->pkey = X509_get_pubkey(signer); } @@ -647,7 +702,7 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts, for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) { cch = sk_CMS_CertificateChoices_value(certs, j); - if (cch->type != 0) + if (cch->type != CMS_CERTCHOICE_CERT) continue; x = cch->d.certificate; if (CMS_SignerInfo_cert_cmp(si, x) == 0) { @@ -680,7 +735,9 @@ ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si) } static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, - CMS_SignerInfo *si, BIO *chain) + CMS_SignerInfo *si, BIO *chain, + const unsigned char *md, + unsigned int mdlen) { EVP_MD_CTX *mctx = EVP_MD_CTX_new(); int r = 0; @@ -688,7 +745,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, const CMS_CTX *ctx = ossl_cms_get0_cmsctx(cms); if (mctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); return 0; } @@ -706,13 +763,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, /* * If any signed attributes calculate and add messageDigest attribute */ - if (CMS_signed_get_attr_count(si) >= 0) { - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mdlen; + unsigned char computed_md[EVP_MAX_MD_SIZE]; - if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) - goto err; + if (md == NULL) { + if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen)) + goto err; + md = computed_md; + } if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING, md, mdlen)) goto err; @@ -725,19 +783,18 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, } else if (si->pctx) { unsigned char *sig; size_t siglen; - unsigned char md[EVP_MAX_MD_SIZE]; - unsigned int mdlen; + unsigned char computed_md[EVP_MAX_MD_SIZE]; pctx = si->pctx; si->pctx = NULL; - if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) - goto err; - siglen = EVP_PKEY_get_size(si->pkey); - sig = OPENSSL_malloc(siglen); - if (sig == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); - goto err; + if (md == NULL) { + if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen)) + goto err; + md = computed_md; } + siglen = EVP_PKEY_get_size(si->pkey); + if (siglen == 0 || (sig = OPENSSL_malloc(siglen)) == NULL) + goto err; if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) { OPENSSL_free(sig); goto err; @@ -747,11 +804,13 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, unsigned char *sig; unsigned int siglen; - sig = OPENSSL_malloc(EVP_PKEY_get_size(si->pkey)); - if (sig == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + if (md != NULL) { + ERR_raise(ERR_LIB_CMS, CMS_R_OPERATION_UNSUPPORTED); goto err; } + siglen = EVP_PKEY_get_size(si->pkey); + if (siglen == 0 || (sig = OPENSSL_malloc(siglen)) == NULL) + goto err; if (!EVP_SignFinal_ex(mctx, sig, &siglen, si->pkey, ossl_cms_ctx_get0_libctx(ctx), ossl_cms_ctx_get0_propq(ctx))) { @@ -771,7 +830,9 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, } -int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) +int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain, + const unsigned char *precomp_md, + unsigned int precomp_mdlen) { STACK_OF(CMS_SignerInfo) *sinfos; CMS_SignerInfo *si; @@ -780,7 +841,8 @@ int ossl_cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain) sinfos = CMS_get0_SignerInfos(cms); for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) { si = sk_CMS_SignerInfo_value(sinfos, i); - if (!cms_SignerInfo_content_sign(cms, si, chain)) + if (!cms_SignerInfo_content_sign(cms, si, chain, + precomp_md, precomp_mdlen)) return 0; } cms->d.signedData->encapContentInfo->partial = 0; @@ -795,13 +857,15 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) int alen; size_t siglen; const CMS_CTX *ctx = si->cms_ctx; - char md_name[OSSL_MAX_NAME_SIZE]; + char md_name_buf[OSSL_MAX_NAME_SIZE], *md_name; - if (OBJ_obj2txt(md_name, sizeof(md_name), - si->digestAlgorithm->algorithm, 0) <= 0) + if (OBJ_obj2txt(md_name_buf, sizeof(md_name_buf), + si->digestAlgorithm->algorithm, 0) <= 0) return 0; + md_name = cms_signature_nomd(si->pkey) ? NULL : md_name_buf; - if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { + if (!si->omit_signing_time + && CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) { if (!cms_add1_signingTime(si, NULL)) goto err; } @@ -809,9 +873,9 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) if (!ossl_cms_si_check_attributes(si)) goto err; - if (si->pctx) + if (si->pctx) { pctx = si->pctx; - else { + } else { EVP_MD_CTX_reset(mctx); if (EVP_DigestSignInit_ex(mctx, &pctx, md_name, ossl_cms_ctx_get0_libctx(ctx), @@ -822,9 +886,16 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) si->pctx = pctx; } + if (md_name == NULL) { + if (ASN1_item_sign_ctx(ASN1_ITEM_rptr(CMS_Attributes_Sign), NULL, + NULL, si->signature, si->signedAttrs, mctx) <= 0) + goto err; + return 1; + } + alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &abuf, ASN1_ITEM_rptr(CMS_Attributes_Sign)); - if (!abuf) + if (alen < 0 || abuf == NULL) goto err; if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) goto err; @@ -869,6 +940,16 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) if (!ossl_cms_si_check_attributes(si)) return -1; + if (cms_signature_nomd(si->pkey)) { + r = ASN1_item_verify_ex(ASN1_ITEM_rptr(CMS_Attributes_Sign), + si->signatureAlgorithm, si->signature, + si->signedAttrs, NULL, si->pkey, + libctx, propq); + if (r <= 0) + ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE); + return r; + } + OBJ_obj2txt(name, sizeof(name), si->digestAlgorithm->algorithm, 0); (void)ERR_set_mark(); @@ -886,7 +967,7 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) (void)ERR_pop_to_mark(); if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } mctx = si->mctx; @@ -925,7 +1006,6 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) } /* Create a chain of digest BIOs from a CMS ContentInfo */ - BIO *ossl_cms_SignedData_init_bio(CMS_ContentInfo *cms) { int i; @@ -967,7 +1047,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) unsigned int mlen; if (mctx == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_EVP_LIB); goto err; } /* If we have any signed attributes look for messageDigest value */ @@ -990,7 +1070,6 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) } /* If messageDigest found compare it */ - if (os != NULL) { if (mlen != (unsigned int)os->length) { ERR_raise(ERR_LIB_CMS, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH); @@ -1000,8 +1079,9 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) if (memcmp(mval, os->data, mlen)) { ERR_raise(ERR_LIB_CMS, CMS_R_VERIFICATION_FAILURE); r = 0; - } else + } else { r = 1; + } } else { const EVP_MD *md = EVP_MD_CTX_get0_md(mctx); const CMS_CTX *ctx = si->cms_ctx; @@ -1036,6 +1116,47 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain) } +BIO *CMS_SignedData_verify(CMS_SignedData *sd, BIO *detached_data, + STACK_OF(X509) *scerts, X509_STORE *store, + STACK_OF(X509) *extra, STACK_OF(X509_CRL) *crls, + unsigned int flags, + OSSL_LIB_CTX *libctx, const char *propq) +{ + CMS_ContentInfo *ci; + BIO *bio = NULL; + int i, res = 0; + + if (sd == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if ((ci = CMS_ContentInfo_new_ex(libctx, propq)) == NULL) + return NULL; + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto end; + ci->contentType = OBJ_nid2obj(NID_pkcs7_signed); + ci->d.signedData = sd; + + for (i = 0; i < sk_X509_num(extra); i++) + if (!CMS_add1_cert(ci, sk_X509_value(extra, i))) + goto end; + for (i = 0; i < sk_X509_CRL_num(crls); i++) + if (!CMS_add1_crl(ci, sk_X509_CRL_value(crls, i))) + goto end; + res = CMS_verify(ci, scerts, store, detached_data, bio, flags); + + end: + if (ci != NULL) + ci->d.signedData = NULL; /* do not indirectly free |sd| */ + CMS_ContentInfo_free(ci); + if (!res) { + BIO_free(bio); + bio = NULL; + } + return bio; +} + int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) { unsigned char *smder = NULL; @@ -1053,36 +1174,33 @@ int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs) int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, int algnid, int keysize) { - X509_ALGOR *alg = NULL; + X509_ALGOR *alg; ASN1_INTEGER *key = NULL; if (keysize > 0) { key = ASN1_INTEGER_new(); - if (key == NULL || !ASN1_INTEGER_set(key, keysize)) - goto err; + if (key == NULL || !ASN1_INTEGER_set(key, keysize)) { + ASN1_INTEGER_free(key); + return 0; + } + } + alg = ossl_X509_ALGOR_from_nid(algnid, key != NULL ? V_ASN1_INTEGER : + V_ASN1_UNDEF, key); + if (alg == NULL) { + ASN1_INTEGER_free(key); + return 0; } - alg = X509_ALGOR_new(); - if (alg == NULL) - goto err; - if (!X509_ALGOR_set0(alg, OBJ_nid2obj(algnid), - key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key)) - goto err; - key = NULL; if (*algs == NULL) *algs = sk_X509_ALGOR_new_null(); - if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) - goto err; + if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) { + X509_ALGOR_free(alg); + return 0; + } return 1; - - err: - ASN1_INTEGER_free(key); - X509_ALGOR_free(alg); - return 0; } /* Check to see if a cipher exists and if so add S/MIME capabilities */ - static int cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg) { if (EVP_get_cipherbynid(nid)) diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 65da2452fcea..3f3d93fa0095 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,6 +15,7 @@ #include #include "cms_local.h" #include "crypto/asn1.h" +#include "crypto/x509.h" static BIO *cms_get_text_bio(BIO *out, unsigned int flags) { @@ -39,7 +40,7 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags) tmpout = cms_get_text_bio(out, flags); if (tmpout == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); goto err; } @@ -260,7 +261,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, X509_STORE *store, - STACK_OF(X509) *certs, + STACK_OF(X509) *untrusted, STACK_OF(X509_CRL) *crls, STACK_OF(X509) **chain, const CMS_CTX *cms_ctx) @@ -272,11 +273,11 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, 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); + ERR_raise(ERR_LIB_CMS, ERR_R_X509_LIB); goto err; } CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL); - if (!X509_STORE_CTX_init(ctx, store, signer, certs)) { + if (!X509_STORE_CTX_init(ctx, store, signer, untrusted)) { ERR_raise(ERR_LIB_CMS, CMS_R_STORE_INIT_ERROR); goto err; } @@ -302,12 +303,13 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si, } +/* This strongly overlaps with PKCS7_verify() */ 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) *untrusted = NULL; STACK_OF(X509_CRL) *crls = NULL; STACK_OF(X509) **si_chains = NULL; X509 *signer; @@ -337,7 +339,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, 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) + if (signer != NULL) scount++; } @@ -356,18 +358,24 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, 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); + if (si_chains == NULL) goto err; - } } - cms_certs = CMS_get1_certs(cms); - if (!(flags & CMS_NOCRL)) - crls = CMS_get1_crls(cms); + if (!ossl_cms_get1_certs_ex(cms, &untrusted)) + goto err; + if (sk_X509_num(certs) > 0 + && !ossl_x509_add_certs_new(&untrusted, certs, + X509_ADD_FLAG_UP_REF | + X509_ADD_FLAG_NO_DUP)) + goto err; + + if ((flags & CMS_NOCRL) == 0 + && !ossl_cms_get1_crls_ex(cms, &crls)) + goto err; for (i = 0; i < scount; i++) { si = sk_CMS_SignerInfo_value(sinfos, i); - if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls, + if (!cms_signerinfo_verify_cert(si, store, untrusted, crls, si_chains ? &si_chains[i] : NULL, ctx)) goto err; @@ -406,7 +414,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, 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); + ERR_raise(ERR_LIB_CMS, ERR_R_BIO_LIB); goto err2; } } else { @@ -423,7 +431,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, */ tmpout = cms_get_text_bio(out, flags); if (tmpout == NULL) { - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); goto err; } cmsbio = CMS_dataInit(cms, tmpout); @@ -480,10 +488,10 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, err2: if (si_chains != NULL) { for (i = 0; i < scount; ++i) - sk_X509_pop_free(si_chains[i], X509_free); + OSSL_STACK_OF_X509_free(si_chains[i]); OPENSSL_free(si_chains); } - sk_X509_pop_free(cms_certs, X509_free); + sk_X509_pop_free(untrusted, X509_free); sk_X509_CRL_pop_free(crls, X509_CRL_free); return ret; @@ -511,12 +519,16 @@ CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey, int i; cms = CMS_ContentInfo_new_ex(libctx, propq); - if (cms == NULL || !CMS_SignedData_init(cms)) - goto merr; + if (cms == NULL || !CMS_SignedData_init(cms)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } if (flags & CMS_ASCIICRLF && !CMS_set1_eContentType(cms, - OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF))) + OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF))) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); goto err; + } if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) { ERR_raise(ERR_LIB_CMS, CMS_R_ADD_SIGNER_ERROR); @@ -526,8 +538,10 @@ CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey, 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 (!CMS_add1_cert(cms, x)) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } } if (!(flags & CMS_DETACHED)) @@ -539,9 +553,6 @@ CMS_ContentInfo *CMS_sign_ex(X509 *signcert, EVP_PKEY *pkey, else goto err; - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); - err: CMS_ContentInfo_free(cms); return NULL; @@ -638,8 +649,10 @@ CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data, 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; + if (cms == NULL) { + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); + goto err; + } for (i = 0; i < sk_X509_num(certs); i++) { recip = sk_X509_value(certs, i); if (!CMS_add1_recipient_cert(cms, recip, flags)) { @@ -655,10 +668,8 @@ CMS_ContentInfo *CMS_encrypt_ex(STACK_OF(X509) *certs, BIO *data, || CMS_final(cms, data, NULL, flags)) return cms; else - goto err; + ERR_raise(ERR_LIB_CMS, ERR_R_CMS_LIB); - merr: - ERR_raise(ERR_LIB_CMS, ERR_R_MALLOC_FAILURE); err: CMS_ContentInfo_free(cms); return NULL; @@ -742,7 +753,8 @@ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, } /* 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); + if (!EVP_PKEY_up_ref(pk)) + return 0; CMS_RecipientInfo_set0_pkey(ri, pk); r = CMS_RecipientInfo_decrypt(cms, ri); CMS_RecipientInfo_set0_pkey(ri, NULL); @@ -916,7 +928,32 @@ err: } -#ifdef ZLIB +int CMS_final_digest(CMS_ContentInfo *cms, + const unsigned char *md, unsigned int mdlen, + 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; + } + + (void)BIO_flush(cmsbio); + + if (!ossl_cms_DataFinal(cms, cmsbio, md, mdlen)) { + ERR_raise(ERR_LIB_CMS, CMS_R_CMS_DATAFINAL_ERROR); + goto err; + } + ret = 1; + +err: + do_free_upto(cmsbio, dcont); + return ret; +} + +#ifndef OPENSSL_NO_ZLIB int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags) diff --git a/crypto/comp/build.info b/crypto/comp/build.info index 65df46a175cd..7892c96ff2c0 100644 --- a/crypto/comp/build.info +++ b/crypto/comp/build.info @@ -1,4 +1,6 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]= \ comp_lib.c comp_err.c \ + c_brotli.c \ + c_zstd.c \ c_zlib.c diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 9a7087e44404..0fbab8f014fe 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -1,5 +1,5 @@ /* - * 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 @@ -20,16 +20,7 @@ COMP_METHOD *COMP_zlib(void); -static COMP_METHOD zlib_method_nozlib = { - NID_undef, - "(undef)", - NULL, - NULL, - NULL, - NULL, -}; - -#ifndef ZLIB +#ifdef OPENSSL_NO_ZLIB # undef ZLIB_SHARED #else @@ -37,12 +28,12 @@ static COMP_METHOD zlib_method_nozlib = { static int zlib_stateful_init(COMP_CTX *ctx); static void zlib_stateful_finish(COMP_CTX *ctx); -static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen); -static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen); +static ossl_ssize_t zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen); +static ossl_ssize_t zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen); /* memory allocations functions for zlib initialisation */ static void *zlib_zalloc(void *opaque, unsigned int no, unsigned int size) @@ -83,8 +74,10 @@ static COMP_METHOD zlib_stateful_method = { # include "internal/dso.h" /* Function pointers */ -typedef int (*compress_ft) (Bytef *dest, uLongf * destLen, +typedef int (*compress_ft) (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); +typedef int (*uncompress_ft) (Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen); typedef int (*inflateEnd_ft) (z_streamp strm); typedef int (*inflate_ft) (z_streamp strm, int flush); typedef int (*inflateInit__ft) (z_streamp strm, @@ -95,6 +88,7 @@ typedef int (*deflateInit__ft) (z_streamp strm, int level, const char *version, int stream_size); typedef const char *(*zError__ft) (int err); static compress_ft p_compress = NULL; +static uncompress_ft p_uncompress = NULL; static inflateEnd_ft p_inflateEnd = NULL; static inflate_ft p_inflate = NULL; static inflateInit__ft p_inflateInit_ = NULL; @@ -106,6 +100,7 @@ static zError__ft p_zError = NULL; static DSO *zlib_dso = NULL; # define compress p_compress +# define uncompress p_uncompress # define inflateEnd p_inflateEnd # define inflate p_inflate # define inflateInit_ p_inflateInit_ @@ -162,9 +157,9 @@ static void zlib_stateful_finish(COMP_CTX *ctx) OPENSSL_free(state); } -static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen) +static ossl_ssize_t zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen) { int err = Z_OK; struct zlib_state *state = ctx->data; @@ -180,12 +175,14 @@ static int zlib_stateful_compress_block(COMP_CTX *ctx, unsigned char *out, err = deflate(&state->ostream, Z_SYNC_FLUSH); if (err != Z_OK) return -1; - return olen - state->ostream.avail_out; + if (state->ostream.avail_out > olen) + return -1; + return (ossl_ssize_t)(olen - state->ostream.avail_out); } -static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, - unsigned int olen, unsigned char *in, - unsigned int ilen) +static ossl_ssize_t zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen) { int err = Z_OK; struct zlib_state *state = ctx->data; @@ -201,9 +198,75 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, err = inflate(&state->istream, Z_SYNC_FLUSH); if (err != Z_OK) return -1; - return olen - state->istream.avail_out; + if (state->istream.avail_out > olen) + return -1; + return (ossl_ssize_t)(olen - state->istream.avail_out); } +/* ONESHOT COMPRESSION/DECOMPRESSION */ + +static int zlib_oneshot_init(COMP_CTX *ctx) +{ + return 1; +} + +static void zlib_oneshot_finish(COMP_CTX *ctx) +{ +} + +static ossl_ssize_t zlib_oneshot_compress_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen) +{ + uLongf out_size; + + if (ilen == 0) + return 0; + + /* zlib's uLongf defined as unsigned long FAR */ + if (olen > ULONG_MAX) + return -1; + out_size = (uLongf)olen; + + if (compress(out, &out_size, in, ilen) != Z_OK) + return -1; + + if (out_size > OSSL_SSIZE_MAX) + return -1; + return (ossl_ssize_t)out_size; +} + +static ossl_ssize_t zlib_oneshot_expand_block(COMP_CTX *ctx, unsigned char *out, + size_t olen, unsigned char *in, + size_t ilen) +{ + uLongf out_size; + + if (ilen == 0) + return 0; + + /* zlib's uLongf defined as unsigned long FAR */ + if (olen > ULONG_MAX) + return -1; + out_size = (uLongf)olen; + + if (uncompress(out, &out_size, in, ilen) != Z_OK) + return -1; + + if (out_size > OSSL_SSIZE_MAX) + return -1; + return (ossl_ssize_t)out_size; +} + +static COMP_METHOD zlib_oneshot_method = { + NID_zlib_compression, + LN_zlib_compression, + zlib_oneshot_init, + zlib_oneshot_finish, + zlib_oneshot_compress_block, + zlib_oneshot_expand_block +}; + static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init) { @@ -222,6 +285,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init) zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); if (zlib_dso != NULL) { p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); + p_uncompress = (compress_ft) DSO_bind_func(zlib_dso, "uncompress"); p_inflateEnd = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); p_inflateInit_ = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); @@ -230,7 +294,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init) p_deflateInit_ = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); - if (p_compress == NULL || p_inflateEnd == NULL + if (p_compress == NULL || p_uncompress == NULL || p_inflateEnd == NULL || p_inflate == NULL || p_inflateInit_ == NULL || p_deflateEnd == NULL || p_deflate == NULL || p_deflateInit_ == NULL || p_zError == NULL) { @@ -245,9 +309,9 @@ DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init) COMP_METHOD *COMP_zlib(void) { - COMP_METHOD *meth = &zlib_method_nozlib; + COMP_METHOD *meth = NULL; -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) meth = &zlib_stateful_method; #endif @@ -255,6 +319,18 @@ COMP_METHOD *COMP_zlib(void) return meth; } +COMP_METHOD *COMP_zlib_oneshot(void) +{ + COMP_METHOD *meth = NULL; + +#ifndef OPENSSL_NO_ZLIB + if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) + meth = &zlib_oneshot_method; +#endif + + return meth; +} + /* Also called from OPENSSL_cleanup() */ void ossl_comp_zlib_cleanup(void) { @@ -264,7 +340,7 @@ void ossl_comp_zlib_cleanup(void) #endif } -#ifdef ZLIB +#ifndef OPENSSL_NO_ZLIB /* Zlib based compression/decompression filter BIO */ @@ -304,12 +380,18 @@ static const BIO_METHOD bio_meth_zlib = { bio_zlib_free, bio_zlib_callback_ctrl }; +#endif const BIO_METHOD *BIO_f_zlib(void) { - return &bio_meth_zlib; +#ifndef OPENSSL_NO_ZLIB + if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) + return &bio_meth_zlib; +#endif + return NULL; } +#ifndef OPENSSL_NO_ZLIB static int bio_zlib_new(BIO *bi) { BIO_ZLIB_CTX *ctx; @@ -321,10 +403,8 @@ static int bio_zlib_new(BIO *bi) } # endif ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE); + if (ctx == NULL) return 0; - } ctx->ibufsize = ZLIB_DEFAULT_BUFSIZE; ctx->obufsize = ZLIB_DEFAULT_BUFSIZE; ctx->zin.zalloc = Z_NULL; @@ -376,10 +456,8 @@ static int bio_zlib_read(BIO *b, char *out, int outl) BIO_clear_retry_flags(b); if (!ctx->ibuf) { ctx->ibuf = OPENSSL_malloc(ctx->ibufsize); - if (ctx->ibuf == NULL) { - ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE); + if (ctx->ibuf == NULL) return 0; - } if ((ret = inflateInit(zin)) != Z_OK) { ERR_raise_data(ERR_LIB_COMP, COMP_R_ZLIB_INFLATE_ERROR, "zlib error: %s", zError(ret)); @@ -441,10 +519,8 @@ static int bio_zlib_write(BIO *b, const char *in, int inl) if (!ctx->obuf) { ctx->obuf = OPENSSL_malloc(ctx->obufsize); /* Need error here */ - if (ctx->obuf == NULL) { - ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE); + if (ctx->obuf == NULL) return 0; - } ctx->optr = ctx->obuf; ctx->ocount = 0; if ((ret = deflateInit(zout, ctx->comp_level)) != Z_OK) { @@ -564,8 +640,10 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = bio_zlib_flush(b); - if (ret > 0) + if (ret > 0) { ret = BIO_flush(next); + BIO_copy_next_retry(b); + } break; case BIO_C_SET_BUFF_SIZE: diff --git a/crypto/comp/comp_err.c b/crypto/comp/comp_err.c index 70a6eea0f052..2345da693ec6 100644 --- a/crypto/comp/comp_err.c +++ b/crypto/comp/comp_err.c @@ -17,12 +17,25 @@ # ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA COMP_str_reasons[] = { + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_BROTLI_DECODE_ERROR), + "brotli decode error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_BROTLI_ENCODE_ERROR), + "brotli encode error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_BROTLI_NOT_SUPPORTED), + "brotli not supported"}, {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_DEFLATE_ERROR), "zlib deflate error"}, {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_INFLATE_ERROR), "zlib inflate error"}, {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZLIB_NOT_SUPPORTED), "zlib not supported"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZSTD_COMPRESS_ERROR), + "zstd compress error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZSTD_DECODE_ERROR), "zstd decode error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZSTD_DECOMPRESS_ERROR), + "zstd decompress error"}, + {ERR_PACK(ERR_LIB_COMP, 0, COMP_R_ZSTD_NOT_SUPPORTED), + "zstd not supported"}, {0, NULL} }; diff --git a/crypto/comp/comp_lib.c b/crypto/comp/comp_lib.c index bf9069d871a4..56ca17a7a54a 100644 --- a/crypto/comp/comp_lib.c +++ b/crypto/comp/comp_lib.c @@ -19,10 +19,11 @@ COMP_CTX *COMP_CTX_new(COMP_METHOD *meth) { COMP_CTX *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - ERR_raise(ERR_LIB_COMP, ERR_R_MALLOC_FAILURE); + if (meth == NULL) + return NULL; + + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } ret->meth = meth; if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { OPENSSL_free(ret); @@ -38,11 +39,15 @@ const COMP_METHOD *COMP_CTX_get_method(const COMP_CTX *ctx) int COMP_get_type(const COMP_METHOD *meth) { + if (meth == NULL) + return NID_undef; return meth->type; } const char *COMP_get_name(const COMP_METHOD *meth) { + if (meth == NULL) + return NULL; return meth->name; } diff --git a/crypto/comp/comp_local.h b/crypto/comp/comp_local.h index acf113e31cd0..d8be9271a0cb 100644 --- a/crypto/comp/comp_local.h +++ b/crypto/comp/comp_local.h @@ -12,12 +12,12 @@ struct comp_method_st { const char *name; /* A text string to identify the library */ int (*init) (COMP_CTX *ctx); void (*finish) (COMP_CTX *ctx); - int (*compress) (COMP_CTX *ctx, - unsigned char *out, unsigned int olen, - unsigned char *in, unsigned int ilen); - int (*expand) (COMP_CTX *ctx, - unsigned char *out, unsigned int olen, - unsigned char *in, unsigned int ilen); + ossl_ssize_t (*compress) (COMP_CTX *ctx, + unsigned char *out, size_t olen, + unsigned char *in, size_t ilen); + ossl_ssize_t (*expand) (COMP_CTX *ctx, + unsigned char *out, size_t olen, + unsigned char *in, size_t ilen); }; struct comp_ctx_st { diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c index 7a4efe6dbb2b..5b1bf0e78f39 100644 --- a/crypto/conf/conf_api.c +++ b/crypto/conf/conf_api.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,7 +9,7 @@ /* Part of the code in here was originally in conf.c, which is now removed */ -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include #include diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index cda2f3e26792..399aefb19963 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -11,7 +11,7 @@ #include #include -#include "e_os.h" /* struct stat */ +#include "internal/e_os.h" /* struct stat */ #ifdef __TANDEM # include /* needed for stat.h */ # include /* struct stat */ @@ -193,10 +193,10 @@ static int def_load(CONF *conf, const char *name, long *line) static int parsebool(const char *pval, int *flag) { if (OPENSSL_strcasecmp(pval, "on") == 0 - || OPENSSL_strcasecmp(pval, "true") == 0) { + || OPENSSL_strcasecmp(pval, "true") == 0) { *flag = 1; } else if (OPENSSL_strcasecmp(pval, "off") == 0 - || OPENSSL_strcasecmp(pval, "false") == 0) { + || OPENSSL_strcasecmp(pval, "false") == 0) { *flag = 0; } else { ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA); @@ -236,13 +236,11 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) } section = OPENSSL_strdup("default"); - if (section == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + if (section == NULL) goto err; - } if (_CONF_new_data(conf) == 0) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_CONF_LIB); goto err; } @@ -392,8 +390,8 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) psection = section; } p = eat_ws(conf, end); - if (strncmp(pname, ".pragma", 7) == 0 - && (p != pname + 7 || *p == '=')) { + if (CHECK_AND_SKIP_PREFIX(pname, ".pragma") + && (p != pname || *p == '=')) { char *pval; if (*p == '=') { @@ -428,18 +426,16 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) 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); + if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) goto err; - } } /* * We *ignore* any unknown pragma. */ continue; - } else if (strncmp(pname, ".include", 8) == 0 - && (p != pname + 8 || *p == '=')) { + } else if (CHECK_AND_SKIP_PREFIX(pname, ".include") + && (p != pname || *p == '=')) { char *include = NULL; BIO *next; const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE"); @@ -475,7 +471,6 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) include_path = OPENSSL_malloc(newlen); if (include_path == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); OPENSSL_free(include); goto err; } @@ -512,13 +507,13 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) /* 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); + ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB); BIO_free(next); goto err; } } if (!sk_BIO_push(biosk, in)) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB); BIO_free(next); goto err; } @@ -536,16 +531,12 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) 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); + if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) goto err; - } v->name = OPENSSL_strdup(pname); v->value = NULL; - if (v->name == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + if (v->name == NULL) goto err; - } if (!str_copy(conf, psection, &(v->value), start)) goto err; @@ -561,7 +552,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) } else tv = sv; if (_CONF_add_string(conf, tv, v) == 0) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_CONF_LIB); goto err; } v = NULL; @@ -774,7 +765,7 @@ static int str_copy(CONF *conf, char *section, char **pto, char *from) goto err; } if (!BUF_MEM_grow_clean(buf, newsize)) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB); goto err; } while (*p) @@ -858,18 +849,16 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx) if ((namelen > 5 && OPENSSL_strcasecmp(filename + namelen - 5, ".conf") == 0) - || (namelen > 4 - && OPENSSL_strcasecmp(filename + namelen - 4, ".cnf") == 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); + if (newpath == NULL) break; - } #ifdef OPENSSL_SYS_VMS /* * If the given path isn't clear VMS syntax, @@ -903,7 +892,7 @@ static BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx) static int is_keytype(const CONF *conf, char c, unsigned short type) { - const unsigned short * keytypes = (const unsigned short *) conf->meth_data; + const unsigned short *keytypes = (const unsigned short *) conf->meth_data; unsigned char key = (unsigned char)c; #ifdef CHARSET_EBCDIC diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index fc0eee7d2f85..9f1309c507c5 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -1,6 +1,6 @@ /* * 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 diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c index 719af7cb75c6..a8b41b66a2e2 100644 --- a/crypto/conf/conf_lib.c +++ b/crypto/conf/conf_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include "internal/conf.h" @@ -188,7 +188,7 @@ CONF *NCONF_new_ex(OSSL_LIB_CTX *libctx, CONF_METHOD *meth) ret = meth->create(meth); if (ret == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_CONF_LIB); return NULL; } ret->libctx = libctx; @@ -228,7 +228,8 @@ static void collect_section_name(const CONF_VALUE *v, SECTION_NAMES *names) { /* A section is a CONF_VALUE with name == NULL */ if (v->name == NULL) - sk_OPENSSL_CSTRING_push(names, v->section); + /* A failure to push cannot be handled so we ignore the result. */ + (void)sk_OPENSSL_CSTRING_push(names, v->section); } static int section_name_cmp(OPENSSL_CSTRING const *a, OPENSSL_CSTRING const *b) @@ -421,6 +422,12 @@ OPENSSL_INIT_SETTINGS *OPENSSL_INIT_new(void) #ifndef OPENSSL_NO_STDIO +/* + * If CRYPTO_set_mem_functions is called after this, then + * memory allocation and deallocation in this function can + * become disjointed. Avoid this by always using standard + * strdup & free instead of OPENSSL_strdup & OPENSSL_free. + */ int OPENSSL_INIT_set_config_filename(OPENSSL_INIT_SETTINGS *settings, const char *filename) { @@ -444,6 +451,12 @@ void OPENSSL_INIT_set_config_file_flags(OPENSSL_INIT_SETTINGS *settings, settings->flags = flags; } +/* + * If CRYPTO_set_mem_functions is called after this, then + * memory allocation and deallocation in this function can + * become disjointed. Avoid this by always using standard + * strdup & free instead of OPENSSL_strdup & OPENSSL_free. + */ int OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS *settings, const char *appname) { diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c index 1ea32648e9f9..9d49a5f69d10 100644 --- a/crypto/conf/conf_mod.c +++ b/crypto/conf/conf_mod.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,6 +11,7 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include "internal/cryptlib.h" +#include "internal/rcu.h" #include #include #include @@ -63,7 +64,7 @@ struct conf_imodule_st { }; static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT; -static CRYPTO_RWLOCK *module_list_lock = NULL; +static CRYPTO_RCU_LOCK *module_list_lock = NULL; static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */ static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */ @@ -86,7 +87,7 @@ static int conf_modules_finish_int(void); static void module_lists_free(void) { - CRYPTO_THREAD_lock_free(module_list_lock); + ossl_rcu_lock_free(module_list_lock); module_list_lock = NULL; sk_CONF_MODULE_free(supported_modules); @@ -98,9 +99,9 @@ static void module_lists_free(void) DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock) { - module_list_lock = CRYPTO_THREAD_lock_new(); + module_list_lock = ossl_rcu_lock_new(1, NULL); if (module_list_lock == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB); return 0; } @@ -109,7 +110,17 @@ DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock) static int conf_diagnostics(const CONF *cnf) { - return _CONF_get_number(cnf, NULL, "config_diagnostics") != 0; + int status; + long result = 0; + + ERR_set_mark(); + status = NCONF_get_number_e(cnf, NULL, "config_diagnostics", &result); + ERR_pop_to_mark(); + if (status > 0) { + OSSL_LIB_CTX_set_conf_diagnostics(cnf->libctx, result > 0); + return result > 0; + } + return OSSL_LIB_CTX_get_conf_diagnostics(cnf->libctx); } /* Main function: load modules from a CONF structure */ @@ -182,7 +193,7 @@ int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename, { char *file = NULL; CONF *conf = NULL; - int ret = 0, diagnostics = 0; + int ret = 0, diagnostics = OSSL_LIB_CTX_get_conf_diagnostics(libctx); ERR_set_mark(); @@ -212,7 +223,8 @@ int CONF_modules_load_file_ex(OSSL_LIB_CTX *libctx, const char *filename, } ret = CONF_modules_load(conf, appname, flags); - diagnostics = conf_diagnostics(conf); + /* CONF_modules_load() might change the diagnostics setting, reread it. */ + diagnostics = OSSL_LIB_CTX_get_conf_diagnostics(libctx); err: if (filename == NULL) @@ -327,21 +339,26 @@ static CONF_MODULE *module_add(DSO *dso, const char *name, conf_init_func *ifunc, conf_finish_func *ffunc) { CONF_MODULE *tmod = NULL; + STACK_OF(CONF_MODULE) *old_modules; + STACK_OF(CONF_MODULE) *new_modules; if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) return NULL; - if (!CRYPTO_THREAD_write_lock(module_list_lock)) - return NULL; + ossl_rcu_write_lock(module_list_lock); - if (supported_modules == NULL) - supported_modules = sk_CONF_MODULE_new_null(); - if (supported_modules == NULL) + old_modules = ossl_rcu_deref(&supported_modules); + + if (old_modules == NULL) + new_modules = sk_CONF_MODULE_new_null(); + else + new_modules = sk_CONF_MODULE_dup(old_modules); + + if (new_modules == NULL) goto err; - if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) { - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + + if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) goto err; - } tmod->dso = dso; tmod->name = OPENSSL_strdup(name); @@ -350,18 +367,23 @@ static CONF_MODULE *module_add(DSO *dso, const char *name, if (tmod->name == NULL) goto err; - if (!sk_CONF_MODULE_push(supported_modules, tmod)) + if (!sk_CONF_MODULE_push(new_modules, tmod)) goto err; - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_assign_ptr(&supported_modules, &new_modules); + ossl_rcu_write_unlock(module_list_lock); + ossl_synchronize_rcu(module_list_lock); + + sk_CONF_MODULE_free(old_modules); return tmod; err: - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_write_unlock(module_list_lock); if (tmod != NULL) { OPENSSL_free(tmod->name); OPENSSL_free(tmod); } + sk_CONF_MODULE_free(new_modules); return NULL; } @@ -376,6 +398,8 @@ static CONF_MODULE *module_find(const char *name) CONF_MODULE *tmod; int i, nchar; char *p; + STACK_OF(CONF_MODULE) *mods; + p = strrchr(name, '.'); if (p) @@ -386,18 +410,18 @@ static CONF_MODULE *module_find(const char *name) if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) return NULL; - if (!CRYPTO_THREAD_read_lock(module_list_lock)) - return NULL; + ossl_rcu_read_lock(module_list_lock); + mods = ossl_rcu_deref(&supported_modules); - for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) { - tmod = sk_CONF_MODULE_value(supported_modules, i); + for (i = 0; i < sk_CONF_MODULE_num(mods); i++) { + tmod = sk_CONF_MODULE_value(mods, i); if (strncmp(tmod->name, name, nchar) == 0) { - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_read_unlock(module_list_lock); return tmod; } } - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_read_unlock(module_list_lock); return NULL; } @@ -408,6 +432,8 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value, int ret = 1; int init_called = 0; CONF_IMODULE *imod = NULL; + STACK_OF(CONF_IMODULE) *old_modules; + STACK_OF(CONF_IMODULE) *new_modules; /* Otherwise add initialized module to list */ imod = OPENSSL_malloc(sizeof(*imod)); @@ -434,27 +460,34 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value, if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) goto err; - if (!CRYPTO_THREAD_write_lock(module_list_lock)) - goto err; + ossl_rcu_write_lock(module_list_lock); - if (initialized_modules == NULL) { - initialized_modules = sk_CONF_IMODULE_new_null(); - if (initialized_modules == NULL) { - CRYPTO_THREAD_unlock(module_list_lock); - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); - goto err; - } + old_modules = ossl_rcu_deref(&initialized_modules); + + if (old_modules == NULL) + new_modules = sk_CONF_IMODULE_new_null(); + else + new_modules = sk_CONF_IMODULE_dup(old_modules); + + if (new_modules == NULL) { + ossl_rcu_write_unlock(module_list_lock); + ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB); + goto err; } - if (!sk_CONF_IMODULE_push(initialized_modules, imod)) { - CRYPTO_THREAD_unlock(module_list_lock); - ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); + if (!sk_CONF_IMODULE_push(new_modules, imod)) { + ossl_rcu_write_unlock(module_list_lock); + sk_CONF_IMODULE_free(new_modules); + ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB); goto err; } pmod->links++; - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_assign_ptr(&initialized_modules, &new_modules); + ossl_rcu_write_unlock(module_list_lock); + ossl_synchronize_rcu(module_list_lock); + sk_CONF_IMODULE_free(old_modules); return ret; err: @@ -484,30 +517,47 @@ void CONF_modules_unload(int all) { int i; CONF_MODULE *md; + STACK_OF(CONF_MODULE) *old_modules; + STACK_OF(CONF_MODULE) *new_modules; + STACK_OF(CONF_MODULE) *to_delete; if (!conf_modules_finish_int()) /* also inits module list lock */ return; - if (!CRYPTO_THREAD_write_lock(module_list_lock)) + ossl_rcu_write_lock(module_list_lock); + + old_modules = ossl_rcu_deref(&supported_modules); + new_modules = sk_CONF_MODULE_dup(old_modules); + + if (new_modules == NULL) { + ossl_rcu_write_unlock(module_list_lock); return; + } + + to_delete = sk_CONF_MODULE_new_null(); /* unload modules in reverse order */ - for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) { - md = sk_CONF_MODULE_value(supported_modules, i); + for (i = sk_CONF_MODULE_num(new_modules) - 1; i >= 0; i--) { + md = sk_CONF_MODULE_value(new_modules, i); /* If static or in use and 'all' not set ignore it */ if (((md->links > 0) || !md->dso) && !all) continue; /* Since we're working in reverse this is OK */ - (void)sk_CONF_MODULE_delete(supported_modules, i); - module_free(md); + (void)sk_CONF_MODULE_delete(new_modules, i); + sk_CONF_MODULE_push(to_delete, md); } - if (sk_CONF_MODULE_num(supported_modules) == 0) { - sk_CONF_MODULE_free(supported_modules); - supported_modules = NULL; + if (sk_CONF_MODULE_num(new_modules) == 0) { + sk_CONF_MODULE_free(new_modules); + new_modules = NULL; } - CRYPTO_THREAD_unlock(module_list_lock); + ossl_rcu_assign_ptr(&supported_modules, &new_modules); + ossl_rcu_write_unlock(module_list_lock); + ossl_synchronize_rcu(module_list_lock); + sk_CONF_MODULE_free(old_modules); + sk_CONF_MODULE_pop_free(to_delete, module_free); + } /* unload a single module */ @@ -523,23 +573,27 @@ static void module_free(CONF_MODULE *md) static int conf_modules_finish_int(void) { CONF_IMODULE *imod; + STACK_OF(CONF_IMODULE) *old_modules; + STACK_OF(CONF_IMODULE) *new_modules = NULL; if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock)) return 0; /* If module_list_lock is NULL here it means we were already unloaded */ - if (module_list_lock == NULL - || !CRYPTO_THREAD_write_lock(module_list_lock)) + if (module_list_lock == NULL) return 0; - while (sk_CONF_IMODULE_num(initialized_modules) > 0) { - imod = sk_CONF_IMODULE_pop(initialized_modules); + ossl_rcu_write_lock(module_list_lock); + old_modules = ossl_rcu_deref(&initialized_modules); + ossl_rcu_assign_ptr(&initialized_modules, &new_modules); + ossl_rcu_write_unlock(module_list_lock); + ossl_synchronize_rcu(module_list_lock); + + while (sk_CONF_IMODULE_num(old_modules) > 0) { + imod = sk_CONF_IMODULE_pop(old_modules); module_finish(imod); } - sk_CONF_IMODULE_free(initialized_modules); - initialized_modules = NULL; - - CRYPTO_THREAD_unlock(module_list_lock); + sk_CONF_IMODULE_free(old_modules); return 1; } @@ -638,6 +692,18 @@ char *CONF_get1_default_config_file(void) return OPENSSL_strdup(file); t = X509_get_default_cert_area(); + /* + * On windows systems with -DOSSL_WINCTX set, if the needed registry + * keys are not yet set, openssl applets will return, due to an inability + * to locate various directories, like the default cert area. In that + * event, clone an empty string here, so that commands like openssl version + * continue to operate properly without needing to set OPENSSL_CONF. + * Applets like cms will fail gracefully later when they try to parse an + * empty config file + */ + if (t == NULL) + return OPENSSL_strdup(""); + #ifndef OPENSSL_SYS_VMS sep = "/"; #endif diff --git a/crypto/context.c b/crypto/context.c index ac6938e619eb..f15bc3d755e5 100644 --- a/crypto/context.c +++ b/crypto/context.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,55 +9,72 @@ #include "crypto/cryptlib.h" #include +#include #include "internal/thread_once.h" #include "internal/property.h" +#include "internal/cryptlib.h" #include "internal/core.h" #include "internal/bio.h" #include "internal/provider.h" -#include "crypto/ctype.h" -#include "crypto/rand.h" - -struct ossl_lib_ctx_onfree_list_st { - ossl_lib_ctx_onfree_fn *fn; - struct ossl_lib_ctx_onfree_list_st *next; -}; +#include "crypto/decoder.h" +#include "crypto/context.h" struct ossl_lib_ctx_st { CRYPTO_RWLOCK *lock; - CRYPTO_EX_DATA data; - - /* - * For most data in the OSSL_LIB_CTX we just use ex_data to store it. But - * that doesn't work for ex_data itself - so we store that directly. - */ OSSL_EX_DATA_GLOBAL global; - /* Map internal static indexes to dynamically created indexes */ - int dyn_indexes[OSSL_LIB_CTX_MAX_INDEXES]; + void *property_string_data; + void *evp_method_store; + void *provider_store; + void *namemap; + void *property_defns; + void *global_properties; + void *drbg; + void *drbg_nonce; + CRYPTO_THREAD_LOCAL rcu_local_key; +#ifndef FIPS_MODULE + void *provider_conf; + void *bio_core; + void *child_provider; + OSSL_METHOD_STORE *decoder_store; + void *decoder_cache; + OSSL_METHOD_STORE *encoder_store; + OSSL_METHOD_STORE *store_loader_store; + void *self_test_cb; + void *indicator_cb; +#endif +#if defined(OPENSSL_THREADS) + void *threads; +#endif +#ifdef FIPS_MODULE + void *thread_event_handler; + void *fips_prov; +#endif + STACK_OF(SSL_COMP) *comp_methods; - /* Keep a separate lock for each index */ - CRYPTO_RWLOCK *index_locks[OSSL_LIB_CTX_MAX_INDEXES]; - - CRYPTO_RWLOCK *oncelock; - int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE]; - int run_once_ret[OSSL_LIB_CTX_MAX_RUN_ONCE]; - struct ossl_lib_ctx_onfree_list_st *onfreelist; - unsigned int ischild:1; + int ischild; + int conf_diagnostics; }; int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx) { - return CRYPTO_THREAD_write_lock(ossl_lib_ctx_get_concrete(ctx)->lock); + if ((ctx = ossl_lib_ctx_get_concrete(ctx)) == NULL) + return 0; + return CRYPTO_THREAD_write_lock(ctx->lock); } int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx) { - return CRYPTO_THREAD_read_lock(ossl_lib_ctx_get_concrete(ctx)->lock); + if ((ctx = ossl_lib_ctx_get_concrete(ctx)) == NULL) + return 0; + return CRYPTO_THREAD_read_lock(ctx->lock); } int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx) { - return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx)->lock); + if ((ctx = ossl_lib_ctx_get_concrete(ctx)) == NULL) + return 0; + return CRYPTO_THREAD_unlock(ctx->lock); } int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx) @@ -69,76 +86,300 @@ int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx) return ctx->ischild; } +static void context_deinit_objs(OSSL_LIB_CTX *ctx); + static int context_init(OSSL_LIB_CTX *ctx) { - size_t i; int exdata_done = 0; + if (!CRYPTO_THREAD_init_local(&ctx->rcu_local_key, NULL)) + return 0; + ctx->lock = CRYPTO_THREAD_lock_new(); if (ctx->lock == NULL) - return 0; - - ctx->oncelock = CRYPTO_THREAD_lock_new(); - if (ctx->oncelock == NULL) goto err; - for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) { - ctx->index_locks[i] = CRYPTO_THREAD_lock_new(); - ctx->dyn_indexes[i] = -1; - if (ctx->index_locks[i] == NULL) - goto err; - } - - /* OSSL_LIB_CTX is built on top of ex_data so we initialise that directly */ + /* Initialize ex_data. */ if (!ossl_do_ex_data_init(ctx)) goto err; exdata_done = 1; - if (!ossl_crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, - &ctx->data)) + /* P2. We want evp_method_store to be cleaned up before the provider store */ + ctx->evp_method_store = ossl_method_store_new(ctx); + if (ctx->evp_method_store == NULL) goto err; + OSSL_TRACE1(QUERY, "context_init: allocating store %p\n", ctx->evp_method_store); + +#ifndef FIPS_MODULE + /* P2. Must be freed before the provider store is freed */ + ctx->provider_conf = ossl_prov_conf_ctx_new(ctx); + if (ctx->provider_conf == NULL) + goto err; +#endif + + /* P2. */ + ctx->drbg = ossl_rand_ctx_new(ctx); + if (ctx->drbg == NULL) + goto err; + +#ifndef FIPS_MODULE + /* + * P2. We want decoder_store/decoder_cache to be cleaned up before the + * provider store + */ + ctx->decoder_store = ossl_method_store_new(ctx); + if (ctx->decoder_store == NULL) + goto err; + ctx->decoder_cache = ossl_decoder_cache_new(ctx); + if (ctx->decoder_cache == NULL) + goto err; + + /* P2. We want encoder_store to be cleaned up before the provider store */ + ctx->encoder_store = ossl_method_store_new(ctx); + if (ctx->encoder_store == NULL) + goto err; + + /* P2. We want loader_store to be cleaned up before the provider store */ + ctx->store_loader_store = ossl_method_store_new(ctx); + if (ctx->store_loader_store == NULL) + goto err; +#endif + + /* P1. Needs to be freed before the child provider data is freed */ + ctx->provider_store = ossl_provider_store_new(ctx); + if (ctx->provider_store == NULL) + goto err; + + /* Default priority. */ + ctx->property_string_data = ossl_property_string_data_new(ctx); + if (ctx->property_string_data == NULL) + goto err; + + ctx->namemap = ossl_stored_namemap_new(ctx); + if (ctx->namemap == NULL) + goto err; + + ctx->property_defns = ossl_property_defns_new(ctx); + if (ctx->property_defns == NULL) + goto err; + + ctx->global_properties = ossl_ctx_global_properties_new(ctx); + if (ctx->global_properties == NULL) + goto err; + +#ifndef FIPS_MODULE + ctx->bio_core = ossl_bio_core_globals_new(ctx); + if (ctx->bio_core == NULL) + goto err; +#endif + + ctx->drbg_nonce = ossl_prov_drbg_nonce_ctx_new(ctx); + if (ctx->drbg_nonce == NULL) + goto err; + +#ifndef FIPS_MODULE + ctx->self_test_cb = ossl_self_test_set_callback_new(ctx); + if (ctx->self_test_cb == NULL) + goto err; + ctx->indicator_cb = ossl_indicator_set_callback_new(ctx); + if (ctx->indicator_cb == NULL) + goto err; +#endif + +#ifdef FIPS_MODULE + ctx->thread_event_handler = ossl_thread_event_ctx_new(ctx); + if (ctx->thread_event_handler == NULL) + goto err; + + ctx->fips_prov = ossl_fips_prov_ossl_ctx_new(ctx); + if (ctx->fips_prov == NULL) + goto err; +#endif + +#ifndef OPENSSL_NO_THREAD_POOL + ctx->threads = ossl_threads_ctx_new(ctx); + if (ctx->threads == NULL) + goto err; +#endif + + /* Low priority. */ +#ifndef FIPS_MODULE + ctx->child_provider = ossl_child_prov_ctx_new(ctx); + if (ctx->child_provider == NULL) + goto err; +#endif /* Everything depends on properties, so we also pre-initialise that */ if (!ossl_property_parse_init(ctx)) goto err; +#ifndef FIPS_MODULE + ctx->comp_methods = ossl_load_builtin_compressions(); +#endif + return 1; + err: + context_deinit_objs(ctx); + if (exdata_done) ossl_crypto_cleanup_all_ex_data_int(ctx); - for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) - CRYPTO_THREAD_lock_free(ctx->index_locks[i]); - CRYPTO_THREAD_lock_free(ctx->oncelock); + CRYPTO_THREAD_lock_free(ctx->lock); + CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key); memset(ctx, '\0', sizeof(*ctx)); return 0; } +static void context_deinit_objs(OSSL_LIB_CTX *ctx) +{ + /* P2. We want evp_method_store to be cleaned up before the provider store */ + if (ctx->evp_method_store != NULL) { + ossl_method_store_free(ctx->evp_method_store); + ctx->evp_method_store = NULL; + } + + /* P2. */ + if (ctx->drbg != NULL) { + ossl_rand_ctx_free(ctx->drbg); + ctx->drbg = NULL; + } + +#ifndef FIPS_MODULE + /* P2. */ + if (ctx->provider_conf != NULL) { + ossl_prov_conf_ctx_free(ctx->provider_conf); + ctx->provider_conf = NULL; + } + + /* + * P2. We want decoder_store/decoder_cache to be cleaned up before the + * provider store + */ + if (ctx->decoder_store != NULL) { + ossl_method_store_free(ctx->decoder_store); + ctx->decoder_store = NULL; + } + if (ctx->decoder_cache != NULL) { + ossl_decoder_cache_free(ctx->decoder_cache); + ctx->decoder_cache = NULL; + } + + + /* P2. We want encoder_store to be cleaned up before the provider store */ + if (ctx->encoder_store != NULL) { + ossl_method_store_free(ctx->encoder_store); + ctx->encoder_store = NULL; + } + + /* P2. We want loader_store to be cleaned up before the provider store */ + if (ctx->store_loader_store != NULL) { + ossl_method_store_free(ctx->store_loader_store); + ctx->store_loader_store = NULL; + } +#endif + + /* P1. Needs to be freed before the child provider data is freed */ + if (ctx->provider_store != NULL) { + ossl_provider_store_free(ctx->provider_store); + ctx->provider_store = NULL; + } + + /* Default priority. */ + if (ctx->property_string_data != NULL) { + ossl_property_string_data_free(ctx->property_string_data); + ctx->property_string_data = NULL; + } + + if (ctx->namemap != NULL) { + ossl_stored_namemap_free(ctx->namemap); + ctx->namemap = NULL; + } + + if (ctx->property_defns != NULL) { + ossl_property_defns_free(ctx->property_defns); + ctx->property_defns = NULL; + } + + if (ctx->global_properties != NULL) { + ossl_ctx_global_properties_free(ctx->global_properties); + ctx->global_properties = NULL; + } + +#ifndef FIPS_MODULE + if (ctx->bio_core != NULL) { + ossl_bio_core_globals_free(ctx->bio_core); + ctx->bio_core = NULL; + } +#endif + + if (ctx->drbg_nonce != NULL) { + ossl_prov_drbg_nonce_ctx_free(ctx->drbg_nonce); + ctx->drbg_nonce = NULL; + } + +#ifndef FIPS_MODULE + if (ctx->indicator_cb != NULL) { + ossl_indicator_set_callback_free(ctx->indicator_cb); + ctx->indicator_cb = NULL; + } + + if (ctx->self_test_cb != NULL) { + ossl_self_test_set_callback_free(ctx->self_test_cb); + ctx->self_test_cb = NULL; + } +#endif + +#ifdef FIPS_MODULE + if (ctx->thread_event_handler != NULL) { + ossl_thread_event_ctx_free(ctx->thread_event_handler); + ctx->thread_event_handler = NULL; + } + + if (ctx->fips_prov != NULL) { + ossl_fips_prov_ossl_ctx_free(ctx->fips_prov); + ctx->fips_prov = NULL; + } +#endif + +#ifndef OPENSSL_NO_THREAD_POOL + if (ctx->threads != NULL) { + ossl_threads_ctx_free(ctx->threads); + ctx->threads = NULL; + } +#endif + + /* Low priority. */ +#ifndef FIPS_MODULE + if (ctx->child_provider != NULL) { + ossl_child_prov_ctx_free(ctx->child_provider); + ctx->child_provider = NULL; + } +#endif + +#ifndef FIPS_MODULE + if (ctx->comp_methods != NULL) { + ossl_free_compression_methods_int(ctx->comp_methods); + ctx->comp_methods = NULL; + } +#endif + +} + static int context_deinit(OSSL_LIB_CTX *ctx) { - struct ossl_lib_ctx_onfree_list_st *tmp, *onfree; - int i; - if (ctx == NULL) return 1; ossl_ctx_thread_stop(ctx); - onfree = ctx->onfreelist; - while (onfree != NULL) { - onfree->fn(ctx); - tmp = onfree; - onfree = onfree->next; - OPENSSL_free(tmp); - } - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, &ctx->data); - ossl_crypto_cleanup_all_ex_data_int(ctx); - for (i = 0; i < OSSL_LIB_CTX_MAX_INDEXES; i++) - CRYPTO_THREAD_lock_free(ctx->index_locks[i]); + context_deinit_objs(ctx); + + ossl_crypto_cleanup_all_ex_data_int(ctx); - CRYPTO_THREAD_lock_free(ctx->oncelock); CRYPTO_THREAD_lock_free(ctx->lock); ctx->lock = NULL; + CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key); return 1; } @@ -148,17 +389,32 @@ static OSSL_LIB_CTX default_context_int; static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT; static CRYPTO_THREAD_LOCAL default_context_thread_local; +static int default_context_inited = 0; DEFINE_RUN_ONCE_STATIC(default_context_do_init) { - return CRYPTO_THREAD_init_local(&default_context_thread_local, NULL) - && context_init(&default_context_int); + if (!CRYPTO_THREAD_init_local(&default_context_thread_local, NULL)) + goto err; + + if (!context_init(&default_context_int)) + goto deinit_thread; + + default_context_inited = 1; + return 1; + +deinit_thread: + CRYPTO_THREAD_cleanup_local(&default_context_thread_local); +err: + return 0; } void ossl_lib_ctx_default_deinit(void) { + if (!default_context_inited) + return; context_deinit(&default_context_int); CRYPTO_THREAD_cleanup_local(&default_context_thread_local); + default_context_inited = 0; } static OSSL_LIB_CTX *get_thread_default_context(void) @@ -173,7 +429,7 @@ static OSSL_LIB_CTX *get_default_context(void) { OSSL_LIB_CTX *current_defctx = get_thread_default_context(); - if (current_defctx == NULL) + if (current_defctx == NULL && default_context_inited) current_defctx = &default_context_int; return current_defctx; } @@ -275,15 +531,10 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *libctx) void ossl_release_default_drbg_ctx(void) { - int dynidx = default_context_int.dyn_indexes[OSSL_LIB_CTX_DRBG_INDEX]; - - /* early release of the DRBG in global default libctx, no locking */ - if (dynidx != -1) { - void *data; - - data = CRYPTO_get_ex_data(&default_context_int.data, dynidx); - ossl_rand_ctx_free(data); - CRYPTO_set_ex_data(&default_context_int.data, dynidx, NULL); + /* early release of the DRBG in global default libctx */ + if (default_context_int.drbg != NULL) { + ossl_rand_ctx_free(default_context_int.drbg); + default_context_int.drbg = NULL; } } #endif @@ -315,127 +566,73 @@ int ossl_lib_ctx_is_global_default(OSSL_LIB_CTX *ctx) return 0; } -static void ossl_lib_ctx_generic_new(void *parent_ign, void *ptr_ign, - CRYPTO_EX_DATA *ad, int index, - long argl_ign, void *argp) +void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index) { - const OSSL_LIB_CTX_METHOD *meth = argp; - OSSL_LIB_CTX *ctx = ossl_crypto_ex_data_get_ossl_lib_ctx(ad); - void *ptr = meth->new_func(ctx); - - if (ptr != NULL) { - if (!CRYPTO_THREAD_write_lock(ctx->lock)) - /* - * Can't return something, so best to hope that something will - * fail later. :( - */ - return; - CRYPTO_set_ex_data(ad, index, ptr); - CRYPTO_THREAD_unlock(ctx->lock); - } -} -static void ossl_lib_ctx_generic_free(void *parent_ign, void *ptr, - CRYPTO_EX_DATA *ad, int index, - long argl_ign, void *argp) -{ - const OSSL_LIB_CTX_METHOD *meth = argp; - - meth->free_func(ptr); -} - -static int ossl_lib_ctx_init_index(OSSL_LIB_CTX *ctx, int static_index, - const OSSL_LIB_CTX_METHOD *meth) -{ - int idx; - - ctx = ossl_lib_ctx_get_concrete(ctx); - if (ctx == NULL) - return 0; - - idx = ossl_crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OSSL_LIB_CTX, 0, - (void *)meth, - ossl_lib_ctx_generic_new, - NULL, ossl_lib_ctx_generic_free, - meth->priority); - if (idx < 0) - return 0; - - ctx->dyn_indexes[static_index] = idx; - return 1; -} - -void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index, - const OSSL_LIB_CTX_METHOD *meth) -{ - void *data = NULL; - int dynidx; - ctx = ossl_lib_ctx_get_concrete(ctx); if (ctx == NULL) return NULL; - if (!CRYPTO_THREAD_read_lock(ctx->lock)) - return NULL; - dynidx = ctx->dyn_indexes[index]; - CRYPTO_THREAD_unlock(ctx->lock); + switch (index) { + case OSSL_LIB_CTX_PROPERTY_STRING_INDEX: + return ctx->property_string_data; + case OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX: + return ctx->evp_method_store; + case OSSL_LIB_CTX_PROVIDER_STORE_INDEX: + return ctx->provider_store; + case OSSL_LIB_CTX_NAMEMAP_INDEX: + return ctx->namemap; + case OSSL_LIB_CTX_PROPERTY_DEFN_INDEX: + return ctx->property_defns; + case OSSL_LIB_CTX_GLOBAL_PROPERTIES: + return ctx->global_properties; + case OSSL_LIB_CTX_DRBG_INDEX: + return ctx->drbg; + case OSSL_LIB_CTX_DRBG_NONCE_INDEX: + return ctx->drbg_nonce; +#ifndef FIPS_MODULE + case OSSL_LIB_CTX_PROVIDER_CONF_INDEX: + return ctx->provider_conf; + case OSSL_LIB_CTX_BIO_CORE_INDEX: + return ctx->bio_core; + case OSSL_LIB_CTX_CHILD_PROVIDER_INDEX: + return ctx->child_provider; + case OSSL_LIB_CTX_DECODER_STORE_INDEX: + return ctx->decoder_store; + case OSSL_LIB_CTX_DECODER_CACHE_INDEX: + return ctx->decoder_cache; + case OSSL_LIB_CTX_ENCODER_STORE_INDEX: + return ctx->encoder_store; + case OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX: + return ctx->store_loader_store; + case OSSL_LIB_CTX_SELF_TEST_CB_INDEX: + return ctx->self_test_cb; + case OSSL_LIB_CTX_INDICATOR_CB_INDEX: + return ctx->indicator_cb; +#endif +#ifndef OPENSSL_NO_THREAD_POOL + case OSSL_LIB_CTX_THREAD_INDEX: + return ctx->threads; +#endif - if (dynidx != -1) { - if (!CRYPTO_THREAD_read_lock(ctx->index_locks[index])) - return NULL; - if (!CRYPTO_THREAD_read_lock(ctx->lock)) { - CRYPTO_THREAD_unlock(ctx->index_locks[index]); - return NULL; - } - data = CRYPTO_get_ex_data(&ctx->data, dynidx); - CRYPTO_THREAD_unlock(ctx->lock); - CRYPTO_THREAD_unlock(ctx->index_locks[index]); - return data; - } +#ifdef FIPS_MODULE + case OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX: + return ctx->thread_event_handler; - if (!CRYPTO_THREAD_write_lock(ctx->index_locks[index])) - return NULL; - if (!CRYPTO_THREAD_write_lock(ctx->lock)) { - CRYPTO_THREAD_unlock(ctx->index_locks[index]); + case OSSL_LIB_CTX_FIPS_PROV_INDEX: + return ctx->fips_prov; +#endif + + case OSSL_LIB_CTX_COMP_METHODS: + return (void *)&ctx->comp_methods; + + default: return NULL; } +} - dynidx = ctx->dyn_indexes[index]; - if (dynidx != -1) { - data = CRYPTO_get_ex_data(&ctx->data, dynidx); - CRYPTO_THREAD_unlock(ctx->lock); - CRYPTO_THREAD_unlock(ctx->index_locks[index]); - return data; - } - - if (!ossl_lib_ctx_init_index(ctx, index, meth)) { - CRYPTO_THREAD_unlock(ctx->lock); - CRYPTO_THREAD_unlock(ctx->index_locks[index]); - return NULL; - } - - CRYPTO_THREAD_unlock(ctx->lock); - - /* - * The alloc call ensures there's a value there. We release the ctx->lock - * for this, because the allocation itself may recursively call - * ossl_lib_ctx_get_data for other indexes (never this one). The allocation - * will itself aquire the ctx->lock when it actually comes to store the - * allocated data (see ossl_lib_ctx_generic_new() above). We call - * ossl_crypto_alloc_ex_data_intern() here instead of CRYPTO_alloc_ex_data(). - * They do the same thing except that the latter calls CRYPTO_get_ex_data() - * as well - which we must not do without holding the ctx->lock. - */ - if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL, - &ctx->data, ctx->dyn_indexes[index])) { - if (!CRYPTO_THREAD_read_lock(ctx->lock)) - goto end; - data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]); - CRYPTO_THREAD_unlock(ctx->lock); - } - -end: - CRYPTO_THREAD_unlock(ctx->index_locks[index]); - return data; +void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index) +{ + return ossl_lib_ctx_get_data(ctx, index); } OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx) @@ -446,56 +643,6 @@ OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx) return &ctx->global; } -int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, - ossl_lib_ctx_run_once_fn run_once_fn) -{ - int done = 0, ret = 0; - - ctx = ossl_lib_ctx_get_concrete(ctx); - if (ctx == NULL) - return 0; - - if (!CRYPTO_THREAD_read_lock(ctx->oncelock)) - return 0; - done = ctx->run_once_done[idx]; - if (done) - ret = ctx->run_once_ret[idx]; - CRYPTO_THREAD_unlock(ctx->oncelock); - - if (done) - return ret; - - if (!CRYPTO_THREAD_write_lock(ctx->oncelock)) - return 0; - if (ctx->run_once_done[idx]) { - ret = ctx->run_once_ret[idx]; - CRYPTO_THREAD_unlock(ctx->oncelock); - return ret; - } - - ret = run_once_fn(ctx); - ctx->run_once_done[idx] = 1; - ctx->run_once_ret[idx] = ret; - CRYPTO_THREAD_unlock(ctx->oncelock); - - return ret; -} - -int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn) -{ - struct ossl_lib_ctx_onfree_list_st *newonfree - = OPENSSL_malloc(sizeof(*newonfree)); - - if (newonfree == NULL) - return 0; - - newonfree->fn = onfreefn; - newonfree->next = ctx->onfreelist; - ctx->onfreelist = newonfree; - - return 1; -} - const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx) { #ifdef FIPS_MODULE @@ -508,3 +655,27 @@ const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx) return "Non-default library context"; #endif } + +CRYPTO_THREAD_LOCAL *ossl_lib_ctx_get_rcukey(OSSL_LIB_CTX *libctx) +{ + libctx = ossl_lib_ctx_get_concrete(libctx); + if (libctx == NULL) + return NULL; + return &libctx->rcu_local_key; +} + +int OSSL_LIB_CTX_get_conf_diagnostics(OSSL_LIB_CTX *libctx) +{ + libctx = ossl_lib_ctx_get_concrete(libctx); + if (libctx == NULL) + return 0; + return libctx->conf_diagnostics; +} + +void OSSL_LIB_CTX_set_conf_diagnostics(OSSL_LIB_CTX *libctx, int value) +{ + libctx = ossl_lib_ctx_get_concrete(libctx); + if (libctx == NULL) + return; + libctx->conf_diagnostics = value; +} diff --git a/crypto/core_algorithm.c b/crypto/core_algorithm.c index c245c814d98c..16055bad3022 100644 --- a/crypto/core_algorithm.c +++ b/crypto/core_algorithm.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -193,7 +193,5 @@ char *ossl_algorithm_get1_first_name(const OSSL_ALGORITHM *algo) first_name_len = first_name_end - algo->algorithm_names; ret = OPENSSL_strndup(algo->algorithm_names, first_name_len); - if (ret == NULL) - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return ret; } diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c index c063515fc04d..a0ab97b10579 100644 --- a/crypto/core_fetch.c +++ b/crypto/core_fetch.c @@ -10,6 +10,7 @@ #include #include +#include #include "internal/cryptlib.h" #include "internal/core.h" #include "internal/property.h" @@ -110,6 +111,9 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider, == NULL) return; + OSSL_TRACE2(QUERY, + "ossl_method_construct_this: putting an algo to the store %p with no_store %d\n", + (void *)data->store, no_store); /* * Note regarding putting the method in stores: * @@ -120,8 +124,7 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider, * It is *expected* that the put function increments the refcnt * of the passed method. */ - data->mcm->put(no_store ? data->store : NULL, - method, provider, algo->algorithm_names, + data->mcm->put(no_store ? data->store : NULL, method, provider, algo->algorithm_names, algo->property_definition, data->mcm_data); /* refcnt-- because we're dropping the reference */ diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c index ebf7ed5eb165..f36f070fa2ab 100644 --- a/crypto/core_namemap.c +++ b/crypto/core_namemap.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,61 +8,53 @@ */ #include "internal/namemap.h" -#include -#include "crypto/lhash.h" /* ossl_lh_strcasehash */ #include "internal/tsan_assist.h" +#include "internal/hashtable.h" #include "internal/sizes.h" +#include "crypto/context.h" -/*- - * The namenum entry - * ================= - */ -typedef struct { - char *name; - int number; -} NAMENUM_ENTRY; +#define NAMEMAP_HT_BUCKETS 2048 -DEFINE_LHASH_OF(NAMENUM_ENTRY); +HT_START_KEY_DEFN(namenum_key) +HT_DEF_KEY_FIELD_CHAR_ARRAY(name, 64) +HT_END_KEY_DEFN(NAMENUM_KEY) /*- * The namemap itself * ================== */ +typedef STACK_OF(OPENSSL_STRING) NAMES; + +DEFINE_STACK_OF(NAMES) + struct ossl_namemap_st { /* Flags */ unsigned int stored:1; /* If 1, it's stored in a library context */ + HT *namenum_ht; /* Name->number mapping */ + CRYPTO_RWLOCK *lock; - LHASH_OF(NAMENUM_ENTRY) *namenum; /* Name->number mapping */ + STACK_OF(NAMES) *numnames; TSAN_QUALIFIER int max_number; /* Current max number */ }; -/* LHASH callbacks */ - -static unsigned long namenum_hash(const NAMENUM_ENTRY *n) +static void name_string_free(char *name) { - return ossl_lh_strcasehash(n->name); + OPENSSL_free(name); } -static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b) +static void names_free(NAMES *n) { - return OPENSSL_strcasecmp(a->name, b->name); -} - -static void namenum_free(NAMENUM_ENTRY *n) -{ - if (n != NULL) - OPENSSL_free(n->name); - OPENSSL_free(n); + sk_OPENSSL_STRING_pop_free(n, name_string_free); } /* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */ -static void *stored_namemap_new(OSSL_LIB_CTX *libctx) +void *ossl_stored_namemap_new(OSSL_LIB_CTX *libctx) { - OSSL_NAMEMAP *namemap = ossl_namemap_new(); + OSSL_NAMEMAP *namemap = ossl_namemap_new(libctx); if (namemap != NULL) namemap->stored = 1; @@ -70,7 +62,7 @@ static void *stored_namemap_new(OSSL_LIB_CTX *libctx) return namemap; } -static void stored_namemap_free(void *vnamemap) +void ossl_stored_namemap_free(void *vnamemap) { OSSL_NAMEMAP *namemap = vnamemap; @@ -81,12 +73,6 @@ static void stored_namemap_free(void *vnamemap) } } -static const OSSL_LIB_CTX_METHOD stored_namemap_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - stored_namemap_new, - stored_namemap_free, -}; - /*- * API functions * ============= @@ -112,20 +98,6 @@ int ossl_namemap_empty(OSSL_NAMEMAP *namemap) #endif } -typedef struct doall_names_data_st { - int number; - const char **names; - int found; -} DOALL_NAMES_DATA; - -static void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data) -{ - if (namenum->number == data->number) - data->names[data->found++] = namenum->name; -} - -IMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA); - /* * Call the callback for all names in the namemap with the given number. * A return value 1 means that the callback was called for all names. A @@ -135,63 +107,68 @@ int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number, void (*fn)(const char *name, void *data), void *data) { - DOALL_NAMES_DATA cbdata; - size_t num_names; int i; + NAMES *names; - cbdata.number = number; - cbdata.found = 0; - - if (namemap == NULL) + if (namemap == NULL || number <= 0) return 0; /* - * We collect all the names first under a read lock. Subsequently we call + * We duplicate the NAMES stack under a read lock. Subsequently we call * the user function, so that we're not holding the read lock when in user * code. This could lead to deadlocks. */ if (!CRYPTO_THREAD_read_lock(namemap->lock)) return 0; - num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum); - if (num_names == 0) { - CRYPTO_THREAD_unlock(namemap->lock); - return 0; - } - cbdata.names = OPENSSL_malloc(sizeof(*cbdata.names) * num_names); - if (cbdata.names == NULL) { - CRYPTO_THREAD_unlock(namemap->lock); - return 0; - } - lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name, - &cbdata); + names = sk_NAMES_value(namemap->numnames, number - 1); + if (names != NULL) + names = sk_OPENSSL_STRING_dup(names); + CRYPTO_THREAD_unlock(namemap->lock); - for (i = 0; i < cbdata.found; i++) - fn(cbdata.names[i], data); + if (names == NULL) + return 0; - OPENSSL_free(cbdata.names); - return 1; + for (i = 0; i < sk_OPENSSL_STRING_num(names); i++) + fn(sk_OPENSSL_STRING_value(names, i), data); + + sk_OPENSSL_STRING_free(names); + return i > 0; } -static int namemap_name2num_n(const OSSL_NAMEMAP *namemap, - const char *name, size_t name_len) +int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name) { - NAMENUM_ENTRY *namenum_entry, namenum_tmpl; + int number = 0; + HT_VALUE *val; + NAMENUM_KEY key; - if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL) +#ifndef FIPS_MODULE + if (namemap == NULL) + namemap = ossl_namemap_stored(NULL); +#endif + + if (namemap == NULL) return 0; - namenum_tmpl.number = 0; - namenum_entry = - lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl); - OPENSSL_free(namenum_tmpl.name); - return namenum_entry != NULL ? namenum_entry->number : 0; + + HT_INIT_KEY(&key); + HT_SET_KEY_STRING_CASE(&key, name, name); + + val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key)); + + if (val != NULL) + /* We store a (small) int directly instead of a pointer to it. */ + number = (int)(intptr_t)val->value; + + return number; } int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, const char *name, size_t name_len) { - int number; + int number = 0; + HT_VALUE *val; + NAMENUM_KEY key; #ifndef FIPS_MODULE if (namemap == NULL) @@ -201,79 +178,114 @@ int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, if (namemap == NULL) return 0; - if (!CRYPTO_THREAD_read_lock(namemap->lock)) - return 0; - number = namemap_name2num_n(namemap, name, name_len); - CRYPTO_THREAD_unlock(namemap->lock); + HT_INIT_KEY(&key); + HT_SET_KEY_STRING_CASE_N(&key, name, name, name_len); + + val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key)); + + if (val != NULL) + /* We store a (small) int directly instead of a pointer to it. */ + number = (int)(intptr_t)val->value; return number; } -int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name) -{ - if (name == NULL) - return 0; - - return ossl_namemap_name2num_n(namemap, name, strlen(name)); -} - -struct num2name_data_st { - size_t idx; /* Countdown */ - const char *name; /* Result */ -}; - -static void do_num2name(const char *name, void *vdata) -{ - struct num2name_data_st *data = vdata; - - if (data->idx > 0) - data->idx--; - else if (data->name == NULL) - data->name = name; -} - const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number, size_t idx) { - struct num2name_data_st data; + NAMES *names; + const char *ret = NULL; - data.idx = idx; - data.name = NULL; - if (!ossl_namemap_doall_names(namemap, number, do_num2name, &data)) + if (namemap == NULL || number <= 0) return NULL; - return data.name; + + if (!CRYPTO_THREAD_read_lock(namemap->lock)) + return NULL; + + names = sk_NAMES_value(namemap->numnames, number - 1); + if (names != NULL) + ret = sk_OPENSSL_STRING_value(names, idx); + + CRYPTO_THREAD_unlock(namemap->lock); + + return ret; } -static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len) +/* This function is not thread safe, the namemap must be locked */ +static int numname_insert(OSSL_NAMEMAP *namemap, int number, + const char *name) { - NAMENUM_ENTRY *namenum = NULL; - int tmp_number; + NAMES *names; + char *tmpname; - /* If it already exists, we don't add it */ - if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0) - return tmp_number; + if (number > 0) { + names = sk_NAMES_value(namemap->numnames, number - 1); + if (!ossl_assert(names != NULL)) { + /* cannot happen */ + return 0; + } + } else { + /* a completely new entry */ + names = sk_OPENSSL_STRING_new_null(); + if (names == NULL) + return 0; + } - if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL - || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL) + if ((tmpname = OPENSSL_strdup(name)) == NULL) goto err; - /* The tsan_counter use here is safe since we're under lock */ - namenum->number = - number != 0 ? number : 1 + tsan_counter(&namemap->max_number); - (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum); - - if (lh_NAMENUM_ENTRY_error(namemap->namenum)) + if (!sk_OPENSSL_STRING_push(names, tmpname)) goto err; - return namenum->number; + tmpname = NULL; + + if (number <= 0) { + if (!sk_NAMES_push(namemap->numnames, names)) + goto err; + number = sk_NAMES_num(namemap->numnames); + } + return number; err: - namenum_free(namenum); + if (number <= 0) + sk_OPENSSL_STRING_pop_free(names, name_string_free); + OPENSSL_free(tmpname); return 0; } -int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len) +/* This function is not thread safe, the namemap must be locked */ +static int namemap_add_name(OSSL_NAMEMAP *namemap, int number, + const char *name) +{ + int ret; + HT_VALUE val = { 0 }; + NAMENUM_KEY key; + + /* If it already exists, we don't add it */ + if ((ret = ossl_namemap_name2num(namemap, name)) != 0) + return ret; + + if ((number = numname_insert(namemap, number, name)) == 0) + return 0; + + /* Using tsan_store alone here is safe since we're under lock */ + tsan_store(&namemap->max_number, number); + + HT_INIT_KEY(&key); + HT_SET_KEY_STRING_CASE(&key, name, name); + val.value = (void *)(intptr_t)number; + ret = ossl_ht_insert(namemap->namenum_ht, TO_HT_KEY(&key), &val, NULL); + if (!ossl_assert(ret != 0)) /* cannot happen as we are under write lock */ + return 0; + if (ret < 1) { + /* unable to insert due to too many collisions */ + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_NAMES); + return 0; + } + return number; +} + +int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, + const char *name) { int tmp_number; @@ -282,29 +294,20 @@ int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, namemap = ossl_namemap_stored(NULL); #endif - if (name == NULL || name_len == 0 || namemap == NULL) + if (name == NULL || *name == 0 || namemap == NULL) return 0; if (!CRYPTO_THREAD_write_lock(namemap->lock)) return 0; - tmp_number = namemap_add_name_n(namemap, number, name, name_len); + tmp_number = namemap_add_name(namemap, number, name); CRYPTO_THREAD_unlock(namemap->lock); return tmp_number; } -int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name) -{ - if (name == NULL) - return 0; - - return ossl_namemap_add_name_n(namemap, number, name, strlen(name)); -} - int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, const char *names, const char separator) { - const char *p, *q; - size_t l; + char *tmp, *p, *q, *endp; /* Check that we have a namemap */ if (!ossl_assert(namemap != NULL)) { @@ -312,62 +315,71 @@ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number, return 0; } - if (!CRYPTO_THREAD_write_lock(namemap->lock)) + if ((tmp = OPENSSL_strdup(names)) == NULL) return 0; + + if (!CRYPTO_THREAD_write_lock(namemap->lock)) { + OPENSSL_free(tmp); + return 0; + } /* * Check that no name is an empty string, and that all names have at * most one numeric identity together. */ - for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { + for (p = tmp; *p != '\0'; p = q) { int this_number; + size_t l; - if ((q = strchr(p, separator)) == NULL) + if ((q = strchr(p, separator)) == NULL) { l = strlen(p); /* offset to \0 */ - else + q = p + l; + } else { l = q - p; /* offset to the next separator */ - - this_number = namemap_name2num_n(namemap, p, l); - - if (*p == '\0' || *p == separator) { - ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME); - goto err; + *q++ = '\0'; } + + if (*p == '\0') { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME); + number = 0; + goto end; + } + + this_number = ossl_namemap_name2num(namemap, p); + if (number == 0) { number = this_number; } else if (this_number != 0 && this_number != number) { ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES, - "\"%.*s\" has an existing different identity %d (from \"%s\")", - l, p, this_number, names); - goto err; + "\"%s\" has an existing different identity %d (from \"%s\")", + p, this_number, names); + number = 0; + goto end; } } + endp = p; /* Now that we have checked, register all names */ - for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) { + for (p = tmp; p < endp; p = q) { int this_number; - if ((q = strchr(p, separator)) == NULL) - l = strlen(p); /* offset to \0 */ - else - l = q - p; /* offset to the next separator */ + q = p + strlen(p) + 1; - this_number = namemap_add_name_n(namemap, number, p, l); + this_number = namemap_add_name(namemap, number, p); if (number == 0) { number = this_number; } else if (this_number != number) { ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR, "Got number %d when expecting %d", this_number, number); - goto err; + number = 0; + goto end; } } + end: CRYPTO_THREAD_unlock(namemap->lock); + OPENSSL_free(tmp); return number; - - err: - CRYPTO_THREAD_unlock(namemap->lock); - return 0; } /*- @@ -471,8 +483,7 @@ OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx) int nms; #endif OSSL_NAMEMAP *namemap = - ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX, - &stored_namemap_method); + ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX); if (namemap == NULL) return NULL; @@ -507,16 +518,28 @@ OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx) return namemap; } -OSSL_NAMEMAP *ossl_namemap_new(void) +OSSL_NAMEMAP *ossl_namemap_new(OSSL_LIB_CTX *libctx) { OSSL_NAMEMAP *namemap; + HT_CONFIG htconf = { NULL, NULL, NULL, NAMEMAP_HT_BUCKETS, 1, 1 }; - if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL - && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL - && (namemap->namenum = - lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL) - return namemap; + htconf.ctx = libctx; + if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) == NULL) + goto err; + + if ((namemap->lock = CRYPTO_THREAD_lock_new()) == NULL) + goto err; + + if ((namemap->namenum_ht = ossl_ht_new(&htconf)) == NULL) + goto err; + + if ((namemap->numnames = sk_NAMES_new_null()) == NULL) + goto err; + + return namemap; + + err: ossl_namemap_free(namemap); return NULL; } @@ -526,8 +549,9 @@ void ossl_namemap_free(OSSL_NAMEMAP *namemap) if (namemap == NULL || namemap->stored) return; - lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free); - lh_NAMENUM_ENTRY_free(namemap->namenum); + sk_NAMES_pop_free(namemap->numnames, names_free); + + ossl_ht_free(namemap->namenum_ht); CRYPTO_THREAD_lock_free(namemap->lock); OPENSSL_free(namemap); diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index 8574f31a8124..bbcad8e51d2d 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -29,14 +29,32 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = { "insufficient param size"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE), "insufficient secure data space"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INTEGER_OVERFLOW), + "integer overflow"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_NEGATIVE_VALUE), "invalid negative value"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_NULL_ARGUMENT), "invalid null argument"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_INVALID_OSSL_PARAM_TYPE), "invalid ossl param type"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_NO_PARAMS_TO_MERGE), + "no params to merge"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL), + "no space for terminating null"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_ODD_NUMBER_OF_DIGITS), "odd number of digits"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY), + "param cannot be represented exactly"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_NOT_INTEGER_TYPE), + "param not integer type"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE), + "param of incompatible type"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED), + "param unsigned integer negative value unsupported"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT), + "param unsupported floating point format"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION), + "param value too large for destination"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_ALREADY_EXISTS), "provider already exists"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_PROVIDER_SECTION_ERROR), @@ -47,6 +65,7 @@ static const ERR_STRING_DATA CRYPTO_str_reasons[] = { "secure malloc failure"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_STRING_TOO_LONG), "string too long"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_BYTES), "too many bytes"}, + {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_NAMES), "too many names"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_MANY_RECORDS), "too many records"}, {ERR_PACK(ERR_LIB_CRYPTO, 0, CRYPTO_R_TOO_SMALL_BUFFER), diff --git a/crypto/cpuid.c b/crypto/cpuid.c index 090f6fe03ecc..538a5a039f20 100644 --- a/crypto/cpuid.c +++ b/crypto/cpuid.c @@ -1,5 +1,5 @@ /* - * 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 @@ -7,14 +7,14 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "crypto/cryptlib.h" #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(_M_AMD64) || defined(_M_X64) -extern unsigned int OPENSSL_ia32cap_P[4]; +extern unsigned int OPENSSL_ia32cap_P[OPENSSL_IA32CAP_P_MAX_INDEXES]; # if defined(OPENSSL_CPUID_OBJ) @@ -29,18 +29,18 @@ extern unsigned int OPENSSL_ia32cap_P[4]; */ # ifdef _WIN32 typedef WCHAR variant_char; - +# define OPENSSL_IA32CAP_P_MAX_CHAR_SIZE 256 static variant_char *ossl_getenv(const char *name) { /* * Since we pull only one environment variable, it's simpler to - * to just ignore |name| and use equivalent wide-char L-literal. + * just ignore |name| and use equivalent wide-char L-literal. * As well as to ignore excessively long values... */ - static WCHAR value[48]; - DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48); + static WCHAR value[OPENSSL_IA32CAP_P_MAX_CHAR_SIZE]; + DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, OPENSSL_IA32CAP_P_MAX_CHAR_SIZE); - return (len > 0 && len < 48) ? value : NULL; + return (len > 0 && len < OPENSSL_IA32CAP_P_MAX_CHAR_SIZE) ? value : NULL; } # else typedef char variant_char; @@ -71,7 +71,7 @@ static uint64_t ossl_strtouint64(const variant_char *str) base = 16, str++; } - while((digit = todigit(*str++)) < base) + while ((digit = todigit(*str++)) < base) ret = ret * base + digit; return ret; @@ -80,7 +80,7 @@ static uint64_t ossl_strtouint64(const variant_char *str) static variant_char *ossl_strchr(const variant_char *str, char srch) { variant_char c; - while((c = *str)) { + while ((c = *str)) { if (c == srch) return (variant_char *)str; str++; @@ -98,6 +98,7 @@ void OPENSSL_cpuid_setup(void) IA32CAP OPENSSL_ia32_cpuid(unsigned int *); IA32CAP vec; const variant_char *env; + int index = 2; if (trigger) return; @@ -126,23 +127,37 @@ void OPENSSL_cpuid_setup(void) vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); } - if ((env = ossl_strchr(env, ':')) != NULL) { - IA32CAP vecx; - + /* Processed indexes 0, 1 */ + if ((env = ossl_strchr(env, ':')) != NULL) env++; - off = (env[0] == '~') ? 1 : 0; - vecx = ossl_strtouint64(env + off); - if (off) { - OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; - OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); - } else { - OPENSSL_ia32cap_P[2] = (unsigned int)vecx; - OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); + for (; index < OPENSSL_IA32CAP_P_MAX_INDEXES; index += 2) { + if ((env != NULL) && (env[0] != '\0')) { + /* if env[0] == ':' current index is skipped */ + if (env[0] != ':') { + IA32CAP vecx; + + off = (env[0] == '~') ? 1 : 0; + vecx = ossl_strtouint64(env + off); + if (off) { + OPENSSL_ia32cap_P[index] &= ~(unsigned int)vecx; + OPENSSL_ia32cap_P[index + 1] &= ~(unsigned int)(vecx >> 32); + } else { + OPENSSL_ia32cap_P[index] = (unsigned int)vecx; + OPENSSL_ia32cap_P[index + 1] = (unsigned int)(vecx >> 32); + } + } + /* skip delimeter */ + if ((env = ossl_strchr(env, ':')) != NULL) + env++; + } else { /* zeroize the next two indexes */ + OPENSSL_ia32cap_P[index] = 0; + OPENSSL_ia32cap_P[index + 1] = 0; } - } else { - OPENSSL_ia32cap_P[2] = 0; - OPENSSL_ia32cap_P[3] = 0; } + + /* If AVX10 is disabled, zero out its detailed cap bits */ + if (!(OPENSSL_ia32cap_P[6] & (1 << 19))) + OPENSSL_ia32cap_P[9] = 0; } else { vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); } @@ -156,7 +171,7 @@ void OPENSSL_cpuid_setup(void) OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); } # else -unsigned int OPENSSL_ia32cap_P[4]; +unsigned int OPENSSL_ia32cap_P[OPENSSL_IA32CAP_P_MAX_INDEXES]; # endif #endif @@ -173,7 +188,7 @@ void OPENSSL_cpuid_setup(void) */ /* - * The volatile is used to to ensure that the compiler generates code that reads + * The volatile is used to ensure that the compiler generates code that reads * all values from the array and doesn't try to optimize this away. The standard * doesn't actually require this behavior if the original data pointed to is * not volatile, but compilers do this in practice anyway. @@ -181,7 +196,7 @@ void OPENSSL_cpuid_setup(void) * There are also assembler versions of this function. */ # undef CRYPTO_memcmp -int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) +int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) { size_t i; const volatile unsigned char *a = in_a; diff --git a/crypto/crmf/crmf_asn.c b/crypto/crmf/crmf_asn.c index 3354b89736e9..a4a0ff1b172d 100644 --- a/crypto/crmf/crmf_asn.c +++ b/crypto/crmf/crmf_asn.c @@ -1,5 +1,5 @@ /*- - * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -26,14 +26,14 @@ ASN1_SEQUENCE(OSSL_CRMF_PRIVATEKEYINFO) = { } ASN1_SEQUENCE_END(OSSL_CRMF_PRIVATEKEYINFO) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PRIVATEKEYINFO) - ASN1_CHOICE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER) = { - ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.string, ASN1_UTF8STRING), - ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, value.generalName, GENERAL_NAME) + ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, + value.string, ASN1_UTF8STRING), + ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER, + value.generalName, GENERAL_NAME) } ASN1_CHOICE_END(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID_IDENTIFIER) - ASN1_SEQUENCE(OSSL_CRMF_ENCKEYWITHID) = { ASN1_SIMPLE(OSSL_CRMF_ENCKEYWITHID, privateKey, OSSL_CRMF_PRIVATEKEYINFO), ASN1_OPT(OSSL_CRMF_ENCKEYWITHID, identifier, @@ -41,7 +41,6 @@ ASN1_SEQUENCE(OSSL_CRMF_ENCKEYWITHID) = { } ASN1_SEQUENCE_END(OSSL_CRMF_ENCKEYWITHID) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCKEYWITHID) - ASN1_SEQUENCE(OSSL_CRMF_CERTID) = { ASN1_SIMPLE(OSSL_CRMF_CERTID, issuer, GENERAL_NAME), ASN1_SIMPLE(OSSL_CRMF_CERTID, serialNumber, ASN1_INTEGER) @@ -49,7 +48,6 @@ ASN1_SEQUENCE(OSSL_CRMF_CERTID) = { IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTID) IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID) - ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = { ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, intendedAlg, X509_ALGOR, 0), ASN1_IMP_OPT(OSSL_CRMF_ENCRYPTEDVALUE, symmAlg, X509_ALGOR, 1), @@ -60,13 +58,27 @@ ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = { } ASN1_SEQUENCE_END(OSSL_CRMF_ENCRYPTEDVALUE) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE) +/* + * Note from CMP Updates defining CMPv3: + * The EncryptedKey structure defined in CRMF [RFC4211] is reused + * here, which makes the update backward compatible. Using the new + * syntax with the untagged default choice EncryptedValue is bits-on- + * the-wire compatible with the old syntax. + */ +ASN1_CHOICE(OSSL_CRMF_ENCRYPTEDKEY) = { + ASN1_SIMPLE(OSSL_CRMF_ENCRYPTEDKEY, value.encryptedValue, OSSL_CRMF_ENCRYPTEDVALUE), +#ifndef OPENSSL_NO_CMS + ASN1_IMP(OSSL_CRMF_ENCRYPTEDKEY, value.envelopedData, CMS_EnvelopedData, 0), +#endif +} ASN1_CHOICE_END(OSSL_CRMF_ENCRYPTEDKEY) +IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDKEY) + ASN1_SEQUENCE(OSSL_CRMF_SINGLEPUBINFO) = { ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER), ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME) } ASN1_SEQUENCE_END(OSSL_CRMF_SINGLEPUBINFO) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO) - ASN1_SEQUENCE(OSSL_CRMF_PKIPUBLICATIONINFO) = { ASN1_SIMPLE(OSSL_CRMF_PKIPUBLICATIONINFO, action, ASN1_INTEGER), ASN1_SEQUENCE_OF_OPT(OSSL_CRMF_PKIPUBLICATIONINFO, pubInfos, @@ -75,24 +87,22 @@ ASN1_SEQUENCE(OSSL_CRMF_PKIPUBLICATIONINFO) = { IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKIPUBLICATIONINFO) IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_PKIPUBLICATIONINFO) - ASN1_SEQUENCE(OSSL_CRMF_PKMACVALUE) = { ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, algId, X509_ALGOR), ASN1_SIMPLE(OSSL_CRMF_PKMACVALUE, value, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(OSSL_CRMF_PKMACVALUE) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PKMACVALUE) - ASN1_CHOICE(OSSL_CRMF_POPOPRIVKEY) = { ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.thisMessage, ASN1_BIT_STRING, 0), ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.subsequentMessage, ASN1_INTEGER, 1), ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.dhMAC, ASN1_BIT_STRING, 2), ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.agreeMAC, OSSL_CRMF_PKMACVALUE, 3), ASN1_IMP(OSSL_CRMF_POPOPRIVKEY, value.encryptedKey, ASN1_NULL, 4), + /* When supported, ASN1_NULL needs to be replaced by CMS_ENVELOPEDDATA */ } ASN1_CHOICE_END(OSSL_CRMF_POPOPRIVKEY) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY) - ASN1_SEQUENCE(OSSL_CRMF_PBMPARAMETER) = { ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, salt, ASN1_OCTET_STRING), ASN1_SIMPLE(OSSL_CRMF_PBMPARAMETER, owf, X509_ALGOR), @@ -101,7 +111,6 @@ ASN1_SEQUENCE(OSSL_CRMF_PBMPARAMETER) = { } ASN1_SEQUENCE_END(OSSL_CRMF_PBMPARAMETER) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER) - ASN1_CHOICE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) = { ASN1_EXP(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO, value.sender, GENERAL_NAME, 0), @@ -110,7 +119,6 @@ ASN1_CHOICE(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) = { } ASN1_CHOICE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO) - ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEYINPUT) = { ASN1_SIMPLE(OSSL_CRMF_POPOSIGNINGKEYINPUT, authInfo, OSSL_CRMF_POPOSIGNINGKEYINPUT_AUTHINFO), @@ -118,7 +126,6 @@ ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEYINPUT) = { } ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEYINPUT) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEYINPUT) - ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEY) = { ASN1_IMP_OPT(OSSL_CRMF_POPOSIGNINGKEY, poposkInput, OSSL_CRMF_POPOSIGNINGKEYINPUT, 0), @@ -127,7 +134,6 @@ ASN1_SEQUENCE(OSSL_CRMF_POPOSIGNINGKEY) = { } ASN1_SEQUENCE_END(OSSL_CRMF_POPOSIGNINGKEY) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPOSIGNINGKEY) - ASN1_CHOICE(OSSL_CRMF_POPO) = { ASN1_IMP(OSSL_CRMF_POPO, value.raVerified, ASN1_NULL, 0), ASN1_IMP(OSSL_CRMF_POPO, value.signature, OSSL_CRMF_POPOSIGNINGKEY, 1), @@ -136,7 +142,6 @@ ASN1_CHOICE(OSSL_CRMF_POPO) = { } ASN1_CHOICE_END(OSSL_CRMF_POPO) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_POPO) - ASN1_ADB_TEMPLATE(attributetypeandvalue_default) = ASN1_OPT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.other, ASN1_ANY); ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = { @@ -156,6 +161,12 @@ ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = { ADB_ENTRY(NID_id_regCtrl_protocolEncrKey, ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.protocolEncrKey, X509_PUBKEY)), + ADB_ENTRY(NID_id_regCtrl_algId, + ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, + value.algId, X509_ALGOR)), + ADB_ENTRY(NID_id_regCtrl_rsaKeyLen, + ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, + value.rsaKeyLen, ASN1_INTEGER)), ADB_ENTRY(NID_id_regInfo_utf8Pairs, ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, value.utf8Pairs, ASN1_UTF8STRING)), @@ -165,7 +176,6 @@ ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = { } ASN1_ADB_END(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, 0, type, 0, &attributetypeandvalue_default_tt, NULL); - ASN1_SEQUENCE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = { ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE, type, ASN1_OBJECT), ASN1_ADB_OBJECT(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) @@ -174,14 +184,12 @@ ASN1_SEQUENCE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = { IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) - ASN1_SEQUENCE(OSSL_CRMF_OPTIONALVALIDITY) = { ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notBefore, ASN1_TIME, 0), ASN1_EXP_OPT(OSSL_CRMF_OPTIONALVALIDITY, notAfter, ASN1_TIME, 1) } ASN1_SEQUENCE_END(OSSL_CRMF_OPTIONALVALIDITY) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_OPTIONALVALIDITY) - ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = { ASN1_IMP_OPT(OSSL_CRMF_CERTTEMPLATE, version, ASN1_INTEGER, 0), /* @@ -207,7 +215,7 @@ ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = { X509_EXTENSION, 9), } ASN1_SEQUENCE_END(OSSL_CRMF_CERTTEMPLATE) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE) - +IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTTEMPLATE) ASN1_SEQUENCE(OSSL_CRMF_CERTREQUEST) = { ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certReqId, ASN1_INTEGER), @@ -218,7 +226,6 @@ ASN1_SEQUENCE(OSSL_CRMF_CERTREQUEST) = { IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST) IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST) - ASN1_SEQUENCE(OSSL_CRMF_MSG) = { ASN1_SIMPLE(OSSL_CRMF_MSG, certReq, OSSL_CRMF_CERTREQUEST), ASN1_OPT(OSSL_CRMF_MSG, popo, OSSL_CRMF_POPO), diff --git a/crypto/crmf/crmf_err.c b/crypto/crmf/crmf_err.c index 44b2f2757d2c..4727c8335304 100644 --- a/crypto/crmf/crmf_err.c +++ b/crypto/crmf/crmf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,44 +18,57 @@ static const ERR_STRING_DATA CRMF_str_reasons[] = { {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_BAD_PBM_ITERATIONCOUNT), - "bad pbm iterationcount"}, + "bad pbm iterationcount"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CMS_NOT_SUPPORTED), "cms not supported"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CRMFERROR), "crmferror"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR), "error"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_CERTIFICATE), - "error decoding certificate"}, + "error decoding certificate"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY), + "error decoding encryptedkey"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_CERTIFICATE), - "error decrypting certificate"}, + "error decrypting certificate"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY), + "error decrypting encryptedkey"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE), + "error decrypting encryptedvalue"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY), - "error decrypting symmetric key"}, + "error decrypting symmetric key"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_SETTING_PURPOSE), + "error setting purpose"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY), + "error verifying encryptedkey"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_FAILURE_OBTAINING_RANDOM), - "failure obtaining random"}, + "failure obtaining random"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ITERATIONCOUNT_BELOW_100), - "iterationcount below 100"}, + "iterationcount below 100"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPOSKINPUT_NOT_SUPPORTED), - "poposkinput not supported"}, + "poposkinput not supported"}, + {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN), + "popo inconsistent central keygen"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY), - "popo inconsistent public key"}, + "popo inconsistent public key"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY), - "popo missing public key"}, + "popo missing public key"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT), - "popo missing subject"}, + "popo missing subject"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED), - "popo raverified not accepted"}, + "popo raverified not accepted"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE), - "setting mac algor failure"}, + "setting mac algor failure"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE), - "setting owf algor failure"}, + "setting owf algor failure"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_ALGORITHM), - "unsupported algorithm"}, + "unsupported algorithm"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_CIPHER), - "unsupported cipher"}, + "unsupported cipher"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO), - "unsupported method for creating popo"}, + "unsupported method for creating popo"}, {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD), - "unsupported popo method"}, + "unsupported popo method"}, {0, NULL} }; diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c index 3607fb0bf417..8238496e7380 100644 --- a/crypto/crmf/crmf_lib.c +++ b/crypto/crmf/crmf_lib.c @@ -1,5 +1,5 @@ /*- - * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2018 * Copyright Siemens AG 2015-2019 * @@ -31,11 +31,14 @@ #include "crmf_local.h" #include "internal/constant_time.h" #include "internal/sizes.h" +#include "crypto/evp.h" +#include "crypto/x509.h" /* explicit #includes not strictly needed since implied by the above: */ #include #include #include +#include /*- * atyp = Attribute Type @@ -80,7 +83,6 @@ int OSSL_CRMF_MSG_set1_##ctrlinf##_##atyp(OSSL_CRMF_MSG *msg, const valt *in) \ return 0; \ } - /*- * Pushes the given control attribute into the controls stack of a CertRequest * (section 6) @@ -243,7 +245,6 @@ IMPLEMENT_CRMF_CTRL_FUNC(utf8Pairs, ASN1_UTF8STRING, regInfo) /* id-regInfo-certReq to regInfo (section 7.2) */ IMPLEMENT_CRMF_CTRL_FUNC(certReq, OSSL_CRMF_CERTREQUEST, regInfo) - /* retrieves the certificate template of crm */ OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm) { @@ -254,7 +255,6 @@ OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm) return crm->certReq->certTemplate; } - int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm, ASN1_TIME *notBefore, ASN1_TIME *notAfter) { @@ -274,7 +274,6 @@ int OSSL_CRMF_MSG_set0_validity(OSSL_CRMF_MSG *crm, return 1; } - int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid) { if (crm == NULL || crm->certReq == NULL || crm->certReq->certReqId == NULL) { @@ -314,7 +313,6 @@ int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm) return crmf_asn1_get_int(crm->certReq->certReqId); } - int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, X509_EXTENSIONS *exts) { @@ -335,7 +333,6 @@ int OSSL_CRMF_MSG_set0_extensions(OSSL_CRMF_MSG *crm, return 1; } - int OSSL_CRMF_MSG_push0_extension(OSSL_CRMF_MSG *crm, X509_EXTENSION *ext) { @@ -370,11 +367,16 @@ static int create_popo_signature(OSSL_CRMF_POPOSIGNINGKEY *ps, OSSL_LIB_CTX *libctx, const char *propq) { char name[80] = ""; + EVP_PKEY *pub; if (ps == NULL || cr == NULL || pkey == NULL) { ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); return 0; } + pub = X509_PUBKEY_get0(cr->certTemplate->publicKey); + if (!ossl_x509_check_private_key(pub, pkey)) + return 0; + if (ps->poposkInput != NULL) { /* We do not support cases 1+2 defined in RFC 4211, section 4.1 */ ERR_raise(ERR_LIB_CRMF, CRMF_R_POPOSKINPUT_NOT_SUPPORTED); @@ -386,11 +388,11 @@ static int create_popo_signature(OSSL_CRMF_POPOSIGNINGKEY *ps, digest = NULL; return ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST), - ps->algorithmIdentifier, NULL, ps->signature, cr, - NULL, pkey, digest, libctx, propq); + ps->algorithmIdentifier, /* sets this X509_ALGOR */ + NULL, ps->signature, /* sets the ASN1_BIT_STRING */ + cr, NULL, pkey, digest, libctx, propq); } - 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) @@ -506,6 +508,12 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY); return 0; } + + /* + * Should check at this point the contents of the authInfo sub-field + * as requested in FR #19807 according to RFC 4211 section 4.1. + */ + it = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT); asn = sig->poposkInput; } else { @@ -522,6 +530,12 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, return 0; break; case OSSL_CRMF_POPO_KEYENC: + /* + * When OSSL_CMP_certrep_new() supports encrypted certs, + * should return 1 if the type of req->popo->value.keyEncipherment + * is OSSL_CRMF_POPOPRIVKEY_SUBSEQUENTMESSAGE and + * its value.subsequentMessage == OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT + */ case OSSL_CRMF_POPO_KEYAGREE: default: ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_POPO_METHOD); @@ -530,7 +544,44 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs, return 1; } -/* retrieves the serialNumber of the given cert template or NULL on error */ +int OSSL_CRMF_MSG_centralkeygen_requested(const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr) +{ + X509_PUBKEY *pubkey = NULL; + const unsigned char *pk = NULL; + int pklen, ret = 0; + + if (crm == NULL && p10cr == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); + return -1; + } + + if (crm != NULL) + pubkey = OSSL_CRMF_CERTTEMPLATE_get0_publicKey(OSSL_CRMF_MSG_get0_tmpl(crm)); + else + pubkey = p10cr->req_info.pubkey; + + if (pubkey == NULL + || (X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey) + && pklen == 0)) + ret = 1; + + /* + * In case of CRMF, POPO MUST be absent if central key generation + * is requested, otherwise MUST be present + */ + if (crm != NULL && ret != (crm->popo == NULL)) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN); + return -2; + } + return ret; +} + +X509_PUBKEY +*OSSL_CRMF_CERTTEMPLATE_get0_publicKey(const OSSL_CRMF_CERTTEMPLATE *tmpl) +{ + return tmpl != NULL ? tmpl->publicKey : NULL; +} + const ASN1_INTEGER *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl) { @@ -538,40 +589,38 @@ const ASN1_INTEGER } const X509_NAME - *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl) +*OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl) { return tmpl != NULL ? tmpl->subject : NULL; } -/* retrieves the issuer name of the given cert template or NULL on error */ const X509_NAME - *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl) +*OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl) { return tmpl != NULL ? tmpl->issuer : NULL; } X509_EXTENSIONS - *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl) +*OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl) { return tmpl != NULL ? tmpl->extensions : NULL; } -/* retrieves the issuer name of the given CertId or NULL on error */ const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid) { return cid != NULL && cid->issuer->type == GEN_DIRNAME ? cid->issuer->d.directoryName : NULL; } -/* retrieves the serialNumber of the given CertId or NULL on error */ -const ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid) +const ASN1_INTEGER *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID + *cid) { return cid != NULL ? cid->serialNumber : NULL; } /*- - * fill in certificate template. - * Any value argument that is NULL will leave the respective field unchanged. + * Fill in the certificate template |tmpl|. + * Any other NULL argument will leave the respective field unchanged. */ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl, EVP_PKEY *pubkey, @@ -597,47 +646,155 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl, return 1; } +#ifndef OPENSSL_NO_CMS +DECLARE_ASN1_ITEM(CMS_SignedData) /* copied from cms_local.h */ -/*- - * Decrypts the certificate in the given encryptedValue using private key pkey. - * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2. - * - * returns a pointer to the decrypted certificate - * returns NULL on error or if no certificate available - */ -X509 -*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert, - OSSL_LIB_CTX *libctx, const char *propq, - EVP_PKEY *pkey) +/* check for KGA authorization implied by CA flag or by explicit EKU cmKGA */ +static int check_cmKGA(ossl_unused const X509_PURPOSE *purpose, const X509 *x, int ca) +{ + STACK_OF(ASN1_OBJECT) *ekus; + int i, ret = 1; + + if (ca) + return ret; + ekus = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL); + for (i = 0; i < sk_ASN1_OBJECT_num(ekus); i++) { + if (OBJ_obj2nid(sk_ASN1_OBJECT_value(ekus, i)) == NID_cmKGA) + goto end; + } + ret = 0; + + end: + sk_ASN1_OBJECT_pop_free(ekus, ASN1_OBJECT_free); + return ret; +} +#endif /* OPENSSL_NO_CMS */ + +EVP_PKEY *OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(const OSSL_CRMF_ENCRYPTEDKEY *encryptedKey, + X509_STORE *ts, STACK_OF(X509) *extra, EVP_PKEY *pkey, + X509 *cert, ASN1_OCTET_STRING *secret, + OSSL_LIB_CTX *libctx, const char *propq) +{ +#ifndef OPENSSL_NO_CMS + BIO *bio = NULL; + CMS_SignedData *sd = NULL; + BIO *pkey_bio = NULL; + int purpose_id, bak_purpose_id; + X509_VERIFY_PARAM *vpm; +#endif + EVP_PKEY *ret = NULL; + + if (encryptedKey == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); + return NULL; + } + if (encryptedKey->type != OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA) { + unsigned char *p; + const unsigned char *p_copy; + int len; + + p = OSSL_CRMF_ENCRYPTEDVALUE_decrypt(encryptedKey->value.encryptedValue, + libctx, propq, pkey, &len); + if ((p_copy = p) != NULL) + ret = d2i_AutoPrivateKey_ex(NULL, &p_copy, len, libctx, propq); + OPENSSL_free(p); + return ret; + } + +#ifndef OPENSSL_NO_CMS + if (ts == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); + return NULL; + } + if ((bio = CMS_EnvelopedData_decrypt(encryptedKey->value.envelopedData, + NULL, pkey, cert, secret, 0, + libctx, propq)) == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY); + goto end; + } + sd = ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_SignedData), bio, NULL); + if (sd == NULL) + goto end; + + if ((purpose_id = X509_PURPOSE_get_by_sname(SN_cmKGA)) < 0) { + purpose_id = X509_PURPOSE_get_unused_id(libctx); + if (!X509_PURPOSE_add(purpose_id, X509_TRUST_COMPAT, 0, check_cmKGA, + LN_cmKGA, SN_cmKGA, NULL)) + goto end; + } + if ((vpm = X509_STORE_get0_param(ts)) == NULL) + goto end; + + /* temporarily override X509_PURPOSE_SMIME_SIGN: */ + bak_purpose_id = X509_VERIFY_PARAM_get_purpose(vpm); + if (!X509_STORE_set_purpose(ts, purpose_id)) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE); + goto end; + } + + pkey_bio = CMS_SignedData_verify(sd, NULL, NULL /* scerts */, ts, + extra, NULL, 0, libctx, propq); + + if (!X509_STORE_set_purpose(ts, bak_purpose_id)) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE); + goto end; + } + + if (pkey_bio == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY); + goto end; + } + + /* unpack AsymmetricKeyPackage */ + if ((ret = d2i_PrivateKey_ex_bio(pkey_bio, NULL, libctx, propq)) == NULL) + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY); + + end: + CMS_SignedData_free(sd); + BIO_free(bio); + BIO_free(pkey_bio); + return ret; +#else + /* prevent warning on unused parameters: */ + ((void)ts, (void)extra, (void)cert, (void)secret); + ERR_raise(ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED); + return NULL; +#endif /* OPENSSL_NO_CMS */ +} + +unsigned char +*OSSL_CRMF_ENCRYPTEDVALUE_decrypt(const OSSL_CRMF_ENCRYPTEDVALUE *enc, + OSSL_LIB_CTX *libctx, const char *propq, + EVP_PKEY *pkey, int *outlen) { - X509 *cert = NULL; /* decrypted certificate */ EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */ unsigned char *ek = NULL; /* decrypted symmetric encryption key */ size_t eksize = 0; /* size of decrypted symmetric encryption key */ EVP_CIPHER *cipher = NULL; /* used cipher */ int cikeysize = 0; /* key size from cipher */ unsigned char *iv = NULL; /* initial vector for symmetric encryption */ - unsigned char *outbuf = NULL; /* decryption output buffer */ - const unsigned char *p = NULL; /* needed for decoding ASN1 */ - int n, outlen = 0; + unsigned char *out = NULL; /* decryption output buffer */ + int n, ret = 0; EVP_PKEY_CTX *pkctx = NULL; /* private key context */ char name[OSSL_MAX_NAME_SIZE]; - if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL - || ecert->encValue == NULL || pkey == NULL) { + if (outlen == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); + return NULL; + } + *outlen = 0; + if (enc == NULL || enc->symmAlg == NULL || enc->encSymmKey == NULL + || enc->encValue == NULL || pkey == NULL) { ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT); return NULL; } /* select symmetric cipher based on algorithm given in message */ - OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0); - + OBJ_obj2txt(name, sizeof(name), enc->symmAlg->algorithm, 0); (void)ERR_set_mark(); - cipher = EVP_CIPHER_fetch(NULL, name, NULL); - + cipher = EVP_CIPHER_fetch(libctx, name, propq); if (cipher == NULL) - cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name); - + cipher = (EVP_CIPHER *)EVP_get_cipherbyobj(enc->symmAlg->algorithm); if (cipher == NULL) { (void)ERR_clear_last_mark(); ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER); @@ -649,7 +806,7 @@ X509 /* first the symmetric key needs to be decrypted */ pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq); if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx) > 0) { - ASN1_BIT_STRING *encKey = ecert->encSymmKey; + ASN1_BIT_STRING *encKey = enc->encSymmKey; size_t failure; int retval; @@ -657,13 +814,12 @@ X509 encKey->data, encKey->length) <= 0 || (ek = OPENSSL_malloc(eksize)) == NULL) goto end; - retval = EVP_PKEY_decrypt(pkctx, ek, &eksize, - encKey->data, encKey->length); - ERR_clear_error(); /* error state may have sensitive information */ + retval = EVP_PKEY_decrypt(pkctx, ek, &eksize, encKey->data, encKey->length); failure = ~constant_time_is_zero_s(constant_time_msb(retval) | constant_time_is_zero(retval)); failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize); if (failure) { + ERR_clear_error(); /* error state may have sensitive information */ ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY); goto end; } @@ -672,44 +828,118 @@ X509 } if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL) goto end; - if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv, + if (ASN1_TYPE_get_octetstring(enc->symmAlg->parameter, iv, EVP_CIPHER_get_iv_length(cipher)) != EVP_CIPHER_get_iv_length(cipher)) { ERR_raise(ERR_LIB_CRMF, CRMF_R_MALFORMED_IV); goto end; } - /* - * d2i_X509 changes the given pointer, so use p for decoding the message and - * keep the original pointer in outbuf so the memory can be freed later - */ - if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length + - EVP_CIPHER_get_block_size(cipher))) == NULL + if ((out = OPENSSL_malloc(enc->encValue->length + + EVP_CIPHER_get_block_size(cipher))) == NULL || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL) goto end; EVP_CIPHER_CTX_set_padding(evp_ctx, 0); if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv) - || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen, - ecert->encValue->data, - ecert->encValue->length) - || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) { - ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE); + || !EVP_DecryptUpdate(evp_ctx, out, outlen, + enc->encValue->data, + enc->encValue->length) + || !EVP_DecryptFinal(evp_ctx, out + *outlen, &n)) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE); goto end; } - outlen += n; + *outlen += n; + ret = 1; - /* convert decrypted certificate from DER to internal ASN.1 structure */ - if ((cert = X509_new_ex(libctx, propq)) == NULL) - goto end; - if (d2i_X509(&cert, &p, outlen) == NULL) - ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE); end: EVP_PKEY_CTX_free(pkctx); - OPENSSL_free(outbuf); EVP_CIPHER_CTX_free(evp_ctx); EVP_CIPHER_free(cipher); OPENSSL_clear_free(ek, eksize); OPENSSL_free(iv); + if (ret) + return out; + OPENSSL_free(out); + return NULL; +} + +/* + * Decrypts the certificate in the given encryptedValue using private key pkey. + * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2. + * + * returns a pointer to the decrypted certificate + * returns NULL on error or if no certificate available + */ +X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert, + OSSL_LIB_CTX *libctx, const char *propq, + EVP_PKEY *pkey) +{ + unsigned char *buf = NULL; + const unsigned char *p; + int len; + X509 *cert = NULL; + + buf = OSSL_CRMF_ENCRYPTEDVALUE_decrypt(ecert, libctx, propq, pkey, &len); + if ((p = buf) == NULL || (cert = X509_new_ex(libctx, propq)) == NULL) + goto end; + + if (d2i_X509(&cert, &p, len) == NULL) { + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE); + X509_free(cert); + cert = NULL; + } + + end: + OPENSSL_free(buf); return cert; } +/*- + * Decrypts the certificate in the given encryptedKey using private key pkey. + * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2. + * + * returns a pointer to the decrypted certificate + * returns NULL on error or if no certificate available + */ +X509 *OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(const OSSL_CRMF_ENCRYPTEDKEY *ecert, + OSSL_LIB_CTX *libctx, const char *propq, + EVP_PKEY *pkey, unsigned int flags) +{ +#ifndef OPENSSL_NO_CMS + BIO *bio; + X509 *cert = NULL; +#endif + + if (ecert->type != OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA) + return OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(ecert->value.encryptedValue, + libctx, propq, pkey); +#ifndef OPENSSL_NO_CMS + bio = CMS_EnvelopedData_decrypt(ecert->value.envelopedData, NULL, + pkey, NULL /* cert */, NULL, flags, + libctx, propq); + if (bio == NULL) + return NULL; + cert = d2i_X509_bio(bio, NULL); + if (cert == NULL) + ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE); + BIO_free(bio); + return cert; +#else + (void)flags; /* prevent warning on unused parameter */ + ERR_raise(ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED); + return NULL; +#endif /* OPENSSL_NO_CMS */ +} + +#ifndef OPENSSL_NO_CMS +OSSL_CRMF_ENCRYPTEDKEY *OSSL_CRMF_ENCRYPTEDKEY_init_envdata(CMS_EnvelopedData *envdata) +{ + OSSL_CRMF_ENCRYPTEDKEY *ek = OSSL_CRMF_ENCRYPTEDKEY_new(); + + if (ek == NULL) + return NULL; + ek->type = OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA; + ek->value.envelopedData = envdata; + return ek; +} +#endif diff --git a/crypto/crmf/crmf_local.h b/crypto/crmf/crmf_local.h index 3b8c3701b54d..1cda2cb39eb5 100644 --- a/crypto/crmf/crmf_local.h +++ b/crypto/crmf/crmf_local.h @@ -1,5 +1,5 @@ /*- - * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright Nokia 2007-2019 * Copyright Siemens AG 2015-2019 * @@ -15,7 +15,9 @@ # define OSSL_CRYPTO_CRMF_LOCAL_H # include +# include /* for CMS_EnvelopedData and CMS_SignedData */ # include +# include "internal/crmf.h" /* for ossl_crmf_attributetypeandvalue_st */ /* explicit #includes not strictly needed since implied by the above: */ # include @@ -51,6 +53,25 @@ struct ossl_crmf_encryptedvalue_st { ASN1_BIT_STRING *encValue; } /* OSSL_CRMF_ENCRYPTEDVALUE */; +/* + * EncryptedKey ::= CHOICE { + * encryptedValue EncryptedValue, -- Deprecated + * envelopedData [0] EnvelopedData } + * -- The encrypted private key MUST be placed in the envelopedData + * -- encryptedContentInfo encryptedContent OCTET STRING. + */ +# define OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA 1 + +struct ossl_crmf_encryptedkey_st { + int type; + union { + OSSL_CRMF_ENCRYPTEDVALUE *encryptedValue; /* 0 */ /* Deprecated */ +# ifndef OPENSSL_NO_CMS + CMS_EnvelopedData *envelopedData; /* 1 */ +# endif + } value; +} /* OSSL_CRMF_ENCRYPTEDKEY */; + /*- * Attributes ::= SET OF Attribute * => X509_ATTRIBUTE @@ -126,7 +147,6 @@ struct ossl_crmf_singlepubinfo_st { DEFINE_STACK_OF(OSSL_CRMF_SINGLEPUBINFO) typedef STACK_OF(OSSL_CRMF_SINGLEPUBINFO) OSSL_CRMF_PUBINFOS; - /*- * PKIPublicationInfo ::= SEQUENCE { * action INTEGER { @@ -189,6 +209,7 @@ typedef struct ossl_crmf_popoprivkey_st { ASN1_BIT_STRING *dhMAC; /* 2 */ /* Deprecated */ OSSL_CRMF_PKMACVALUE *agreeMAC; /* 3 */ ASN1_NULL *encryptedKey; /* 4 */ + /* When supported, ASN1_NULL needs to be replaced by CMS_ENVELOPEDDATA */ } value; } OSSL_CRMF_POPOPRIVKEY; DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_POPOPRIVKEY) @@ -330,42 +351,11 @@ struct ossl_crmf_certtemplate_st { struct ossl_crmf_certrequest_st { ASN1_INTEGER *certReqId; OSSL_CRMF_CERTTEMPLATE *certTemplate; - STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) *controls; + STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE /* Controls expanded */) *controls; } /* OSSL_CRMF_CERTREQUEST */; DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST) DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST) -struct ossl_crmf_attributetypeandvalue_st { - ASN1_OBJECT *type; - union { - /* NID_id_regCtrl_regToken */ - ASN1_UTF8STRING *regToken; - - /* NID_id_regCtrl_authenticator */ - ASN1_UTF8STRING *authenticator; - - /* NID_id_regCtrl_pkiPublicationInfo */ - OSSL_CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo; - - /* NID_id_regCtrl_oldCertID */ - OSSL_CRMF_CERTID *oldCertID; - - /* NID_id_regCtrl_protocolEncrKey */ - X509_PUBKEY *protocolEncrKey; - - /* NID_id_regInfo_utf8Pairs */ - ASN1_UTF8STRING *utf8Pairs; - - /* NID_id_regInfo_certReq */ - OSSL_CRMF_CERTREQUEST *certReq; - - ASN1_TYPE *other; - } value; -} /* OSSL_CRMF_ATTRIBUTETYPEANDVALUE */; -DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) -DEFINE_STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) -DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) - /*- * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg * CertReqMsg ::= SEQUENCE { diff --git a/crypto/crmf/crmf_pbm.c b/crypto/crmf/crmf_pbm.c index 88a8480cf73a..d4c7af38cb0f 100644 --- a/crypto/crmf/crmf_pbm.c +++ b/crypto/crmf/crmf_pbm.c @@ -11,7 +11,6 @@ * CRMF implementation by Martin Peylo, Miikka Viljanen, and David von Oheimb. */ - #include #include @@ -22,7 +21,6 @@ #include #include #include -#include #include #include @@ -125,6 +123,7 @@ OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(OSSL_LIB_CTX *libctx, size_t slen, * |outlen| if not NULL, will set variable to the length of the mac on success * returns 1 on success, 0 on error */ +/* could be combined with other MAC calculations in the library */ int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq, const OSSL_CRMF_PBMPARAMETER *pbmp, const unsigned char *msg, size_t msglen, @@ -201,10 +200,11 @@ int OSSL_CRMF_pbm_new(OSSL_LIB_CTX *libctx, const char *propq, if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL) || OBJ_obj2txt(hmac_mdname, sizeof(hmac_mdname), - OBJ_nid2obj(hmac_md_nid), 0) <= 0) { + OBJ_nid2obj(hmac_md_nid), 0) <= 0) { ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_ALGORITHM); goto err; } + /* could be generalized to allow non-HMAC: */ if (EVP_Q_mac(libctx, "HMAC", propq, hmac_mdname, NULL, basekey, bklen, msg, msglen, mac_res, EVP_MAX_MD_SIZE, outlen) == NULL) goto err; diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c index 6e73b8352cac..6c1947943879 100644 --- a/crypto/cryptlib.c +++ b/crypto/cryptlib.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-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 @@ -8,11 +8,11 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "crypto/cryptlib.h" #include -#if defined(_WIN32) +#if defined(_WIN32) && !defined(OPENSSL_SYS_UEFI) # include # include # ifdef __WATCOMC__ @@ -256,7 +256,7 @@ void OPENSSL_die(const char *message, const char *file, int line) { OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", file, line, message); -#if !defined(_WIN32) +#if !defined(_WIN32) || defined(OPENSSL_SYS_UEFI) abort(); #else /* diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c index d3f783962aec..2535442063b5 100644 --- a/crypto/ct/ct_b64.c +++ b/crypto/ct/ct_b64.c @@ -34,10 +34,8 @@ static int ct_base64_decode(const char *in, unsigned char **out) outlen = (inlen / 4) * 3; outbuf = OPENSSL_malloc(outlen); - if (outbuf == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (outbuf == NULL) goto err; - } outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); if (outlen < 0) { @@ -71,7 +69,7 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, int declen; if (sct == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CT, ERR_R_CT_LIB); return NULL; } diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c index d19dda2cd2f2..95084dc76fcd 100644 --- a/crypto/ct/ct_log.c +++ b/crypto/ct/ct_log.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -62,9 +62,6 @@ static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void) { CTLOG_STORE_LOAD_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); - return ctx; } @@ -104,23 +101,19 @@ CTLOG_STORE *CTLOG_STORE_new_ex(OSSL_LIB_CTX *libctx, const char *propq) { CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->libctx = libctx; if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); - if (ret->propq == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ret->propq == NULL) goto err; - } } ret->logs = sk_CTLOG_new_null(); if (ret->logs == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CT, ERR_R_CRYPTO_LIB); goto err; } @@ -196,7 +189,7 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len, tmp = OPENSSL_strndup(log_name, log_name_len); if (tmp == NULL) - goto mem_err; + return -1; ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp); OPENSSL_free(tmp); @@ -212,14 +205,11 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len, } if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) { - goto mem_err; + CTLOG_free(ct_log); + ERR_raise(ERR_LIB_CT, ERR_R_CRYPTO_LIB); + return -1; } return 1; - -mem_err: - CTLOG_free(ct_log); - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); - return -1; } int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file) @@ -269,25 +259,19 @@ CTLOG *CTLOG_new_ex(EVP_PKEY *public_key, const char *name, OSSL_LIB_CTX *libctx { CTLOG *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->libctx = libctx; if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); - if (ret->propq == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ret->propq == NULL) goto err; - } } ret->name = OPENSSL_strdup(name); - if (ret->name == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ret->name == NULL) goto err; - } if (ct_v1_log_id_from_pkey(ret, public_key) != 1) goto err; diff --git a/crypto/ct/ct_oct.c b/crypto/ct/ct_oct.c index 72a43374797c..145b277109ef 100644 --- a/crypto/ct/ct_oct.c +++ b/crypto/ct/ct_oct.c @@ -178,10 +178,8 @@ int i2o_SCT_signature(const SCT *sct, unsigned char **out) *out += len; } else { pstart = p = OPENSSL_malloc(len); - if (p == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (p == NULL) goto err; - } *out = p; } @@ -225,10 +223,8 @@ int i2o_SCT(const SCT *sct, unsigned char **out) *out += len; } else { pstart = p = OPENSSL_malloc(len); - if (p == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (p == NULL) goto err; - } *out = p; } @@ -330,10 +326,8 @@ int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp) ERR_raise(ERR_LIB_CT, CT_R_SCT_LIST_INVALID); return -1; } - if ((*pp = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if ((*pp = OPENSSL_malloc(len)) == NULL) return -1; - } is_pp_new = 1; } p = *pp + 2; diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c index 80a8baabe163..725be7ce2ae0 100644 --- a/crypto/ct/ct_policy.c +++ b/crypto/ct/ct_policy.c @@ -13,7 +13,7 @@ #include #include -#include +#include "internal/time.h" #include "ct_local.h" @@ -29,25 +29,23 @@ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq) { CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX)); + OSSL_TIME now; - if (ctx == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (ctx == NULL) return NULL; - } ctx->libctx = libctx; if (propq != NULL) { ctx->propq = OPENSSL_strdup(propq); if (ctx->propq == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); OPENSSL_free(ctx); return NULL; } } - /* time(NULL) shouldn't ever fail, so don't bother checking for -1. */ - ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) * - 1000; + now = ossl_time_add(ossl_time_now(), + ossl_seconds2time(SCT_CLOCK_DRIFT_TOLERANCE)); + ctx->epoch_time_in_ms = ossl_time2ms(now); return ctx; } diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c index 10a67ed6d68d..ec87d02309f3 100644 --- a/crypto/ct/ct_sct.c +++ b/crypto/ct/ct_sct.c @@ -23,10 +23,8 @@ SCT *SCT_new(void) { SCT *sct = OPENSSL_zalloc(sizeof(*sct)); - if (sct == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (sct == NULL) return NULL; - } sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET; sct->version = SCT_VERSION_NOT_SET; @@ -105,10 +103,8 @@ int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, size_t log_id_len) if (log_id != NULL && log_id_len > 0) { sct->log_id = OPENSSL_memdup(log_id, log_id_len); - if (sct->log_id == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (sct->log_id == NULL) return 0; - } sct->log_id_len = log_id_len; } return 1; @@ -157,10 +153,8 @@ int SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len) if (ext != NULL && ext_len > 0) { sct->ext = OPENSSL_memdup(ext, ext_len); - if (sct->ext == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (sct->ext == NULL) return 0; - } sct->ext_len = ext_len; } return 1; @@ -183,10 +177,8 @@ int SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len) if (sig != NULL && sig_len > 0) { sct->sig = OPENSSL_memdup(sig, sig_len); - if (sct->sig == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (sct->sig == NULL) return 0; - } sct->sig_len = sig_len; } return 1; diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c index 8653684814ee..effd724a0af3 100644 --- a/crypto/ct/ct_sct_ctx.c +++ b/crypto/ct/ct_sct_ctx.c @@ -24,16 +24,13 @@ SCT_CTX *SCT_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) { SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx)); - if (sctx == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); + if (sctx == NULL) return NULL; - } sctx->libctx = libctx; if (propq != NULL) { sctx->propq = OPENSSL_strdup(propq); if (sctx->propq == NULL) { - ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE); OPENSSL_free(sctx); return NULL; } diff --git a/crypto/ctype.c b/crypto/ctype.c index de2e836ff783..48b3025ba539 100644 --- a/crypto/ctype.c +++ b/crypto/ctype.c @@ -1,5 +1,5 @@ /* - * 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 @@ -258,7 +258,7 @@ int ossl_ctype_check(int c, unsigned int mask) } /* - * Implement some of the simplier functions directly to avoid the overhead of + * Implement some of the simpler functions directly to avoid the overhead of * accessing memory via ctype_char_map[]. */ diff --git a/crypto/cversion.c b/crypto/cversion.c index 530b0e805e8d..eaa6ac0d656d 100644 --- a/crypto/cversion.c +++ b/crypto/cversion.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,12 @@ * https://www.openssl.org/source/license.html */ +#include +#include +#include "internal/e_os.h" #include "internal/cryptlib.h" +#include "internal/common.h" +#include "internal/thread_once.h" #include "buildinf.h" @@ -43,8 +48,41 @@ const char *OPENSSL_version_build_metadata(void) extern char ossl_cpu_info_str[]; +#if defined(_WIN32) && defined(OSSL_WINCTX) +/* size: MAX_PATH + sizeof("OPENSSLDIR: \"\"") */ +static char openssldir[MAX_PATH + 15]; + +/* size: MAX_PATH + sizeof("ENGINESDIR: \"\"") */ +static char enginesdir[MAX_PATH + 15]; + +/* size: MAX_PATH + sizeof("MODULESDIR: \"\"") */ +static char modulesdir[MAX_PATH + 15]; + +static CRYPTO_ONCE version_strings_once = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(version_strings_setup) +{ + BIO_snprintf(openssldir, sizeof(openssldir), "OPENSSLDIR: \"%s\"", + ossl_get_openssldir()); + BIO_snprintf(enginesdir, sizeof(enginesdir), "ENGINESDIR: \"%s\"", + ossl_get_enginesdir()); + BIO_snprintf(modulesdir, sizeof(modulesdir), "MODULESDIR: \"%s\"", + ossl_get_modulesdir()); + return 1; +} + +# define TOSTR(x) #x +# define OSSL_WINCTX_STRING "OSSL_WINCTX: \"" TOSTR(OSSL_WINCTX) "\"" + +#endif + const char *OpenSSL_version(int t) { +#if defined(_WIN32) && defined(OSSL_WINCTX) + /* Cannot really fail but we would return empty strings anyway */ + (void)RUN_ONCE(&version_strings_once, version_strings_setup); +#endif + switch (t) { case OPENSSL_VERSION: return OPENSSL_VERSION_TEXT; @@ -58,29 +96,44 @@ const char *OpenSSL_version(int t) return compiler_flags; case OPENSSL_PLATFORM: return PLATFORM; +#if defined(_WIN32) && defined(OSSL_WINCTX) case OPENSSL_DIR: -#ifdef OPENSSLDIR - return "OPENSSLDIR: \"" OPENSSLDIR "\""; -#else - return "OPENSSLDIR: N/A"; -#endif + return openssldir; case OPENSSL_ENGINES_DIR: -#ifdef ENGINESDIR - return "ENGINESDIR: \"" ENGINESDIR "\""; -#else - return "ENGINESDIR: N/A"; -#endif + return enginesdir; case OPENSSL_MODULES_DIR: -#ifdef MODULESDIR - return "MODULESDIR: \"" MODULESDIR "\""; + return modulesdir; #else + case OPENSSL_DIR: +# ifdef OPENSSLDIR + return "OPENSSLDIR: \"" OPENSSLDIR "\""; +# else + return "OPENSSLDIR: N/A"; +# endif + case OPENSSL_ENGINES_DIR: +# ifdef ENGINESDIR + return "ENGINESDIR: \"" ENGINESDIR "\""; +# else + return "ENGINESDIR: N/A"; +# endif + case OPENSSL_MODULES_DIR: +# ifdef MODULESDIR + return "MODULESDIR: \"" MODULESDIR "\""; +# else return "MODULESDIR: N/A"; +# endif #endif case OPENSSL_CPU_INFO: if (OPENSSL_info(OPENSSL_INFO_CPU_SETTINGS) != NULL) return ossl_cpu_info_str; else return "CPUINFO: N/A"; + case OPENSSL_WINCTX: +#if defined(_WIN32) && defined(OSSL_WINCTX) + return OSSL_WINCTX_STRING; +#else + return "OSSL_WINCTX: Undefined"; +#endif } return "not available"; } diff --git a/crypto/der_writer.c b/crypto/der_writer.c index 2ab7480a6749..bd330785f903 100644 --- a/crypto/der_writer.c +++ b/crypto/der_writer.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/des/cfb_enc.c b/crypto/des/cfb_enc.c index 30458d50a12a..51c4dd2ab916 100644 --- a/crypto/des/cfb_enc.c +++ b/crypto/des/cfb_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,7 +13,7 @@ */ #include "internal/deprecated.h" -#include "e_os.h" +#include "internal/e_os.h" #include "des_local.h" #include diff --git a/crypto/des/des_local.h b/crypto/des/des_local.h index f888cb800169..d43f2c87374d 100644 --- a/crypto/des/des_local.h +++ b/crypto/des/des_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -37,19 +37,19 @@ l1=l2=0; \ switch (n) { \ case 8: l2 =((DES_LONG)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((DES_LONG)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((DES_LONG)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((DES_LONG)(*(--(c)))); \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((DES_LONG)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((DES_LONG)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((DES_LONG)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((DES_LONG)(*(--(c)))); \ } \ } @@ -59,39 +59,24 @@ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ *((c)++)=(unsigned char)(((l)>>24L)&0xff)) -/* - * replacements for htonl and ntohl since I have no idea what to do when - * faced with machines with 8 byte longs. - */ - -# define n2l(c,l) (l =((DES_LONG)(*((c)++)))<<24L, \ - l|=((DES_LONG)(*((c)++)))<<16L, \ - l|=((DES_LONG)(*((c)++)))<< 8L, \ - l|=((DES_LONG)(*((c)++)))) - -# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - /* NOTE - c is not incremented as per l2c */ # define l2cn(l1,l2,c,n) { \ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } @@ -109,6 +94,19 @@ : "cc"); \ ret; \ }) +# elif defined(__riscv_zbb) || defined(__riscv_zbkb) +# if __riscv_xlen == 64 +# define ROTATE(x, n) ({ register unsigned int ret; \ + asm ("roriw %0, %1, %2" \ + : "=r"(ret) \ + : "r"(x), "i"(n)); ret; }) +# endif +# if __riscv_xlen == 32 +# define ROTATE(x, n) ({ register unsigned int ret; \ + asm ("rori %0, %1, %2" \ + : "=r"(ret) \ + : "r"(x), "i"(n)); ret; }) +# endif # endif # endif # ifndef ROTATE diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c index adcfb7f12451..5c958cdbb6aa 100644 --- a/crypto/des/set_key.c +++ b/crypto/des/set_key.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -324,8 +324,9 @@ int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule) void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule) { - static const int shifts2[16] = - { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 }; + static const int shifts2[16] = { + 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0 + }; register DES_LONG c, d, t, s, t2; register const unsigned char *in; register DES_LONG *k; diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 8430872a9ab6..80e1612256be 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -121,12 +121,12 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) str = ASN1_STRING_new(); if (str == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB); goto err; } str->length = i2d_dhp(pkey, dh, &str->data); if (str->length <= 0) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB); goto err; } ptype = V_ASN1_SEQUENCE; @@ -140,7 +140,7 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) ASN1_INTEGER_free(pub_key); if (penclen <= 0) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB); goto err; } @@ -184,13 +184,13 @@ static int dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) params = ASN1_STRING_new(); if (params == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB); goto err; } params->length = i2d_dhp(pkey, pkey->pkey.dh, ¶ms->data); if (params->length <= 0) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_ASN1_LIB); goto err; } params->type = V_ASN1_SEQUENCE; @@ -514,7 +514,7 @@ static int dh_pkey_import_from_type(const OSSL_PARAM params[], void *vpctx, DH *dh = ossl_dh_new_ex(pctx->libctx); if (dh == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_DH_LIB); return 0; } DH_clear_flags(dh, DH_FLAG_TYPE_MASK); diff --git a/crypto/dh/dh_backend.c b/crypto/dh/dh_backend.c index 726843fd30cd..1aaa88dacae1 100644 --- a/crypto/dh/dh_backend.c +++ b/crypto/dh/dh_backend.c @@ -1,5 +1,5 @@ /* - * 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 @@ -31,13 +31,7 @@ static int dh_ffc_params_fromdata(DH *dh, const OSSL_PARAM params[]) { int ret; - FFC_PARAMS *ffc; - - if (dh == NULL) - return 0; - ffc = ossl_dh_get0_params(dh); - if (ffc == NULL) - return 0; + FFC_PARAMS *ffc = ossl_dh_get0_params(dh); ret = ossl_ffc_params_fromdata(ffc, params); if (ret) diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index e20eb62081c5..ae23f61839ea 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -351,7 +351,7 @@ int ossl_dh_check_pairwise(const DH *dh) /* recalculate the public key = (g ^ priv) mod p */ if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key)) goto err; - /* check it matches the existing pubic_key */ + /* check it matches the existing public_key */ ret = BN_cmp(pub_key, dh->pub_key) == 0; err: BN_free(pub_key); diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c index f76ac0dd1463..4d6d2acd98a8 100644 --- a/crypto/dh/dh_err.c +++ b/crypto/dh/dh_err.c @@ -42,6 +42,7 @@ static const ERR_STRING_DATA DH_str_reasons[] = { "invalid parameter nid"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_PUBKEY), "invalid public key"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_SECRET), "invalid secret"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_INVALID_SIZE), "invalid size"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_KEYS_NOT_SET), "keys not set"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_MISSING_PUBKEY), "missing pubkey"}, diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c index aec6b853169a..b73bfb7f3b8d 100644 --- a/crypto/dh/dh_gen.c +++ b/crypto/dh/dh_gen.c @@ -28,6 +28,7 @@ #include #include #include "crypto/dh.h" +#include "crypto/security_bits.h" #include "dh_local.h" #ifndef FIPS_MODULE @@ -219,6 +220,9 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, goto err; if (!BN_set_word(ret->params.g, g)) goto err; + /* We are using safe prime p, set key length equivalent to RFC 7919 */ + ret->length = (2 * ossl_ifc_ffc_compute_security_bits(prime_len) + + 24) / 25 * 25; ret->dirty_cnt++; ok = 1; err: diff --git a/crypto/dh/dh_kdf.c b/crypto/dh/dh_kdf.c index 6e99466e60b3..64f8064d9dda 100644 --- a/crypto/dh/dh_kdf.c +++ b/crypto/dh/dh_kdf.c @@ -13,8 +13,7 @@ */ #include "internal/deprecated.h" -#include "e_os.h" -#include "e_os.h" +#include "internal/e_os.h" #include #include #include diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index afc49f5cdc87..7132b9b68e53 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -190,7 +190,11 @@ static int dh_bn_mod_exp(const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) { +#ifdef S390X_MOD_EXP + return s390x_mod_exp(r, a, p, m, ctx, m_ctx); +#else return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); +#endif } static int dh_init(DH *dh) @@ -429,14 +433,15 @@ size_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf_out, size_t size, if (!alloc) { if (size >= (size_t)p_size) pbuf = *pbuf_out; + if (pbuf == NULL) + ERR_raise(ERR_LIB_DH, DH_R_INVALID_SIZE); } else { pbuf = OPENSSL_malloc(p_size); } - if (pbuf == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + /* Errors raised above */ + if (pbuf == NULL) return 0; - } /* * As per Section 4.2.8.1 of RFC 8446 left pad public * key with zeros to the size of p diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c index 5577413e1e0c..93e08b3f8c71 100644 --- a/crypto/dh/dh_lib.c +++ b/crypto/dh/dh_lib.c @@ -75,15 +75,18 @@ static DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx) { DH *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + if (ret == NULL) + return NULL; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ERR_raise(ERR_LIB_DH, ERR_R_CRYPTO_LIB); + OPENSSL_free(ret); return NULL; } - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { + CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; } @@ -137,8 +140,8 @@ void DH_free(DH *r) if (r == NULL) return; - CRYPTO_DOWN_REF(&r->references, &i, r->lock); - REF_PRINT_COUNT("DH", r); + CRYPTO_DOWN_REF(&r->references, &i); + REF_PRINT_COUNT("DH", i, r); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -153,6 +156,7 @@ void DH_free(DH *r) #endif CRYPTO_THREAD_lock_free(r->lock); + CRYPTO_FREE_REF(&r->references); ossl_ffc_params_cleanup(&r->params); BN_clear_free(r->pub_key); @@ -164,10 +168,10 @@ int DH_up_ref(DH *r) { int i; - if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; - REF_PRINT_COUNT("DH", r); + REF_PRINT_COUNT("DH", i, r); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } diff --git a/crypto/dh/dh_meth.c b/crypto/dh/dh_meth.c index 5c15cd2b8cc2..f5652e07852e 100644 --- a/crypto/dh/dh_meth.c +++ b/crypto/dh/dh_meth.c @@ -31,7 +31,6 @@ DH_METHOD *DH_meth_new(const char *name, int flags) OPENSSL_free(dhm); } - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); return NULL; } @@ -57,7 +56,6 @@ DH_METHOD *DH_meth_dup(const DH_METHOD *dhm) OPENSSL_free(ret); } - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); return NULL; } @@ -70,10 +68,8 @@ int DH_meth_set1_name(DH_METHOD *dhm, const char *name) { char *tmpname = OPENSSL_strdup(name); - if (tmpname == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + if (tmpname == NULL) return 0; - } OPENSSL_free(dhm->name); dhm->name = tmpname; diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index f201eede0df4..c11ada98267c 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -55,10 +55,8 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx) { DH_PKEY_CTX *dctx; - if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) return 0; - } dctx->prime_len = 2048; dctx->subprime_len = -1; dctx->generator = 2; @@ -445,10 +443,8 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, ret = 0; if ((Zlen = DH_size(dh)) <= 0) return 0; - if ((Z = OPENSSL_malloc(Zlen)) == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + if ((Z = OPENSSL_malloc(Zlen)) == NULL) return 0; - } if (DH_compute_key_padded(Z, dhpubbn, dh) <= 0) goto err; if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid, diff --git a/crypto/dllmain.c b/crypto/dllmain.c index 48c0cd31227a..96198a939737 100644 --- a/crypto/dllmain.c +++ b/crypto/dllmain.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "crypto/cryptlib.h" #if defined(_WIN32) || defined(__CYGWIN__) diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 482b9e1e0aa7..169c1bb677a5 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -54,7 +54,7 @@ static int dsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) } else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF)) { if ((dsa = DSA_new()) == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_DSA_LIB); goto err; } } else { @@ -101,12 +101,12 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) && dsa->params.g != NULL) { str = ASN1_STRING_new(); if (str == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } str->length = i2d_DSAparams(dsa, &str->data); if (str->length <= 0) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } ptype = V_ASN1_SEQUENCE; @@ -116,7 +116,7 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) pubint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL); if (pubint == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } @@ -124,7 +124,7 @@ static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) ASN1_INTEGER_free(pubint); if (penclen <= 0) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } @@ -175,13 +175,13 @@ static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) params = ASN1_STRING_new(); if (params == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } params->length = i2d_DSAparams(pkey->pkey.dsa, ¶ms->data); if (params->length <= 0) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_ASN1_LIB); goto err; } params->type = V_ASN1_SEQUENCE; @@ -483,7 +483,7 @@ static int dsa_pkey_import_from(const OSSL_PARAM params[], void *vpctx) DSA *dsa = ossl_dsa_new(pctx->libctx); if (dsa == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_DSA_LIB); return 0; } @@ -516,26 +516,24 @@ static int dsa_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) /* NB these are sorted in pkey_id order, lowest first */ -const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[5] = { - - { - EVP_PKEY_DSA2, - EVP_PKEY_DSA, - ASN1_PKEY_ALIAS}, +const EVP_PKEY_ASN1_METHOD ossl_dsa_asn1_meths[4] = { + /* This aliases NID_dsa with NID_dsa_2 */ { EVP_PKEY_DSA1, EVP_PKEY_DSA, ASN1_PKEY_ALIAS}, + /* This aliases NID_dsaWithSHA with NID_dsaWithSHA_2 */ { EVP_PKEY_DSA4, - EVP_PKEY_DSA, + EVP_PKEY_DSA2, ASN1_PKEY_ALIAS}, + /* This aliases NID_dsaWithSHA with NID_dsaWithSHA1 */ { EVP_PKEY_DSA3, - EVP_PKEY_DSA, + EVP_PKEY_DSA2, ASN1_PKEY_ALIAS}, { diff --git a/crypto/dsa/dsa_backend.c b/crypto/dsa/dsa_backend.c index 389df304bdce..8bd4b8ad7e0e 100644 --- a/crypto/dsa/dsa_backend.c +++ b/crypto/dsa/dsa_backend.c @@ -158,11 +158,11 @@ DSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, } /* Calculate public key */ if ((dsa_pubkey = BN_new()) == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB); goto dsaerr; } if ((ctx = BN_CTX_new()) == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSA, ERR_R_BN_LIB); goto dsaerr; } diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c index 801b932d8724..e1375dfad9c0 100644 --- a/crypto/dsa/dsa_check.c +++ b/crypto/dsa/dsa_check.c @@ -124,7 +124,7 @@ int ossl_dsa_check_pairwise(const DSA *dsa) /* recalculate the public key = (g ^ priv) mod p */ if (!ossl_dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key)) goto err; - /* check it matches the existing pubic_key */ + /* check it matches the existing public_key */ ret = BN_cmp(pub_key, dsa->pub_key) == 0; err: BN_free(pub_key); diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 1f951a9d36a9..1c2bab1714b3 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -1,5 +1,5 @@ /* - * 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 @@ -28,8 +28,7 @@ # define MIN_STRENGTH 80 #endif -static int dsa_keygen(DSA *dsa, int pairwise_test); -static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg); +static int dsa_keygen(DSA *dsa); int DSA_generate_key(DSA *dsa) { @@ -37,7 +36,7 @@ int DSA_generate_key(DSA *dsa) if (dsa->meth->dsa_keygen != NULL) return dsa->meth->dsa_keygen(dsa); #endif - return dsa_keygen(dsa, 0); + return dsa_keygen(dsa); } int ossl_dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, @@ -59,7 +58,93 @@ err: return ret; } -static int dsa_keygen(DSA *dsa, int pairwise_test) +#ifdef FIPS_MODULE +/* + * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 + * Perform a KAT by duplicating the public key generation. + * + * NOTE: This issue requires a background understanding, provided in a separate + * document; the current IG 10.3.A AC1 is insufficient regarding the PCT for + * the key agreement scenario. + * + * Currently IG 10.3.A requires PCT in the mode of use prior to use of the + * key pair, citing the PCT defined in the associated standard. For key + * agreement, the only PCT defined in SP 800-56A is that of Section 5.6.2.4: + * the comparison of the original public key to a newly calculated public key. + */ +static int dsa_keygen_knownanswer_test(DSA *dsa, BN_CTX *ctx, + OSSL_CALLBACK *cb, void *cbarg) +{ + int len, ret = 0; + OSSL_SELF_TEST *st = NULL; + unsigned char bytes[512] = {0}; + BIGNUM *pub_key2 = BN_new(); + + if (pub_key2 == NULL) + return 0; + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + goto err; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT_KAT, + OSSL_SELF_TEST_DESC_PCT_DSA); + + if (!ossl_dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key2)) + goto err; + + if (BN_num_bytes(pub_key2) > (int)sizeof(bytes)) + goto err; + len = BN_bn2bin(pub_key2, bytes); + OSSL_SELF_TEST_oncorrupt_byte(st, bytes); + if (BN_bin2bn(bytes, len, pub_key2) != NULL) + ret = !BN_cmp(dsa->pub_key, pub_key2); + +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + BN_free(pub_key2); + return ret; +} + +/* + * FIPS 140-2 IG 9.9 AS09.33 + * Perform a sign/verify operation. + */ +static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg) +{ + int ret = 0; + unsigned char dgst[16] = {0}; + unsigned int dgst_len = (unsigned int)sizeof(dgst); + DSA_SIG *sig = NULL; + OSSL_SELF_TEST *st = NULL; + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + goto err; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, + OSSL_SELF_TEST_DESC_PCT_DSA); + + sig = DSA_do_sign(dgst, (int)dgst_len, dsa); + if (sig == NULL) + goto err; + + OSSL_SELF_TEST_oncorrupt_byte(st, dgst); + + if (DSA_do_verify(dgst, dgst_len, sig, dsa) != 1) + goto err; + + ret = 1; +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + DSA_SIG_free(sig); + return ret; +} +#endif /* FIPS_MODULE */ + +static int dsa_keygen(DSA *dsa) { int ok = 0; BN_CTX *ctx = NULL; @@ -103,17 +188,15 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) dsa->priv_key = priv_key; dsa->pub_key = pub_key; -#ifdef FIPS_MODULE - pairwise_test = 1; -#endif /* FIPS_MODULE */ - ok = 1; - if (pairwise_test) { +#ifdef FIPS_MODULE + { OSSL_CALLBACK *cb = NULL; void *cbarg = NULL; OSSL_SELF_TEST_get_callback(dsa->libctx, &cb, &cbarg); - ok = dsa_keygen_pairwise_test(dsa, cb, cbarg); + ok = dsa_keygen_pairwise_test(dsa, cb, cbarg) + && dsa_keygen_knownanswer_test(dsa, ctx, cb, cbarg); if (!ok) { ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); BN_free(dsa->pub_key); @@ -124,6 +207,7 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) return ok; } } +#endif dsa->dirty_cnt++; err: @@ -135,39 +219,3 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) return ok; } - -/* - * FIPS 140-2 IG 9.9 AS09.33 - * Perform a sign/verify operation. - */ -static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg) -{ - int ret = 0; - unsigned char dgst[16] = {0}; - unsigned int dgst_len = (unsigned int)sizeof(dgst); - DSA_SIG *sig = NULL; - OSSL_SELF_TEST *st = NULL; - - st = OSSL_SELF_TEST_new(cb, cbarg); - if (st == NULL) - goto err; - - OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, - OSSL_SELF_TEST_DESC_PCT_DSA); - - sig = DSA_do_sign(dgst, (int)dgst_len, dsa); - if (sig == NULL) - goto err; - - OSSL_SELF_TEST_oncorrupt_byte(st, dgst); - - if (DSA_do_verify(dgst, dgst_len, sig, dsa) != 1) - goto err; - - ret = 1; -err: - OSSL_SELF_TEST_onend(st, ret); - OSSL_SELF_TEST_free(st); - DSA_SIG_free(sig); - return ret; -} diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c index 2ae3f8e36b26..db6e3b059b4d 100644 --- a/crypto/dsa/dsa_lib.c +++ b/crypto/dsa/dsa_lib.c @@ -134,15 +134,18 @@ static DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx) { DSA *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + if (ret == NULL) + return NULL; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ERR_raise(ERR_LIB_DSA, ERR_R_CRYPTO_LIB); + OPENSSL_free(ret); return NULL; } - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { + CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; } @@ -214,8 +217,8 @@ void DSA_free(DSA *r) if (r == NULL) return; - CRYPTO_DOWN_REF(&r->references, &i, r->lock); - REF_PRINT_COUNT("DSA", r); + CRYPTO_DOWN_REF(&r->references, &i); + REF_PRINT_COUNT("DSA", i, r); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -231,6 +234,7 @@ void DSA_free(DSA *r) #endif CRYPTO_THREAD_lock_free(r->lock); + CRYPTO_FREE_REF(&r->references); ossl_ffc_params_cleanup(&r->params); BN_clear_free(r->pub_key); @@ -242,10 +246,10 @@ int DSA_up_ref(DSA *r) { int i; - if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; - REF_PRINT_COUNT("DSA", r); + REF_PRINT_COUNT("DSA", i, r); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } @@ -349,13 +353,7 @@ FFC_PARAMS *ossl_dsa_get0_params(DSA *dsa) int ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[]) { int ret; - FFC_PARAMS *ffc; - - if (dsa == NULL) - return 0; - ffc = ossl_dsa_get0_params(dsa); - if (ffc == NULL) - return 0; + FFC_PARAMS *ffc = ossl_dsa_get0_params(dsa); ret = ossl_ffc_params_fromdata(ffc, params); if (ret) diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h index 9e33fae131ea..38cb64a82941 100644 --- a/crypto/dsa/dsa_local.h +++ b/crypto/dsa/dsa_local.h @@ -14,7 +14,7 @@ struct dsa_st { /* * This first variable is used to pick up errors where a DSA is passed - * instead of of a EVP_PKEY + * instead of an EVP_PKEY */ int pad; int32_t version; @@ -69,4 +69,6 @@ struct dsa_method { int (*dsa_keygen) (DSA *dsa); }; -DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa); +DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq); diff --git a/crypto/dsa/dsa_meth.c b/crypto/dsa/dsa_meth.c index 2f0a0bf4608e..f2b759a9dea6 100644 --- a/crypto/dsa/dsa_meth.c +++ b/crypto/dsa/dsa_meth.c @@ -32,7 +32,6 @@ DSA_METHOD *DSA_meth_new(const char *name, int flags) OPENSSL_free(dsam); } - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); return NULL; } @@ -58,7 +57,6 @@ DSA_METHOD *DSA_meth_dup(const DSA_METHOD *dsam) OPENSSL_free(ret); } - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); return NULL; } @@ -71,10 +69,8 @@ int DSA_meth_set1_name(DSA_METHOD *dsam, const char *name) { char *tmpname = OPENSSL_strdup(name); - if (tmpname == NULL) { - ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE); + if (tmpname == NULL) return 0; - } OPENSSL_free(dsam->name); dsam->name = tmpname; diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 0c18b78f7633..59b26d73696b 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -20,6 +20,7 @@ #include #include "dsa_local.h" #include +#include "internal/deterministic_nonce.h" #define MIN_DSA_SIGN_QBITS 128 #define MAX_DSA_SIGN_RETRIES 8 @@ -28,7 +29,9 @@ 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); + BIGNUM **rp, const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq); static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa); static int dsa_init(DSA *dsa); @@ -70,7 +73,9 @@ 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) +DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { BIGNUM *kinv = NULL; BIGNUM *m, *blind, *blindm, *tmp; @@ -110,7 +115,8 @@ DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa) goto err; redo: - if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen)) + if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen, + nonce_type, digestname, libctx, propq)) goto err; if (dlen > BN_num_bytes(dsa->params.q)) @@ -197,18 +203,22 @@ DSA_SIG *ossl_dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa) static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { - return ossl_dsa_do_sign_int(dgst, dlen, dsa); + return ossl_dsa_do_sign_int(dgst, dlen, dsa, + 0, NULL, NULL, NULL); } 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); + return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0, + 0, NULL, NULL, NULL); } static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, - const unsigned char *dgst, int dlen) + const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { BN_CTX *ctx = NULL; BIGNUM *k, *kinv = NULL, *r = *rp; @@ -258,14 +268,25 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, /* 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 (!ossl_bn_gen_dsa_nonce_fixed_top(k, dsa->params.q, - dsa->priv_key, dgst, - dlen, ctx)) - goto err; + if (nonce_type == 1) { +#ifndef FIPS_MODULE + if (!ossl_gen_deterministic_nonce_rfc6979(k, dsa->params.q, + dsa->priv_key, + dgst, dlen, + digestname, + libctx, propq)) +#endif + goto err; + } else { + /* + * We calculate k from SHA512(private_key + H(message) + random). + * This protects the private key from a weak PRNG. + */ + if (!ossl_bn_gen_dsa_nonce_fixed_top(k, dsa->params.q, + dsa->priv_key, dgst, + dlen, ctx)) + goto err; + } } else if (!ossl_bn_priv_rand_range_fixed_top(k, dsa->params.q, 0, ctx)) goto err; } while (ossl_bn_is_word_fixed_top(k, 0)); diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c index ba6be720a296..00ac18fdffea 100644 --- a/crypto/dsa/dsa_pmeth.c +++ b/crypto/dsa/dsa_pmeth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -78,7 +78,7 @@ static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { - int ret; + int ret, md_size; unsigned int sltmp; DSA_PKEY_CTX *dctx = ctx->data; /* @@ -88,8 +88,13 @@ static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, */ DSA *dsa = (DSA *)EVP_PKEY_get0_DSA(ctx->pkey); - if (dctx->md != NULL && tbslen != (size_t)EVP_MD_get_size(dctx->md)) - return 0; + if (dctx->md != NULL) { + md_size = EVP_MD_get_size(dctx->md); + if (md_size <= 0) + return 0; + if (tbslen != (size_t)md_size) + return 0; + } ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa); @@ -103,7 +108,7 @@ static int pkey_dsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen) { - int ret; + int ret, md_size; DSA_PKEY_CTX *dctx = ctx->data; /* * Discard const. Its marked as const because this may be a cached copy of @@ -112,8 +117,13 @@ static int pkey_dsa_verify(EVP_PKEY_CTX *ctx, */ DSA *dsa = (DSA *)EVP_PKEY_get0_DSA(ctx->pkey); - if (dctx->md != NULL && tbslen != (size_t)EVP_MD_get_size(dctx->md)) - return 0; + if (dctx->md != NULL) { + md_size = EVP_MD_get_size(dctx->md); + if (md_size <= 0) + return 0; + if (tbslen != (size_t)md_size) + return 0; + } ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa); diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index 91d334ea533a..aab7953c0d9b 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -34,8 +34,7 @@ int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) 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; } @@ -152,7 +151,9 @@ int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) } int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, - unsigned char *sig, unsigned int *siglen, DSA *dsa) + unsigned char *sig, unsigned int *siglen, DSA *dsa, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { DSA_SIG *s; @@ -165,7 +166,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, 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); + s = ossl_dsa_do_sign_int(dgst, dlen, dsa, + nonce_type, digestname, libctx, propq); if (s == NULL) { *siglen = 0; return 0; @@ -178,7 +180,8 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, 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); + return ossl_dsa_sign_int(type, dgst, dlen, sig, siglen, dsa, + 0, NULL, NULL, NULL); } /* data has already been hashed (probably with SHA or SHA-1). */ diff --git a/crypto/dso/dso_dl.c b/crypto/dso/dso_dl.c index 05b63cf1d9c2..7bfb02093b9e 100644 --- a/crypto/dso/dso_dl.c +++ b/crypto/dso/dso_dl.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -165,20 +165,16 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2) */ if (!filespec2 || filespec1[0] == '/') { merged = OPENSSL_strdup(filespec1); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } /* * If the first file specification is missing, the second one rules. */ else if (!filespec1) { merged = OPENSSL_strdup(filespec2); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } else /* * This part isn't as trivial as it looks. It assumes that the @@ -198,10 +194,8 @@ static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2) len--; } merged = OPENSSL_malloc(len + 2); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } strcpy(merged, filespec2); merged[spec2len] = '/'; strcpy(&merged[spec2len + 1], filespec1); @@ -223,7 +217,7 @@ static char *dl_name_converter(DSO *dso, const char *filename) len = strlen(filename); rsize = len + 1; - transform = (strstr(filename, "/") == NULL); + transform = (strchr(filename, '/') == NULL); if (transform) { /* We will convert this to "%s.s?" or "lib%s.s?" */ rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */ diff --git a/crypto/dso/dso_dlfcn.c b/crypto/dso/dso_dlfcn.c index 1107da5fe657..b5a7b7be2cbc 100644 --- a/crypto/dso/dso_dlfcn.c +++ b/crypto/dso/dso_dlfcn.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,7 +17,7 @@ #endif #include "dso_local.h" -#include "e_os.h" +#include "internal/e_os.h" #ifdef DSO_DLFCN @@ -207,20 +207,16 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1, */ if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) { merged = OPENSSL_strdup(filespec1); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } /* * If the first file specification is missing, the second one rules. */ else if (!filespec1) { merged = OPENSSL_strdup(filespec2); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } else { /* * This part isn't as trivial as it looks. It assumes that the @@ -239,10 +235,8 @@ static char *dlfcn_merger(DSO *dso, const char *filespec1, len--; } merged = OPENSSL_malloc(len + 2); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } strcpy(merged, filespec2); merged[spec2len] = '/'; strcpy(&merged[spec2len + 1], filespec1); @@ -257,7 +251,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename) len = strlen(filename); rsize = len + 1; - transform = (strstr(filename, "/") == NULL); + transform = (strchr(filename, '/') == NULL); if (transform) { /* We will convert this to "%s.so" or "lib%s.so" etc */ rsize += strlen(DSO_EXTENSION); /* The length of ".so" */ diff --git a/crypto/dso/dso_lib.c b/crypto/dso/dso_lib.c index 9d755986d755..65579cb8b360 100644 --- a/crypto/dso/dso_lib.c +++ b/crypto/dso/dso_lib.c @@ -1,5 +1,5 @@ /* - * 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 @@ -15,22 +15,17 @@ static DSO *DSO_new_method(DSO_METHOD *meth) DSO *ret; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->meth_data = sk_void_new_null(); if (ret->meth_data == NULL) { /* sk_new doesn't generate any errors so we do */ - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSO, ERR_R_CRYPTO_LIB); OPENSSL_free(ret); return NULL; } ret->meth = DSO_METHOD_openssl(); - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { sk_void_free(ret->meth_data); OPENSSL_free(ret); return NULL; @@ -56,10 +51,10 @@ int DSO_free(DSO *dso) if (dso == NULL) return 1; - if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0) + if (CRYPTO_DOWN_REF(&dso->references, &i) <= 0) return 0; - REF_PRINT_COUNT("DSO", dso); + REF_PRINT_COUNT("DSO", i, dso); if (i > 0) return 1; REF_ASSERT_ISNT(i < 0); @@ -79,7 +74,7 @@ int DSO_free(DSO *dso) sk_void_free(dso->meth_data); OPENSSL_free(dso->filename); OPENSSL_free(dso->loaded_filename); - CRYPTO_THREAD_lock_free(dso->lock); + CRYPTO_FREE_REF(&dso->references); OPENSSL_free(dso); return 1; } @@ -98,10 +93,10 @@ int DSO_up_ref(DSO *dso) return 0; } - if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0) + if (CRYPTO_UP_REF(&dso->references, &i) <= 0) return 0; - REF_PRINT_COUNT("DSO", dso); + REF_PRINT_COUNT("DSO", i, dso); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } @@ -114,7 +109,7 @@ DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) if (dso == NULL) { ret = DSO_new_method(meth); if (ret == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSO, ERR_R_DSO_LIB); goto err; } allocated = 1; @@ -241,10 +236,8 @@ int DSO_set_filename(DSO *dso, const char *filename) } /* We'll duplicate filename */ copied = OPENSSL_strdup(filename); - if (copied == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (copied == NULL) return 0; - } OPENSSL_free(dso->filename); dso->filename = copied; return 1; @@ -289,10 +282,8 @@ char *DSO_convert_filename(DSO *dso, const char *filename) } if (result == NULL) { result = OPENSSL_strdup(filename); - if (result == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (result == NULL) return NULL; - } } return result; } diff --git a/crypto/dso/dso_local.h b/crypto/dso/dso_local.h index 8aa29c1826fe..d7af0b064e50 100644 --- a/crypto/dso/dso_local.h +++ b/crypto/dso/dso_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 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 @@ -61,7 +61,6 @@ struct dso_st { * loaded. */ char *loaded_filename; - CRYPTO_RWLOCK *lock; }; struct dso_meth_st { diff --git a/crypto/dso/dso_vms.c b/crypto/dso/dso_vms.c index aa2dfaa4d15f..6c84bb198828 100644 --- a/crypto/dso/dso_vms.c +++ b/crypto/dso/dso_vms.c @@ -22,13 +22,26 @@ # include "../vms_rms.h" /* Some compiler options may mask the declaration of "_malloc32". */ +# define DSO_MALLOC OPENSSL_malloc # if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE # if __INITIAL_POINTER_SIZE == 64 # pragma pointer_size save # pragma pointer_size 32 void *_malloc32(__size_t); +static void *dso_malloc(__size_t num, const char *file, int line) +{ + void *ret = _malloc32(num); + if (ret == NULL && (file != NULL || line != 0)) { + ERR_new(); + ERR_set_debug(file, line, NULL); + ERR_set_error(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE, NULL); + } + return ret; +} +# undef DSO_MALLOC +# define DSO_MALLOC(num) dso_malloc((num), OPENSSL_FILE, OPENSSL_LINE) # pragma pointer_size restore -# endif /* __INITIAL_POINTER_SIZE == 64 */ +# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ # endif /* __INITIAL_POINTER_SIZE && defined * _ANSI_C_SOURCE */ @@ -88,19 +101,22 @@ static int vms_load(DSO *dso) char *filename = DSO_convert_filename(dso, NULL); /* Ensure 32-bit pointer for "p", and appropriate malloc() function. */ -# if __INITIAL_POINTER_SIZE == 64 -# define DSO_MALLOC _malloc32 -# pragma pointer_size save -# pragma pointer_size 32 -# else /* __INITIAL_POINTER_SIZE == 64 */ -# define DSO_MALLOC OPENSSL_malloc -# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ +# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size save +# pragma pointer_size 32 +# endif /* __INITIAL_POINTER_SIZE == 64 */ +# endif /* __INITIAL_POINTER_SIZE && defined + * _ANSI_C_SOURCE */ DSO_VMS_INTERNAL *p = NULL; -# if __INITIAL_POINTER_SIZE == 64 -# pragma pointer_size restore -# endif /* __INITIAL_POINTER_SIZE == 64 */ +# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE +# if __INITIAL_POINTER_SIZE == 64 +# pragma pointer_size restore +# endif /* __INITIAL_POINTER_SIZE == 64 */ +# endif /* __INITIAL_POINTER_SIZE && defined + * _ANSI_C_SOURCE */ const char *sp1, *sp2; /* Search result */ const char *ext = NULL; /* possible extension to add */ @@ -174,10 +190,8 @@ static int vms_load(DSO *dso) } p = DSO_MALLOC(sizeof(*p)); - if (p == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (p == NULL) goto err; - } strncpy(p->filename, sp1, sp2 - sp1); p->filename[sp2 - sp1] = '\0'; @@ -443,12 +457,10 @@ static char *vms_merger(DSO *dso, const char *filespec1, merged = OPENSSL_malloc(nam.NAMX_ESL + 1); if (merged == NULL) - goto malloc_err; + return NULL; strncpy(merged, nam.NAMX_ESA, nam.NAMX_ESL); merged[nam.NAMX_ESL] = '\0'; return merged; - malloc_err: - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); } static char *vms_name_converter(DSO *dso, const char *filename) diff --git a/crypto/dso/dso_win32.c b/crypto/dso/dso_win32.c index 91a1a9d9aeb5..085ddef9695b 100644 --- a/crypto/dso/dso_win32.c +++ b/crypto/dso/dso_win32.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "dso_local.h" #if defined(DSO_WIN32) @@ -110,10 +110,8 @@ static int win32_load(DSO *dso) goto err; } p = OPENSSL_malloc(sizeof(*p)); - if (p == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (p == NULL) goto err; - } *p = h; if (!sk_void_push(dso->meth_data, p)) { ERR_raise(ERR_LIB_DSO, DSO_R_STACK_ERROR); @@ -214,10 +212,8 @@ static struct file_st *win32_splitter(DSO *dso, const char *filename, } result = OPENSSL_zalloc(sizeof(*result)); - if (result == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (result == NULL) return NULL; - } position = IN_DEVICE; @@ -333,10 +329,8 @@ static char *win32_joiner(DSO *dso, const struct file_st *file_split) } result = OPENSSL_malloc(len + 1); - if (result == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (result == NULL) return NULL; - } if (file_split->node) { strcpy(&result[offset], "\\\\"); @@ -399,25 +393,21 @@ static char *win32_merger(DSO *dso, const char *filespec1, } if (!filespec2) { merged = OPENSSL_strdup(filespec1); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } else if (!filespec1) { merged = OPENSSL_strdup(filespec2); - if (merged == NULL) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + if (merged == NULL) return NULL; - } } else { filespec1_split = win32_splitter(dso, filespec1, 0); if (!filespec1_split) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSO, ERR_R_DSO_LIB); return NULL; } filespec2_split = win32_splitter(dso, filespec2, 1); if (!filespec2_split) { - ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DSO, ERR_R_DSO_LIB); OPENSSL_free(filespec1_split); return NULL; } diff --git a/crypto/ec/asm/ecp_nistz256-armv8.pl b/crypto/ec/asm/ecp_nistz256-armv8.pl index 81ee3947d7e4..35b14c695df0 100644 --- a/crypto/ec/asm/ecp_nistz256-armv8.pl +++ b/crypto/ec/asm/ecp_nistz256-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -55,7 +55,7 @@ my ($acc6,$acc7)=($ap,$bp); # used in __ecp_nistz256_sqr_mont $code.=<<___; #include "arm_arch.h" -.text +.rodata ___ ######################################################################## # Convert ecp_nistz256_table.c to layout expected by ecp_nistz_gather_w7 @@ -117,28 +117,34 @@ $code.=<<___; .quad 0xccd1c8aaee00bc4f .asciz "ECP_NISTZ256 for ARMv8, CRYPTOGAMS by " +.text + // void ecp_nistz256_to_mont(BN_ULONG x0[4],const BN_ULONG x1[4]); .globl ecp_nistz256_to_mont .type ecp_nistz256_to_mont,%function .align 6 ecp_nistz256_to_mont: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-32]! add x29,sp,#0 stp x19,x20,[sp,#16] - ldr $bi,.LRR // bp[0] + adrp $bi,.LRR + ldr $bi,[$bi,:lo12:.LRR] // bp[0] ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 - adr $bp,.LRR // &bp[0] + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] + adrp $bp,.LRR // &bp[0] + add $bp,$bp,:lo12:.LRR bl __ecp_nistz256_mul_mont ldp x19,x20,[sp,#16] ldp x29,x30,[sp],#32 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_to_mont,.-ecp_nistz256_to_mont @@ -147,7 +153,7 @@ ecp_nistz256_to_mont: .type ecp_nistz256_from_mont,%function .align 4 ecp_nistz256_from_mont: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-32]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -155,15 +161,18 @@ ecp_nistz256_from_mont: mov $bi,#1 // bp[0] ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 - adr $bp,.Lone // &bp[0] + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] + adrp $bp,.Lone // &bp[0] + add $bp,$bp,:lo12:.Lone bl __ecp_nistz256_mul_mont ldp x19,x20,[sp,#16] ldp x29,x30,[sp],#32 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_from_mont,.-ecp_nistz256_from_mont @@ -173,7 +182,7 @@ ecp_nistz256_from_mont: .type ecp_nistz256_mul_mont,%function .align 4 ecp_nistz256_mul_mont: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-32]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -181,14 +190,16 @@ ecp_nistz256_mul_mont: ldr $bi,[$bp] // bp[0] ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_mul_mont ldp x19,x20,[sp,#16] ldp x29,x30,[sp],#32 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_mul_mont,.-ecp_nistz256_mul_mont @@ -197,21 +208,23 @@ ecp_nistz256_mul_mont: .type ecp_nistz256_sqr_mont,%function .align 4 ecp_nistz256_sqr_mont: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-32]! add x29,sp,#0 stp x19,x20,[sp,#16] ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_sqr_mont ldp x19,x20,[sp,#16] ldp x29,x30,[sp],#32 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_sqr_mont,.-ecp_nistz256_sqr_mont @@ -221,7 +234,7 @@ ecp_nistz256_sqr_mont: .type ecp_nistz256_add,%function .align 4 ecp_nistz256_add: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -229,13 +242,15 @@ ecp_nistz256_add: ldp $t0,$t1,[$bp] ldp $acc2,$acc3,[$ap,#16] ldp $t2,$t3,[$bp,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_add ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_add,.-ecp_nistz256_add @@ -244,19 +259,21 @@ ecp_nistz256_add: .type ecp_nistz256_div_by_2,%function .align 4 ecp_nistz256_div_by_2: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 ldp $acc0,$acc1,[$ap] ldp $acc2,$acc3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_div_by_2 ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_div_by_2,.-ecp_nistz256_div_by_2 @@ -265,14 +282,16 @@ ecp_nistz256_div_by_2: .type ecp_nistz256_mul_by_2,%function .align 4 ecp_nistz256_mul_by_2: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 ldp $acc0,$acc1,[$ap] ldp $acc2,$acc3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] mov $t0,$acc0 mov $t1,$acc1 mov $t2,$acc2 @@ -281,7 +300,7 @@ ecp_nistz256_mul_by_2: bl __ecp_nistz256_add // ret = a+a // 2*a ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2 @@ -290,14 +309,16 @@ ecp_nistz256_mul_by_2: .type ecp_nistz256_mul_by_3,%function .align 4 ecp_nistz256_mul_by_3: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 ldp $acc0,$acc1,[$ap] ldp $acc2,$acc3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] mov $t0,$acc0 mov $t1,$acc1 mov $t2,$acc2 @@ -317,7 +338,7 @@ ecp_nistz256_mul_by_3: bl __ecp_nistz256_add // ret += a // 2*a+a=3*a ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_mul_by_3,.-ecp_nistz256_mul_by_3 @@ -327,19 +348,21 @@ ecp_nistz256_mul_by_3: .type ecp_nistz256_sub,%function .align 4 ecp_nistz256_sub: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 ldp $acc0,$acc1,[$ap] ldp $acc2,$acc3,[$ap,#16] - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_sub_from ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_sub,.-ecp_nistz256_sub @@ -348,7 +371,7 @@ ecp_nistz256_sub: .type ecp_nistz256_neg,%function .align 4 ecp_nistz256_neg: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -357,13 +380,15 @@ ecp_nistz256_neg: mov $acc1,xzr mov $acc2,xzr mov $acc3,xzr - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] bl __ecp_nistz256_sub_from ldp x29,x30,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_neg,.-ecp_nistz256_neg @@ -724,7 +749,7 @@ $code.=<<___; .type ecp_nistz256_point_double,%function .align 5 ecp_nistz256_point_double: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-96]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -736,9 +761,11 @@ ecp_nistz256_point_double: mov $rp_real,$rp ldp $acc2,$acc3,[$ap,#48] mov $ap_real,$ap - ldr $poly1,.Lpoly+8 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] mov $t0,$acc0 - ldr $poly3,.Lpoly+24 + ldr $poly3,[$poly3,#24] mov $t1,$acc1 ldp $a0,$a1,[$ap_real,#64] // forward load for p256_sqr_mont mov $t2,$acc2 @@ -859,7 +886,7 @@ ecp_nistz256_point_double: ldp x19,x20,[x29,#16] ldp x21,x22,[x29,#32] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_point_double,.-ecp_nistz256_point_double ___ @@ -882,7 +909,7 @@ $code.=<<___; .type ecp_nistz256_point_add,%function .align 5 ecp_nistz256_point_add: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-96]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -897,8 +924,10 @@ ecp_nistz256_point_add: mov $rp_real,$rp mov $ap_real,$ap mov $bp_real,$bp - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] orr $t0,$a0,$a1 orr $t2,$a2,$a3 orr $in2infty,$t0,$t2 @@ -1117,7 +1146,7 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#96 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_point_add,.-ecp_nistz256_point_add ___ @@ -1139,7 +1168,7 @@ $code.=<<___; .type ecp_nistz256_point_add_affine,%function .align 5 ecp_nistz256_point_add_affine: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-80]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -1151,8 +1180,10 @@ ecp_nistz256_point_add_affine: mov $rp_real,$rp mov $ap_real,$ap mov $bp_real,$bp - ldr $poly1,.Lpoly+8 - ldr $poly3,.Lpoly+24 + adrp $poly3,.Lpoly + add $poly3,$poly3,:lo12:.Lpoly + ldr $poly1,[$poly3,#8] + ldr $poly3,[$poly3,#24] ldp $a0,$a1,[$ap,#64] // in1_z ldp $a2,$a3,[$ap,#64+16] @@ -1303,7 +1334,8 @@ $code.=<<___; stp $acc2,$acc3,[$rp_real,#$i+16] ___ $code.=<<___ if ($i == 0); - adr $bp_real,.Lone_mont-64 + adrp $bp_real,.Lone_mont-64 + add $bp_real,$bp_real,:lo12:.Lone_mont-64 ___ } $code.=<<___; @@ -1328,7 +1360,7 @@ $code.=<<___; ldp x23,x24,[x29,#48] ldp x25,x26,[x29,#64] ldp x29,x30,[sp],#80 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size ecp_nistz256_point_add_affine,.-ecp_nistz256_point_add_affine ___ @@ -1346,13 +1378,16 @@ $code.=<<___; .type ecp_nistz256_ord_mul_mont,%function .align 4 ecp_nistz256_ord_mul_mont: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-64]! add x29,sp,#0 stp x19,x20,[sp,#16] stp x21,x22,[sp,#32] stp x23,x24,[sp,#48] - adr $ordk,.Lord + adrp $ordk,.Lord + add $ordk,$ordk,:lo12:.Lord ldr $bi,[$bp] // bp[0] ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] @@ -1487,13 +1522,16 @@ $code.=<<___; .type ecp_nistz256_ord_sqr_mont,%function .align 4 ecp_nistz256_ord_sqr_mont: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-64]! add x29,sp,#0 stp x19,x20,[sp,#16] stp x21,x22,[sp,#32] stp x23,x24,[sp,#48] - adr $ordk,.Lord + adrp $ordk,.Lord + add $ordk,$ordk,:lo12:.Lord ldp $a0,$a1,[$ap] ldp $a2,$a3,[$ap,#16] @@ -1641,6 +1679,8 @@ $code.=<<___; .type ecp_nistz256_scatter_w5,%function .align 4 ecp_nistz256_scatter_w5: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -1703,6 +1743,8 @@ ecp_nistz256_scatter_w5: .type ecp_nistz256_gather_w5,%function .align 4 ecp_nistz256_gather_w5: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -1780,6 +1822,8 @@ ecp_nistz256_gather_w5: .type ecp_nistz256_scatter_w7,%function .align 4 ecp_nistz256_scatter_w7: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -1824,6 +1868,8 @@ ecp_nistz256_scatter_w7: .type ecp_nistz256_gather_w7,%function .align 4 ecp_nistz256_gather_w7: + AARCH64_VALID_CALL_TARGET + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 diff --git a/crypto/ec/asm/ecp_nistz256-x86_64.pl b/crypto/ec/asm/ecp_nistz256-x86_64.pl index 430b14c86d8d..4da9a149a99a 100755 --- a/crypto/ec/asm/ecp_nistz256-x86_64.pl +++ b/crypto/ec/asm/ecp_nistz256-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2024 The OpenSSL Project Authors. All Rights Reserved. # Copyright (c) 2014, Intel Corporation. All Rights Reserved. # Copyright (c) 2015 CloudFlare, Inc. # @@ -85,6 +85,7 @@ $code.=<<___; .extern OPENSSL_ia32cap_P # The polynomial +.section .rodata align=4096 .align 64 .Lpoly: .quad 0xffffffffffffffff, 0x00000000ffffffff, 0x0000000000000000, 0xffffffff00000001 @@ -107,6 +108,7 @@ $code.=<<___; .quad 0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000 .LordK: .quad 0xccd1c8aaee00bc4f +.previous ___ { @@ -4723,7 +4725,7 @@ close TABLE; die "insane number of elements" if ($#arr != 64*16*37-1); print <<___; -.text +.section .rodata align=4096 .globl ecp_nistz256_precomputed .type ecp_nistz256_precomputed,\@object .align 4096 diff --git a/crypto/ec/build.info b/crypto/ec/build.info index 6dd98e9f4f17..dbe69578ef52 100644 --- a/crypto/ec/build.info +++ b/crypto/ec/build.info @@ -3,9 +3,12 @@ IF[{- !$disabled{asm} -}] $ECASM_x86=ecp_nistz256.c ecp_nistz256-x86.S $ECDEF_x86=ECP_NISTZ256_ASM - $ECASM_x86_64=ecp_nistz256.c ecp_nistz256-x86_64.s x25519-x86_64.s - $ECDEF_x86_64=ECP_NISTZ256_ASM X25519_ASM - + $ECASM_x86_64=ecp_nistz256.c ecp_nistz256-x86_64.s + $ECDEF_x86_64=ECP_NISTZ256_ASM + IF[{- !$disabled{'ecx'} -}] + $ECASM_x86_64=$ECASM_x86_64 x25519-x86_64.s + $ECDEF_x86_64=$ECDEF_x86_64 X25519_ASM + ENDIF $ECASM_ia64= $ECASM_sparcv9=ecp_nistz256.c ecp_nistz256-sparcv9.S @@ -18,25 +21,41 @@ IF[{- !$disabled{asm} -}] $ECASM_mips32= $ECASM_mips64= - $ECASM_s390x=ecp_s390x_nistp.c ecx_s390x.c + $ECASM_s390x=ecp_s390x_nistp.c + IF[{- !$disabled{'ecx'} -}] + $ECASM_s390x=$ECASM_s390x ecx_s390x.c + ENDIF $ECDEF_s390x=S390X_EC_ASM $ECASM_armv4=ecp_nistz256.c ecp_nistz256-armv4.S $ECDEF_armv4=ECP_NISTZ256_ASM $ECASM_aarch64=ecp_nistz256.c ecp_nistz256-armv8.S $ECDEF_aarch64=ECP_NISTZ256_ASM + IF[{- !$disabled{'sm2'} -}] + $ECASM_aarch64=$ECASM_aarch64 ecp_sm2p256.c ecp_sm2p256-armv8.S + IF[{- !$disabled{'sm2-precomp'} -}] + $ECASM_aarch64=$ECASM_aarch64 ecp_sm2p256_table.c + ENDIF + $ECDEF_aarch64=$ECDEF_aarch64 ECP_SM2P256_ASM + ENDIF $ECASM_parisc11= $ECASM_parisc20_64= $ECASM_ppc32= - $ECASM_ppc64=ecp_nistz256.c ecp_ppc.c ecp_nistz256-ppc64.s x25519-ppc64.s - $ECDEF_ppc64=ECP_NISTZ256_ASM X25519_ASM + $ECASM_ppc64=ecp_nistz256.c ecp_ppc.c ecp_nistz256-ppc64.s + $ECDEF_ppc64=ECP_NISTZ256_ASM IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}] - $ECASM_ppc64=$ECASM_ppc64 ecp_nistp521-ppc64.s - $ECDEF_ppc64=$ECDEF_ppc64 ECP_NISTP521_ASM + $ECASM_ppc64=$ECASM_ppc64 ecp_nistp384-ppc64.s ecp_nistp521-ppc64.s + $ECDEF_ppc64=$ECDEF_ppc64 ECP_NISTP384_ASM ECP_NISTP521_ASM + INCLUDE[ecp_nistp384.o]=.. INCLUDE[ecp_nistp521.o]=.. ENDIF + IF[{- !$disabled{'ecx'} -}] + $ECASM_ppc64=$ECASM_ppc64 x25519-ppc64.s + $ECDEF_ppc64=$ECDEF_ppc64 X25519_ASM + INCLUDE[ecx_s390x.o]=.. + ENDIF $ECASM_c64xplus= @@ -49,22 +68,29 @@ IF[{- !$disabled{asm} -}] ENDIF $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \ - ec_curve.c ec_check.c ec_key.c ec_kmeth.c ecx_key.c ec_asn1.c \ + ec_curve.c ec_check.c ec_key.c ec_kmeth.c ec_asn1.c \ ec2_smpl.c \ ecp_oct.c ec2_oct.c ec_oct.c ecdh_ossl.c \ - ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \ - curve448/f_generic.c curve448/scalar.c \ - curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \ - $ECASM ec_backend.c ecx_backend.c ecdh_kdf.c curve448/arch_64/f_impl64.c \ - curve448/arch_32/f_impl32.c + ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c \ + $ECASM ec_backend.c ecdh_kdf.c -IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}] - $COMMON=$COMMON ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c +IF[{- !$disabled{'ecx'} -}] + $COMMON=$COMMON curve25519.c curve448/f_generic.c curve448/scalar.c \ + curve448/arch_64/f_impl64.c ecx_backend.c curve448/arch_32/f_impl32.c \ + curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \ + ecx_key.c ENDIF -SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c \ +IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}] + $COMMON=$COMMON ecp_nistp224.c ecp_nistp256.c ecp_nistp384.c ecp_nistp521.c ecp_nistputil.c +ENDIF + +SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c \ ec_err.c eck_prn.c \ ec_deprecated.c ec_print.c +IF[{- !$disabled{'ecx'} -}] + SOURCE[../../libcrypto]=ecx_meth.c +ENDIF SOURCE[../../providers/libfips.a]=$COMMON # Implementations are now spread across several libraries, so the defines @@ -90,8 +116,10 @@ GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl INCLUDE[ecp_nistz256-sparcv9.o]=.. INCLUDE[ecp_s390x_nistp.o]=.. -INCLUDE[ecx_s390x.o]=.. -INCLUDE[ecx_meth.o]=.. +IF[{- !$disabled{'ecx'} -}] + INCLUDE[ecx_meth.o]=.. + INCLUDE[ecx_key.o]=.. +ENDIF GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl INCLUDE[ecp_nistz256-armv4.o]=.. @@ -99,7 +127,15 @@ GENERATE[ecp_nistz256-armv8.S]=asm/ecp_nistz256-armv8.pl INCLUDE[ecp_nistz256-armv8.o]=.. GENERATE[ecp_nistz256-ppc64.s]=asm/ecp_nistz256-ppc64.pl +GENERATE[ecp_nistp384-ppc64.s]=asm/ecp_nistp384-ppc64.pl GENERATE[ecp_nistp521-ppc64.s]=asm/ecp_nistp521-ppc64.pl +IF[{- !$disabled{'ecx'} -}] GENERATE[x25519-x86_64.s]=asm/x25519-x86_64.pl GENERATE[x25519-ppc64.s]=asm/x25519-ppc64.pl +ENDIF + +IF[{- !$disabled{'sm2'} -}] + GENERATE[ecp_sm2p256-armv8.S]=asm/ecp_sm2p256-armv8.pl + INCLUDE[ecp_sm2p256-armv8.o]=.. +ENDIF diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c index 50a8e6b169d2..68c06ae624f1 100644 --- a/crypto/ec/curve25519.c +++ b/crypto/ec/curve25519.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -1868,7 +1868,7 @@ static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) { fe u; fe v; - fe v3; + fe w; fe vxx; fe check; @@ -1879,15 +1879,10 @@ static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) fe_sub(u, u, h->Z); /* u = y^2-1 */ fe_add(v, v, h->Z); /* v = dy^2+1 */ - fe_sq(v3, v); - fe_mul(v3, v3, v); /* v3 = v^3 */ - fe_sq(h->X, v3); - fe_mul(h->X, h->X, v); - fe_mul(h->X, h->X, u); /* x = uv^7 */ + fe_mul(w, u, v); /* w = u*v */ - fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ - fe_mul(h->X, h->X, v3); - fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ + fe_pow22523(h->X, w); /* x = w^((q-5)/8) */ + fe_mul(h->X, h->X, u); /* x = u * w^((q-5)/8) */ fe_sq(vxx, h->X); fe_mul(vxx, vxx, v); @@ -5439,9 +5434,47 @@ static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b, s[31] = (uint8_t) (s11 >> 17); } +static int hash_init_with_dom(EVP_MD_CTX *hash_ctx, + EVP_MD *sha512, + const uint8_t dom2flag, + const uint8_t phflag, + const uint8_t *context, + const size_t context_len) +{ + /* ASCII: "SigEd25519 no Ed25519 collisions", in hex for EBCDIC compatibility */ + const char dom_s[] = + "\x53\x69\x67\x45\x64\x32\x35\x35\x31\x39\x20\x6e" + "\x6f\x20\x45\x64\x32\x35\x35\x31\x39\x20\x63\x6f" + "\x6c\x6c\x69\x73\x69\x6f\x6e\x73"; + uint8_t dom[2]; + + if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL)) + return 0; + + /* return early if dom2flag is not set */ + if (!dom2flag) + return 1; + + if (context_len > UINT8_MAX) + return 0; + + dom[0] = (uint8_t)(phflag >= 1 ? 1 : 0); + dom[1] = (uint8_t)context_len; + + if (!EVP_DigestUpdate(hash_ctx, dom_s, sizeof(dom_s)-1) + || !EVP_DigestUpdate(hash_ctx, dom, sizeof(dom)) + || !EVP_DigestUpdate(hash_ctx, context, context_len)) { + return 0; + } + + return 1; +} + int -ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, +ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *tbs, size_t tbs_len, const uint8_t public_key[32], const uint8_t private_key[32], + const uint8_t dom2flag, const uint8_t phflag, const uint8_t csflag, + const uint8_t *context, size_t context_len, OSSL_LIB_CTX *libctx, const char *propq) { uint8_t az[SHA512_DIGEST_LENGTH]; @@ -5453,6 +5486,17 @@ ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, unsigned int sz; int res = 0; + if (context == NULL) + context_len = 0; + + /* if csflag is set, then a non-empty context-string is required */ + if (csflag && context_len == 0) + goto err; + + /* if dom2flag is not set, then an empty context-string is required */ + if (!dom2flag && context_len > 0) + goto err; + if (sha512 == NULL || hash_ctx == NULL) goto err; @@ -5465,9 +5509,9 @@ ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, az[31] &= 63; az[31] |= 64; - if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + if (!hash_init_with_dom(hash_ctx, sha512, dom2flag, phflag, context, context_len) || !EVP_DigestUpdate(hash_ctx, az + 32, 32) - || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestUpdate(hash_ctx, tbs, tbs_len) || !EVP_DigestFinal_ex(hash_ctx, nonce, &sz)) goto err; @@ -5475,10 +5519,10 @@ ossl_ed25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, ge_scalarmult_base(&R, nonce); ge_p3_tobytes(out_sig, &R); - if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + if (!hash_init_with_dom(hash_ctx, sha512, dom2flag, phflag, context, context_len) || !EVP_DigestUpdate(hash_ctx, out_sig, 32) || !EVP_DigestUpdate(hash_ctx, public_key, 32) - || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestUpdate(hash_ctx, tbs, tbs_len) || !EVP_DigestFinal_ex(hash_ctx, hram, &sz)) goto err; @@ -5494,11 +5538,28 @@ err: return res; } +/* + * This function should not be necessary since ossl_ed25519_verify() already + * does this check internally. + * For some reason the FIPS ACVP requires a EDDSA KeyVer test. + */ +int +ossl_ed25519_pubkey_verify(const uint8_t *pub, size_t pub_len) +{ + ge_p3 A; + + if (pub_len != ED25519_KEYLEN) + return 0; + return (ge_frombytes_vartime(&A, pub) == 0); +} + static const char allzeroes[15]; int -ossl_ed25519_verify(const uint8_t *message, size_t message_len, +ossl_ed25519_verify(const uint8_t *tbs, size_t tbs_len, const uint8_t signature[64], const uint8_t public_key[32], + const uint8_t dom2flag, const uint8_t phflag, const uint8_t csflag, + const uint8_t *context, size_t context_len, OSSL_LIB_CTX *libctx, const char *propq) { int i; @@ -5517,6 +5578,17 @@ ossl_ed25519_verify(const uint8_t *message, size_t message_len, 0xDE, 0xF9, 0xDE, 0x14 }; + if (context == NULL) + context_len = 0; + + /* if csflag is set, then a non-empty context-string is required */ + if (csflag && context_len == 0) + return 0; + + /* if dom2flag is not set, then an empty context-string is required */ + if (!dom2flag && context_len > 0) + return 0; + r = signature; s = signature + 32; @@ -5561,10 +5633,10 @@ ossl_ed25519_verify(const uint8_t *message, size_t message_len, if (hash_ctx == NULL) goto err; - if (!EVP_DigestInit_ex(hash_ctx, sha512, NULL) + if (!hash_init_with_dom(hash_ctx, sha512, dom2flag, phflag, context, context_len) || !EVP_DigestUpdate(hash_ctx, r, 32) || !EVP_DigestUpdate(hash_ctx, public_key, 32) - || !EVP_DigestUpdate(hash_ctx, message, message_len) + || !EVP_DigestUpdate(hash_ctx, tbs, tbs_len) || !EVP_DigestFinal_ex(hash_ctx, h, &sz)) goto err; @@ -5575,6 +5647,14 @@ ossl_ed25519_verify(const uint8_t *message, size_t message_len, ge_tobytes(rcheck, &R); res = CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0; + + /* note that we have used the strict verification equation here. + * we checked that ENC( [h](-A) + [s]B ) == r + * B is the base point. + * + * the less strict verification equation uses the curve cofactor: + * [h*8](-A) + [s*8]B == [8]R + */ err: EVP_MD_free(sha512); EVP_MD_CTX_free(hash_ctx); diff --git a/crypto/ec/curve448/arch_32/f_impl32.c b/crypto/ec/curve448/arch_32/f_impl32.c index 8714a5142216..140c73c64fc1 100644 --- a/crypto/ec/curve448/arch_32/f_impl32.c +++ b/crypto/ec/curve448/arch_32/f_impl32.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -10,7 +10,7 @@ * Originally written by Mike Hamburg */ -#include "e_os.h" +#include "internal/e_os.h" #include #include "internal/numbers.h" @@ -21,7 +21,7 @@ NON_EMPTY_TRANSLATION_UNIT # include "../field.h" -void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) +void ossl_gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) { const uint32_t *a = as->limb, *b = bs->limb; uint32_t *c = cs->limb; @@ -70,7 +70,7 @@ void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) c[1] += ((uint32_t)(accum1)); } -void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) +void ossl_gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) { const uint32_t *a = as->limb; uint32_t *c = cs->limb; @@ -98,8 +98,8 @@ void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) c[1] += (uint32_t)(accum8 >> 28); } -void gf_sqr(gf_s * RESTRICT cs, const gf as) +void ossl_gf_sqr(gf_s * RESTRICT cs, const gf as) { - gf_mul(cs, as, as); /* Performs better with a dedicated square */ + ossl_gf_mul(cs, as, as); /* Performs better with a dedicated square */ } #endif diff --git a/crypto/ec/curve448/arch_64/f_impl64.c b/crypto/ec/curve448/arch_64/f_impl64.c index dfe75b8fc5ca..06cc33a96471 100644 --- a/crypto/ec/curve448/arch_64/f_impl64.c +++ b/crypto/ec/curve448/arch_64/f_impl64.c @@ -10,7 +10,7 @@ * Originally written by Mike Hamburg */ -#include "e_os.h" +#include "internal/e_os.h" #include #include "internal/numbers.h" @@ -21,7 +21,7 @@ NON_EMPTY_TRANSLATION_UNIT # include "../field.h" -void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) +void ossl_gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) { const uint64_t *a = as->limb, *b = bs->limb; uint64_t *c = cs->limb; @@ -73,7 +73,7 @@ void gf_mul(gf_s * RESTRICT cs, const gf as, const gf bs) c[1] += ((uint64_t)(accum1)); } -void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) +void ossl_gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) { const uint64_t *a = as->limb; uint64_t *c = cs->limb; @@ -99,7 +99,7 @@ void gf_mulw_unsigned(gf_s * RESTRICT cs, const gf as, uint32_t b) c[1] += accum4 >> 56; } -void gf_sqr(gf_s * RESTRICT cs, const gf as) +void ossl_gf_sqr(gf_s * RESTRICT cs, const gf as) { const uint64_t *a = as->limb; uint64_t *c = cs->limb; diff --git a/crypto/ec/curve448/curve448.c b/crypto/ec/curve448/curve448.c index 6928d9693ca5..1db78ee5c6b5 100644 --- a/crypto/ec/curve448/curve448.c +++ b/crypto/ec/curve448/curve448.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -44,42 +44,43 @@ static void gf_invert(gf y, const gf x, int assert_nonzero) mask_t ret; gf t1, t2; - gf_sqr(t1, x); /* o^2 */ + ossl_gf_sqr(t1, x); /* o^2 */ ret = gf_isr(t2, t1); /* +-1/sqrt(o^2) = +-1/o */ (void)ret; if (assert_nonzero) assert(ret); - gf_sqr(t1, t2); - gf_mul(t2, t1, x); /* not direct to y in case of alias. */ + ossl_gf_sqr(t1, t2); + ossl_gf_mul(t2, t1, x); /* not direct to y in case of alias. */ gf_copy(y, t2); } /** identity = (0,1) */ -const curve448_point_t ossl_curve448_point_identity = - { {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} }; +const curve448_point_t ossl_curve448_point_identity = { + {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} +}; static void point_double_internal(curve448_point_t p, const curve448_point_t q, int before_double) { gf a, b, c, d; - gf_sqr(c, q->x); - gf_sqr(a, q->y); + ossl_gf_sqr(c, q->x); + ossl_gf_sqr(a, q->y); gf_add_nr(d, c, a); /* 2+e */ gf_add_nr(p->t, q->y, q->x); /* 2+e */ - gf_sqr(b, p->t); + ossl_gf_sqr(b, p->t); gf_subx_nr(b, b, d, 3); /* 4+e */ gf_sub_nr(p->t, a, c); /* 3+e */ - gf_sqr(p->x, q->z); + ossl_gf_sqr(p->x, q->z); gf_add_nr(p->z, p->x, p->x); /* 2+e */ gf_subx_nr(a, p->z, p->t, 4); /* 6+e */ if (GF_HEADROOM == 5) gf_weak_reduce(a); /* or 1+e */ - gf_mul(p->x, a, b); - gf_mul(p->z, p->t, a); - gf_mul(p->y, p->t, d); + ossl_gf_mul(p->x, a, b); + ossl_gf_mul(p->z, p->t, a); + ossl_gf_mul(p->y, p->t, d); if (!before_double) - gf_mul(p->t, b, d); + ossl_gf_mul(p->t, b, d); } void ossl_curve448_point_double(curve448_point_t p, const curve448_point_t q) @@ -108,17 +109,17 @@ static void pniels_to_pt(curve448_point_t e, const pniels_t d) gf_add(eu, d->n->b, d->n->a); gf_sub(e->y, d->n->b, d->n->a); - gf_mul(e->t, e->y, eu); - gf_mul(e->x, d->z, e->y); - gf_mul(e->y, d->z, eu); - gf_sqr(e->z, d->z); + ossl_gf_mul(e->t, e->y, eu); + ossl_gf_mul(e->x, d->z, e->y); + ossl_gf_mul(e->y, d->z, eu); + ossl_gf_sqr(e->z, d->z); } static void niels_to_pt(curve448_point_t e, const niels_t n) { gf_add(e->y, n->b, n->a); gf_sub(e->x, n->b, n->a); - gf_mul(e->t, e->y, e->x); + ossl_gf_mul(e->t, e->y, e->x); gf_copy(e->z, ONE); } @@ -128,19 +129,19 @@ static void add_niels_to_pt(curve448_point_t d, const niels_t e, gf a, b, c; gf_sub_nr(b, d->y, d->x); /* 3+e */ - gf_mul(a, e->a, b); + ossl_gf_mul(a, e->a, b); gf_add_nr(b, d->x, d->y); /* 2+e */ - gf_mul(d->y, e->b, b); - gf_mul(d->x, e->c, d->t); + ossl_gf_mul(d->y, e->b, b); + ossl_gf_mul(d->x, e->c, d->t); gf_add_nr(c, a, d->y); /* 2+e */ gf_sub_nr(b, d->y, a); /* 3+e */ gf_sub_nr(d->y, d->z, d->x); /* 3+e */ gf_add_nr(a, d->x, d->z); /* 2+e */ - gf_mul(d->z, a, d->y); - gf_mul(d->x, d->y, b); - gf_mul(d->y, a, c); + ossl_gf_mul(d->z, a, d->y); + ossl_gf_mul(d->x, d->y, b); + ossl_gf_mul(d->y, a, c); if (!before_double) - gf_mul(d->t, b, c); + ossl_gf_mul(d->t, b, c); } static void sub_niels_from_pt(curve448_point_t d, const niels_t e, @@ -149,19 +150,19 @@ static void sub_niels_from_pt(curve448_point_t d, const niels_t e, gf a, b, c; gf_sub_nr(b, d->y, d->x); /* 3+e */ - gf_mul(a, e->b, b); + ossl_gf_mul(a, e->b, b); gf_add_nr(b, d->x, d->y); /* 2+e */ - gf_mul(d->y, e->a, b); - gf_mul(d->x, e->c, d->t); + ossl_gf_mul(d->y, e->a, b); + ossl_gf_mul(d->x, e->c, d->t); gf_add_nr(c, a, d->y); /* 2+e */ gf_sub_nr(b, d->y, a); /* 3+e */ gf_add_nr(d->y, d->z, d->x); /* 2+e */ gf_sub_nr(a, d->z, d->x); /* 3+e */ - gf_mul(d->z, a, d->y); - gf_mul(d->x, d->y, b); - gf_mul(d->y, a, c); + ossl_gf_mul(d->z, a, d->y); + ossl_gf_mul(d->x, d->y, b); + ossl_gf_mul(d->y, a, c); if (!before_double) - gf_mul(d->t, b, c); + ossl_gf_mul(d->t, b, c); } static void add_pniels_to_pt(curve448_point_t p, const pniels_t pn, @@ -169,7 +170,7 @@ static void add_pniels_to_pt(curve448_point_t p, const pniels_t pn, { gf L0; - gf_mul(L0, p->z, pn->z); + ossl_gf_mul(L0, p->z, pn->z); gf_copy(p->z, L0); add_niels_to_pt(p, pn->n, before_double); } @@ -179,7 +180,7 @@ static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn, { gf L0; - gf_mul(L0, p->z, pn->z); + ossl_gf_mul(L0, p->z, pn->z); gf_copy(p->z, L0); sub_niels_from_pt(p, pn->n, before_double); } @@ -192,8 +193,8 @@ ossl_curve448_point_eq(const curve448_point_t p, gf a, b; /* equality mod 2-torsion compares x/y */ - gf_mul(a, p->y, q->x); - gf_mul(b, q->y, p->x); + ossl_gf_mul(a, p->y, q->x); + ossl_gf_mul(b, q->y, p->x); succ = gf_eq(a, b); return mask_to_bool(succ); @@ -205,15 +206,15 @@ ossl_curve448_point_valid(const curve448_point_t p) mask_t out; gf a, b, c; - gf_mul(a, p->x, p->y); - gf_mul(b, p->z, p->t); + ossl_gf_mul(a, p->x, p->y); + ossl_gf_mul(b, p->z, p->t); out = gf_eq(a, b); - gf_sqr(a, p->x); - gf_sqr(b, p->y); + ossl_gf_sqr(a, p->x); + ossl_gf_sqr(b, p->y); gf_sub(a, b, a); - gf_sqr(b, p->t); + ossl_gf_sqr(b, p->t); gf_mulw(c, b, TWISTED_D); - gf_sqr(b, p->z); + ossl_gf_sqr(b, p->z); gf_add(b, b, c); out &= gf_eq(a, b); out &= ~gf_eq(p->z, ZERO); @@ -221,7 +222,7 @@ ossl_curve448_point_valid(const curve448_point_t p) } static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni, - const niels_t * table, + const niels_t *table, int nelts, int idx) { constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx); @@ -229,7 +230,7 @@ static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni, void ossl_curve448_precomputed_scalarmul(curve448_point_t out, - const curve448_precomputed_s * table, + const curve448_precomputed_s *table, const curve448_scalar_t scalar) { unsigned int i, j, k; @@ -290,26 +291,26 @@ ossl_curve448_point_mul_by_ratio_and_encode_like_eddsa( /* 4-isogeny: 2xy/(y^+x^2), (y^2-x^2)/(2z^2-y^2+x^2) */ gf u; - gf_sqr(x, q->x); - gf_sqr(t, q->y); + ossl_gf_sqr(x, q->x); + ossl_gf_sqr(t, q->y); gf_add(u, x, t); gf_add(z, q->y, q->x); - gf_sqr(y, z); + ossl_gf_sqr(y, z); gf_sub(y, y, u); gf_sub(z, t, x); - gf_sqr(x, q->z); + ossl_gf_sqr(x, q->z); gf_add(t, x, x); gf_sub(t, t, z); - gf_mul(x, t, y); - gf_mul(y, z, u); - gf_mul(z, u, t); + ossl_gf_mul(x, t, y); + ossl_gf_mul(y, z, u); + ossl_gf_mul(z, u, t); OPENSSL_cleanse(u, sizeof(u)); } /* Affinize */ gf_invert(z, z, 1); - gf_mul(t, x, z); - gf_mul(x, y, z); + ossl_gf_mul(t, x, z); + ossl_gf_mul(x, y, z); /* Encode */ enc[EDDSA_448_PRIVATE_BYTES - 1] = 0; @@ -340,15 +341,15 @@ ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio( succ = gf_deserialize(p->y, enc2, 1, 0); succ &= word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1]); - gf_sqr(p->x, p->y); + ossl_gf_sqr(p->x, p->y); gf_sub(p->z, ONE, p->x); /* num = 1-y^2 */ gf_mulw(p->t, p->x, EDWARDS_D); /* dy^2 */ gf_sub(p->t, ONE, p->t); /* denom = 1-dy^2 or 1-d + dy^2 */ - gf_mul(p->x, p->z, p->t); + ossl_gf_mul(p->x, p->z, p->t); succ &= gf_isr(p->t, p->x); /* 1/sqrt(num * denom) */ - gf_mul(p->x, p->t, p->z); /* sqrt(num / denom) */ + ossl_gf_mul(p->x, p->t, p->z); /* sqrt(num / denom) */ gf_cond_neg(p->x, gf_lobit(p->x) ^ low); gf_copy(p->z, ONE); @@ -356,20 +357,20 @@ ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio( gf a, b, c, d; /* 4-isogeny 2xy/(y^2-ax^2), (y^2+ax^2)/(2-y^2-ax^2) */ - gf_sqr(c, p->x); - gf_sqr(a, p->y); + ossl_gf_sqr(c, p->x); + ossl_gf_sqr(a, p->y); gf_add(d, c, a); gf_add(p->t, p->y, p->x); - gf_sqr(b, p->t); + ossl_gf_sqr(b, p->t); gf_sub(b, b, d); gf_sub(p->t, a, c); - gf_sqr(p->x, p->z); + ossl_gf_sqr(p->x, p->z); gf_add(p->z, p->x, p->x); gf_sub(a, p->z, d); - gf_mul(p->x, a, b); - gf_mul(p->z, p->t, a); - gf_mul(p->y, p->t, d); - gf_mul(p->t, b, d); + ossl_gf_mul(p->x, a, b); + ossl_gf_mul(p->z, p->t, a); + ossl_gf_mul(p->y, p->t, d); + ossl_gf_mul(p->t, b, d); OPENSSL_cleanse(a, sizeof(a)); OPENSSL_cleanse(b, sizeof(b)); OPENSSL_cleanse(c, sizeof(c)); @@ -424,30 +425,30 @@ ossl_x448_int(uint8_t out[X_PUBLIC_BYTES], gf_add_nr(t1, x2, z2); /* A = x2 + z2 */ /* 2+e */ gf_sub_nr(t2, x2, z2); /* B = x2 - z2 */ /* 3+e */ gf_sub_nr(z2, x3, z3); /* D = x3 - z3 */ /* 3+e */ - gf_mul(x2, t1, z2); /* DA */ + ossl_gf_mul(x2, t1, z2); /* DA */ gf_add_nr(z2, z3, x3); /* C = x3 + z3 */ /* 2+e */ - gf_mul(x3, t2, z2); /* CB */ + ossl_gf_mul(x3, t2, z2); /* CB */ gf_sub_nr(z3, x2, x3); /* DA-CB */ /* 3+e */ - gf_sqr(z2, z3); /* (DA-CB)^2 */ - gf_mul(z3, x1, z2); /* z3 = x1(DA-CB)^2 */ + ossl_gf_sqr(z2, z3); /* (DA-CB)^2 */ + ossl_gf_mul(z3, x1, z2); /* z3 = x1(DA-CB)^2 */ gf_add_nr(z2, x2, x3); /* (DA+CB) */ /* 2+e */ - gf_sqr(x3, z2); /* x3 = (DA+CB)^2 */ + ossl_gf_sqr(x3, z2); /* x3 = (DA+CB)^2 */ - gf_sqr(z2, t1); /* AA = A^2 */ - gf_sqr(t1, t2); /* BB = B^2 */ - gf_mul(x2, z2, t1); /* x2 = AA*BB */ + ossl_gf_sqr(z2, t1); /* AA = A^2 */ + ossl_gf_sqr(t1, t2); /* BB = B^2 */ + ossl_gf_mul(x2, z2, t1); /* x2 = AA*BB */ gf_sub_nr(t2, z2, t1); /* E = AA-BB */ /* 3+e */ gf_mulw(t1, t2, -EDWARDS_D); /* E*-d = a24*E */ gf_add_nr(t1, t1, z2); /* AA + a24*E */ /* 2+e */ - gf_mul(z2, t2, t1); /* z2 = E(AA+a24*E) */ + ossl_gf_mul(z2, t2, t1); /* z2 = E(AA+a24*E) */ } /* Finish */ gf_cond_swap(x2, x3, swap); gf_cond_swap(z2, z3, swap); gf_invert(z2, z2, 0); - gf_mul(x1, x2, z2); + ossl_gf_mul(x1, x2, z2); gf_serialize(out, x1, 1); nz = ~gf_eq(x1, ZERO); @@ -471,8 +472,8 @@ ossl_curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t curve448_point_copy(q, p); gf_invert(q->t, q->x, 0); /* 1/x */ - gf_mul(q->z, q->t, q->y); /* y/x */ - gf_sqr(q->y, q->z); /* (y/x)^2 */ + ossl_gf_mul(q->z, q->t, q->y); /* y/x */ + ossl_gf_sqr(q->y, q->z); /* (y/x)^2 */ gf_serialize(out, q->y, 1); ossl_curve448_point_destroy(q); } @@ -586,9 +587,15 @@ static int recode_wnaf(struct smvt_control *control, int32_t delta = odd & mask; assert(position >= 0); - assert(pos < 32); /* can't fail since current & 0xFFFF != 0 */ if (odd & (1 << (table_bits + 1))) delta -= (1 << (table_bits + 1)); + /* + * Coverity gets confused by the value of pos, thinking it might be + * 32. This would require current & 0xFFFF to be zero which isn't + * possible. Suppress this false positive, since adding a check + * isn't desirable. + */ + /* coverity[overflow_before_widen] */ current -= delta * (1 << pos); control[position].power = pos + 16 * (w - 1); control[position].addend = delta; @@ -606,7 +613,7 @@ static int recode_wnaf(struct smvt_control *control, return n - 1; } -static void prepare_wnaf_table(pniels_t * output, +static void prepare_wnaf_table(pniels_t *output, const curve448_point_t working, unsigned int tbits) { diff --git a/crypto/ec/curve448/curve448_local.h b/crypto/ec/curve448/curve448_local.h index 3410f091a655..5c569ea8b9d2 100644 --- a/crypto/ec/curve448/curve448_local.h +++ b/crypto/ec/curve448/curve448_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -10,15 +10,4 @@ # define OSSL_CRYPTO_EC_CURVE448_LOCAL_H # include "curve448utils.h" -int -ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], - const uint8_t public_key[57], const uint8_t private_key[57], - const uint8_t *context, size_t context_len, const char *propq); - -int -ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], - const uint8_t signature[114], const uint8_t public_key[57], - const uint8_t *context, size_t context_len, - const char *propq); - #endif /* OSSL_CRYPTO_EC_CURVE448_LOCAL_H */ diff --git a/crypto/ec/curve448/ed448.h b/crypto/ec/curve448/ed448.h index 00b2bae580ba..f4f01892d3c3 100644 --- a/crypto/ec/curve448/ed448.h +++ b/crypto/ec/curve448/ed448.h @@ -21,7 +21,7 @@ /* Number of bytes in an EdDSA private key. */ # define EDDSA_448_PRIVATE_BYTES EDDSA_448_PUBLIC_BYTES -/* Number of bytes in an EdDSA private key. */ +/* Number of bytes in an EdDSA signature. */ # define EDDSA_448_SIGNATURE_BYTES (EDDSA_448_PUBLIC_BYTES + \ EDDSA_448_PRIVATE_BYTES) diff --git a/crypto/ec/curve448/eddsa.c b/crypto/ec/curve448/eddsa.c index 6648692ff395..080486e9f369 100644 --- a/crypto/ec/curve448/eddsa.c +++ b/crypto/ec/curve448/eddsa.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -61,12 +61,8 @@ static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, size_t context_len, const char *propq) { -#ifdef CHARSET_EBCDIC - const char dom_s[] = {0x53, 0x69, 0x67, 0x45, - 0x64, 0x34, 0x34, 0x38, 0x00}; -#else - const char dom_s[] = "SigEd448"; -#endif + /* ASCII: "SigEd448", in hex for EBCDIC compatibility */ + const char dom_s[] = "\x53\x69\x67\x45\x64\x34\x34\x38"; uint8_t dom[2]; EVP_MD *shake256 = NULL; @@ -82,7 +78,7 @@ static c448_error_t hash_init_with_dom(OSSL_LIB_CTX *ctx, EVP_MD_CTX *hashctx, return C448_FAILURE; if (!EVP_DigestInit_ex(hashctx, shake256, NULL) - || !EVP_DigestUpdate(hashctx, dom_s, strlen(dom_s)) + || !EVP_DigestUpdate(hashctx, dom_s, sizeof(dom_s)-1) || !EVP_DigestUpdate(hashctx, dom, sizeof(dom)) || !EVP_DigestUpdate(hashctx, context, context_len)) { EVP_MD_free(shake256); @@ -276,6 +272,17 @@ ossl_c448_ed448_sign_prehash( context, context_len, propq); } +static c448_error_t +c448_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len) +{ + curve448_point_t pk_point; + + if (pub_len != EDDSA_448_PUBLIC_BYTES) + return C448_FAILURE; + + return ossl_curve448_point_decode_like_eddsa_and_mul_by_ratio(pk_point, pub); +} + c448_error_t ossl_c448_ed448_verify( OSSL_LIB_CTX *ctx, @@ -373,47 +380,40 @@ ossl_c448_ed448_verify_prehash( } int -ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t *message, - size_t message_len, const uint8_t public_key[57], - const uint8_t private_key[57], const uint8_t *context, - size_t context_len, const char *propq) +ossl_ed448_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, + const uint8_t *message, size_t message_len, + const uint8_t public_key[57], const uint8_t private_key[57], + const uint8_t *context, size_t context_len, + const uint8_t phflag, const char *propq) { return ossl_c448_ed448_sign(ctx, out_sig, private_key, public_key, message, - message_len, 0, context, context_len, + message_len, phflag, context, context_len, propq) == C448_SUCCESS; } +/* + * This function should not be necessary since ossl_ed448_verify() already + * does this check internally. + * For some reason the FIPS ACVP requires a EDDSA KeyVer test. + */ int -ossl_ed448_verify(OSSL_LIB_CTX *ctx, const uint8_t *message, size_t message_len, +ossl_ed448_pubkey_verify(const uint8_t *pub, size_t pub_len) +{ + return c448_ed448_pubkey_verify(pub, pub_len); +} + +int +ossl_ed448_verify(OSSL_LIB_CTX *ctx, + const uint8_t *message, size_t message_len, const uint8_t signature[114], const uint8_t public_key[57], - const uint8_t *context, size_t context_len, const char *propq) + const uint8_t *context, size_t context_len, + const uint8_t phflag, const char *propq) { return ossl_c448_ed448_verify(ctx, signature, public_key, message, - message_len, 0, context, (uint8_t)context_len, + message_len, phflag, context, (uint8_t)context_len, propq) == C448_SUCCESS; } -int -ossl_ed448ph_sign(OSSL_LIB_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64], - const uint8_t public_key[57], const uint8_t private_key[57], - const uint8_t *context, size_t context_len, const char *propq) -{ - return ossl_c448_ed448_sign_prehash(ctx, out_sig, private_key, public_key, - hash, context, context_len, - propq) == C448_SUCCESS; -} - -int -ossl_ed448ph_verify(OSSL_LIB_CTX *ctx, const uint8_t hash[64], - const uint8_t signature[114], const uint8_t public_key[57], - const uint8_t *context, size_t context_len, - const char *propq) -{ - return ossl_c448_ed448_verify_prehash(ctx, signature, public_key, hash, - context, (uint8_t)context_len, - propq) == C448_SUCCESS; -} - int ossl_ed448_public_from_private(OSSL_LIB_CTX *ctx, uint8_t out_public_key[57], const uint8_t private_key[57], const char *propq) diff --git a/crypto/ec/curve448/f_generic.c b/crypto/ec/curve448/f_generic.c index 4c571810d3af..9a4675a8b3db 100644 --- a/crypto/ec/curve448/f_generic.c +++ b/crypto/ec/curve448/f_generic.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -18,7 +18,7 @@ static const gf MODULUS = { }; /* Serialize to wire format. */ -void gf_serialize(uint8_t *serial, const gf x, int with_hibit) +void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit) { unsigned int j = 0, fill = 0; dword_t buffer = 0; @@ -173,32 +173,32 @@ mask_t gf_isr(gf a, const gf x) { gf L0, L1, L2; - gf_sqr(L1, x); - gf_mul(L2, x, L1); - gf_sqr(L1, L2); - gf_mul(L2, x, L1); + ossl_gf_sqr(L1, x); + ossl_gf_mul(L2, x, L1); + ossl_gf_sqr(L1, L2); + ossl_gf_mul(L2, x, L1); gf_sqrn(L1, L2, 3); - gf_mul(L0, L2, L1); + ossl_gf_mul(L0, L2, L1); gf_sqrn(L1, L0, 3); - gf_mul(L0, L2, L1); + ossl_gf_mul(L0, L2, L1); gf_sqrn(L2, L0, 9); - gf_mul(L1, L0, L2); - gf_sqr(L0, L1); - gf_mul(L2, x, L0); + ossl_gf_mul(L1, L0, L2); + ossl_gf_sqr(L0, L1); + ossl_gf_mul(L2, x, L0); gf_sqrn(L0, L2, 18); - gf_mul(L2, L1, L0); + ossl_gf_mul(L2, L1, L0); gf_sqrn(L0, L2, 37); - gf_mul(L1, L2, L0); + ossl_gf_mul(L1, L2, L0); gf_sqrn(L0, L1, 37); - gf_mul(L1, L2, L0); + ossl_gf_mul(L1, L2, L0); gf_sqrn(L0, L1, 111); - gf_mul(L2, L1, L0); - gf_sqr(L0, L2); - gf_mul(L1, x, L0); + ossl_gf_mul(L2, L1, L0); + ossl_gf_sqr(L0, L2); + ossl_gf_mul(L1, x, L0); gf_sqrn(L0, L1, 223); - gf_mul(L1, L2, L0); - gf_sqr(L2, L1); - gf_mul(L0, L2, x); + ossl_gf_mul(L1, L2, L0); + ossl_gf_sqr(L2, L1); + ossl_gf_mul(L0, L2, x); gf_copy(a, L1); return gf_eq(L0, ONE); } diff --git a/crypto/ec/curve448/field.h b/crypto/ec/curve448/field.h index e1c633378950..80b1355b77aa 100644 --- a/crypto/ec/curve448/field.h +++ b/crypto/ec/curve448/field.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2014 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -54,15 +54,15 @@ static INLINE_UNUSED void gf_weak_reduce(gf inout); void gf_strong_reduce(gf inout); void gf_add(gf out, const gf a, const gf b); void gf_sub(gf out, const gf a, const gf b); -void gf_mul(gf_s * RESTRICT out, const gf a, const gf b); -void gf_mulw_unsigned(gf_s * RESTRICT out, const gf a, uint32_t b); -void gf_sqr(gf_s * RESTRICT out, const gf a); +void ossl_gf_mul(gf_s * RESTRICT out, const gf a, const gf b); +void ossl_gf_mulw_unsigned(gf_s * RESTRICT out, const gf a, uint32_t b); +void ossl_gf_sqr(gf_s * RESTRICT out, const gf a); mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ mask_t gf_eq(const gf x, const gf y); mask_t gf_lobit(const gf x); mask_t gf_hibit(const gf x); -void gf_serialize(uint8_t *serial, const gf x, int with_highbit); +void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_highbit); mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit, uint8_t hi_nmask); @@ -85,16 +85,16 @@ static ossl_inline void gf_sqrn(gf_s * RESTRICT y, const gf x, int n) assert(n > 0); if (n & 1) { - gf_sqr(y, x); + ossl_gf_sqr(y, x); n--; } else { - gf_sqr(tmp, x); - gf_sqr(y, tmp); + ossl_gf_sqr(tmp, x); + ossl_gf_sqr(y, tmp); n -= 2; } for (; n; n -= 2) { - gf_sqr(tmp, y); - gf_sqr(y, tmp); + ossl_gf_sqr(tmp, y); + ossl_gf_sqr(y, tmp); } } @@ -122,9 +122,9 @@ static ossl_inline void gf_subx_nr(gf c, const gf a, const gf b, int amt) static ossl_inline void gf_mulw(gf c, const gf a, int32_t w) { if (w > 0) { - gf_mulw_unsigned(c, a, w); + ossl_gf_mulw_unsigned(c, a, w); } else { - gf_mulw_unsigned(c, a, -w); + ossl_gf_mulw_unsigned(c, a, -w); gf_sub(c, ZERO, c); } } diff --git a/crypto/ec/curve448/point_448.h b/crypto/ec/curve448/point_448.h index e67ea68044eb..96a54558d6b3 100644 --- a/crypto/ec/curve448/point_448.h +++ b/crypto/ec/curve448/point_448.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -271,7 +271,7 @@ ossl_x448_derive_public_key(uint8_t out[X448_PUBLIC_BYTES], */ void ossl_curve448_precomputed_scalarmul(curve448_point_t scaled, - const curve448_precomputed_s * base, + const curve448_precomputed_s *base, const curve448_scalar_t scalar); /* diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c index 10a4932591d6..4ed6287562a7 100644 --- a/crypto/ec/ec2_oct.c +++ b/crypto/ec/ec2_oct.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2022 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 @@ -272,7 +272,7 @@ int ossl_ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, } /* - * The first octet is the point converison octet PC, see X9.62, page 4 + * The first octet is the point conversion octet PC, see X9.62, page 4 * and section 4.4.2. It must be: * 0x00 for the point at infinity * 0x02 or 0x03 for compressed form diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c index 3a59544c8b2f..13e702684eab 100644 --- a/crypto/ec/ec2_smpl.c +++ b/crypto/ec/ec2_smpl.c @@ -9,7 +9,7 @@ */ /* - * ECDSA low level APIs are deprecated for public use, but still ok for + * ECDSA low-level APIs are deprecated for public use, but still ok for * internal use. */ #include "internal/deprecated.h" @@ -188,7 +188,7 @@ int ossl_ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } @@ -545,7 +545,7 @@ int ossl_ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point * We have a curve defined by a Weierstrass equation * y^2 + x*y = x^3 + a*x^2 + b. * <=> x^3 + a*x^2 + x*y + b + y^2 = 0 - * <=> ((x + a) * x + y ) * x + b + y^2 = 0 + * <=> ((x + a) * x + y) * x + b + y^2 = 0 */ if (!BN_GF2m_add(lh, point->X, group->a)) goto err; @@ -826,7 +826,7 @@ int ec_GF2m_simple_ladder_post(const EC_GROUP *group, t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t2 == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -905,7 +905,7 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, */ if ((t = EC_POINT_new(group)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } @@ -923,7 +923,7 @@ int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r, /*- * Computes the multiplicative inverse of a in GF(2^m), storing the result in r. - * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * If a is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. * SCA hardening is with blinding: BN_GF2m_mod_inv does that. */ static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r, diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index d4348ff244c7..ad28ba6827d4 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -568,7 +568,7 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, if (ecbits <= 0) goto err; - sz = (ecbits + 7 ) / 8; + sz = (ecbits + 7) / 8; if (!OSSL_PARAM_BLD_push_BN_pad(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, priv_key, sz)) @@ -613,7 +613,7 @@ static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx) EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery); if (ec == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c index c018f392894d..643d2d8d7b82 100644 --- a/crypto/ec/ec_asn1.c +++ b/crypto/ec/ec_asn1.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,7 @@ #include #include #include "internal/nelem.h" +#include "crypto/asn1.h" #include "crypto/asn1_dsa.h" #ifndef FIPS_MODULE @@ -205,7 +206,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) if (nid == NID_X9_62_prime_field) { if ((tmp = BN_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* the parameters are specified by the prime number p */ @@ -234,7 +235,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two = field->p.char_two; if (char_two == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } @@ -260,7 +261,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two->p.tpBasis = ASN1_INTEGER_new(); if (char_two->p.tpBasis == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } if (!ASN1_INTEGER_set(char_two->p.tpBasis, (long)k)) { @@ -275,7 +276,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) char_two->p.ppBasis = X9_62_PENTANOMIAL_new(); if (char_two->p.ppBasis == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } @@ -288,7 +289,7 @@ static int ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) /* for ONB the parameters are (asn1) NULL */ char_two->p.onBasis = ASN1_NULL_new(); if (char_two->p.onBasis == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } @@ -317,7 +318,7 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) return 0; if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -334,10 +335,8 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) */ len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8; if ((a_buf = OPENSSL_malloc(len)) == NULL - || (b_buf = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + || (b_buf = OPENSSL_malloc(len)) == NULL) goto err; - } if (BN_bn2binpad(tmp_1, a_buf, len) < 0 || BN_bn2binpad(tmp_2, b_buf, len) < 0) { ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); @@ -355,11 +354,10 @@ static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) if (group->seed) { if (!curve->seed) if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } - curve->seed->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - curve->seed->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(curve->seed, 0); if (!ASN1_BIT_STRING_set(curve->seed, group->seed, (int)group->seed_len)) { ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); @@ -393,7 +391,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, if (params == NULL) { if ((ret = ECPARAMETERS_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } } else @@ -429,7 +427,7 @@ ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group, } if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) { OPENSSL_free(buffer); - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } ASN1_STRING_set0(ret->base, buffer, len); @@ -474,7 +472,7 @@ ECPKPARAMETERS *EC_GROUP_get_ecpkparameters(const EC_GROUP *group, if (ret == NULL) { if ((ret = ECPKPARAMETERS_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); return NULL; } } else { @@ -580,7 +578,7 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) } if ((p = BN_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -698,10 +696,8 @@ EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params) goto err; } OPENSSL_free(ret->seed); - if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((ret->seed = OPENSSL_malloc(params->curve->seed->length)) == NULL) goto err; - } memcpy(ret->seed, params->curve->seed->data, params->curve->seed->length); ret->seed_len = params->curve->seed->length; @@ -945,7 +941,7 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len) if (a == NULL || *a == NULL) { if ((ret = EC_KEY_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } else @@ -1033,7 +1029,7 @@ int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out) } if ((priv_key = EC_PRIVATEKEY_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1061,7 +1057,7 @@ int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out) if (!(a->enc_flag & EC_PKEY_NO_PUBKEY)) { priv_key->publicKey = ASN1_BIT_STRING_new(); if (priv_key->publicKey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); goto err; } @@ -1072,8 +1068,7 @@ int i2d_ECPrivateKey(const EC_KEY *a, unsigned char **out) goto err; } - priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(priv_key->publicKey, 0); ASN1_STRING_set0(priv_key->publicKey, pub, publen); pub = NULL; } @@ -1110,7 +1105,7 @@ EC_KEY *d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len) if (a == NULL || *a == NULL) { if ((ret = EC_KEY_new()) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return NULL; } } else @@ -1174,10 +1169,8 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out) return buf_len; if (*out == NULL) { - if ((*out = OPENSSL_malloc(buf_len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((*out = OPENSSL_malloc(buf_len)) == NULL) return 0; - } new_buffer = 1; } if (!EC_POINT_point2oct(a->group, a->pub_key, a->conv_form, @@ -1202,8 +1195,7 @@ DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG) ECDSA_SIG *ECDSA_SIG_new(void) { ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig)); - if (sig == NULL) - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return sig; } diff --git a/crypto/ec/ec_backend.c b/crypto/ec/ec_backend.c index cad576fc48a1..f0191a7db3b0 100644 --- a/crypto/ec/ec_backend.c +++ b/crypto/ec/ec_backend.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -24,7 +24,8 @@ #include "crypto/bn.h" #include "crypto/ec.h" #include "ec_local.h" -#include "e_os.h" +#include "internal/e_os.h" +#include "internal/nelem.h" #include "internal/param_build_set.h" /* Mapping between a flag and a name */ @@ -183,14 +184,13 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P); param_a = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A); param_b = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B); - if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL) - { + if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL) { BIGNUM *p = BN_CTX_get(bnctx); BIGNUM *a = BN_CTX_get(bnctx); BIGNUM *b = BN_CTX_get(bnctx); if (b == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -201,7 +201,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_P, p) || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_A, a) || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_B, b)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -216,7 +216,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, } if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_ORDER, order)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -226,7 +226,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, if (!ossl_param_build_set_utf8_string(tmpl, params, OSSL_PKEY_PARAM_EC_FIELD_TYPE, field_type)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -249,7 +249,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, if (!ossl_param_build_set_octet_string(tmpl, params, OSSL_PKEY_PARAM_EC_GENERATOR, *genbuf, genbuf_len)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -261,7 +261,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, if (cofactor != NULL && !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -276,7 +276,7 @@ static int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, && !ossl_param_build_set_octet_string(tmpl, params, OSSL_PKEY_PARAM_EC_SEED, seed, seed_len)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } } @@ -295,7 +295,7 @@ int ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl, point_conversion_form_t genform; if (group == NULL) { - ERR_raise(ERR_LIB_EC,EC_R_PASSED_NULL_PARAMETER); + ERR_raise(ERR_LIB_EC, EC_R_PASSED_NULL_PARAMETER); return 0; } @@ -523,7 +523,7 @@ static int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[]) p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); if (p != NULL) { if (!ossl_ec_pt_format_param2id(p, &format)) { - ECerr(0, EC_R_INVALID_FORM); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); return 0; } EC_KEY_set_conv_form(ec, format); @@ -767,7 +767,7 @@ EC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg, X509_ALGOR_get0(NULL, &ptype, &pval, palg); if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto ecerr; } diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c index 484124915dc6..9ed94b328c69 100644 --- a/crypto/ec/ec_check.c +++ b/crypto/ec/ec_check.c @@ -30,7 +30,7 @@ int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only, if (ctx == NULL) { ctx = new_ctx = BN_CTX_new_ex(NULL); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return NID_undef; } } @@ -69,7 +69,7 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c index b5b2f3342dfb..f46aac5d33f9 100644 --- a/crypto/ec/ec_curve.c +++ b/crypto/ec/ec_curve.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2024 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 @@ -383,7 +383,7 @@ static const struct { static const struct { EC_CURVE_DATA h; - unsigned char data[20 + 32 * 6]; + unsigned char data[20 + 32 * 8]; } _EC_X9_62_PRIME_256V1 = { { NID_X9_62_prime_field, 20, 32, 1 @@ -415,7 +415,15 @@ static const struct { /* order */ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, - 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51, + /* RR for prime */ + 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + /* RR for order */ + 0x66, 0xe1, 0x2d, 0x94, 0xf3, 0xd9, 0x56, 0x20, 0x28, 0x45, 0xb2, 0x39, + 0x2b, 0x6b, 0xec, 0x59, 0x46, 0x99, 0x79, 0x9c, 0x49, 0xbd, 0x6f, 0xa6, + 0x83, 0x24, 0x4c, 0x95, 0xbe, 0x79, 0xee, 0xa2 } }; @@ -2838,6 +2846,8 @@ static const ec_list_element curve_list[] = { {NID_secp384r1, &_EC_NIST_PRIME_384.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp384_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + ossl_ec_GFp_nistp384_method, # else 0, # endif @@ -2931,6 +2941,8 @@ static const ec_list_element curve_list[] = { {NID_secp384r1, &_EC_NIST_PRIME_384.h, # if defined(S390X_EC_ASM) EC_GFp_s390x_nistp384_method, +# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128) + ossl_ec_GFp_nistp384_method, # else 0, # endif @@ -3107,8 +3119,13 @@ static const ec_list_element curve_list[] = { "RFC 5639 curve over a 512 bit prime field"}, {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, "RFC 5639 curve over a 512 bit prime field"}, -# ifndef OPENSSL_NO_SM2 - {NID_sm2, &_EC_sm2p256v1.h, 0, +#ifndef OPENSSL_NO_SM2 + {NID_sm2, &_EC_sm2p256v1.h, +# ifdef ECP_SM2P256_ASM + EC_GFp_sm2p256_method, +# else + 0, +# endif "SM2 curve over a 256 bit prime field"}, # endif }; @@ -3151,7 +3168,7 @@ static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx, curve.meth != NULL ? curve.meth() : NULL); if ((ctx = BN_CTX_new_ex(libctx)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -3159,6 +3176,24 @@ static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx, seed_len = data->seed_len; param_len = data->param_len; params = (const unsigned char *)(data + 1); /* skip header */ + + if (curve.meth != NULL) { + meth = curve.meth(); + if ((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + if (group->meth->group_full_init != NULL) { + if (!group->meth->group_full_init(group, params)){ + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + EC_GROUP_set_curve_name(group, curve.nid); + BN_CTX_free(ctx); + return group; + } + } + params += seed_len; /* skip seed */ if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL @@ -3168,10 +3203,8 @@ static EC_GROUP *ec_group_new_from_data(OSSL_LIB_CTX *libctx, goto err; } - if (curve.meth != 0) { - meth = curve.meth(); - if (((group = ossl_ec_group_new_ex(libctx, propq, meth)) == NULL) || - (!(group->meth->group_set_curve(group, p, a, b, ctx)))) { + if (group != NULL) { + if (group->meth->group_set_curve(group, p, a, b, ctx) == 0) { ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } diff --git a/crypto/ec/ec_deprecated.c b/crypto/ec/ec_deprecated.c index 765894c32977..905b56063835 100644 --- a/crypto/ec/ec_deprecated.c +++ b/crypto/ec/ec_deprecated.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -47,10 +47,8 @@ EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, if ((buf_len = BN_num_bytes(bn)) == 0) buf_len = 1; - if ((buf = OPENSSL_malloc(buf_len)) == NULL) { - ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(buf_len)) == NULL) return NULL; - } if (BN_bn2binpad(bn, buf, buf_len) < 0) { OPENSSL_free(buf); diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 729d338b3379..a3907ca5994d 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -24,6 +24,7 @@ #endif #include #include "prov/providercommon.h" +#include "prov/ecx.h" #include "crypto/bn.h" static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, @@ -74,8 +75,8 @@ void EC_KEY_free(EC_KEY *r) if (r == NULL) return; - CRYPTO_DOWN_REF(&r->references, &i, r->lock); - REF_PRINT_COUNT("EC_KEY", r); + CRYPTO_DOWN_REF(&r->references, &i); + REF_PRINT_COUNT("EC_KEY", i, r); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -93,7 +94,7 @@ void EC_KEY_free(EC_KEY *r) #ifndef FIPS_MODULE CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data); #endif - CRYPTO_THREAD_lock_free(r->lock); + CRYPTO_FREE_REF(&r->references); EC_GROUP_free(r->group); EC_POINT_free(r->pub_key); BN_clear_free(r->priv_key); @@ -193,10 +194,10 @@ int EC_KEY_up_ref(EC_KEY *r) { int i; - if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; - REF_PRINT_COUNT("EC_KEY", r); + REF_PRINT_COUNT("EC_KEY", i, r); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } @@ -236,6 +237,56 @@ int ossl_ec_key_gen(EC_KEY *eckey) return ret; } +/* + * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 + * Perform a KAT by duplicating the public key generation. + * + * NOTE: This issue requires a background understanding, provided in a separate + * document; the current IG 10.3.A AC1 is insufficient regarding the PCT for + * the key agreement scenario. + * + * Currently IG 10.3.A requires PCT in the mode of use prior to use of the + * key pair, citing the PCT defined in the associated standard. For key + * agreement, the only PCT defined in SP 800-56A is that of Section 5.6.2.4: + * the comparison of the original public key to a newly calculated public key. + */ +static int ecdsa_keygen_knownanswer_test(EC_KEY *eckey, BN_CTX *ctx, + OSSL_CALLBACK *cb, void *cbarg) +{ + int len, ret = 0; + OSSL_SELF_TEST *st = NULL; + unsigned char bytes[512] = {0}; + EC_POINT *pub_key2 = NULL; + + st = OSSL_SELF_TEST_new(cb, cbarg); + if (st == NULL) + return 0; + + OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT_KAT, + OSSL_SELF_TEST_DESC_PCT_ECDSA); + + if ((pub_key2 = EC_POINT_new(eckey->group)) == NULL) + goto err; + + /* pub_key = priv_key * G (where G is a point on the curve) */ + if (!EC_POINT_mul(eckey->group, pub_key2, eckey->priv_key, NULL, NULL, ctx)) + goto err; + + if (BN_num_bytes(pub_key2->X) > (int)sizeof(bytes)) + goto err; + len = BN_bn2bin(pub_key2->X, bytes); + if (OSSL_SELF_TEST_oncorrupt_byte(st, bytes) + && BN_bin2bn(bytes, len, pub_key2->X) == NULL) + goto err; + ret = !EC_POINT_cmp(eckey->group, eckey->pub_key, pub_key2, ctx); + +err: + OSSL_SELF_TEST_onend(st, ret); + OSSL_SELF_TEST_free(st); + EC_POINT_free(pub_key2); + return ret; +} + /* * ECC Key generation. * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates" @@ -332,7 +383,8 @@ static int ec_generate_key(EC_KEY *eckey, int pairwise_test) void *cbarg = NULL; OSSL_SELF_TEST_get_callback(eckey->libctx, &cb, &cbarg); - ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg); + ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg) + && ecdsa_keygen_knownanswer_test(eckey, ctx, cb, cbarg); } err: /* Step (9): If there is an error return an invalid keypair. */ @@ -350,6 +402,43 @@ err: return ok; } +#ifndef FIPS_MODULE +/* + * This is similar to ec_generate_key(), except it uses an ikm to + * derive the private key. + */ +int ossl_ec_generate_key_dhkem(EC_KEY *eckey, + const unsigned char *ikm, size_t ikmlen) +{ + int ok = 0; + + if (eckey->priv_key == NULL) { + eckey->priv_key = BN_secure_new(); + if (eckey->priv_key == NULL) + goto err; + } + if (ossl_ec_dhkem_derive_private(eckey, eckey->priv_key, ikm, ikmlen) <= 0) + goto err; + if (eckey->pub_key == NULL) { + eckey->pub_key = EC_POINT_new(eckey->group); + if (eckey->pub_key == NULL) + goto err; + } + if (!ossl_ec_key_simple_generate_public_key(eckey)) + goto err; + + ok = 1; +err: + if (!ok) { + BN_clear_free(eckey->priv_key); + eckey->priv_key = NULL; + if (eckey->pub_key != NULL) + EC_POINT_set_to_infinity(eckey->group, eckey->pub_key); + } + return ok; +} +#endif + int ossl_ec_key_simple_generate_key(EC_KEY *eckey) { return ec_generate_key(eckey, 0); @@ -474,10 +563,16 @@ int ossl_ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx) int ret = 0; EC_POINT *point = NULL; const BIGNUM *order = NULL; + const BIGNUM *cofactor = EC_GROUP_get0_cofactor(eckey->group); if (!ossl_ec_key_public_check_quick(eckey, ctx)) return 0; + if (cofactor != NULL && BN_is_one(cofactor)) { + /* Skip the unnecessary expensive computation for curves with cofactor of 1. */ + return 1; + } + point = EC_POINT_new(eckey->group); if (point == NULL) return 0; @@ -954,7 +1049,7 @@ int ossl_ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, if (eckey->priv_key == NULL) eckey->priv_key = BN_secure_new(); if (eckey->priv_key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } if (BN_bin2bn(buf, len, eckey->priv_key) == NULL) { @@ -973,10 +1068,8 @@ size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf) len = EC_KEY_priv2oct(eckey, NULL, 0); if (len == 0) return 0; - if ((buf = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(len)) == NULL) return 0; - } len = EC_KEY_priv2oct(eckey, buf, len); if (len == 0) { OPENSSL_free(buf); diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c index 8c011635cb42..054a3333a78f 100644 --- a/crypto/ec/ec_kmeth.c +++ b/crypto/ec/ec_kmeth.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -83,25 +83,19 @@ EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq, { EC_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) + return NULL; + + if (!CRYPTO_NEW_REF(&ret->references, 1)) { + OPENSSL_free(ret); return NULL; } ret->libctx = libctx; if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); - if (ret->propq == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret->propq == NULL) goto err; - } - } - - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); - goto err; } ret->meth = EC_KEY_get_default_method(); @@ -129,6 +123,7 @@ EC_KEY *ossl_ec_key_new_method_int(OSSL_LIB_CTX *libctx, const char *propq, /* No ex_data inside the FIPS provider */ #ifndef FIPS_MODULE if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EC_KEY, ret, &ret->ex_data)) { + ERR_raise(ERR_LIB_EC, ERR_R_CRYPTO_LIB); goto err; } #endif diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c index a082876fb479..b55677fb1f4f 100644 --- a/crypto/ec/ec_lib.c +++ b/crypto/ec/ec_lib.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "crypto/ec.h" #include "crypto/bn.h" #include "internal/nelem.h" @@ -41,18 +42,14 @@ EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq, } ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->libctx = libctx; if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); - if (ret->propq == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret->propq == NULL) goto err; - } } ret->meth = meth; if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) { @@ -103,12 +100,16 @@ void EC_pre_comp_free(EC_GROUP *group) case PCT_nistp256: EC_nistp256_pre_comp_free(group->pre_comp.nistp256); break; + case PCT_nistp384: + ossl_ec_nistp384_pre_comp_free(group->pre_comp.nistp384); + break; case PCT_nistp521: EC_nistp521_pre_comp_free(group->pre_comp.nistp521); break; #else case PCT_nistp224: case PCT_nistp256: + case PCT_nistp384: case PCT_nistp521: break; #endif @@ -192,12 +193,16 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) case PCT_nistp256: dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256); break; + case PCT_nistp384: + dest->pre_comp.nistp384 = ossl_ec_nistp384_pre_comp_dup(src->pre_comp.nistp384); + break; case PCT_nistp521: dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521); break; #else case PCT_nistp224: case PCT_nistp256: + case PCT_nistp384: case PCT_nistp521: break; #endif @@ -247,10 +252,8 @@ int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src) if (src->seed) { OPENSSL_free(dest->seed); - if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) return 0; - } if (!memcpy(dest->seed, src->seed, src->seed_len)) return 0; dest->seed_len = src->seed_len; @@ -533,10 +536,8 @@ size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len) if (!len || !p) return 1; - if ((group->seed = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((group->seed = OPENSSL_malloc(len)) == NULL) return 0; - } memcpy(group->seed, p, len); group->seed_len = len; @@ -727,10 +728,8 @@ EC_POINT *EC_POINT_new(const EC_GROUP *group) } ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->meth = group->meth; ret->curve_name = group->curve_name; @@ -748,9 +747,13 @@ void EC_POINT_free(EC_POINT *point) if (point == NULL) return; +#ifdef OPENSSL_PEDANTIC_ZEROIZATION + EC_POINT_clear_free(point); +#else if (point->meth->point_finish != 0) point->meth->point_finish(point); OPENSSL_free(point); +#endif } void EC_POINT_clear_free(EC_POINT *point) @@ -1508,7 +1511,7 @@ int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]) p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT); if (p != NULL) { if (!ossl_ec_pt_format_param2id(p, &format)) { - ECerr(0, EC_R_INVALID_FORM); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); return 0; } EC_GROUP_set_point_conversion_form(group, format); @@ -1517,7 +1520,7 @@ int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]) p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING); if (p != NULL) { if (!ossl_ec_encoding_param2id(p, &encoding_flag)) { - ECerr(0, EC_R_INVALID_FORM); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM); return 0; } EC_GROUP_set_asn1_flag(group, encoding_flag); @@ -1528,7 +1531,7 @@ int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[]) /* The seed is allowed to be NULL */ if (p->data_type != OSSL_PARAM_OCTET_STRING || !EC_GROUP_set_seed(group, p->data, p->data_size)) { - ECerr(0, EC_R_INVALID_SEED); + ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED); return 0; } } @@ -1583,7 +1586,7 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], /* If it gets here then we are trying explicit parameters */ bnctx = BN_CTX_new_ex(libctx); if (bnctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } BN_CTX_start(bnctx); @@ -1593,7 +1596,7 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], b = BN_CTX_get(bnctx); order = BN_CTX_get(bnctx); if (order == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -1759,3 +1762,38 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], return group; #endif /* FIPS_MODULE */ } + +OSSL_PARAM *EC_GROUP_to_params(const EC_GROUP *group, OSSL_LIB_CTX *libctx, + const char *propq, BN_CTX *bnctx) +{ + OSSL_PARAM_BLD *tmpl = NULL; + BN_CTX *new_bnctx = NULL; + unsigned char *gen_buf = NULL; + OSSL_PARAM *params = NULL; + + if (group == NULL) + goto err; + + tmpl = OSSL_PARAM_BLD_new(); + if (tmpl == NULL) + goto err; + + if (bnctx == NULL) + bnctx = new_bnctx = BN_CTX_new_ex(libctx); + if (bnctx == NULL) + goto err; + BN_CTX_start(bnctx); + + if (!ossl_ec_group_todata( + group, tmpl, NULL, libctx, propq, bnctx, &gen_buf)) + goto err; + + params = OSSL_PARAM_BLD_to_param(tmpl); + + err: + OSSL_PARAM_BLD_free(tmpl); + OPENSSL_free(gen_buf); + BN_CTX_end(bnctx); + BN_CTX_free(new_bnctx); + return params; +} diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h index f34e06aea89a..91c3a7190299 100644 --- a/crypto/ec/ec_local.h +++ b/crypto/ec/ec_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2024 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 @@ -196,6 +196,7 @@ struct ec_method_st { int (*ladder_post)(const EC_GROUP *group, EC_POINT *r, EC_POINT *s, EC_POINT *p, BN_CTX *ctx); + int (*group_full_init)(EC_GROUP *group, const unsigned char *data); }; /* @@ -203,6 +204,7 @@ struct ec_method_st { */ typedef struct nistp224_pre_comp_st NISTP224_PRE_COMP; typedef struct nistp256_pre_comp_st NISTP256_PRE_COMP; +typedef struct nistp384_pre_comp_st NISTP384_PRE_COMP; typedef struct nistp521_pre_comp_st NISTP521_PRE_COMP; typedef struct nistz256_pre_comp_st NISTZ256_PRE_COMP; typedef struct ec_pre_comp_st EC_PRE_COMP; @@ -245,7 +247,7 @@ struct ec_group_st { * equation of the form y^2 + x*y = x^3 + a*x^2 + b. */ BIGNUM *a, *b; - /* enable optimized point arithmetics for special case */ + /* enable optimized point arithmetic for special case */ int a_is_minus3; /* method-specific (e.g., Montgomery structure) */ void *field_data1; @@ -264,12 +266,13 @@ struct ec_group_st { */ enum { PCT_none, - PCT_nistp224, PCT_nistp256, PCT_nistp521, PCT_nistz256, + PCT_nistp224, PCT_nistp256, PCT_nistp384, PCT_nistp521, PCT_nistz256, PCT_ec } pre_comp_type; union { NISTP224_PRE_COMP *nistp224; NISTP256_PRE_COMP *nistp256; + NISTP384_PRE_COMP *nistp384; NISTP521_PRE_COMP *nistp521; NISTZ256_PRE_COMP *nistz256; EC_PRE_COMP *ec; @@ -298,7 +301,6 @@ struct ec_key_st { #ifndef FIPS_MODULE CRYPTO_EX_DATA ex_data; #endif - CRYPTO_RWLOCK *lock; OSSL_LIB_CTX *libctx; char *propq; @@ -318,7 +320,7 @@ struct ec_point_st { BIGNUM *Y; BIGNUM *Z; /* Jacobian projective coordinates: * (X, Y, * Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ - int Z_is_one; /* enable optimized point arithmetics for + int Z_is_one; /* enable optimized point arithmetic for * special case */ }; @@ -333,6 +335,7 @@ static ossl_inline int ec_point_is_compat(const EC_POINT *point, NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *); NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *); +NISTP384_PRE_COMP *ossl_ec_nistp384_pre_comp_dup(NISTP384_PRE_COMP *); NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *); NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *); NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *); @@ -341,6 +344,7 @@ EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *); void EC_pre_comp_free(EC_GROUP *group); void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *); void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *); +void ossl_ec_nistp384_pre_comp_free(NISTP384_PRE_COMP *); void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *); void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *); void EC_ec_pre_comp_free(EC_PRE_COMP *); @@ -552,6 +556,27 @@ int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, int ossl_ec_GFp_nistp256_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ossl_ec_GFp_nistp256_have_precompute_mult(const EC_GROUP *group); +/* method functions in ecp_nistp384.c */ +int ossl_ec_GFp_nistp384_group_init(EC_GROUP *group); +int ossl_ec_GFp_nistp384_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *); +int ossl_ec_GFp_nistp384_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx); +int ossl_ec_GFp_nistp384_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], const BIGNUM *scalars[], + BN_CTX *); +int ossl_ec_GFp_nistp384_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx); +int ossl_ec_GFp_nistp384_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int ossl_ec_GFp_nistp384_have_precompute_mult(const EC_GROUP *group); +const EC_METHOD *ossl_ec_GFp_nistp384_method(void); + /* method functions in ecp_nistp521.c */ int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group); int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, @@ -629,6 +654,11 @@ int ossl_ec_key_simple_generate_key(EC_KEY *eckey); int ossl_ec_key_simple_generate_public_key(EC_KEY *eckey); int ossl_ec_key_simple_check_key(const EC_KEY *eckey); +#ifdef ECP_SM2P256_ASM +/* Returns optimized methods for SM2 */ +const EC_METHOD *EC_GFp_sm2p256_method(void); +#endif + int ossl_ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx); /* EC_METHOD definitions */ diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c index c6ec2964b7c4..e9092a6c9db4 100644 --- a/crypto/ec/ec_mult.c +++ b/crypto/ec/ec_mult.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-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 @@ -45,7 +45,6 @@ struct ec_pre_comp_st { * objects followed by a NULL */ size_t num; /* numblocks * 2^(w-1) */ CRYPTO_REF_COUNT references; - CRYPTO_RWLOCK *lock; }; static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) @@ -56,19 +55,14 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group) return NULL; ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return ret; - } ret->group = group; ret->blocksize = 8; /* default */ ret->w = 4; /* default */ - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { OPENSSL_free(ret); return NULL; } @@ -79,7 +73,7 @@ EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre) { int i; if (pre != NULL) - CRYPTO_UP_REF(&pre->references, &i, pre->lock); + CRYPTO_UP_REF(&pre->references, &i); return pre; } @@ -90,8 +84,8 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre) if (pre == NULL) return; - CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_ec", pre); + CRYPTO_DOWN_REF(&pre->references, &i); + REF_PRINT_COUNT("EC_ec", i, pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -103,7 +97,7 @@ void EC_ec_pre_comp_free(EC_PRE_COMP *pre) EC_POINT_free(*pts); OPENSSL_free(pre->points); } - CRYPTO_THREAD_lock_free(pre->lock); + CRYPTO_FREE_REF(&pre->references); OPENSSL_free(pre); } @@ -171,7 +165,7 @@ int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, if (((p = EC_POINT_new(group)) == NULL) || ((s = EC_POINT_new(group)) == NULL)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -195,7 +189,7 @@ int ossl_ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, lambda = BN_CTX_get(ctx); k = BN_CTX_get(ctx); if (k == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -520,10 +514,8 @@ int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, if (wNAF != NULL) wNAF[0] = NULL; /* preliminary pivot */ - if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) goto err; - } /* * num_val will be the total number of temporarily precomputed points @@ -633,7 +625,6 @@ int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, wNAF[i + 1] = NULL; wNAF[i] = OPENSSL_malloc(wNAF_len[i]); if (wNAF[i] == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(tmp_wNAF); goto err; } @@ -661,10 +652,8 @@ int ossl_ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * subarray of 'pre_comp->points' if we already have precomputation. */ val = OPENSSL_malloc((num_val + 1) * sizeof(val[0])); - if (val == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (val == NULL) goto err; - } val[num_val] = NULL; /* pivot element */ /* allocate points for precomputation */ @@ -893,23 +882,21 @@ int ossl_ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) * and store */ points = OPENSSL_malloc(sizeof(*points) * (num + 1)); - if (points == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (points == NULL) goto err; - } var = points; var[num] = NULL; /* pivot */ for (i = 0; i < num; i++) { if ((var[i] = EC_POINT_new(group)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } } if ((tmp_point = EC_POINT_new(group)) == NULL || (base = EC_POINT_new(group)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } diff --git a/crypto/ec/ec_oct.c b/crypto/ec/ec_oct.c index 2b77e9738883..886e5fd310f4 100644 --- a/crypto/ec/ec_oct.c +++ b/crypto/ec/ec_oct.c @@ -144,10 +144,8 @@ size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point, len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); if (len == 0) return 0; - if ((buf = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(len)) == NULL) return 0; - } len = EC_POINT_point2oct(group, point, form, buf, len, ctx); if (len == 0) { OPENSSL_free(buf); diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c index 19e2f0d0c04d..716b1860bbf4 100644 --- a/crypto/ec/ec_pmeth.c +++ b/crypto/ec/ec_pmeth.c @@ -48,10 +48,8 @@ static int pkey_ec_init(EVP_PKEY_CTX *ctx) { EC_PKEY_CTX *dctx; - if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) return 0; - } dctx->cofactor_mode = -1; dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; @@ -229,10 +227,8 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, return 0; if (!pkey_ec_derive(ctx, NULL, &ktmplen)) return 0; - if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) return 0; - } if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) goto err; /* Do KDF stuff */ diff --git a/crypto/ec/ec_print.c b/crypto/ec/ec_print.c index ffe112052fbd..e14ffc002c0c 100644 --- a/crypto/ec/ec_print.c +++ b/crypto/ec/ec_print.c @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,18 +9,17 @@ #include /* strlen */ #include +#include "internal/cryptlib.h" #include "ec_local.h" -static const char *HEX_DIGITS = "0123456789ABCDEF"; - /* the return value must be freed (using OPENSSL_free()) */ char *EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, BN_CTX *ctx) { char *ret, *p; - size_t buf_len = 0, i; - unsigned char *buf = NULL, *pbuf; + size_t buf_len, i; + unsigned char *buf = NULL; buf_len = EC_POINT_point2buf(group, point, form, &buf, ctx); @@ -28,21 +27,16 @@ char *EC_POINT_point2hex(const EC_GROUP *group, return NULL; ret = OPENSSL_malloc(buf_len * 2 + 2); - if (ret == NULL) { - OPENSSL_free(buf); - return NULL; - } + if (ret == NULL) + goto err; + p = ret; - pbuf = buf; - for (i = buf_len; i > 0; i--) { - int v = (int)*(pbuf++); - *(p++) = HEX_DIGITS[v >> 4]; - *(p++) = HEX_DIGITS[v & 0x0F]; - } + for (i = 0; i < buf_len; ++i) + p += ossl_to_hex(p, buf[i]); *p = '\0'; + err: OPENSSL_free(buf); - return ret; } diff --git a/crypto/ec/ecdh_ossl.c b/crypto/ec/ecdh_ossl.c index 8016c6d7ad73..41f7e3904614 100644 --- a/crypto/ec/ecdh_ossl.c +++ b/crypto/ec/ecdh_ossl.c @@ -63,7 +63,7 @@ int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, BN_CTX_start(ctx); x = BN_CTX_get(ctx); if (x == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -80,16 +80,19 @@ int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, * * peer_public_key. */ if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { - if (!EC_GROUP_get_cofactor(group, x, NULL) || - !BN_mul(x, x, priv_key, ctx)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!EC_GROUP_get_cofactor(group, x, NULL)) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + if (!BN_mul(x, x, priv_key, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -118,10 +121,8 @@ int ossl_ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR); goto err; } - if ((buf = OPENSSL_malloc(buflen)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(buflen)) == NULL) goto err; - } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index 775b7ec911be..6104e5cbfc96 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -19,6 +19,7 @@ #include #include "crypto/bn.h" #include "ec_local.h" +#include "internal/deterministic_nonce.h" #define MIN_ECDSA_SIGN_ORDERBITS 64 /* @@ -29,6 +30,12 @@ */ #define MAX_ECDSA_SIGN_RETRIES 8 +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq); + int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { @@ -85,9 +92,48 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, return 1; } +int ossl_ecdsa_deterministic_sign(const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + EC_KEY *eckey, unsigned int nonce_type, + const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) +{ + ECDSA_SIG *s; + BIGNUM *kinv = NULL, *r = NULL; + int ret = 0; + + if (sig == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (digestname == NULL) { + ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST); + return 0; + } + + *siglen = 0; + if (!ecdsa_sign_setup(eckey, NULL, &kinv, &r, dgst, dlen, + nonce_type, digestname, libctx, propq)) + return 0; + + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); + if (s == NULL) + goto end; + + *siglen = i2d_ECDSA_SIG(s, &sig); + ECDSA_SIG_free(s); + ret = 1; +end: + BN_clear_free(kinv); + BN_clear_free(r); + return ret; +} + static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, - const unsigned char *dgst, int dlen) + const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *X = NULL; @@ -114,7 +160,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, if ((ctx = ctx_in) == NULL) { if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -123,7 +169,7 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, 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); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { @@ -146,19 +192,29 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, goto err; do { - /* get random k */ + /* get random or deterministic value of k */ do { + int res = 0; + if (dgst != NULL) { - if (!ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key, - dgst, dlen, ctx)) { - ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); - goto err; + if (nonce_type == 1) { +#ifndef FIPS_MODULE + res = ossl_gen_deterministic_nonce_rfc6979(k, order, + priv_key, + dgst, dlen, + digestname, + libctx, propq); +#endif + } else { + res = ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key, + dgst, dlen, ctx); } } else { - if (!ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx)) { - ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); - goto err; - } + res = ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx); + } + if (!res) { + ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); + goto err; } } while (ossl_bn_is_word_fixed_top(k, 0)); @@ -207,7 +263,8 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, 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); + return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0, + 0, NULL, NULL, NULL); } ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, @@ -242,20 +299,20 @@ ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, ret = ECDSA_SIG_new(); if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); 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); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); 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); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } @@ -281,7 +338,8 @@ ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, } do { if (in_kinv == NULL || in_r == NULL) { - if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { + if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len, + 0, NULL, NULL, NULL)) { ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); goto err; } @@ -289,7 +347,7 @@ ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, } else { ckinv = in_kinv; if (BN_copy(ret->r, in_r) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } @@ -408,7 +466,7 @@ int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, ctx = BN_CTX_new_ex(eckey->libctx); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return -1; } BN_CTX_start(ctx); @@ -467,7 +525,7 @@ int ossl_ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, } if ((point = EC_POINT_new(group)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c index 96ced7c8be0d..1bb58c6f3385 100644 --- a/crypto/ec/eck_prn.c +++ b/crypto/ec/eck_prn.c @@ -89,7 +89,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) ctx = BN_CTX_new(); if (ctx == NULL) { - reason = ERR_R_MALLOC_FAILURE; + reason = ERR_R_BN_LIB; goto err; } @@ -127,7 +127,7 @@ int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || (b = BN_new()) == NULL) { - reason = ERR_R_MALLOC_FAILURE; + reason = ERR_R_BN_LIB; goto err; } diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c index 35b492453f57..f0ef12621e02 100644 --- a/crypto/ec/ecp_mont.c +++ b/crypto/ec/ecp_mont.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -9,7 +9,7 @@ */ /* - * ECDSA low level APIs are deprecated for public use, but still ok for + * ECDSA low-level APIs are deprecated for public use, but still ok for * internal use. */ #include "internal/deprecated.h" @@ -217,7 +217,7 @@ int ossl_ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a /*- * Computes the multiplicative inverse of a in GF(p), storing the result in r. - * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * If a is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. * We have a Mont structure, so SCA hardening is FLT inversion. */ int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, @@ -258,7 +258,7 @@ int ossl_ec_GFp_mont_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a ret = 1; - err: + err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c index 5ab0dd7bef4f..6485f46f717c 100644 --- a/crypto/ec/ecp_nistp224.c +++ b/crypto/ec/ecp_nistp224.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-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 @@ -238,7 +238,6 @@ static const felem gmul[2][16][3] = { struct nistp224_pre_comp_st { felem g_pre_comp[2][16][3]; CRYPTO_REF_COUNT references; - CRYPTO_RWLOCK *lock; }; const EC_METHOD *EC_GFp_nistp224_method(void) @@ -1238,16 +1237,11 @@ static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) { NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); - if (!ret) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return ret; - } - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { OPENSSL_free(ret); return NULL; } @@ -1258,7 +1252,7 @@ NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *p) { int i; if (p != NULL) - CRYPTO_UP_REF(&p->references, &i, p->lock); + CRYPTO_UP_REF(&p->references, &i); return p; } @@ -1269,13 +1263,13 @@ void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p) if (p == NULL) return; - CRYPTO_DOWN_REF(&p->references, &i, p->lock); - REF_PRINT_COUNT("EC_nistp224", p); + CRYPTO_DOWN_REF(&p->references, &i); + REF_PRINT_COUNT("EC_nistp224", i, p); if (i > 0) return; REF_ASSERT_ISNT(i < 0); - CRYPTO_THREAD_lock_free(p->lock); + CRYPTO_FREE_REF(&p->references); OPENSSL_free(p); } @@ -1487,10 +1481,8 @@ int ossl_ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, tmp_felems = OPENSSL_malloc(sizeof(felem) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) - || (mixed && (tmp_felems == NULL))) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + || (mixed && (tmp_felems == NULL))) goto err; - } /* * we treat NULL scalars as 0, and NULL points as points at infinity, diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c index 4a55f925c465..eaf9dddbc8ec 100644 --- a/crypto/ec/ecp_nistp256.c +++ b/crypto/ec/ecp_nistp256.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -97,7 +97,7 @@ static const felem_bytearray nistp256_curve_params[5] = { * values, or four 64-bit values. The field element represented is: * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + v[3]*2^192 (mod p) * or: - * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[8]*2^512 (mod p) + * v[0]*2^0 + v[1]*2^64 + v[2]*2^128 + ... + v[7]*2^448 (mod p) * * 128-bit values are called 'limbs'. Since the limbs are spaced only 64 bits * apart, but are 128-bits wide, the most significant bits of each limb overlap @@ -118,8 +118,9 @@ typedef limb longfelem[NLIMBS * 2]; typedef u64 smallfelem[NLIMBS]; /* This is the value of the prime as four 64-bit words, little-endian. */ -static const u64 kPrime[4] = - { 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul }; +static const u64 kPrime[4] = { + 0xfffffffffffffffful, 0xffffffff, 0, 0xffffffff00000001ul +}; static const u64 bottom63bits = 0x7ffffffffffffffful; /* @@ -292,8 +293,9 @@ static void felem_diff(felem out, const felem in) #define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11) /* zero107 is 0 mod p */ -static const felem zero107 = - { two107m43m11, two107, two107m43p11, two107m43p11 }; +static const felem zero107 = { + two107m43m11, two107, two107m43p11, two107m43p11 +}; /*- * An alternative felem_diff for larger inputs |in| @@ -1773,7 +1775,6 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, struct nistp256_pre_comp_st { smallfelem g_pre_comp[2][16][3]; CRYPTO_REF_COUNT references; - CRYPTO_RWLOCK *lock; }; const EC_METHOD *EC_GFp_nistp256_method(void) @@ -1849,16 +1850,10 @@ static NISTP256_PRE_COMP *nistp256_pre_comp_new(void) { NISTP256_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return ret; - } - ret->references = 1; - - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { OPENSSL_free(ret); return NULL; } @@ -1869,7 +1864,7 @@ NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *p) { int i; if (p != NULL) - CRYPTO_UP_REF(&p->references, &i, p->lock); + CRYPTO_UP_REF(&p->references, &i); return p; } @@ -1880,13 +1875,13 @@ void EC_nistp256_pre_comp_free(NISTP256_PRE_COMP *pre) if (pre == NULL) return; - CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_nistp256", pre); + CRYPTO_DOWN_REF(&pre->references, &i); + REF_PRINT_COUNT("EC_nistp256", i, pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); - CRYPTO_THREAD_lock_free(pre->lock); + CRYPTO_FREE_REF(&pre->references); OPENSSL_free(pre); } @@ -2099,10 +2094,8 @@ int ossl_ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r, tmp_smallfelems = OPENSSL_malloc(sizeof(*tmp_smallfelems) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) - || (mixed && (tmp_smallfelems == NULL))) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + || (mixed && (tmp_smallfelems == NULL))) goto err; - } /* * we treat NULL scalars as 0, and NULL points as points at infinity, diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c index 31a97d793742..fe6836a14714 100644 --- a/crypto/ec/ecp_nistp521.c +++ b/crypto/ec/ecp_nistp521.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 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 @@ -676,8 +676,8 @@ static void felem_reduce(felem out, const largefelem in) } #if defined(ECP_NISTP521_ASM) -void felem_square_wrapper(largefelem out, const felem in); -void felem_mul_wrapper(largefelem out, const felem in1, const felem in2); +static void felem_square_wrapper(largefelem out, const felem in); +static void felem_mul_wrapper(largefelem out, const felem in1, const felem in2); static void (*felem_square_p)(largefelem out, const felem in) = felem_square_wrapper; @@ -691,7 +691,7 @@ void p521_felem_mul(largefelem out, const felem in1, const felem in2); # include "crypto/ppc_arch.h" # endif -void felem_select(void) +static void felem_select(void) { # if defined(_ARCH_PPC64) if ((OPENSSL_ppccap_P & PPC_MADD300) && (OPENSSL_ppccap_P & PPC_ALTIVEC)) { @@ -707,13 +707,13 @@ void felem_select(void) felem_mul_p = felem_mul_ref; } -void felem_square_wrapper(largefelem out, const felem in) +static void felem_square_wrapper(largefelem out, const felem in) { felem_select(); felem_square_p(out, in); } -void felem_mul_wrapper(largefelem out, const felem in1, const felem in2) +static void felem_mul_wrapper(largefelem out, const felem in1, const felem in2) { felem_select(); felem_mul_p(out, in1, in2); @@ -782,7 +782,6 @@ static void felem_inv(felem out, const felem in) felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */ felem_square(tmp, ftmp3); felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */ - felem_assign(ftmp4, ftmp3); felem_mul(tmp, ftmp3, ftmp); felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */ felem_square(tmp, ftmp4); @@ -843,9 +842,9 @@ static void felem_inv(felem out, const felem in) felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */ } felem_mul(tmp, ftmp3, ftmp4); - felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */ + felem_reduce(ftmp3, tmp); /* 2^521 - 2^2 */ felem_mul(tmp, ftmp3, in); - felem_reduce(out, tmp); /* 2^512 - 3 */ + felem_reduce(out, tmp); /* 2^521 - 3 */ } /* This is 2^521-1, expressed as an felem */ @@ -1666,7 +1665,6 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, struct nistp521_pre_comp_st { felem g_pre_comp[16][3]; CRYPTO_REF_COUNT references; - CRYPTO_RWLOCK *lock; }; const EC_METHOD *EC_GFp_nistp521_method(void) @@ -1742,16 +1740,10 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) { NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return ret; - } - ret->references = 1; - - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { OPENSSL_free(ret); return NULL; } @@ -1762,7 +1754,7 @@ NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *p) { int i; if (p != NULL) - CRYPTO_UP_REF(&p->references, &i, p->lock); + CRYPTO_UP_REF(&p->references, &i); return p; } @@ -1773,13 +1765,13 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) if (p == NULL) return; - CRYPTO_DOWN_REF(&p->references, &i, p->lock); - REF_PRINT_COUNT("EC_nistp521", p); + CRYPTO_DOWN_REF(&p->references, &i); + REF_PRINT_COUNT("EC_nistp521", i, p); if (i > 0) return; REF_ASSERT_ISNT(i < 0); - CRYPTO_THREAD_lock_free(p->lock); + CRYPTO_FREE_REF(&p->references); OPENSSL_free(p); } @@ -1992,10 +1984,8 @@ int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, tmp_felems = OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) - || (mixed && (tmp_felems == NULL))) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + || (mixed && (tmp_felems == NULL))) goto err; - } /* * we treat NULL scalars as 0, and NULL points as points at infinity, diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index d65f6984ded3..0e405c0e681d 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2014, Intel Corporation. All Rights Reserved. * Copyright (c) 2015, CloudFlare, Inc. * @@ -37,14 +37,6 @@ # define TOBN(hi,lo) ((BN_ULONG)hi<<32|lo) #endif -#if defined(__GNUC__) -# define ALIGN32 __attribute((aligned(32))) -#elif defined(_MSC_VER) -# define ALIGN32 __declspec(align(32)) -#else -# define ALIGN32 -#endif - #define ALIGNPTR(p,N) ((unsigned char *)p+N-(size_t)p%N) #define P256_LIMBS (256/BN_BITS2) @@ -75,7 +67,6 @@ struct nistz256_pre_comp_st { PRECOMP256_ROW *precomp; void *precomp_storage; CRYPTO_REF_COUNT references; - CRYPTO_RWLOCK *lock; }; /* Functions implemented in assembly */ @@ -636,10 +627,8 @@ __owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group, OPENSSL_malloc((num * 16 + 5) * sizeof(P256_POINT) + 64)) == NULL || (p_str = OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL - || (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + || (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) goto err; - } table = (void *)ALIGNPTR(table_storage, 64); temp = (P256_POINT *)(table + num); @@ -868,10 +857,8 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) w = 7; if ((precomp_storage = - OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) goto err; - } preComputedTable = (void *)ALIGNPTR(precomp_storage, 64); @@ -974,7 +961,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, BIGNUM *tmp_scalar; if ((num + 1) == 0 || (num + 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_PASSED_INVALID_ARGUMENT); return 0; } @@ -1123,16 +1110,12 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, * handled like a normal point. */ new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *)); - if (new_scalars == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (new_scalars == NULL) goto err; - } new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *)); - if (new_points == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (new_points == NULL) goto err; - } memcpy(new_scalars, scalars, num * sizeof(BIGNUM *)); new_scalars[num] = scalar; @@ -1226,18 +1209,13 @@ static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group) ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return ret; - } ret->group = group; ret->w = 6; /* default */ - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { OPENSSL_free(ret); return NULL; } @@ -1248,7 +1226,7 @@ NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *p) { int i; if (p != NULL) - CRYPTO_UP_REF(&p->references, &i, p->lock); + CRYPTO_UP_REF(&p->references, &i); return p; } @@ -1259,14 +1237,14 @@ void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre) if (pre == NULL) return; - CRYPTO_DOWN_REF(&pre->references, &i, pre->lock); - REF_PRINT_COUNT("EC_nistz256", pre); + CRYPTO_DOWN_REF(&pre->references, &i); + REF_PRINT_COUNT("EC_nistz256", i, pre); if (i > 0) return; REF_ASSERT_ISNT(i < 0); OPENSSL_free(pre->precomp_storage); - CRYPTO_THREAD_lock_free(pre->lock); + CRYPTO_FREE_REF(&pre->references); OPENSSL_free(pre); } @@ -1378,7 +1356,7 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, /* * The bottom 128 bit of the exponent are processed with fixed 4-bit window */ - for(i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { /* expLo - the low 128 bits of the exponent we use (ord(p256) - 2), * split into nibbles */ static const unsigned char expLo[32] = { @@ -1467,6 +1445,131 @@ err: # define ecp_nistz256_inv_mod_ord NULL #endif +static int ecp_nistz256group_full_init(EC_GROUP *group, + const unsigned char *params) { + BN_CTX *ctx = NULL; + BN_MONT_CTX *mont = NULL, *ordmont = NULL; + const int param_len = 32; + const int seed_len = 20; + int ok = 0; + uint32_t hi_order_n = 0xccd1c8aa; + uint32_t lo_order_n = 0xee00bc4f; + BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *one = NULL, + *order = NULL; + EC_POINT *P = NULL; + + if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!EC_GROUP_set_seed(group, params, seed_len)) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + params += seed_len; + + if ((p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) == NULL + || (a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) == NULL + || (b = BN_bin2bn(params + 2 * param_len, param_len, NULL)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto err; + } + + /* + * Set up curve params and montgomery for field + * Start by setting up montgomery and one + */ + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + + if (!ossl_bn_mont_ctx_set(mont, p, 256, params + 6 * param_len, param_len, + 1, 0)) + goto err; + + one = BN_new(); + if (one == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto err; + } + if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)){ + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto err; + } + group->field_data1 = mont; + mont = NULL; + group->field_data2 = one; + one = NULL; + + if (!ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + + if ((P = EC_POINT_new(group)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + + if ((x = BN_bin2bn(params + 3 * param_len, param_len, NULL)) == NULL + || (y = BN_bin2bn(params + 4 * param_len, param_len, NULL)) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto err; + } + if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + if ((order = BN_bin2bn(params + 5 * param_len, param_len, NULL)) == NULL + || !BN_set_word(x, (BN_ULONG)1)) { /* cofactor is 1 */ + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); + goto err; + } + + /* + * Set up generator and order and montgomery data + */ + group->generator = EC_POINT_new(group); + if (group->generator == NULL){ + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); + goto err; + } + if (!EC_POINT_copy(group->generator, P)) + goto err; + if (!BN_copy(group->order, order)) + goto err; + if (!BN_set_word(group->cofactor, 1)) + goto err; + + ordmont = BN_MONT_CTX_new(); + if (ordmont == NULL) + goto err; + if (!ossl_bn_mont_ctx_set(ordmont, order, 256, params + 7 * param_len, + param_len, lo_order_n, hi_order_n)) + goto err; + + group->mont_data = ordmont; + ordmont = NULL; + + ok = 1; + + err: + EC_POINT_free(P); + BN_CTX_free(ctx); + BN_MONT_CTX_free(mont); + BN_MONT_CTX_free(ordmont); + BN_free(p); + BN_free(one); + BN_free(a); + BN_free(b); + BN_free(order); + BN_free(x); + BN_free(y); + + return ok; +} + const EC_METHOD *EC_GFp_nistz256_method(void) { static const EC_METHOD ret = { @@ -1523,7 +1626,8 @@ const EC_METHOD *EC_GFp_nistz256_method(void) 0, /* blind_coordinates */ 0, /* ladder_pre */ 0, /* ladder_step */ - 0 /* ladder_post */ + 0, /* ladder_post */ + ecp_nistz256group_full_init }; return &ret; diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c index 0c10196ea34e..f13f8bed242d 100644 --- a/crypto/ec/ecp_s390x_nistp.c +++ b/crypto/ec/ecp_s390x_nistp.c @@ -1,5 +1,5 @@ /* - * 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 @@ -152,14 +152,14 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst, k = BN_secure_new(); sig = ECDSA_SIG_new(); if (k == NULL || sig == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); goto ret; } sig->r = BN_new(); sig->s = BN_new(); if (sig->r == NULL || sig->s == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto ret; } @@ -178,7 +178,7 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst, goto ret; } /* - * Generate random k and copy to param param block. RAND_priv_bytes_ex + * Generate random k and copy to param block. RAND_priv_bytes_ex * is used instead of BN_priv_rand_range or BN_generate_dsa_nonce * because kdsa instruction constructs an in-range, invertible nonce * internally implementing counter-measures for RNG weakness. @@ -247,7 +247,7 @@ static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen, ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return -1; } @@ -256,7 +256,7 @@ static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen, x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (x == NULL || y == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto ret; } diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c index bde8cad34641..112a4f0a2f4d 100644 --- a/crypto/ec/ecp_smpl.c +++ b/crypto/ec/ecp_smpl.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2022 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 @@ -9,7 +9,7 @@ */ /* - * ECDSA low level APIs are deprecated for public use, but still ok for + * ECDSA low-level APIs are deprecated for public use, but still ok for * internal use. */ #include "internal/deprecated.h" @@ -171,7 +171,7 @@ int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *group, /* group->a */ if (!BN_nnmod(tmp_a, a, p, ctx)) goto err; - if (group->meth->field_encode) { + if (group->meth->field_encode != NULL) { if (!group->meth->field_encode(group, group->a, tmp_a, ctx)) goto err; } else if (!BN_copy(group->a, tmp_a)) @@ -180,7 +180,7 @@ int ossl_ec_GFp_simple_group_set_curve(EC_GROUP *group, /* group->b */ if (!BN_nnmod(group->b, b, p, ctx)) goto err; - if (group->meth->field_encode) + if (group->meth->field_encode != NULL) if (!group->meth->field_encode(group, group->b, group->b, ctx)) goto err; @@ -209,7 +209,7 @@ int ossl_ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, } if (a != NULL || b != NULL) { - if (group->meth->field_decode) { + if (group->meth->field_decode != NULL) { if (ctx == NULL) { ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) @@ -258,7 +258,7 @@ int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, if (ctx == NULL) { ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } } @@ -271,7 +271,7 @@ int ossl_ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, if (order == NULL) goto err; - if (group->meth->field_decode) { + if (group->meth->field_decode != NULL) { if (!group->meth->field_decode(group, a, group->a, ctx)) goto err; if (!group->meth->field_decode(group, b, group->b, ctx)) @@ -440,7 +440,7 @@ int ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group, BN_CTX *new_ctx = NULL; int ret = 0; - if (group->meth->field_decode != 0) { + if (group->meth->field_decode != NULL) { if (ctx == NULL) { ctx = new_ctx = BN_CTX_new_ex(group->libctx); if (ctx == NULL) @@ -529,7 +529,7 @@ int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */ - if (group->meth->field_decode) { + if (group->meth->field_decode != NULL) { if (!group->meth->field_decode(group, Z, point->Z, ctx)) goto err; Z_ = Z; @@ -538,7 +538,7 @@ int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, } if (BN_is_one(Z_)) { - if (group->meth->field_decode) { + if (group->meth->field_decode != NULL) { if (x != NULL) { if (!group->meth->field_decode(group, x, point->X, ctx)) goto err; @@ -563,7 +563,7 @@ int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, goto err; } - if (group->meth->field_encode == 0) { + if (group->meth->field_encode == NULL) { /* field_sqr works on standard representation */ if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) goto err; @@ -582,7 +582,7 @@ int ossl_ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group, } if (y != NULL) { - if (group->meth->field_encode == 0) { + if (group->meth->field_encode == NULL) { /* * field_mul works on standard representation */ @@ -1275,7 +1275,7 @@ int ossl_ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - if (group->meth->field_encode != 0) { + if (group->meth->field_encode != NULL) { /* * In the Montgomery case, we just turned R*H (representing H) into * 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to @@ -1376,7 +1376,7 @@ int ossl_ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM /*- * Computes the multiplicative inverse of a in GF(p), storing the result in r. - * If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error. + * If a is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. * Since we don't have a Mont structure here, SCA hardening is with blinding. * NB: "a" must be in _decoded_ form. (i.e. field_decode must precede.) */ @@ -1423,8 +1423,8 @@ int ossl_ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, /*- * Apply randomization of EC point projective coordinates: * - * (X, Y ,Z ) = (lambda^2*X, lambda^3*Y, lambda*Z) - * lambda = [1,group->field) + * (X, Y, Z) = (lambda^2*X, lambda^3*Y, lambda*Z) + * lambda = [1, group->field) * */ int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, @@ -1438,7 +1438,7 @@ int ossl_ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, lambda = BN_CTX_get(ctx); temp = BN_CTX_get(ctx); if (temp == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto end; } diff --git a/crypto/ec/ecx_backend.c b/crypto/ec/ecx_backend.c index e42767d6bf0f..d21c037841ae 100644 --- a/crypto/ec/ecx_backend.c +++ b/crypto/ec/ecx_backend.c @@ -110,22 +110,16 @@ ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) { ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } - - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - OPENSSL_free(ret); - return NULL; - } ret->libctx = key->libctx; ret->haspubkey = 0; ret->keylen = key->keylen; ret->type = key->type; - ret->references = 1; + + if (!CRYPTO_NEW_REF(&ret->references, 1)) + goto err; if (key->propq != NULL) { ret->propq = OPENSSL_strdup(key->propq); @@ -141,16 +135,18 @@ ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 && key->privkey != NULL) { - if (ossl_ecx_key_allocate_privkey(ret) == NULL) + if (ossl_ecx_key_allocate_privkey(ret) == NULL) { + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; + } memcpy(ret->privkey, key->privkey, ret->keylen); } return ret; err: + CRYPTO_FREE_REF(&ret->references); ossl_ecx_key_free(ret); - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return NULL; } @@ -189,7 +185,7 @@ ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); if (key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); return 0; } pubkey = key->pubkey; @@ -199,7 +195,7 @@ ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, } else { privkey = ossl_ecx_key_allocate_privkey(key); if (privkey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } if (op == KEY_OP_KEYGEN) { diff --git a/crypto/ec/ecx_key.c b/crypto/ec/ecx_key.c index dcec26c2e9b3..7b094949126f 100644 --- a/crypto/ec/ecx_key.c +++ b/crypto/ec/ecx_key.c @@ -1,5 +1,5 @@ /* - * 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 @@ -9,7 +9,13 @@ #include #include +#include #include "crypto/ecx.h" +#include "internal/common.h" /* for ossl_assert() */ + +#ifdef S390X_EC_ASM +# include "s390x_arch.h" +#endif ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey, const char *propq) @@ -36,20 +42,21 @@ ECX_KEY *ossl_ecx_key_new(OSSL_LIB_CTX *libctx, ECX_KEY_TYPE type, int haspubkey break; } ret->type = type; - ret->references = 1; + + if (!CRYPTO_NEW_REF(&ret->references, 1)) + goto err; if (propq != NULL) { ret->propq = OPENSSL_strdup(propq); if (ret->propq == NULL) goto err; } - - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) - goto err; return ret; err: - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (ret != NULL) { + OPENSSL_free(ret->propq); + CRYPTO_FREE_REF(&ret->references); + } OPENSSL_free(ret); return NULL; } @@ -61,15 +68,18 @@ void ossl_ecx_key_free(ECX_KEY *key) if (key == NULL) return; - CRYPTO_DOWN_REF(&key->references, &i, key->lock); - REF_PRINT_COUNT("ECX_KEY", key); + CRYPTO_DOWN_REF(&key->references, &i); + REF_PRINT_COUNT("ECX_KEY", i, key); if (i > 0) return; REF_ASSERT_ISNT(i < 0); OPENSSL_free(key->propq); +#ifdef OPENSSL_PEDANTIC_ZEROIZATION + OPENSSL_cleanse(&key->pubkey, sizeof(key->pubkey)); +#endif OPENSSL_secure_clear_free(key->privkey, key->keylen); - CRYPTO_THREAD_lock_free(key->lock); + CRYPTO_FREE_REF(&key->references); OPENSSL_free(key); } @@ -82,10 +92,10 @@ int ossl_ecx_key_up_ref(ECX_KEY *key) { int i; - if (CRYPTO_UP_REF(&key->references, &i, key->lock) <= 0) + if (CRYPTO_UP_REF(&key->references, &i) <= 0) return 0; - REF_PRINT_COUNT("ECX_KEY", key); + REF_PRINT_COUNT("ECX_KEY", i, key); REF_ASSERT_ISNT(i < 2); return ((i > 1) ? 1 : 0); } @@ -96,3 +106,61 @@ unsigned char *ossl_ecx_key_allocate_privkey(ECX_KEY *key) return key->privkey; } + +int ossl_ecx_compute_key(ECX_KEY *peer, ECX_KEY *priv, size_t keylen, + unsigned char *secret, size_t *secretlen, size_t outlen) +{ + if (priv == NULL + || priv->privkey == NULL + || peer == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return 0; + } + + if (!ossl_assert(keylen == X25519_KEYLEN + || keylen == X448_KEYLEN)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + + if (secret == NULL) { + *secretlen = keylen; + return 1; + } + if (outlen < keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (keylen == X25519_KEYLEN) { +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] + & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) { + if (s390x_x25519_mul(secret, peer->pubkey, priv->privkey) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION); + return 0; + } + } else +#endif + if (ossl_x25519(secret, priv->privkey, peer->pubkey) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION); + return 0; + } + } else { +#ifdef S390X_EC_ASM + if (OPENSSL_s390xcap_P.pcc[1] + & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) { + if (s390x_x448_mul(secret, peer->pubkey, priv->privkey) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION); + return 0; + } + } else +#endif + if (ossl_x448(secret, priv->privkey, peer->pubkey) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION); + return 0; + } + } + *secretlen = keylen; + return 1; +} diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index c97dc472ac57..6c445f9121b6 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -39,15 +39,13 @@ static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) } penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey)); - if (penc == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + if (penc == NULL) 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); + ERR_raise(ERR_LIB_EC, ERR_R_X509_LIB); return 0; } return 1; @@ -115,14 +113,14 @@ static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) penclen = i2d_ASN1_OCTET_STRING(&oct, &penc); if (penclen < 0) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); 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); + ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB); return 0; } @@ -138,7 +136,7 @@ static int ecx_bits(const EVP_PKEY *pkey) { if (IS25519(pkey->ameth->pkey_id)) { return X25519_BITS; - } else if(ISX448(pkey->ameth->pkey_id)) { + } else if (ISX448(pkey->ameth->pkey_id)) { return X448_BITS; } else { return ED448_BITS; @@ -392,7 +390,7 @@ static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx, pctx->propquery); if (ecx == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_EC_LIB); return 0; } @@ -561,17 +559,23 @@ static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, return 2; } +static int ecd_item_sign(X509_ALGOR *alg1, X509_ALGOR *alg2, int nid) +{ + /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */ + /* Set algorithms identifiers */ + (void)X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); + if (alg2 != NULL) + (void)X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL); + /* Algorithm identifiers set: carry on as normal */ + return 3; +} + 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; + return ecd_item_sign(alg1, alg2, NID_ED25519); } static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg, @@ -587,12 +591,7 @@ static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it, 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; + return ecd_item_sign(alg1, alg2, NID_ED448); } static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg, @@ -822,8 +821,10 @@ static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig, return 0; } - if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL, - NULL) == 0) + if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, + 0, 0, 0, + NULL, 0, + NULL, NULL) == 0) return 0; *siglen = ED25519_SIGSIZE; return 1; @@ -850,7 +851,7 @@ static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig, } if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey, - edkey->privkey, NULL, 0, edkey->propq) == 0) + edkey->privkey, NULL, 0, 0, edkey->propq) == 0) return 0; *siglen = ED448_SIGSIZE; return 1; @@ -871,6 +872,8 @@ static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig, return 0; return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey, + 0, 0, 0, + NULL, 0, edkey->libctx, edkey->propq); } @@ -889,7 +892,7 @@ static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig, return 0; return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey, - NULL, 0, edkey->propq); + NULL, 0, 0, edkey->propq); } static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) @@ -945,7 +948,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) unsigned char *privkey = NULL, *pubkey; if (key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -953,7 +956,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) privkey = ossl_ecx_key_allocate_privkey(key); if (privkey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -988,7 +991,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) unsigned char *privkey = NULL, *pubkey; if (key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -996,7 +999,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) privkey = ossl_ecx_key_allocate_privkey(key); if (privkey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1037,7 +1040,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) int rv; if (key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1045,7 +1048,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) privkey = ossl_ecx_key_allocate_privkey(key); if (privkey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1103,7 +1106,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) int rv; if (key == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } @@ -1111,7 +1114,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) privkey = ossl_ecx_key_allocate_privkey(key); if (privkey == NULL) { - ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); goto err; } diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c index 2e4b7ed60b9c..ffcf3cde1155 100644 --- a/crypto/encode_decode/decoder_lib.c +++ b/crypto/encode_decode/decoder_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,9 +18,10 @@ #include #include "internal/bio.h" #include "internal/provider.h" +#include "internal/namemap.h" #include "crypto/decoder.h" #include "encoder_local.h" -#include "e_os.h" +#include "internal/e_os.h" struct decoder_process_data_st { OSSL_DECODER_CTX *ctx; @@ -209,6 +210,34 @@ int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, return 1; } +OSSL_DECODER_INSTANCE * +ossl_decoder_instance_new_forprov(OSSL_DECODER *decoder, void *provctx, + const char *input_structure) +{ + void *decoderctx; + + if (!ossl_assert(decoder != NULL)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + decoderctx = decoder->newctx(provctx); + if (decoderctx == NULL) + return 0; + if (input_structure != NULL && decoder->set_ctx_params != NULL) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + (char *)input_structure, 0); + if (!decoder->set_ctx_params(decoderctx, params)) { + decoder->freectx(decoderctx); + return 0; + } + } + return ossl_decoder_instance_new(decoder, decoderctx); +} + OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, void *decoderctx) { @@ -223,10 +252,8 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, return 0; } - if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + if ((decoder_inst = OPENSSL_zalloc(sizeof(*decoder_inst))) == NULL) return 0; - } prov = OSSL_DECODER_get0_provider(decoder); libctx = ossl_provider_libctx(prov); @@ -241,6 +268,7 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder, /* The "input" property is mandatory */ prop = ossl_property_find_property(props, libctx, "input"); decoder_inst->input_type = ossl_property_get_string_value(libctx, prop); + decoder_inst->input_type_id = 0; if (decoder_inst->input_type == NULL) { ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION, "the mandatory 'input' property is missing " @@ -281,6 +309,47 @@ void ossl_decoder_instance_free(OSSL_DECODER_INSTANCE *decoder_inst) } } +OSSL_DECODER_INSTANCE *ossl_decoder_instance_dup(const OSSL_DECODER_INSTANCE *src) +{ + OSSL_DECODER_INSTANCE *dest; + const OSSL_PROVIDER *prov; + void *provctx; + + if ((dest = OPENSSL_zalloc(sizeof(*dest))) == NULL) + return NULL; + + *dest = *src; + if (!OSSL_DECODER_up_ref(dest->decoder)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); + goto err; + } + prov = OSSL_DECODER_get0_provider(dest->decoder); + provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + + dest->decoderctx = dest->decoder->newctx(provctx); + if (dest->decoderctx == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); + OSSL_DECODER_free(dest->decoder); + goto err; + } + + return dest; + + err: + OPENSSL_free(dest); + return NULL; +} + +void ossl_decoder_ctx_set_harderr(OSSL_DECODER_CTX *ctx) +{ + ctx->harderr = 1; +} + +int ossl_decoder_ctx_get_harderr(const OSSL_DECODER_CTX *ctx) +{ + return ctx->harderr; +} + int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx, OSSL_DECODER_INSTANCE *di) { @@ -289,7 +358,7 @@ int ossl_decoder_ctx_add_decoder_inst(OSSL_DECODER_CTX *ctx, if (ctx->decoder_insts == NULL && (ctx->decoder_insts = sk_OSSL_DECODER_INSTANCE_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); return 0; } @@ -343,6 +412,8 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder) struct collect_extra_decoder_data_st { OSSL_DECODER_CTX *ctx; const char *output_type; + int output_type_id; + /* * 0 to check that the decoder's input type is the same as the decoder name * 1 to check that the decoder's input type differs from the decoder name @@ -370,7 +441,7 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder); void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); - if (OSSL_DECODER_is_a(decoder, data->output_type)) { + if (ossl_decoder_fast_is_a(decoder, data->output_type, &data->output_type_id)) { void *decoderctx = NULL; OSSL_DECODER_INSTANCE *di = NULL; @@ -405,6 +476,20 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) if ((decoderctx = decoder->newctx(provctx)) == NULL) return; + if (decoder->set_ctx_params != NULL + && data->ctx->input_structure != NULL) { + OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END }; + const char *str = data->ctx->input_structure; + + params[0] = + OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + (char *)str, 0); + if (!decoder->set_ctx_params(decoderctx, params)) { + decoder->freectx(decoderctx); + return; + } + } + if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) { decoder->freectx(decoderctx); return; @@ -413,8 +498,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) switch (data->type_check) { case IS_SAME: /* If it differs, this is not a decoder to add for now. */ - if (!OSSL_DECODER_is_a(decoder, - OSSL_DECODER_INSTANCE_get_input_type(di))) { + if (!ossl_decoder_fast_is_a(decoder, + OSSL_DECODER_INSTANCE_get_input_type(di), + &di->input_type_id)) { ossl_decoder_instance_free(di); OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, @@ -425,8 +511,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg) break; case IS_DIFFERENT: /* If it's the same, this is not a decoder to add for now. */ - if (OSSL_DECODER_is_a(decoder, - OSSL_DECODER_INSTANCE_get_input_type(di))) { + if (ossl_decoder_fast_is_a(decoder, + OSSL_DECODER_INSTANCE_get_input_type(di), + &di->input_type_id)) { ossl_decoder_instance_free(di); OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, @@ -502,7 +589,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, skdecoders = sk_OSSL_DECODER_new_null(); if (skdecoders == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); return 0; } OSSL_DECODER_do_all_provided(libctx, collect_all_decoders, skdecoders); @@ -534,6 +621,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, data.output_type = OSSL_DECODER_INSTANCE_get_input_type(decoder_inst); + data.output_type_id = 0; for (j = 0; j < numdecoders; j++) collect_extra_decoder(sk_OSSL_DECODER_value(skdecoders, j), @@ -687,6 +775,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) struct decoder_process_data_st new_data; const char *data_type = NULL; const char *data_structure = NULL; + /* Saved to restore on return, mutated in PEM->DER transition. */ + const char *start_input_type = ctx->start_input_type; /* * This is an indicator up the call stack that something was indeed @@ -777,6 +867,23 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &data_structure)) goto end; + /* Get the new input type if there is one */ + p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_INPUT_TYPE); + if (p != NULL) { + if (!OSSL_PARAM_get_utf8_string_ptr(p, &ctx->start_input_type)) + goto end; + /* + * When switching PKCS8 from PEM to DER we decrypt the data if needed + * and then determine the algorithm OID. Likewise, with SPKI, only + * this time sans decryption. + */ + if (ctx->input_structure != NULL + && (OPENSSL_strcasecmp(ctx->input_structure, "SubjectPublicKeyInfo") == 0 + || OPENSSL_strcasecmp(data_structure, "PrivateKeyInfo") == 0 + || OPENSSL_strcasecmp(ctx->input_structure, "PrivateKeyInfo") == 0)) + data->flag_input_structure_checked = 1; + } + /* * If the data structure is "type-specific" and the data type is * given, we drop the data structure. The reasoning is that the @@ -818,7 +925,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) } if ((cbio = ossl_core_bio_new_from_bio(bio)) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_BIO_LIB); goto end; } @@ -827,6 +934,7 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) sk_OSSL_DECODER_INSTANCE_value(ctx->decoder_insts, i); OSSL_DECODER *new_decoder = OSSL_DECODER_INSTANCE_get_decoder(new_decoder_inst); + const char *new_decoder_name = NULL; void *new_decoderctx = OSSL_DECODER_INSTANCE_get_decoder_ctx(new_decoder_inst); const char *new_input_type = @@ -837,12 +945,13 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) &n_i_s_was_set); OSSL_TRACE_BEGIN(DECODER) { + new_decoder_name = OSSL_DECODER_get0_name(new_decoder); BIO_printf(trc_out, "(ctx %p) %s [%u] Considering decoder instance %p (decoder %p):\n" " %s with %s\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, (void *)new_decoder_inst, (void *)new_decoder, - OSSL_DECODER_get0_name(new_decoder), + new_decoder_name, OSSL_DECODER_get0_properties(new_decoder)); } OSSL_TRACE_END(DECODER); @@ -868,7 +977,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) * |new_input_type| holds the value of the "input-type" parameter * for the decoder we're currently considering. */ - if (decoder != NULL && !OSSL_DECODER_is_a(decoder, new_input_type)) { + if (decoder != NULL && !ossl_decoder_fast_is_a(decoder, new_input_type, + &new_decoder_inst->input_type_id)) { OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, "(ctx %p) %s [%u] the input type doesn't match the name of the previous decoder (%p), skipping...\n", @@ -946,9 +1056,9 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) /* Recurse */ OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, - "(ctx %p) %s [%u] Running decoder instance %p\n", + "(ctx %p) %s [%u] Running decoder instance %s (%p)\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, - (void *)new_decoder_inst); + new_decoder_name, (void *)new_decoder_inst); } OSSL_TRACE_END(DECODER); /* @@ -968,10 +1078,10 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) OSSL_TRACE_BEGIN(DECODER) { BIO_printf(trc_out, - "(ctx %p) %s [%u] Running decoder instance %p => %d" + "(ctx %p) %s [%u] Running decoder instance %s (%p) => %d" " (recursed further: %s, construct called: %s)\n", (void *)new_data.ctx, LEVEL, (unsigned int)i, - (void *)new_decoder_inst, ok, + new_decoder_name, (void *)new_decoder_inst, ok, new_data.flag_next_level_called ? "yes" : "no", new_data.flag_construct_called ? "yes" : "no"); } OSSL_TRACE_END(DECODER); @@ -996,5 +1106,6 @@ static int decoder_process(const OSSL_PARAM params[], void *arg) end: ossl_core_bio_free(cbio); BIO_free(new_data.bio); + ctx->start_input_type = start_input_type; return ok; } diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c index 56899a926981..85ab3b528673 100644 --- a/crypto/encode_decode/decoder_meth.c +++ b/crypto/encode_decode/decoder_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,26 +17,35 @@ #include "internal/provider.h" #include "crypto/decoder.h" #include "encoder_local.h" +#include "crypto/context.h" /* * Decoder can have multiple names, separated with colons in a name string */ #define NAME_SEPARATOR ':' +static void ossl_decoder_free(void *data) +{ + OSSL_DECODER_free(data); +} + +static int ossl_decoder_up_ref(void *data) +{ + return OSSL_DECODER_up_ref(data); +} + /* Simple method structure constructor and destructor */ static OSSL_DECODER *ossl_decoder_new(void) { OSSL_DECODER *decoder = NULL; - if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL - || (decoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { + if ((decoder = OPENSSL_zalloc(sizeof(*decoder))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&decoder->base.refcnt, 1)) { OSSL_DECODER_free(decoder); - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); return NULL; } - decoder->base.refcnt = 1; - return decoder; } @@ -44,7 +53,7 @@ int OSSL_DECODER_up_ref(OSSL_DECODER *decoder) { int ref = 0; - CRYPTO_UP_REF(&decoder->base.refcnt, &ref, decoder->base.lock); + CRYPTO_UP_REF(&decoder->base.refcnt, &ref); return 1; } @@ -55,35 +64,16 @@ void OSSL_DECODER_free(OSSL_DECODER *decoder) if (decoder == NULL) return; - CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref, decoder->base.lock); + CRYPTO_DOWN_REF(&decoder->base.refcnt, &ref); if (ref > 0) return; OPENSSL_free(decoder->base.name); ossl_property_free(decoder->base.parsed_propdef); ossl_provider_free(decoder->base.prov); - CRYPTO_THREAD_lock_free(decoder->base.lock); + CRYPTO_FREE_REF(&decoder->base.refcnt); OPENSSL_free(decoder); } -/* Permanent decoder method store, constructor and destructor */ -static void decoder_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *decoder_store_new(OSSL_LIB_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OSSL_LIB_CTX_METHOD decoder_store_method = { - /* We want decoder_store to be cleaned up before the provider store */ - OSSL_LIB_CTX_METHOD_PRIORITY_2, - decoder_store_new, - decoder_store_free, -}; - /* Data to be passed through ossl_method_construct() */ struct decoder_data_st { OSSL_LIB_CTX *libctx; @@ -120,8 +110,7 @@ static void dealloc_tmp_decoder_store(void *store) /* Get the permanent decoder store */ static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX, - &decoder_store_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_STORE_INDEX); } static int reserve_decoder_store(void *store, void *data) @@ -212,8 +201,8 @@ static int put_decoder_in_store(void *store, void *method, return 0; return ossl_method_store_add(store, prov, id, propdef, method, - (int (*)(void *))OSSL_DECODER_up_ref, - (void (*)(void *))OSSL_DECODER_free); + ossl_decoder_up_ref, + ossl_decoder_free); } /* Create and populate a decoder method */ @@ -359,38 +348,27 @@ static void free_decoder(void *method) /* Fetching support. Can fetch by numeric identity or by name */ static OSSL_DECODER * -inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id, +inner_ossl_decoder_fetch(struct decoder_data_st *methdata, const char *name, const char *properties) { OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx); OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); const char *const propq = properties != NULL ? properties : ""; void *method = NULL; - int unsupported = 0; + int unsupported, id; if (store == NULL || namemap == NULL) { ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - /* - * If we have been passed both an id and a name, we have an - * internal programming error. - */ - if (!ossl_assert(id == 0 || name == NULL)) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); - return NULL; - } - - if (id == 0 && name != NULL) - id = ossl_namemap_name2num(namemap, name); + id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0; /* * If we haven't found the name yet, chances are that the algorithm to * be fetched is unsupported. */ - if (id == 0) - unsupported = 1; + unsupported = id == 0; if (id == 0 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { @@ -455,20 +433,7 @@ OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name, methdata.libctx = libctx; methdata.tmp_store = NULL; - method = inner_ossl_decoder_fetch(&methdata, 0, name, properties); - dealloc_tmp_decoder_store(methdata.tmp_store); - return method; -} - -OSSL_DECODER *ossl_decoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id, - const char *properties) -{ - struct decoder_data_st methdata; - void *method; - - methdata.libctx = libctx; - methdata.tmp_store = NULL; - method = inner_ossl_decoder_fetch(&methdata, id, NULL, properties); + method = inner_ossl_decoder_fetch(&methdata, name, properties); dealloc_tmp_decoder_store(methdata.tmp_store); return method; } @@ -558,6 +523,24 @@ int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name) return 0; } +static int resolve_name(OSSL_DECODER *decoder, const char *name) +{ + OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + return ossl_namemap_name2num(namemap, name); +} + +int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, const char *name, int *id_cache) +{ + int id = *id_cache; + + if (id <= 0) + *id_cache = id = resolve_name(decoder, name); + + return id > 0 && ossl_decoder_get_number(decoder) == id; +} + struct do_one_data_st { void (*user_fn)(OSSL_DECODER *decoder, void *arg); void *user_arg; @@ -580,7 +563,7 @@ void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx, methdata.libctx = libctx; methdata.tmp_store = NULL; - (void)inner_ossl_decoder_fetch(&methdata, 0, NULL, NULL /* properties */); + (void)inner_ossl_decoder_fetch(&methdata, NULL, NULL /* properties */); data.user_fn = user_fn; data.user_arg = user_arg; @@ -650,9 +633,7 @@ OSSL_DECODER_CTX *OSSL_DECODER_CTX_new(void) { OSSL_DECODER_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); - + ctx = OPENSSL_zalloc(sizeof(*ctx)); return ctx; } diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c index ad5e2805319b..f99566bde744 100644 --- a/crypto/encode_decode/decoder_pkey.c +++ b/crypto/encode_decode/decoder_pkey.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,7 +17,11 @@ #include #include "crypto/evp.h" #include "crypto/decoder.h" +#include "crypto/evp/evp_local.h" +#include "crypto/lhash.h" #include "encoder_local.h" +#include "internal/namemap.h" +#include "internal/sizes.h" int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx, const unsigned char *kstr, @@ -61,6 +65,7 @@ struct decoder_pkey_data_st { STACK_OF(EVP_KEYMGMT) *keymgmts; char *object_type; /* recorded object data type, may be NULL */ void **object; /* Where the result should end up */ + OSSL_DECODER_CTX *ctx; /* The parent decoder context */ }; static int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst, @@ -167,6 +172,14 @@ static int decoder_construct_pkey(OSSL_DECODER_INSTANCE *decoder_inst, keydata = import_data.keydata; import_data.keydata = NULL; } + /* + * When load or import fails, because this is not an acceptable key + * (despite the provided key material being syntactically valid), the + * reason why the key is rejected would be lost, unless we signal a + * hard error, and suppress resetting for another try. + */ + if (keydata == NULL) + ossl_decoder_ctx_set_harderr(data->ctx); if (keydata != NULL && (pkey = evp_keymgmt_util_make_pkey(keymgmt, keydata)) == NULL) @@ -199,53 +212,97 @@ static void decoder_clean_pkey_construct_arg(void *construct_data) } } -static void collect_name(const char *name, void *arg) -{ - STACK_OF(OPENSSL_CSTRING) *names = arg; - - sk_OPENSSL_CSTRING_push(names, name); -} - -static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg) -{ - STACK_OF(EVP_KEYMGMT) *keymgmts = arg; - - if (!EVP_KEYMGMT_up_ref(keymgmt) /* ref++ */) - return; - if (sk_EVP_KEYMGMT_push(keymgmts, keymgmt) <= 0) { - EVP_KEYMGMT_free(keymgmt); /* ref-- */ - return; - } -} - -struct collect_decoder_data_st { - STACK_OF(OPENSSL_CSTRING) *names; +struct collect_data_st { + OSSL_LIB_CTX *libctx; OSSL_DECODER_CTX *ctx; - int total; - unsigned int error_occurred:1; + const char *keytype; /* the keytype requested, if any */ + int keytype_id; /* if keytype_resolved is set, keymgmt name_id; else 0 */ + int sm2_id; /* if keytype_resolved is set and EC, SM2 name_id; else 0 */ + int total; /* number of matching results */ + char error_occurred; + char keytype_resolved; + + STACK_OF(EVP_KEYMGMT) *keymgmts; }; -static void collect_decoder(OSSL_DECODER *decoder, void *arg) +static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder, + void *provctx, struct collect_data_st *data) { - struct collect_decoder_data_st *data = arg; - size_t i, end_i; - const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder); - void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + void *decoderctx = NULL; + OSSL_DECODER_INSTANCE *di = NULL; - if (data->error_occurred) + /* + * We already checked the EVP_KEYMGMT is applicable in check_keymgmt so we + * don't check it again here. + */ + + if (keymgmt->name_id != decoder->base.id) + /* Mismatch is not an error, continue. */ return; - if (data->names == NULL) { + if ((decoderctx = decoder->newctx(provctx)) == NULL) { + data->error_occurred = 1; + return; + } + + if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) { + decoder->freectx(decoderctx); data->error_occurred = 1; return; } /* - * Either the caller didn't give a selection, or if they did, - * the decoder must tell us if it supports that selection to - * be accepted. If the decoder doesn't have |does_selection|, - * it's seen as taking anything. + * Input types must be compatible, but we must accept DER encoders when the + * start input type is "PEM". + */ + if (data->ctx->start_input_type != NULL + && di->input_type != NULL + && OPENSSL_strcasecmp(di->input_type, data->ctx->start_input_type) != 0 + && (OPENSSL_strcasecmp(di->input_type, "DER") != 0 + || OPENSSL_strcasecmp(data->ctx->start_input_type, "PEM") != 0)) { + /* Mismatch is not an error, continue. */ + ossl_decoder_instance_free(di); + return; + } + + OSSL_TRACE_BEGIN(DECODER) { + BIO_printf(trc_out, + "(ctx %p) Checking out decoder %p:\n" + " %s with %s\n", + (void *)data->ctx, (void *)decoder, + OSSL_DECODER_get0_name(decoder), + OSSL_DECODER_get0_properties(decoder)); + } OSSL_TRACE_END(DECODER); + + if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) { + ossl_decoder_instance_free(di); + data->error_occurred = 1; + return; + } + + ++data->total; +} + +static void collect_decoder(OSSL_DECODER *decoder, void *arg) +{ + struct collect_data_st *data = arg; + STACK_OF(EVP_KEYMGMT) *keymgmts = data->keymgmts; + int i, end_i; + EVP_KEYMGMT *keymgmt; + const OSSL_PROVIDER *prov; + void *provctx; + + if (data->error_occurred) + return; + + prov = OSSL_DECODER_get0_provider(decoder); + provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + + /* + * Either the caller didn't give us a selection, or if they did, the decoder + * must tell us if it supports that selection to be accepted. If the decoder + * doesn't have |does_selection|, it's seen as taking anything. */ if (decoder->does_selection != NULL && !decoder->does_selection(provctx, data->ctx->selection)) @@ -260,68 +317,101 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg) OSSL_DECODER_get0_properties(decoder)); } OSSL_TRACE_END(DECODER); - end_i = sk_OPENSSL_CSTRING_num(data->names); - for (i = 0; i < end_i; i++) { - const char *name = sk_OPENSSL_CSTRING_value(data->names, i); + end_i = sk_EVP_KEYMGMT_num(keymgmts); + for (i = 0; i < end_i; ++i) { + keymgmt = sk_EVP_KEYMGMT_value(keymgmts, i); - if (OSSL_DECODER_is_a(decoder, name)) { - void *decoderctx = NULL; - OSSL_DECODER_INSTANCE *di = NULL; - - if ((decoderctx = decoder->newctx(provctx)) == NULL) { - data->error_occurred = 1; - return; - } - if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) { - decoder->freectx(decoderctx); - data->error_occurred = 1; - return; - } - - OSSL_TRACE_BEGIN(DECODER) { - BIO_printf(trc_out, - "(ctx %p) Checking out decoder %p:\n" - " %s with %s\n", - (void *)data->ctx, (void *)decoder, - OSSL_DECODER_get0_name(decoder), - OSSL_DECODER_get0_properties(decoder)); - } OSSL_TRACE_END(DECODER); - - if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) { - ossl_decoder_instance_free(di); - data->error_occurred = 1; - return; - } - data->total++; - - /* Success */ + collect_decoder_keymgmt(keymgmt, decoder, provctx, data); + if (data->error_occurred) return; - } } - - /* Decoder not suitable - but not a fatal error */ - data->error_occurred = 0; } -int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx, - EVP_PKEY **pkey, const char *keytype, - OSSL_LIB_CTX *libctx, - const char *propquery) +/* + * Is this EVP_KEYMGMT applicable given the key type given in the call to + * ossl_decoder_ctx_setup_for_pkey (if any)? + */ +static int check_keymgmt(EVP_KEYMGMT *keymgmt, struct collect_data_st *data) { - struct decoder_pkey_data_st *process_data = NULL; - STACK_OF(OPENSSL_CSTRING) *names = NULL; - const char *input_type = ctx->start_input_type; - const char *input_structure = ctx->input_structure; - int ok = 0; - int isecoid = 0; - int i, end; + /* If no keytype was specified, everything matches. */ + if (data->keytype == NULL) + return 1; - if (keytype != NULL - && (strcmp(keytype, "id-ecPublicKey") == 0 - || strcmp(keytype, "1.2.840.10045.2.1") == 0)) - isecoid = 1; + if (!data->keytype_resolved) { + /* We haven't cached the IDs from the keytype string yet. */ + OSSL_NAMEMAP *namemap = ossl_namemap_stored(data->libctx); + data->keytype_id = ossl_namemap_name2num(namemap, data->keytype); + + /* + * If keytype is a value ambiguously used for both EC and SM2, + * collect the ID for SM2 as well. + */ + if (data->keytype_id != 0 + && (strcmp(data->keytype, "id-ecPublicKey") == 0 + || strcmp(data->keytype, "1.2.840.10045.2.1") == 0)) + data->sm2_id = ossl_namemap_name2num(namemap, "SM2"); + + /* + * If keytype_id is zero the name was not found, but we still + * set keytype_resolved to avoid trying all this again. + */ + data->keytype_resolved = 1; + } + + /* Specified keytype could not be resolved, so nothing matches. */ + if (data->keytype_id == 0) + return 0; + + /* Does not match the keytype specified, so skip. */ + if (keymgmt->name_id != data->keytype_id + && keymgmt->name_id != data->sm2_id) + return 0; + + return 1; +} + +static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg) +{ + struct collect_data_st *data = arg; + + if (!check_keymgmt(keymgmt, data)) + return; + + /* + * We have to ref EVP_KEYMGMT here because in the success case, + * data->keymgmts is referenced by the constructor we register in the + * OSSL_DECODER_CTX. The registered cleanup function + * (decoder_clean_pkey_construct_arg) unrefs every element of the stack and + * frees it. + */ + if (!EVP_KEYMGMT_up_ref(keymgmt)) + return; + + if (sk_EVP_KEYMGMT_push(data->keymgmts, keymgmt) <= 0) { + EVP_KEYMGMT_free(keymgmt); + data->error_occurred = 1; + } +} + +/* + * This function does the actual binding of decoders to the OSSL_DECODER_CTX. It + * searches for decoders matching 'keytype', which is a string like "RSA", "DH", + * etc. If 'keytype' is NULL, decoders for all keytypes are bound. + */ +static int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx, + const char *keytype, + OSSL_LIB_CTX *libctx, + const char *propquery) +{ + int ok = 0; + struct decoder_pkey_data_st *process_data = NULL; + struct collect_data_st collect_data = { NULL }; + STACK_OF(EVP_KEYMGMT) *keymgmts = NULL; OSSL_TRACE_BEGIN(DECODER) { + const char *input_type = ctx->start_input_type; + const char *input_structure = ctx->input_structure; + BIO_printf(trc_out, "(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n", (void *)ctx, @@ -333,81 +423,66 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx, input_structure != NULL ? input_structure : ""); } OSSL_TRACE_END(DECODER); - if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL - || (propquery != NULL - && (process_data->propq = OPENSSL_strdup(propquery)) == NULL) - || (process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL - || (names = sk_OPENSSL_CSTRING_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + /* Allocate data. */ + if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL) + goto err; + if ((propquery != NULL + && (process_data->propq = OPENSSL_strdup(propquery)) == NULL)) + goto err; + + /* Allocate our list of EVP_KEYMGMTs. */ + keymgmts = sk_EVP_KEYMGMT_new_null(); + if (keymgmts == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); goto err; } - process_data->object = (void **)pkey; - process_data->libctx = libctx; + process_data->object = NULL; + process_data->libctx = libctx; process_data->selection = ctx->selection; + process_data->keymgmts = keymgmts; - /* First, find all keymgmts to form goals */ - EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, - process_data->keymgmts); + /* + * Enumerate all keymgmts into a stack. + * + * We could nest EVP_KEYMGMT_do_all_provided inside + * OSSL_DECODER_do_all_provided or vice versa but these functions become + * bottlenecks if called repeatedly, which is why we collect the + * EVP_KEYMGMTs into a stack here and call both functions only once. + * + * We resolve the keytype string to a name ID so we don't have to resolve it + * multiple times, avoiding repeated calls to EVP_KEYMGMT_is_a, which is a + * performance bottleneck. However, we do this lazily on the first call to + * collect_keymgmt made by EVP_KEYMGMT_do_all_provided, rather than do it + * upfront, as this ensures that the names for all loaded providers have + * been registered by the time we try to resolve the keytype string. + */ + collect_data.ctx = ctx; + collect_data.libctx = libctx; + collect_data.keymgmts = keymgmts; + collect_data.keytype = keytype; + EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, &collect_data); - /* Then, we collect all the keymgmt names */ - end = sk_EVP_KEYMGMT_num(process_data->keymgmts); - for (i = 0; i < end; i++) { - EVP_KEYMGMT *keymgmt = sk_EVP_KEYMGMT_value(process_data->keymgmts, i); + if (collect_data.error_occurred) + goto err; - /* - * If the key type is given by the caller, we only use the matching - * KEYMGMTs, otherwise we use them all. - * We have to special case SM2 here because of its abuse of the EC OID. - * The EC OID can be used to identify an EC key or an SM2 key - so if - * we have seen that OID we try both key types - */ - if (keytype == NULL - || EVP_KEYMGMT_is_a(keymgmt, keytype) - || (isecoid && EVP_KEYMGMT_is_a(keymgmt, "SM2"))) { - if (!EVP_KEYMGMT_names_do_all(keymgmt, collect_name, names)) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR); - goto err; - } - } - } + /* Enumerate all matching decoders. */ + OSSL_DECODER_do_all_provided(libctx, collect_decoder, &collect_data); + + if (collect_data.error_occurred) + goto err; OSSL_TRACE_BEGIN(DECODER) { - end = sk_OPENSSL_CSTRING_num(names); BIO_printf(trc_out, - " Found %d keytypes (possibly with duplicates)", - end); - for (i = 0; i < end; i++) - BIO_printf(trc_out, "%s%s", - i == 0 ? ": " : ", ", - sk_OPENSSL_CSTRING_value(names, i)); - BIO_printf(trc_out, "\n"); + "(ctx %p) Got %d decoders producing keys\n", + (void *)ctx, collect_data.total); } OSSL_TRACE_END(DECODER); /* - * Finally, find all decoders that have any keymgmt of the collected - * keymgmt names + * Finish initializing the decoder context. If one or more decoders matched + * above then the number of decoders attached to the OSSL_DECODER_CTX will + * be nonzero. Else nothing was found and we do nothing. */ - { - struct collect_decoder_data_st collect_decoder_data = { NULL, }; - - collect_decoder_data.names = names; - collect_decoder_data.ctx = ctx; - OSSL_DECODER_do_all_provided(libctx, - collect_decoder, &collect_decoder_data); - sk_OPENSSL_CSTRING_free(names); - names = NULL; - - if (collect_decoder_data.error_occurred) - goto err; - - OSSL_TRACE_BEGIN(DECODER) { - BIO_printf(trc_out, - "(ctx %p) Got %d decoders producing keys\n", - (void *)ctx, collect_decoder_data.total); - } OSSL_TRACE_END(DECODER); - } - if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) { if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_pkey) || !OSSL_DECODER_CTX_set_construct_data(ctx, process_data) @@ -421,11 +496,267 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx, ok = 1; err: decoder_clean_pkey_construct_arg(process_data); - sk_OPENSSL_CSTRING_free(names); - return ok; } +/* Only const here because deep_copy requires it */ +static EVP_KEYMGMT *keymgmt_dup(const EVP_KEYMGMT *keymgmt) +{ + if (!EVP_KEYMGMT_up_ref((EVP_KEYMGMT *)keymgmt)) + return NULL; + + return (EVP_KEYMGMT *)keymgmt; +} + +/* + * Duplicates a template OSSL_DECODER_CTX that has been setup for an EVP_PKEY + * operation and sets up the duplicate for a new operation. + * It does not duplicate the pwdata on the assumption that this does not form + * part of the template. That is set up later. + */ +static OSSL_DECODER_CTX * +ossl_decoder_ctx_for_pkey_dup(OSSL_DECODER_CTX *src, + EVP_PKEY **pkey, + const char *input_type, + const char *input_structure) +{ + OSSL_DECODER_CTX *dest; + struct decoder_pkey_data_st *process_data_src, *process_data_dest = NULL; + + if (src == NULL) + return NULL; + + if ((dest = OSSL_DECODER_CTX_new()) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + return NULL; + } + + if (!OSSL_DECODER_CTX_set_input_type(dest, input_type) + || !OSSL_DECODER_CTX_set_input_structure(dest, input_structure)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + goto err; + } + dest->selection = src->selection; + + if (src->decoder_insts != NULL) { + dest->decoder_insts + = sk_OSSL_DECODER_INSTANCE_deep_copy(src->decoder_insts, + ossl_decoder_instance_dup, + ossl_decoder_instance_free); + if (dest->decoder_insts == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + goto err; + } + } + + if (!OSSL_DECODER_CTX_set_construct(dest, + OSSL_DECODER_CTX_get_construct(src))) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + process_data_src = OSSL_DECODER_CTX_get_construct_data(src); + if (process_data_src != NULL) { + process_data_dest = OPENSSL_zalloc(sizeof(*process_data_dest)); + if (process_data_dest == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); + goto err; + } + if (process_data_src->propq != NULL) { + process_data_dest->propq = OPENSSL_strdup(process_data_src->propq); + if (process_data_dest->propq == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); + goto err; + } + } + + if (process_data_src->keymgmts != NULL) { + process_data_dest->keymgmts + = sk_EVP_KEYMGMT_deep_copy(process_data_src->keymgmts, + keymgmt_dup, + EVP_KEYMGMT_free); + if (process_data_dest->keymgmts == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_EVP_LIB); + goto err; + } + } + + process_data_dest->object = (void **)pkey; + process_data_dest->libctx = process_data_src->libctx; + process_data_dest->selection = process_data_src->selection; + process_data_dest->ctx = dest; + if (!OSSL_DECODER_CTX_set_construct_data(dest, process_data_dest)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + goto err; + } + process_data_dest = NULL; + } + + if (!OSSL_DECODER_CTX_set_cleanup(dest, + OSSL_DECODER_CTX_get_cleanup(src))) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + goto err; + } + + return dest; + err: + decoder_clean_pkey_construct_arg(process_data_dest); + OSSL_DECODER_CTX_free(dest); + return NULL; +} + +typedef struct { + char *input_type; + char *input_structure; + char *keytype; + int selection; + char *propquery; + OSSL_DECODER_CTX *template; +} DECODER_CACHE_ENTRY; + +DEFINE_LHASH_OF_EX(DECODER_CACHE_ENTRY); + +typedef struct { + CRYPTO_RWLOCK *lock; + LHASH_OF(DECODER_CACHE_ENTRY) *hashtable; +} DECODER_CACHE; + +static void decoder_cache_entry_free(DECODER_CACHE_ENTRY *entry) +{ + if (entry == NULL) + return; + OPENSSL_free(entry->input_type); + OPENSSL_free(entry->input_structure); + OPENSSL_free(entry->keytype); + OPENSSL_free(entry->propquery); + OSSL_DECODER_CTX_free(entry->template); + OPENSSL_free(entry); +} + +static unsigned long decoder_cache_entry_hash(const DECODER_CACHE_ENTRY *cache) +{ + unsigned long hash = 17; + + hash = (hash * 23) + + (cache->propquery == NULL + ? 0 : ossl_lh_strcasehash(cache->propquery)); + hash = (hash * 23) + + (cache->input_structure == NULL + ? 0 : ossl_lh_strcasehash(cache->input_structure)); + hash = (hash * 23) + + (cache->input_type == NULL + ? 0 : ossl_lh_strcasehash(cache->input_type)); + hash = (hash * 23) + + (cache->keytype == NULL + ? 0 : ossl_lh_strcasehash(cache->keytype)); + + hash ^= cache->selection; + + return hash; +} + +static ossl_inline int nullstrcmp(const char *a, const char *b, int casecmp) +{ + if (a == NULL || b == NULL) { + if (a == NULL) { + if (b == NULL) + return 0; + else + return 1; + } else { + return -1; + } + } else { + if (casecmp) + return OPENSSL_strcasecmp(a, b); + else + return strcmp(a, b); + } +} + +static int decoder_cache_entry_cmp(const DECODER_CACHE_ENTRY *a, + const DECODER_CACHE_ENTRY *b) +{ + int cmp; + + if (a->selection != b->selection) + return (a->selection < b->selection) ? -1 : 1; + + cmp = nullstrcmp(a->keytype, b->keytype, 1); + if (cmp != 0) + return cmp; + + cmp = nullstrcmp(a->input_type, b->input_type, 1); + if (cmp != 0) + return cmp; + + cmp = nullstrcmp(a->input_structure, b->input_structure, 1); + if (cmp != 0) + return cmp; + + cmp = nullstrcmp(a->propquery, b->propquery, 0); + + return cmp; +} + +void *ossl_decoder_cache_new(OSSL_LIB_CTX *ctx) +{ + DECODER_CACHE *cache = OPENSSL_malloc(sizeof(*cache)); + + if (cache == NULL) + return NULL; + + cache->lock = CRYPTO_THREAD_lock_new(); + if (cache->lock == NULL) { + OPENSSL_free(cache); + return NULL; + } + cache->hashtable = lh_DECODER_CACHE_ENTRY_new(decoder_cache_entry_hash, + decoder_cache_entry_cmp); + if (cache->hashtable == NULL) { + CRYPTO_THREAD_lock_free(cache->lock); + OPENSSL_free(cache); + return NULL; + } + + return cache; +} + +void ossl_decoder_cache_free(void *vcache) +{ + DECODER_CACHE *cache = (DECODER_CACHE *)vcache; + + lh_DECODER_CACHE_ENTRY_doall(cache->hashtable, decoder_cache_entry_free); + lh_DECODER_CACHE_ENTRY_free(cache->hashtable); + CRYPTO_THREAD_lock_free(cache->lock); + OPENSSL_free(cache); +} + +/* + * Called whenever a provider gets activated/deactivated. In that case the + * decoders that are available might change so we flush our cache. + */ +int ossl_decoder_cache_flush(OSSL_LIB_CTX *libctx) +{ + DECODER_CACHE *cache + = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_CACHE_INDEX); + + if (cache == NULL) + return 0; + + + if (!CRYPTO_THREAD_write_lock(cache->lock)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + return 0; + } + + lh_DECODER_CACHE_ENTRY_doall(cache->hashtable, decoder_cache_entry_free); + lh_DECODER_CACHE_ENTRY_flush(cache->hashtable); + + CRYPTO_THREAD_unlock(cache->lock); + return 1; +} + OSSL_DECODER_CTX * OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey, const char *input_type, @@ -434,33 +765,142 @@ OSSL_DECODER_CTX_new_for_pkey(EVP_PKEY **pkey, OSSL_LIB_CTX *libctx, const char *propquery) { OSSL_DECODER_CTX *ctx = NULL; + OSSL_PARAM decoder_params[] = { + OSSL_PARAM_END, + OSSL_PARAM_END, + OSSL_PARAM_END + }; + DECODER_CACHE *cache + = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DECODER_CACHE_INDEX); + DECODER_CACHE_ENTRY cacheent, *res, *newcache = NULL; + int i = 0; - if ((ctx = OSSL_DECODER_CTX_new()) == NULL) { - ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE); + if (cache == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + return NULL; + } + if (input_structure != NULL) + decoder_params[i++] = + OSSL_PARAM_construct_utf8_string(OSSL_OBJECT_PARAM_DATA_STRUCTURE, + (char *)input_structure, 0); + if (propquery != NULL) + decoder_params[i++] = + OSSL_PARAM_construct_utf8_string(OSSL_DECODER_PARAM_PROPERTIES, + (char *)propquery, 0); + + /* It is safe to cast away the const here */ + cacheent.input_type = (char *)input_type; + cacheent.input_structure = (char *)input_structure; + cacheent.keytype = (char *)keytype; + cacheent.selection = selection; + cacheent.propquery = (char *)propquery; + + if (!CRYPTO_THREAD_read_lock(cache->lock)) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); return NULL; } - OSSL_TRACE_BEGIN(DECODER) { - BIO_printf(trc_out, - "(ctx %p) Looking for %s decoders with selection %d\n", - (void *)ctx, keytype, selection); - BIO_printf(trc_out, " input type: %s, input structure: %s\n", - input_type, input_structure); - } OSSL_TRACE_END(DECODER); + /* First see if we have a template OSSL_DECODER_CTX */ + res = lh_DECODER_CACHE_ENTRY_retrieve(cache->hashtable, &cacheent); + + if (res == NULL) { + /* + * There is no template so we will have to construct one. This will be + * time consuming so release the lock and we will later upgrade it to a + * write lock. + */ + CRYPTO_THREAD_unlock(cache->lock); + + if ((ctx = OSSL_DECODER_CTX_new()) == NULL) { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + return NULL; + } - if (OSSL_DECODER_CTX_set_input_type(ctx, input_type) - && OSSL_DECODER_CTX_set_input_structure(ctx, input_structure) - && OSSL_DECODER_CTX_set_selection(ctx, selection) - && ossl_decoder_ctx_setup_for_pkey(ctx, pkey, keytype, - libctx, propquery) - && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery)) { OSSL_TRACE_BEGIN(DECODER) { - BIO_printf(trc_out, "(ctx %p) Got %d decoders\n", - (void *)ctx, OSSL_DECODER_CTX_get_num_decoders(ctx)); + BIO_printf(trc_out, + "(ctx %p) Looking for %s decoders with selection %d\n", + (void *)ctx, keytype, selection); + BIO_printf(trc_out, " input type: %s, input structure: %s\n", + input_type, input_structure); } OSSL_TRACE_END(DECODER); - return ctx; + + if (OSSL_DECODER_CTX_set_input_type(ctx, input_type) + && OSSL_DECODER_CTX_set_input_structure(ctx, input_structure) + && OSSL_DECODER_CTX_set_selection(ctx, selection) + && ossl_decoder_ctx_setup_for_pkey(ctx, keytype, libctx, propquery) + && OSSL_DECODER_CTX_add_extra(ctx, libctx, propquery) + && (propquery == NULL + || OSSL_DECODER_CTX_set_params(ctx, decoder_params))) { + OSSL_TRACE_BEGIN(DECODER) { + BIO_printf(trc_out, "(ctx %p) Got %d decoders\n", + (void *)ctx, OSSL_DECODER_CTX_get_num_decoders(ctx)); + } OSSL_TRACE_END(DECODER); + } else { + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_OSSL_DECODER_LIB); + OSSL_DECODER_CTX_free(ctx); + return NULL; + } + + newcache = OPENSSL_zalloc(sizeof(*newcache)); + if (newcache == NULL) { + OSSL_DECODER_CTX_free(ctx); + return NULL; + } + + if (input_type != NULL) { + newcache->input_type = OPENSSL_strdup(input_type); + if (newcache->input_type == NULL) + goto err; + } + if (input_structure != NULL) { + newcache->input_structure = OPENSSL_strdup(input_structure); + if (newcache->input_structure == NULL) + goto err; + } + if (keytype != NULL) { + newcache->keytype = OPENSSL_strdup(keytype); + if (newcache->keytype == NULL) + goto err; + } + if (propquery != NULL) { + newcache->propquery = OPENSSL_strdup(propquery); + if (newcache->propquery == NULL) + goto err; + } + newcache->selection = selection; + newcache->template = ctx; + + if (!CRYPTO_THREAD_write_lock(cache->lock)) { + ctx = NULL; + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); + goto err; + } + res = lh_DECODER_CACHE_ENTRY_retrieve(cache->hashtable, &cacheent); + if (res == NULL) { + (void)lh_DECODER_CACHE_ENTRY_insert(cache->hashtable, newcache); + if (lh_DECODER_CACHE_ENTRY_error(cache->hashtable)) { + ctx = NULL; + ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_CRYPTO_LIB); + goto err; + } + } else { + /* + * We raced with another thread to construct this and lost. Free + * what we just created and use the entry from the hashtable instead + */ + decoder_cache_entry_free(newcache); + ctx = res->template; + } + } else { + ctx = res->template; } + ctx = ossl_decoder_ctx_for_pkey_dup(ctx, pkey, input_type, input_structure); + CRYPTO_THREAD_unlock(cache->lock); + + return ctx; + err: + decoder_cache_entry_free(newcache); OSSL_DECODER_CTX_free(ctx); return NULL; } diff --git a/crypto/encode_decode/encoder_lib.c b/crypto/encode_decode/encoder_lib.c index a88332b79d52..59d0c885a3e4 100644 --- a/crypto/encode_decode/encoder_lib.c +++ b/crypto/encode_decode/encoder_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,6 +7,8 @@ * https://www.openssl.org/source/license.html */ +#include + #include #include #include @@ -14,10 +16,31 @@ #include #include #include +#include #include "internal/bio.h" +#include "internal/ffc.h" #include "internal/provider.h" +#include "internal/encoder.h" #include "encoder_local.h" +/* Number of octets per line */ +#define LABELED_BUF_PRINT_WIDTH 15 + +# ifdef SIXTY_FOUR_BIT_LONG +# define BN_FMTu "%lu" +# define BN_FMTx "%lx" +# endif + +# ifdef SIXTY_FOUR_BIT +# define BN_FMTu "%llu" +# define BN_FMTx "%llx" +# endif + +# ifdef THIRTY_TWO_BIT +# define BN_FMTu "%u" +# define BN_FMTx "%x" +# endif + struct encoder_process_data_st { OSSL_ENCODER_CTX *ctx; @@ -198,10 +221,8 @@ static OSSL_ENCODER_INSTANCE *ossl_encoder_instance_new(OSSL_ENCODER *encoder, return 0; } - if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + if ((encoder_inst = OPENSSL_zalloc(sizeof(*encoder_inst))) == NULL) return 0; - } if (!OSSL_ENCODER_up_ref(encoder)) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR); @@ -264,7 +285,7 @@ static int ossl_encoder_ctx_add_encoder_inst(OSSL_ENCODER_CTX *ctx, if (ctx->encoder_insts == NULL && (ctx->encoder_insts = sk_OSSL_ENCODER_INSTANCE_new_null()) == NULL) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_CRYPTO_LIB); return 0; } @@ -527,7 +548,7 @@ static int encoder_process(struct encoder_process_data_st *data) OSSL_TRACE_BEGIN(ENCODER) { BIO_printf(trc_out, - "[%d] Skipping because recusion level %d failed\n", + "[%d] Skipping because recursion level %d failed\n", data->level, new_data.level); } OSSL_TRACE_END(ENCODER); } @@ -677,3 +698,161 @@ static int encoder_process(struct encoder_process_data_st *data) data->ctx->cleanup(data->ctx->construct_data); return ok; } + +int ossl_bio_print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn) +{ + int ret = 0, use_sep = 0; + char *hex_str = NULL, *p; + const char spaces[] = " "; + const char *post_label_spc = " "; + + const char *neg = ""; + int bytes; + + if (bn == NULL) + return 0; + if (label == NULL) { + label = ""; + post_label_spc = ""; + } + + if (BN_is_zero(bn)) + return BIO_printf(out, "%s%s0\n", label, post_label_spc); + + if (BN_num_bytes(bn) <= BN_BYTES) { + BN_ULONG *words = bn_get_words(bn); + + if (BN_is_negative(bn)) + neg = "-"; + + return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n", + label, post_label_spc, neg, words[0], neg, words[0]); + } + + hex_str = BN_bn2hex(bn); + if (hex_str == NULL) + return 0; + + p = hex_str; + if (*p == '-') { + ++p; + neg = " (Negative)"; + } + if (BIO_printf(out, "%s%s\n", label, neg) <= 0) + goto err; + + /* Keep track of how many bytes we have printed out so far */ + bytes = 0; + + if (BIO_printf(out, "%s", spaces) <= 0) + goto err; + + /* Add a leading 00 if the top bit is set */ + if (*p >= '8') { + if (BIO_printf(out, "%02x", 0) <= 0) + goto err; + ++bytes; + use_sep = 1; + } + while (*p != '\0') { + /* Do a newline after every 15 hex bytes + add the space indent */ + if ((bytes % 15) == 0 && bytes > 0) { + if (BIO_printf(out, ":\n%s", spaces) <= 0) + goto err; + use_sep = 0; /* The first byte on the next line doesn't have a : */ + } + if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "", + tolower((unsigned char)p[0]), + tolower((unsigned char)p[1])) <= 0) + goto err; + ++bytes; + p += 2; + use_sep = 1; + } + if (BIO_printf(out, "\n") <= 0) + goto err; + ret = 1; +err: + OPENSSL_free(hex_str); + return ret; +} + +int ossl_bio_print_labeled_buf(BIO *out, const char *label, + const unsigned char *buf, size_t buflen) +{ + size_t i; + + if (BIO_printf(out, "%s\n", label) <= 0) + return 0; + + for (i = 0; i < buflen; i++) { + if ((i % LABELED_BUF_PRINT_WIDTH) == 0) { + if (i > 0 && BIO_printf(out, "\n") <= 0) + return 0; + if (BIO_printf(out, " ") <= 0) + return 0; + } + + if (BIO_printf(out, "%02x%s", buf[i], + (i == buflen - 1) ? "" : ":") <= 0) + return 0; + } + if (BIO_printf(out, "\n") <= 0) + return 0; + + return 1; +} + +#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) +int ossl_bio_print_ffc_params(BIO *out, const FFC_PARAMS *ffc) +{ + if (ffc->nid != NID_undef) { +#ifndef OPENSSL_NO_DH + const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid); + const char *name = ossl_ffc_named_group_get_name(group); + + if (name == NULL) + goto err; + if (BIO_printf(out, "GROUP: %s\n", name) <= 0) + goto err; + return 1; +#else + /* How could this be? We should not have a nid in a no-dh build. */ + goto err; +#endif + } + + if (!ossl_bio_print_labeled_bignum(out, "P: ", ffc->p)) + goto err; + if (ffc->q != NULL) { + if (!ossl_bio_print_labeled_bignum(out, "Q: ", ffc->q)) + goto err; + } + if (!ossl_bio_print_labeled_bignum(out, "G: ", ffc->g)) + goto err; + if (ffc->j != NULL) { + if (!ossl_bio_print_labeled_bignum(out, "J: ", ffc->j)) + goto err; + } + if (ffc->seed != NULL) { + if (!ossl_bio_print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen)) + goto err; + } + if (ffc->gindex != -1) { + if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0) + goto err; + } + if (ffc->pcounter != -1) { + if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0) + goto err; + } + if (ffc->h != 0) { + if (BIO_printf(out, "h: %d\n", ffc->h) <= 0) + goto err; + } + return 1; +err: + return 0; +} + +#endif diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h index c1885ffc771f..a2846d309ea8 100644 --- a/crypto/encode_decode/encoder_local.h +++ b/crypto/encode_decode/encoder_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,6 +12,7 @@ #include #include #include +#include "crypto/decoder.h" #include "internal/cryptlib.h" #include "internal/passphrase.h" #include "internal/property.h" @@ -25,7 +26,6 @@ struct ossl_endecode_base_st { OSSL_PROPERTY_LIST *parsed_propdef; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; }; struct ossl_encoder_st { @@ -108,6 +108,7 @@ struct ossl_decoder_instance_st { void *decoderctx; /* Never NULL */ const char *input_type; /* Never NULL */ const char *input_structure; /* May be NULL */ + int input_type_id; unsigned int flag_input_structure_was_set : 1; }; @@ -156,9 +157,15 @@ struct ossl_decoder_ctx_st { /* For any function that needs a passphrase reader */ struct ossl_passphrase_data_st pwdata; + + /* Signal that further processing should not continue. */ + int harderr; }; const OSSL_PROPERTY_LIST * ossl_decoder_parsed_properties(const OSSL_DECODER *decoder); const OSSL_PROPERTY_LIST * ossl_encoder_parsed_properties(const OSSL_ENCODER *encoder); + +int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, + const char *name, int *id_cache); diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c index 89e7b6abf855..e99eaecbfb39 100644 --- a/crypto/encode_decode/encoder_meth.c +++ b/crypto/encode_decode/encoder_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,26 +17,35 @@ #include "internal/provider.h" #include "crypto/encoder.h" #include "encoder_local.h" +#include "crypto/context.h" /* * Encoder can have multiple names, separated with colons in a name string */ #define NAME_SEPARATOR ':' +static void ossl_encoder_free(void *data) +{ + OSSL_ENCODER_free(data); +} + +static int ossl_encoder_up_ref(void *data) +{ + return OSSL_ENCODER_up_ref(data); +} + /* Simple method structure constructor and destructor */ static OSSL_ENCODER *ossl_encoder_new(void) { OSSL_ENCODER *encoder = NULL; - if ((encoder = OPENSSL_zalloc(sizeof(*encoder))) == NULL - || (encoder->base.lock = CRYPTO_THREAD_lock_new()) == NULL) { + if ((encoder = OPENSSL_zalloc(sizeof(*encoder))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&encoder->base.refcnt, 1)) { OSSL_ENCODER_free(encoder); - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); return NULL; } - encoder->base.refcnt = 1; - return encoder; } @@ -44,7 +53,7 @@ int OSSL_ENCODER_up_ref(OSSL_ENCODER *encoder) { int ref = 0; - CRYPTO_UP_REF(&encoder->base.refcnt, &ref, encoder->base.lock); + CRYPTO_UP_REF(&encoder->base.refcnt, &ref); return 1; } @@ -55,35 +64,16 @@ void OSSL_ENCODER_free(OSSL_ENCODER *encoder) if (encoder == NULL) return; - CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref, encoder->base.lock); + CRYPTO_DOWN_REF(&encoder->base.refcnt, &ref); if (ref > 0) return; OPENSSL_free(encoder->base.name); ossl_property_free(encoder->base.parsed_propdef); ossl_provider_free(encoder->base.prov); - CRYPTO_THREAD_lock_free(encoder->base.lock); + CRYPTO_FREE_REF(&encoder->base.refcnt); OPENSSL_free(encoder); } -/* Permanent encoder method store, constructor and destructor */ -static void encoder_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *encoder_store_new(OSSL_LIB_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OSSL_LIB_CTX_METHOD encoder_store_method = { - /* We want encoder_store to be cleaned up before the provider store */ - OSSL_LIB_CTX_METHOD_PRIORITY_2, - encoder_store_new, - encoder_store_free, -}; - /* Data to be passed through ossl_method_construct() */ struct encoder_data_st { OSSL_LIB_CTX *libctx; @@ -120,8 +110,7 @@ static void dealloc_tmp_encoder_store(void *store) /* Get the permanent encoder store */ static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX, - &encoder_store_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_ENCODER_STORE_INDEX); } static int reserve_encoder_store(void *store, void *data) @@ -212,8 +201,8 @@ static int put_encoder_in_store(void *store, void *method, return 0; return ossl_method_store_add(store, prov, id, propdef, method, - (int (*)(void *))OSSL_ENCODER_up_ref, - (void (*)(void *))OSSL_ENCODER_free); + ossl_encoder_up_ref, + ossl_encoder_free); } /* Create and populate a encoder method */ @@ -369,38 +358,27 @@ static void free_encoder(void *method) /* Fetching support. Can fetch by numeric identity or by name */ static OSSL_ENCODER * -inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, +inner_ossl_encoder_fetch(struct encoder_data_st *methdata, const char *name, const char *properties) { OSSL_METHOD_STORE *store = get_encoder_store(methdata->libctx); OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); const char *const propq = properties != NULL ? properties : ""; void *method = NULL; - int unsupported = 0; + int unsupported, id; if (store == NULL || namemap == NULL) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - /* - * If we have been passed both an id and a name, we have an - * internal programming error. - */ - if (!ossl_assert(id == 0 || name == NULL)) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR); - return NULL; - } - - if (id == 0) - id = ossl_namemap_name2num(namemap, name); + id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0; /* * If we haven't found the name yet, chances are that the algorithm to * be fetched is unsupported. */ - if (id == 0) - unsupported = 1; + unsupported = id == 0; if (id == 0 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { @@ -464,20 +442,7 @@ OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *libctx, const char *name, methdata.libctx = libctx; methdata.tmp_store = NULL; - method = inner_ossl_encoder_fetch(&methdata, 0, name, properties); - dealloc_tmp_encoder_store(methdata.tmp_store); - return method; -} - -OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id, - const char *properties) -{ - struct encoder_data_st methdata; - void *method; - - methdata.libctx = libctx; - methdata.tmp_store = NULL; - method = inner_ossl_encoder_fetch(&methdata, id, NULL, properties); + method = inner_ossl_encoder_fetch(&methdata, name, properties); dealloc_tmp_encoder_store(methdata.tmp_store); return method; } @@ -589,7 +554,7 @@ void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx, methdata.libctx = libctx; methdata.tmp_store = NULL; - (void)inner_ossl_encoder_fetch(&methdata, 0, NULL, NULL /* properties */); + (void)inner_ossl_encoder_fetch(&methdata, NULL, NULL /* properties */); data.user_fn = user_fn; data.user_arg = user_arg; @@ -652,9 +617,7 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new(void) { OSSL_ENCODER_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); - + ctx = OPENSSL_zalloc(sizeof(*ctx)); return ctx; } diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c index 39266a95309d..97aad8820229 100644 --- a/crypto/encode_decode/encoder_pkey.c +++ b/crypto/encode_decode/encoder_pkey.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,6 +17,7 @@ #include #include "internal/provider.h" #include "internal/property.h" +#include "internal/namemap.h" #include "crypto/evp.h" #include "encoder_local.h" @@ -72,6 +73,7 @@ int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx, struct collected_encoder_st { STACK_OF(OPENSSL_CSTRING) *names; + int *id_names; const char *output_structure; const char *output_type; @@ -85,41 +87,42 @@ struct collected_encoder_st { static void collect_encoder(OSSL_ENCODER *encoder, void *arg) { struct collected_encoder_st *data = arg; - size_t i, end_i; + const OSSL_PROVIDER *prov; if (data->error_occurred) return; data->error_occurred = 1; /* Assume the worst */ - if (data->names == NULL) - return; - - end_i = sk_OPENSSL_CSTRING_num(data->names); - for (i = 0; i < end_i; i++) { - const char *name = sk_OPENSSL_CSTRING_value(data->names, i); - const OSSL_PROVIDER *prov = OSSL_ENCODER_get0_provider(encoder); + prov = OSSL_ENCODER_get0_provider(encoder); + /* + * collect_encoder() is called in two passes, one where the encoders + * from the same provider as the keymgmt are looked up, and one where + * the other encoders are looked up. |data->flag_find_same_provider| + * tells us which pass we're in. + */ + if ((data->keymgmt_prov == prov) == data->flag_find_same_provider) { void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov); + int i, end_i = sk_OPENSSL_CSTRING_num(data->names); + int match; - /* - * collect_encoder() is called in two passes, one where the encoders - * from the same provider as the keymgmt are looked up, and one where - * the other encoders are looked up. |data->flag_find_same_provider| - * tells us which pass we're in. - */ - if ((data->keymgmt_prov == prov) != data->flag_find_same_provider) - continue; + for (i = 0; i < end_i; i++) { + if (data->flag_find_same_provider) + match = (data->id_names[i] == encoder->base.id); + else + match = OSSL_ENCODER_is_a(encoder, + sk_OPENSSL_CSTRING_value(data->names, i)); + if (!match + || (encoder->does_selection != NULL + && !encoder->does_selection(provctx, data->ctx->selection)) + || (data->keymgmt_prov != prov + && encoder->import_object == NULL)) + continue; - if (!OSSL_ENCODER_is_a(encoder, name) - || (encoder->does_selection != NULL - && !encoder->does_selection(provctx, data->ctx->selection)) - || (data->keymgmt_prov != prov - && encoder->import_object == NULL)) - continue; - - /* Only add each encoder implementation once */ - if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder)) - break; + /* Only add each encoder implementation once */ + if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder)) + break; + } } data->error_occurred = 0; /* All is good now */ @@ -207,6 +210,7 @@ encoder_construct_pkey(OSSL_ENCODER_INSTANCE *encoder_inst, void *arg) static void encoder_destruct_pkey(void *arg) { struct construct_data_st *data = arg; + int match = (data->obj == data->constructed_obj); if (data->encoder_inst != NULL) { OSSL_ENCODER *encoder = @@ -215,6 +219,8 @@ static void encoder_destruct_pkey(void *arg) encoder->free_object(data->constructed_obj); } data->constructed_obj = NULL; + if (match) + data->obj = NULL; } /* @@ -231,7 +237,8 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, struct construct_data_st *data = NULL; const OSSL_PROVIDER *prov = NULL; OSSL_LIB_CTX *libctx = NULL; - int ok = 0; + int ok = 0, i, end; + OSSL_NAMEMAP *namemap; if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) { ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER); @@ -247,10 +254,8 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, struct collected_encoder_st encoder_data; struct collected_names_st keymgmt_data; - if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + if ((data = OPENSSL_zalloc(sizeof(*data))) == NULL) goto err; - } /* * Select the first encoder implementations in two steps. @@ -258,7 +263,7 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, */ keymgmt_data.names = sk_OPENSSL_CSTRING_new_null(); if (keymgmt_data.names == NULL) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_CRYPTO_LIB); goto err; } @@ -275,7 +280,27 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, encoder_data.error_occurred = 0; encoder_data.keymgmt_prov = prov; encoder_data.ctx = ctx; + encoder_data.id_names = NULL; + /* + * collect_encoder() is called many times, and for every call it converts all encoder_data.names + * into namemap ids if it calls OSSL_ENCODER_is_a(). We cache the ids here instead, + * and can use them for encoders with the same provider as the keymgmt. + */ + namemap = ossl_namemap_stored(libctx); + end = sk_OPENSSL_CSTRING_num(encoder_data.names); + if (end > 0) { + encoder_data.id_names = OPENSSL_malloc(end * sizeof(int)); + if (encoder_data.id_names == NULL) { + sk_OPENSSL_CSTRING_free(keymgmt_data.names); + goto err; + } + for (i = 0; i < end; ++i) { + const char *name = sk_OPENSSL_CSTRING_value(keymgmt_data.names, i); + + encoder_data.id_names[i] = ossl_namemap_name2num(namemap, name); + } + } /* * Place the encoders with the a different provider as the keymgmt * last (the chain is processed in reverse order) @@ -290,9 +315,10 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx, encoder_data.flag_find_same_provider = 1; OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data); + OPENSSL_free(encoder_data.id_names); sk_OPENSSL_CSTRING_free(keymgmt_data.names); if (encoder_data.error_occurred) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_CRYPTO_LIB); goto err; } } @@ -339,7 +365,7 @@ OSSL_ENCODER_CTX *OSSL_ENCODER_CTX_new_for_pkey(const EVP_PKEY *pkey, } if ((ctx = OSSL_ENCODER_CTX_new()) == NULL) { - ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_OSSL_ENCODER_LIB); return NULL; } diff --git a/crypto/engine/eng_ctrl.c b/crypto/engine/eng_ctrl.c index 5d7e15634e6e..f1da9b23bb58 100644 --- a/crypto/engine/eng_ctrl.c +++ b/crypto/engine/eng_ctrl.c @@ -1,5 +1,5 @@ /* - * 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 @@ -127,20 +127,15 @@ static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) { - int ctrl_exists, ref_exists; + int ctrl_exists; + if (e == NULL) { ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER); return 0; } - if (!CRYPTO_THREAD_write_lock(global_engine_lock)) - return 0; - ref_exists = ((e->struct_ref > 0) ? 1 : 0); - CRYPTO_THREAD_unlock(global_engine_lock); + ctrl_exists = ((e->ctrl == NULL) ? 0 : 1); - if (!ref_exists) { - ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_REFERENCE); - return 0; - } + /* * Intercept any "root-level" commands before trying to hand them on to * ctrl() handlers. diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c index 6d402927c546..cc3a2b0aa313 100644 --- a/crypto/engine/eng_dyn.c +++ b/crypto/engine/eng_dyn.c @@ -159,13 +159,11 @@ static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx) dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c)); int ret = 0; - if (c == NULL) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + if (c == NULL) return 0; - } c->dirs = sk_OPENSSL_STRING_new_null(); if (c->dirs == NULL) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); goto end; } c->DYNAMIC_F1 = "v_check"; @@ -357,13 +355,11 @@ static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) } { char *tmp_str = OPENSSL_strdup(p); - if (tmp_str == NULL) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + if (tmp_str == NULL) return 0; - } if (!sk_OPENSSL_STRING_push(ctx->dirs, tmp_str)) { OPENSSL_free(tmp_str); - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return 0; } } diff --git a/crypto/engine/eng_init.c b/crypto/engine/eng_init.c index c204eb189986..0ac91ff5ed79 100644 --- a/crypto/engine/eng_init.c +++ b/crypto/engine/eng_init.c @@ -1,5 +1,5 @@ /* - * 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 @@ -10,11 +10,11 @@ /* We need to use some engine deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED -#include "e_os.h" +#include "internal/e_os.h" #include "eng_local.h" /* - * Initialise a engine type for use (or up its functional reference count if + * Initialise an engine type for use (or up its functional reference count if * it's already in use). This version is only used internally. */ int engine_unlocked_init(ENGINE *e) @@ -28,11 +28,16 @@ int engine_unlocked_init(ENGINE *e) */ to_return = e->init(e); if (to_return) { + int ref; + /* * OK, we return a functional reference which is also a structural * reference. */ - e->struct_ref++; + if (!CRYPTO_UP_REF(&e->struct_ref, &ref)) { + e->finish(e); + return 0; + } e->funct_ref++; ENGINE_REF_PRINT(e, 0, 1); ENGINE_REF_PRINT(e, 1, 1); @@ -41,7 +46,7 @@ int engine_unlocked_init(ENGINE *e) } /* - * Free a functional reference to a engine type. This version is only used + * Free a functional reference to an engine type. This version is only used * internally. */ int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) @@ -86,7 +91,8 @@ int ENGINE_init(ENGINE *e) return 0; } if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return 0; } if (!CRYPTO_THREAD_write_lock(global_engine_lock)) diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c index cfdb5a50f481..412363fa371e 100644 --- a/crypto/engine/eng_lib.c +++ b/crypto/engine/eng_lib.c @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "eng_local.h" #include #include "internal/refcount.h" @@ -28,14 +28,20 @@ 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); + if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return 0; + } + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&ret->struct_ref, 1)) { + OPENSSL_free(ret); 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)) { + CRYPTO_FREE_REF(&ret->struct_ref); OPENSSL_free(ret); return NULL; } @@ -74,10 +80,7 @@ int engine_free_util(ENGINE *e, int not_locked) if (e == NULL) return 1; - if (not_locked) - CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock); - else - i = --e->struct_ref; + CRYPTO_DOWN_REF(&e->struct_ref, &i); ENGINE_REF_PRINT(e, 0, -1); if (i > 0) return 1; @@ -93,6 +96,7 @@ int engine_free_util(ENGINE *e, int not_locked) e->destroy(e); engine_remove_dynamic_id(e, not_locked); CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data); + CRYPTO_FREE_REF(&e->struct_ref); OPENSSL_free(e); return 1; } @@ -125,10 +129,8 @@ 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); + if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) return NULL; - } item->cb = cb; return item; } diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c index f2eed3b07174..0f24f2f4504c 100644 --- a/crypto/engine/eng_list.c +++ b/crypto/engine/eng_list.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2024 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 @@ -58,6 +58,7 @@ static int engine_list_add(ENGINE *e) { int conflict = 0; ENGINE *iterator = NULL; + int ref; if (e == NULL) { ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER); @@ -72,9 +73,19 @@ static int engine_list_add(ENGINE *e) ERR_raise(ERR_LIB_ENGINE, ENGINE_R_CONFLICTING_ENGINE_ID); return 0; } + + /* + * Having the engine in the list assumes a structural reference. + */ + if (!CRYPTO_UP_REF(&e->struct_ref, &ref)) { + ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + ENGINE_REF_PRINT(e, 0, 1); if (engine_list_head == NULL) { /* We are adding to an empty list. */ - if (engine_list_tail) { + if (engine_list_tail != NULL) { + CRYPTO_DOWN_REF(&e->struct_ref, &ref); ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } @@ -82,6 +93,7 @@ static int engine_list_add(ENGINE *e) * The first time the list allocates, we should register the cleanup. */ if (!engine_cleanup_add_last(engine_list_cleanup)) { + CRYPTO_DOWN_REF(&e->struct_ref, &ref); ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } @@ -90,17 +102,14 @@ static int engine_list_add(ENGINE *e) } else { /* We are adding to the tail of an existing list. */ if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) { + CRYPTO_DOWN_REF(&e->struct_ref, &ref); ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } engine_list_tail->next = e; e->prev = engine_list_tail; } - /* - * Having the engine in the list assumes a structural reference. - */ - e->struct_ref++; - ENGINE_REF_PRINT(e, 0, 1); + /* However it came to be, e is the last item in the list. */ engine_list_tail = e; e->next = NULL; @@ -222,7 +231,8 @@ ENGINE *ENGINE_get_first(void) ENGINE *ret; if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return NULL; } @@ -230,7 +240,13 @@ ENGINE *ENGINE_get_first(void) return NULL; ret = engine_list_head; if (ret) { - ret->struct_ref++; + int ref; + + if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(ret, 0, 1); } CRYPTO_THREAD_unlock(global_engine_lock); @@ -242,7 +258,8 @@ ENGINE *ENGINE_get_last(void) ENGINE *ret; if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return NULL; } @@ -250,7 +267,13 @@ ENGINE *ENGINE_get_last(void) return NULL; ret = engine_list_tail; if (ret) { - ret->struct_ref++; + int ref; + + if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(ret, 0, 1); } CRYPTO_THREAD_unlock(global_engine_lock); @@ -269,8 +292,14 @@ ENGINE *ENGINE_get_next(ENGINE *e) return NULL; ret = e->next; if (ret) { + int ref; + /* Return a valid structural reference to the next ENGINE */ - ret->struct_ref++; + if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(ret, 0, 1); } CRYPTO_THREAD_unlock(global_engine_lock); @@ -290,8 +319,14 @@ ENGINE *ENGINE_get_prev(ENGINE *e) return NULL; ret = e->prev; if (ret) { + int ref; + /* Return a valid structural reference to the next ENGINE */ - ret->struct_ref++; + if (!CRYPTO_UP_REF(&ret->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(ret, 0, 1); } CRYPTO_THREAD_unlock(global_engine_lock); @@ -373,7 +408,7 @@ static void engine_cpy(ENGINE *dest, const ENGINE *src) ENGINE *ENGINE_by_id(const char *id) { ENGINE *iterator; - char *load_dir = NULL; + const char *load_dir = NULL; if (id == NULL) { ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER); return NULL; @@ -381,7 +416,8 @@ ENGINE *ENGINE_by_id(const char *id) ENGINE_load_builtin_engines(); if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return NULL; } @@ -405,7 +441,13 @@ ENGINE *ENGINE_by_id(const char *id) iterator = cp; } } else { - iterator->struct_ref++; + int ref; + + if (!CRYPTO_UP_REF(&iterator->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(iterator, 0, 1); } } @@ -417,7 +459,7 @@ ENGINE *ENGINE_by_id(const char *id) */ if (strcmp(id, "dynamic")) { if ((load_dir = ossl_safe_getenv("OPENSSL_ENGINES")) == NULL) - load_dir = ENGINESDIR; + load_dir = ossl_get_enginesdir(); iterator = ENGINE_by_id("dynamic"); if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) || !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) || @@ -442,6 +484,6 @@ int ENGINE_up_ref(ENGINE *e) ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER); return 0; } - CRYPTO_UP_REF(&e->struct_ref, &i, global_engine_lock); + CRYPTO_UP_REF(&e->struct_ref, &i); return 1; } diff --git a/crypto/engine/eng_local.h b/crypto/engine/eng_local.h index 75bc9e6f1675..24920973e7b5 100644 --- a/crypto/engine/eng_local.h +++ b/crypto/engine/eng_local.h @@ -31,8 +31,8 @@ extern CRYPTO_RWLOCK *global_engine_lock; (void *)(e), (isfunct ? "funct" : "struct"), \ ((isfunct) \ ? ((e)->funct_ref - (diff)) \ - : ((e)->struct_ref - (diff))), \ - ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \ + : (eng_struct_ref(e) - (diff))), \ + ((isfunct) ? (e)->funct_ref : eng_struct_ref(e)), \ (OPENSSL_FILE), (OPENSSL_LINE)) /* @@ -156,6 +156,14 @@ struct engine_st { typedef struct st_engine_pile ENGINE_PILE; -DEFINE_LHASH_OF(ENGINE_PILE); +DEFINE_LHASH_OF_EX(ENGINE_PILE); + +static ossl_unused ossl_inline int eng_struct_ref(ENGINE *e) +{ + int res; + + CRYPTO_GET_REF(&e->struct_ref, &res); + return res; +} #endif /* OSSL_CRYPTO_ENGINE_ENG_LOCAL_H */ diff --git a/crypto/engine/eng_openssl.c b/crypto/engine/eng_openssl.c index 91656e6b8084..cc4fe96218eb 100644 --- a/crypto/engine/eng_openssl.c +++ b/crypto/engine/eng_openssl.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -422,7 +422,11 @@ static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id, EVP_PKEY *key; fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n", key_id); +# if defined(OPENSSL_SYS_WINDOWS) + in = BIO_new_file(key_id, "rb"); +# else in = BIO_new_file(key_id, "r"); +# endif if (!in) return NULL; key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL); @@ -450,10 +454,8 @@ static int ossl_hmac_init(EVP_PKEY_CTX *ctx) { OSSL_HMAC_PKEY_CTX *hctx; - if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) return 0; - } hctx->ktmp.type = V_ASN1_OCTET_STRING; hctx->ctx = HMAC_CTX_new(); if (hctx->ctx == NULL) { diff --git a/crypto/engine/eng_rdrand.c b/crypto/engine/eng_rdrand.c index f46a5145974e..b3ece7bd9123 100644 --- a/crypto/engine/eng_rdrand.c +++ b/crypto/engine/eng_rdrand.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2020 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 @@ -20,6 +20,12 @@ #include #include +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# include +# endif +#endif + #if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ) @@ -32,6 +38,16 @@ static int get_random_bytes(unsigned char *buf, int num) return 0; } +# if defined(__has_feature) +# if __has_feature(memory_sanitizer) + /* + * MemorySanitizer fails to understand asm and produces false positive + * use-of-uninitialized-value warnings. + */ + __msan_unpoison(buf, num); +# endif +# endif + return (size_t)num == OPENSSL_ia32_rdrand_bytes(buf, (size_t)num); } diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c index 81f8e7add0e7..c74fc4700b4f 100644 --- a/crypto/engine/tb_asnmth.c +++ b/crypto/engine/tb_asnmth.c @@ -1,5 +1,5 @@ /* - * 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 @@ -10,7 +10,7 @@ /* We need to use some engine deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED -#include "e_os.h" +#include "internal/e_os.h" #include "eng_local.h" #include #include "crypto/asn1.h" @@ -196,16 +196,23 @@ const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, fstr.len = len; if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { - ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); + /* Maybe this should be raised in do_engine_lock_init() */ + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); return NULL; } - if (!CRYPTO_THREAD_write_lock(global_engine_lock)) + if (!CRYPTO_THREAD_read_lock(global_engine_lock)) return NULL; engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr); /* If found obtain a structural reference to engine */ - if (fstr.e) { - fstr.e->struct_ref++; + if (fstr.e != NULL) { + int ref; + + if (!CRYPTO_UP_REF(&fstr.e->struct_ref, &ref)) { + CRYPTO_THREAD_unlock(global_engine_lock); + ERR_raise(ERR_LIB_ENGINE, ERR_R_CRYPTO_LIB); + return NULL; + } ENGINE_REF_PRINT(fstr.e, 0, 1); } *pe = fstr.e; diff --git a/crypto/err/build.info b/crypto/err/build.info index 98f8801e34a6..8552d7c393fd 100644 --- a/crypto/err/build.info +++ b/crypto/err/build.info @@ -1,3 +1,3 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ - err_blocks.c err.c err_all.c err_all_legacy.c err_prn.c + err_blocks.c err_mark.c err.c err_all.c err_all_legacy.c err_prn.c err_save.c diff --git a/crypto/err/err.c b/crypto/err/err.c index ec55642308c4..b95182d7029a 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -1,5 +1,5 @@ /* - * 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 @@ -23,7 +23,7 @@ #include "internal/thread_once.h" #include "crypto/ctype.h" #include "internal/constant_time.h" -#include "e_os.h" +#include "internal/e_os.h" #include "err_local.h" /* Forward declaration in case it's not published because of configuration */ @@ -33,7 +33,6 @@ ERR_STATE *ERR_get_state(void); static int err_load_strings(const ERR_STRING_DATA *str); #endif -static void ERR_STATE_free(ERR_STATE *s); #ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"}, @@ -199,16 +198,16 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) } #endif -static void ERR_STATE_free(ERR_STATE *s) +void OSSL_ERR_STATE_free(ERR_STATE *state) { int i; - if (s == NULL) + if (state == NULL) return; for (i = 0; i < ERR_NUM_ERRORS; i++) { - err_clear(s, i, 1); + err_clear(state, i, 1); } - OPENSSL_free(s); + CRYPTO_free(state, OPENSSL_FILE, OPENSSL_LINE); } DEFINE_RUN_ONCE_STATIC(do_err_strings_init) @@ -552,7 +551,8 @@ void ossl_err_string_int(unsigned long e, const char *func, } #endif if (rs == NULL) { - BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r); + BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", + r & ~(ERR_RFLAGS_MASK << ERR_RFLAGS_OFFSET)); rs = rsbuf; } @@ -648,7 +648,7 @@ static void err_delete_thread_state(void *unused) return; CRYPTO_THREAD_set_local(&err_thread_local, NULL); - ERR_STATE_free(state); + OSSL_ERR_STATE_free(state); } #ifndef OPENSSL_NO_DEPRECATED_1_1_0 @@ -688,14 +688,15 @@ ERR_STATE *ossl_err_get_state_int(void) if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1)) return NULL; - if ((state = OPENSSL_zalloc(sizeof(*state))) == NULL) { + state = OSSL_ERR_STATE_new(); + if (state == NULL) { CRYPTO_THREAD_set_local(&err_thread_local, NULL); return NULL; } if (!ossl_init_thread_start(NULL, NULL, err_delete_thread_state) || !CRYPTO_THREAD_set_local(&err_thread_local, state)) { - ERR_STATE_free(state); + OSSL_ERR_STATE_free(state); CRYPTO_THREAD_set_local(&err_thread_local, NULL); return NULL; } @@ -830,10 +831,11 @@ void ERR_add_error_vdata(int num, va_list args) i = es->top; /* - * If err_data is allocated already, re-use the space. + * If err_data is allocated already, reuse the space. * Otherwise, allocate a small new buffer. */ - if ((es->err_data_flags[i] & flags) == flags) { + if ((es->err_data_flags[i] & flags) == flags + && ossl_assert(es->err_data[i] != NULL)) { str = es->err_data[i]; size = es->err_data_size[i]; @@ -875,61 +877,6 @@ void ERR_add_error_vdata(int num, va_list args) OPENSSL_free(str); } -int ERR_set_mark(void) -{ - ERR_STATE *es; - - es = ossl_err_get_state_int(); - if (es == NULL) - return 0; - - if (es->bottom == es->top) - return 0; - es->err_marks[es->top]++; - return 1; -} - -int ERR_pop_to_mark(void) -{ - ERR_STATE *es; - - es = ossl_err_get_state_int(); - if (es == NULL) - return 0; - - while (es->bottom != es->top - && es->err_marks[es->top] == 0) { - err_clear(es, es->top, 0); - es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1; - } - - if (es->bottom == es->top) - return 0; - es->err_marks[es->top]--; - return 1; -} - -int ERR_clear_last_mark(void) -{ - ERR_STATE *es; - int top; - - es = ossl_err_get_state_int(); - if (es == NULL) - return 0; - - top = es->top; - while (es->bottom != top - && es->err_marks[top] == 0) { - top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1; - } - - if (es->bottom == top) - return 0; - es->err_marks[top]--; - return 1; -} - void err_clear_last_constant_time(int clear) { ERR_STATE *es; diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index 55aa2b8dbd56..86b609a555f0 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -1,5 +1,5 @@ /* - * 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 @@ -85,7 +85,9 @@ int ossl_err_load_crypto_strings(void) # ifndef OPENSSL_NO_ENGINE || ossl_err_load_ENGINE_strings() == 0 # endif +# ifndef OPENSSL_NO_HTTP || ossl_err_load_HTTP_strings() == 0 +# endif # ifndef OPENSSL_NO_OCSP || ossl_err_load_OCSP_strings() == 0 # endif diff --git a/crypto/err/err_local.h b/crypto/err/err_local.h index d4e19dff241b..c5c5bf45ba5c 100644 --- a/crypto/err/err_local.h +++ b/crypto/err/err_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -7,6 +7,7 @@ * https://www.openssl.org/source/license.html */ +#include #include #include @@ -56,14 +57,18 @@ static ossl_inline void err_set_debug(ERR_STATE *es, size_t i, OPENSSL_free(es->err_file[i]); if (file == NULL || file[0] == '\0') es->err_file[i] = NULL; - else - es->err_file[i] = OPENSSL_strdup(file); + else if ((es->err_file[i] = CRYPTO_malloc(strlen(file) + 1, + NULL, 0)) != NULL) + /* We cannot use OPENSSL_strdup due to possible recursion */ + strcpy(es->err_file[i], file); + es->err_line[i] = line; OPENSSL_free(es->err_func[i]); if (fn == NULL || fn[0] == '\0') es->err_func[i] = NULL; - else - es->err_func[i] = OPENSSL_strdup(fn); + else if ((es->err_func[i] = CRYPTO_malloc(strlen(fn) + 1, + NULL, 0)) != NULL) + strcpy(es->err_func[i], fn); } static ossl_inline void err_set_data(ERR_STATE *es, size_t i, diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index f3802a05b5c3..22f87d4c1397 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -17,7 +17,7 @@ L ASN1 include/openssl/asn1err.h crypto/asn1/asn1_err.c L CONF include/openssl/conferr.h crypto/conf/conf_err.c include/crypto/conferr.h L CRYPTO include/openssl/cryptoerr.h crypto/cpt_err.c include/crypto/cryptoerr.h L EC include/openssl/ecerr.h crypto/ec/ec_err.c include/crypto/ecerr.h -L SSL include/openssl/sslerr.h ssl/ssl_err.c ssl/sslerr.h +L SSL include/openssl/sslerr.h crypto/ssl_err.c crypto/sslerr.h L BIO include/openssl/bioerr.h crypto/bio/bio_err.c include/crypto/bioerr.h L PKCS7 include/openssl/pkcs7err.h crypto/pkcs7/pkcs7err.c include/crypto/pkcs7err.h L X509V3 include/openssl/x509v3err.h crypto/x509/v3err.c include/crypto/x509v3err.h diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 756fafdfa24a..17981605c028 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -32,6 +32,7 @@ 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_GENERALIZEDTIME_IS_TOO_SHORT:232:generalizedtime is too short 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 @@ -119,6 +120,7 @@ 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_UTCTIME_IS_TOO_SHORT:233:utctime is too short 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 @@ -142,14 +144,20 @@ 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_LOCAL_ADDR_NOT_AVAILABLE:111:local addr not available 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_NON_FATAL:112:non fatal 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_PEER_ADDR_NOT_AVAILABLE:114:peer addr not available +BIO_R_PORT_MISMATCH:150:port mismatch +BIO_R_TFO_DISABLED:106:tfo disabled +BIO_R_TFO_NO_KERNEL_SUPPORT:108:tfo no kernel support 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 @@ -158,6 +166,7 @@ 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_UNABLE_TO_TFO:109:unable to tfo BIO_R_UNAVAILABLE_IP_FAMILY:145:unavailable ip family BIO_R_UNINITIALIZED:120:uninitialized BIO_R_UNKNOWN_INFO_TYPE:140:unknown info type @@ -220,12 +229,22 @@ 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_EXPECTED_POLLREQ:104:expected pollreq CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain +CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY:203:failed extracting central gen key 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_GENERATE_CERTREQTEMPLATE:197:generate certreqtemplate +CMP_R_GENERATE_CRLSTATUS:198:error creating crlstatus +CMP_R_GETTING_GENP:192:getting genp +CMP_R_GET_ITAV:199:get itav CMP_R_INVALID_ARGS:100:invalid args +CMP_R_INVALID_GENP:193:invalid genp +CMP_R_INVALID_KEYSPEC:202:invalid keyspec CMP_R_INVALID_OPTION:174:invalid option +CMP_R_INVALID_ROOTCAKEYUPDATE:195:invalid rootcakeyupdate +CMP_R_MISSING_CENTRAL_GEN_KEY:204:missing central gen key CMP_R_MISSING_CERTID:165:missing certid CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\ missing key input for creating protection @@ -261,14 +280,22 @@ 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_UNCLEAN_CTX:191:unclean ctx +CMP_R_UNEXPECTED_CENTRAL_GEN_KEY:205:unexpected central gen key +CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile +CMP_R_UNEXPECTED_CRLSTATUSLIST:201:unexpected crlstatuslist CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus +CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq CMP_R_UNEXPECTED_PVNO:153:unexpected pvno +CMP_R_UNEXPECTED_SENDER:106:unexpected sender CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type +CMP_R_UNKNOWN_CRL_ISSUER:200:unknown crl issuer 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_PKIBODY:101:unsupported pkibody CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\ unsupported protection alg dhbasedmac CMP_R_VALUE_TOO_LARGE:175:value too large @@ -347,6 +374,7 @@ 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_OPERATION_UNSUPPORTED:182:operation unsupported CMS_R_PEER_KEY_ERROR:188:peer key error CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE:136:\ private key does not match certificate @@ -383,9 +411,16 @@ 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_BROTLI_DECODE_ERROR:102:brotli decode error +COMP_R_BROTLI_ENCODE_ERROR:103:brotli encode error +COMP_R_BROTLI_NOT_SUPPORTED:104:brotli not supported 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 +COMP_R_ZSTD_COMPRESS_ERROR:105:zstd compress error +COMP_R_ZSTD_DECODE_ERROR:106:zstd decode error +COMP_R_ZSTD_DECOMPRESS_ERROR:107:zstd decompress error +COMP_R_ZSTD_NOT_SUPPORTED:108:zstd 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 @@ -416,16 +451,23 @@ 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_CMS_NOT_SUPPORTED:122:cms not supported CRMF_R_CRMFERROR:102:crmferror CRMF_R_ERROR:103:error CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate +CRMF_R_ERROR_DECODING_ENCRYPTEDKEY:123:error decoding encryptedkey CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate +CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY:124:error decrypting encryptedkey +CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE:125:error decrypting encryptedvalue CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key +CRMF_R_ERROR_SETTING_PURPOSE:126:error setting purpose +CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY:127:error verifying encryptedkey 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_CENTRAL_KEYGEN:128:popo inconsistent central keygen 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 @@ -445,16 +487,30 @@ 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_INTEGER_OVERFLOW:127:integer overflow 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_NO_PARAMS_TO_MERGE:131:no params to merge +CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL:128:no space for terminating null CRYPTO_R_ODD_NUMBER_OF_DIGITS:103:odd number of digits +CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY:123:\ + param cannot be represented exactly +CRYPTO_R_PARAM_NOT_INTEGER_TYPE:124:param not integer type +CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE:129:param of incompatible type +CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED:125:\ + param unsigned integer negative value unsupported +CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT:130:\ + param unsupported floating point format +CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION:126:\ + param value too large for destination 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_NAMES:132:too many names 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 @@ -493,6 +549,7 @@ 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_INVALID_SIZE:129:invalid size 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 @@ -692,6 +749,8 @@ 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_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED:229:\ + getting AlgorithmIdentifier not supported 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 @@ -733,10 +792,13 @@ 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_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE:226:\ + operation not supported for this signature type 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_PIPELINE_NOT_SUPPORTED:230:pipeline not supported 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 @@ -744,17 +806,23 @@ 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_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE:228:\ + signature type and key type incompatible +EVP_R_TOO_MANY_PIPES:231:too many pipes 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_BITS:166:unknown bits 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_MAX_SIZE:167:unknown max size EVP_R_UNKNOWN_OPTION:169:unknown option EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm +EVP_R_UNKNOWN_SECURITY_BITS:168:unknown security bits EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm EVP_R_UNSUPPORTED_CIPHER:107:unsupported cipher EVP_R_UNSUPPORTED_KEYLENGTH:123:unsupported keylength @@ -794,6 +862,7 @@ 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_RESPONSE_TOO_MANY_HDRLINES:130:response too many hdrlines 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 @@ -897,7 +966,9 @@ 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 +PEM_R_UNSUPPORTED_PVK_KEY_TYPE:133:unsupported pvk key type +PKCS12_R_CALLBACK_FAILED:115:callback failed +PKCS12_R_CANT_PACK_STRUCTURE:100:can't 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 @@ -979,8 +1050,12 @@ 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_COFACTOR_REQUIRED:236:cofactor required PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed +PROV_R_EMS_NOT_ENABLED:233:ems not enabled +PROV_R_ENTROPY_SOURCE_FAILED_CONTINUOUS_TESTS:244:\ + entropy source failed continuous tests 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 @@ -992,6 +1067,7 @@ 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_FINAL_CALL_OUT_OF_ORDER:237:final call out of order 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 @@ -999,8 +1075,10 @@ 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_INIT_CALL_OUT_OF_ORDER:238:init call out of order PROV_R_INSUFFICIENT_DRBG_STRENGTH:181:insufficient drbg strength PROV_R_INVALID_AAD:108:invalid aad +PROV_R_INVALID_AEAD:231:invalid aead 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 @@ -1009,16 +1087,21 @@ 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_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION:243:\ + invalid eddsa instance for attempted operation 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_KDF:232:invalid kdf 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_MEMORY_SIZE:235:invalid memory size 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_PREHASHED_DIGEST_LENGTH:241:invalid prehashed digest length 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 @@ -1026,6 +1109,7 @@ 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_THREAD_POOL_SIZE:234:invalid thread pool size 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 @@ -1048,6 +1132,8 @@ 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_ML_DSA_NO_FORMAT:245:ml dsa no format +PROV_R_ML_KEM_NO_FORMAT:246:ml kem no format 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 @@ -1055,8 +1141,12 @@ 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_INSTANCE_ALLOWED:242:no instance allowed PROV_R_NO_KEY_SET:114:no key set PROV_R_NO_PARAMETERS_SET:177:no parameters set +PROV_R_NULL_LENGTH_POINTER:247:null length pointer +PROV_R_NULL_OUTPUT_BUFFER:248:null output buffer +PROV_R_ONESHOT_CALL_OUT_OF_ORDER:239:oneshot call out of order 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 @@ -1087,12 +1177,16 @@ 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_UNEXPECTED_KEY_PARAMETERS:249:unexpected key parameters 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_UNSUPPORTED_SELECTION:250:unsupported selection +PROV_R_UPDATE_CALL_OUT_OF_ORDER:240:update call out of order PROV_R_URI_AUTHORITY_UNSUPPORTED:223:uri authority unsupported PROV_R_VALUE_ERROR:138:value error +PROV_R_WRONG_CIPHERTEXT_SIZE:251:wrong ciphertext size 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 @@ -1118,6 +1212,7 @@ 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_INVALID_PROPERTY_QUERY:137:invalid property query 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 @@ -1128,6 +1223,7 @@ 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_IS_EMPTY:142:random pool is empty 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 @@ -1250,8 +1346,10 @@ 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_CERTIFICATE:348:bad certificate SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec SSL_R_BAD_CIPHER:186:bad cipher +SSL_R_BAD_COMPRESSION_ALGORITHM:326:bad compression algorithm 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 @@ -1308,6 +1406,7 @@ 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_CONN_USE_ONLY:356:conn use only 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 @@ -1333,21 +1432,27 @@ SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:281:\ 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_DOMAIN_USE_ONLY:422:domain use only 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_RAW_PUBLIC_KEY:349:empty raw public key 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_IN_SYSTEM_DEFAULT_CONFIG:419:error in system default config 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_GET_PARAMETER:316:failed to get parameter SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async +SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE:417:feature negotiation not complete +SSL_R_FEATURE_NOT_RENEGOTIABLE:413:feature not renegotiable 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 @@ -1372,6 +1477,8 @@ 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_RAW_PUBLIC_KEY:350:invalid raw public key +SSL_R_INVALID_RECORD:317:invalid record 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 @@ -1385,11 +1492,14 @@ 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_LISTENER_USE_ONLY:421:listener use only +SSL_R_MAXIMUM_ENCRYPTED_PKTS_REACHED:395:maximum encrypted pkts reached 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_QUIC_TLS_FUNCTIONS:423:missing quic tls functions 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 @@ -1397,6 +1507,8 @@ 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_SUPPORTED_VERSIONS_EXTENSION:420:\ + missing supported versions 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:\ @@ -1427,9 +1539,11 @@ 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_STREAM:355:no stream 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_RECORD_LAYER:322:no suitable record layer 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 @@ -1447,16 +1561,23 @@ 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_POLL_REQUEST_NOT_SUPPORTED:418:poll request not supported 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_QUIC_HANDSHAKE_LAYER_ERROR:393:quic handshake layer error +SSL_R_QUIC_NETWORK_ERROR:387:quic network error +SSL_R_QUIC_PROTOCOL_ERROR:382:quic protocol error SSL_R_READ_BIO_NOT_SET:211:read bio not set SSL_R_READ_TIMEOUT_EXPIRED:312:read timeout expired +SSL_R_RECORDS_NOT_RELEASED:321:records not released +SSL_R_RECORD_LAYER_FAILURE:313:record layer failure SSL_R_RECORD_LENGTH_MISMATCH:213:record length mismatch SSL_R_RECORD_TOO_SMALL:298:record too small +SSL_R_REMOTE_PEER_ADDRESS_NOT_SET:346:remote peer address not set 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 @@ -1467,6 +1588,7 @@ 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_SEQUENCE_CTR_WRAPPED:327:sequence ctr wrapped 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 @@ -1483,6 +1605,18 @@ SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH:232:\ 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_SSLV3_ALERT_BAD_CERTIFICATE:1042:ssl/tls alert bad certificate +SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:1020:ssl/tls alert bad record mac +SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:1045:ssl/tls alert certificate expired +SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:1044:ssl/tls alert certificate revoked +SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:1046:ssl/tls alert certificate unknown +SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:1030:ssl/tls alert decompression failure +SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:1040:ssl/tls alert handshake failure +SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:1047:ssl/tls alert illegal parameter +SSL_R_SSLV3_ALERT_NO_CERTIFICATE:1041:ssl/tls alert no certificate +SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:1010:ssl/tls alert unexpected message +SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:1043:\ + ssl/tls alert unsupported certificate 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 @@ -1498,6 +1632,35 @@ 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_STREAM_COUNT_LIMITED:411:stream count limited +SSL_R_STREAM_FINISHED:365:stream finished +SSL_R_STREAM_RECV_ONLY:366:stream recv only +SSL_R_STREAM_RESET:375:stream reset +SSL_R_STREAM_SEND_ONLY:379:stream send only +SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED:1116:tlsv13 alert certificate required +SSL_R_TLSV13_ALERT_MISSING_EXTENSION:1109:tlsv13 alert missing extension +SSL_R_TLSV1_ALERT_ACCESS_DENIED:1049:tlsv1 alert access denied +SSL_R_TLSV1_ALERT_DECODE_ERROR:1050:tlsv1 alert decode error +SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:1021:tlsv1 alert decryption failed +SSL_R_TLSV1_ALERT_DECRYPT_ERROR:1051:tlsv1 alert decrypt error +SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:1060:tlsv1 alert export restriction +SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK:1086:tlsv1 alert inappropriate fallback +SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:1071:tlsv1 alert insufficient security +SSL_R_TLSV1_ALERT_INTERNAL_ERROR:1080:tlsv1 alert internal error +SSL_R_TLSV1_ALERT_NO_APPLICATION_PROTOCOL:1120:\ + tlsv1 alert no application protocol +SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:1100:tlsv1 alert no renegotiation +SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:1070:tlsv1 alert protocol version +SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:1022:tlsv1 alert record overflow +SSL_R_TLSV1_ALERT_UNKNOWN_CA:1048:tlsv1 alert unknown ca +SSL_R_TLSV1_ALERT_UNKNOWN_PSK_IDENTITY:1115:tlsv1 alert unknown psk identity +SSL_R_TLSV1_ALERT_USER_CANCELLED:1090:tlsv1 alert user cancelled +SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE:1114:tlsv1 bad certificate hash value +SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE:1113:\ + tlsv1 bad certificate status response +SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE:1111:tlsv1 certificate unobtainable +SSL_R_TLSV1_UNRECOGNIZED_NAME:1112:tlsv1 unrecognized name +SSL_R_TLSV1_UNSUPPORTED_EXTENSION:1110:tlsv1 unsupported extension 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 @@ -1522,6 +1685,7 @@ 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_MANDATORY_PARAMETER:323:unknown mandatory parameter 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 @@ -1530,16 +1694,21 @@ 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_CONFIG_VALUE:414:unsupported config value +SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS:415:unsupported config value class +SSL_R_UNSUPPORTED_CONFIG_VALUE_OP:416:unsupported config value op 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_UNSUPPORTED_WRITE_FLAG:412:unsupported write flag 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_RPK_TYPE:351:wrong rpk type 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 @@ -1602,6 +1771,8 @@ 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_BAD_OPTION:170:bad option +X509V3_R_BAD_VALUE:171:bad value 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 @@ -1661,6 +1832,7 @@ 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_PURPOSE_NOT_UNIQUE:173:purpose not unique 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 @@ -1668,6 +1840,7 @@ 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_UNKNOWN_VALUE:172:unknown value X509V3_R_UNSUPPORTED_OPTION:117:unsupported option X509V3_R_UNSUPPORTED_TYPE:167:unsupported type X509V3_R_USER_TOO_LONG:132:user too long @@ -1675,7 +1848,7 @@ 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_CANT_CHECK_DH_KEY:114:can't 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 @@ -1713,5 +1886,6 @@ 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_UNSUPPORTED_VERSION:145:unsupported version X509_R_WRONG_LOOKUP_TYPE:112:wrong lookup type X509_R_WRONG_TYPE:122:wrong type diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c index cd42f951f7b8..ff174470da76 100644 --- a/crypto/ess/ess_lib.c +++ b/crypto/ess/ess_lib.c @@ -29,28 +29,38 @@ ESS_SIGNING_CERT *OSSL_ESS_signing_cert_new_init(const X509 *signcert, ESS_SIGNING_CERT *sc; int i; - if ((sc = ESS_SIGNING_CERT_new()) == NULL) + if ((sc = ESS_SIGNING_CERT_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; + } if (sc->cert_ids == NULL - && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL) + && (sc->cert_ids = sk_ESS_CERT_ID_new_null()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); goto err; + } if ((cid = ESS_CERT_ID_new_init(signcert, set_issuer_serial)) == NULL - || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) + || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; + } for (i = 0; i < sk_X509_num(certs); ++i) { X509 *cert = sk_X509_value(certs, i); - if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL - || !sk_ESS_CERT_ID_push(sc->cert_ids, cid)) + if ((cid = ESS_CERT_ID_new_init(cert, 1)) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; + } + if (!sk_ESS_CERT_ID_push(sc->cert_ids, cid)) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); + goto err; + } } return sc; err: ESS_SIGNING_CERT_free(sc); ESS_CERT_ID_free(cid); - ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); return NULL; } @@ -61,38 +71,53 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(const X509 *cert, GENERAL_NAME *name = NULL; unsigned char cert_sha1[SHA_DIGEST_LENGTH]; - if ((cid = ESS_CERT_ID_new()) == NULL) + if ((cid = ESS_CERT_ID_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; - if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) + } + if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL)) { + ERR_raise(ERR_LIB_ESS, ERR_R_X509_LIB); goto err; - if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) + } + if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH)) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } /* Setting the issuer/serial if requested. */ if (!set_issuer_serial) return cid; if (cid->issuer_serial == NULL - && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) + && (cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; - if ((name = GENERAL_NAME_new()) == NULL) + } + if ((name = GENERAL_NAME_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } name->type = GEN_DIRNAME; - if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) + if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_X509_LIB); goto err; - if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) + } + if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); goto err; + } name = NULL; /* Ownership is lost. */ ASN1_INTEGER_free(cid->issuer_serial->serial); - if ((cid->issuer_serial->serial = - ASN1_INTEGER_dup(X509_get0_serialNumber(cert))) == NULL) + if ((cid->issuer_serial->serial + = ASN1_INTEGER_dup(X509_get0_serialNumber(cert))) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } return cid; err: GENERAL_NAME_free(name); ESS_CERT_ID_free(cid); - ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); return NULL; } @@ -106,22 +131,32 @@ ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg, ESS_SIGNING_CERT_V2 *sc; int i; - if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) + if ((sc = ESS_SIGNING_CERT_V2_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; + } cid = ESS_CERT_ID_V2_new_init(hash_alg, signcert, set_issuer_serial); - if (cid == NULL) + if (cid == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; - if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + } + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); goto err; + } cid = NULL; for (i = 0; i < sk_X509_num(certs); ++i) { X509 *cert = sk_X509_value(certs, i); - if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL) + if ((cid = ESS_CERT_ID_V2_new_init(hash_alg, cert, 1)) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; - if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) + } + if (!sk_ESS_CERT_ID_V2_push(sc->cert_ids, cid)) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); goto err; + } cid = NULL; } @@ -129,7 +164,6 @@ ESS_SIGNING_CERT_V2 *OSSL_ESS_signing_cert_v2_new_init(const EVP_MD *hash_alg, err: ESS_SIGNING_CERT_V2_free(sc); ESS_CERT_ID_V2_free(cid); - ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); return NULL; } @@ -145,52 +179,71 @@ static ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new_init(const EVP_MD *hash_alg, memset(hash, 0, sizeof(hash)); - if ((cid = ESS_CERT_ID_V2_new()) == NULL) + if ((cid = ESS_CERT_ID_V2_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; + } if (!EVP_MD_is_a(hash_alg, SN_sha256)) { alg = X509_ALGOR_new(); - if (alg == NULL) + if (alg == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } X509_ALGOR_set_md(alg, hash_alg); - if (alg->algorithm == NULL) + if (alg->algorithm == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } cid->hash_alg = alg; alg = NULL; } else { cid->hash_alg = NULL; } - if (!X509_digest(cert, hash_alg, hash, &hash_len)) + if (!X509_digest(cert, hash_alg, hash, &hash_len)) { + ERR_raise(ERR_LIB_ESS, ERR_R_X509_LIB); goto err; + } - if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) + if (!ASN1_OCTET_STRING_set(cid->hash, hash, hash_len)) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } if (!set_issuer_serial) return cid; - if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) + if ((cid->issuer_serial = ESS_ISSUER_SERIAL_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ESS_LIB); goto err; - if ((name = GENERAL_NAME_new()) == NULL) + } + if ((name = GENERAL_NAME_new()) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } name->type = GEN_DIRNAME; - if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) + if ((name->d.dirn = X509_NAME_dup(X509_get_issuer_name(cert))) == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; - if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) + } + if (!sk_GENERAL_NAME_push(cid->issuer_serial->issuer, name)) { + ERR_raise(ERR_LIB_ESS, ERR_R_CRYPTO_LIB); goto err; + } name = NULL; /* Ownership is lost. */ ASN1_INTEGER_free(cid->issuer_serial->serial); cid->issuer_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(cert)); - if (cid->issuer_serial->serial == NULL) + if (cid->issuer_serial->serial == NULL) { + ERR_raise(ERR_LIB_ESS, ERR_R_ASN1_LIB); goto err; + } return cid; err: X509_ALGOR_free(alg); GENERAL_NAME_free(name); ESS_CERT_ID_V2_free(cid); - ERR_raise(ERR_LIB_ESS, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c index b7784c899457..ded0a9245121 100644 --- a/crypto/evp/asymcipher.c +++ b/crypto/evp/asymcipher.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,6 +17,16 @@ #include "crypto/evp.h" #include "evp_local.h" +static void evp_asym_cipher_free(void *data) +{ + EVP_ASYM_CIPHER_free(data); +} + +static int evp_asym_cipher_up_ref(void *data) +{ + return EVP_ASYM_CIPHER_up_ref(data); +} + static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, const OSSL_PARAM params[]) { @@ -189,7 +199,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation, ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); return -2; } - switch(ctx->operation) { + switch (ctx->operation) { case EVP_PKEY_OP_ENCRYPT: if (ctx->pmeth->encrypt_init == NULL) return 1; @@ -298,25 +308,39 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); } +/* decrypt to new buffer of dynamic size, checking any pre-determined size */ +int evp_pkey_decrypt_alloc(EVP_PKEY_CTX *ctx, unsigned char **outp, + size_t *outlenp, size_t expected_outlen, + const unsigned char *in, size_t inlen) +{ + if (EVP_PKEY_decrypt(ctx, NULL, outlenp, in, inlen) <= 0 + || (*outp = OPENSSL_malloc(*outlenp)) == NULL) + return -1; + if (EVP_PKEY_decrypt(ctx, *outp, outlenp, in, inlen) <= 0 + || *outlenp == 0 + || (expected_outlen != 0 && *outlenp != expected_outlen)) { + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); + OPENSSL_clear_free(*outp, *outlenp); + *outp = NULL; + return 0; + } + return 1; +} static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov) { EVP_ASYM_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_ASYM_CIPHER)); - if (cipher == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (cipher == NULL) return NULL; - } - cipher->lock = CRYPTO_THREAD_lock_new(); - if (cipher->lock == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&cipher->refcnt, 1) + || !ossl_provider_up_ref(prov)) { + CRYPTO_FREE_REF(&cipher->refcnt); OPENSSL_free(cipher); return NULL; } cipher->prov = prov; - ossl_provider_up_ref(prov); - cipher->refcnt = 1; return cipher; } @@ -331,7 +355,7 @@ static void *evp_asym_cipher_from_algorithm(int name_id, int gparamfncnt = 0, sparamfncnt = 0; if ((cipher = evp_asym_cipher_new(prov)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } @@ -444,12 +468,12 @@ void EVP_ASYM_CIPHER_free(EVP_ASYM_CIPHER *cipher) if (cipher == NULL) return; - CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock); + CRYPTO_DOWN_REF(&cipher->refcnt, &i); if (i > 0) return; OPENSSL_free(cipher->type_name); ossl_provider_free(cipher->prov); - CRYPTO_THREAD_lock_free(cipher->lock); + CRYPTO_FREE_REF(&cipher->refcnt); OPENSSL_free(cipher); } @@ -457,7 +481,7 @@ int EVP_ASYM_CIPHER_up_ref(EVP_ASYM_CIPHER *cipher) { int ref = 0; - CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock); + CRYPTO_UP_REF(&cipher->refcnt, &ref); return 1; } @@ -471,8 +495,8 @@ EVP_ASYM_CIPHER *EVP_ASYM_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, { return evp_generic_fetch(ctx, OSSL_OP_ASYM_CIPHER, algorithm, properties, evp_asym_cipher_from_algorithm, - (int (*)(void *))EVP_ASYM_CIPHER_up_ref, - (void (*)(void *))EVP_ASYM_CIPHER_free); + evp_asym_cipher_up_ref, + evp_asym_cipher_free); } EVP_ASYM_CIPHER *evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER *prov, @@ -482,8 +506,8 @@ EVP_ASYM_CIPHER *evp_asym_cipher_fetch_from_prov(OSSL_PROVIDER *prov, return evp_generic_fetch_from_prov(prov, OSSL_OP_ASYM_CIPHER, algorithm, properties, evp_asym_cipher_from_algorithm, - (int (*)(void *))EVP_ASYM_CIPHER_up_ref, - (void (*)(void *))EVP_ASYM_CIPHER_free); + evp_asym_cipher_up_ref, + evp_asym_cipher_free); } int EVP_ASYM_CIPHER_is_a(const EVP_ASYM_CIPHER *cipher, const char *name) @@ -514,8 +538,8 @@ void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx, evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER, (void (*)(void *, void *))fn, arg, evp_asym_cipher_from_algorithm, - (int (*)(void *))EVP_ASYM_CIPHER_up_ref, - (void (*)(void *))EVP_ASYM_CIPHER_free); + evp_asym_cipher_up_ref, + evp_asym_cipher_free); } diff --git a/crypto/evp/bio_b64.c b/crypto/evp/bio_b64.c index 81d2609c302b..98a8fa552569 100644 --- a/crypto/evp/bio_b64.c +++ b/crypto/evp/bio_b64.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -39,8 +39,8 @@ typedef struct b64_struct { int start; /* have we started decoding yet? */ int cont; /* <= 0 when finished */ EVP_ENCODE_CTX *base64; - char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; - char tmp[B64_BLOCK_SIZE]; + unsigned char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; + unsigned char tmp[B64_BLOCK_SIZE]; } BIO_B64_CTX; static const BIO_METHOD methods_b64 = { @@ -58,7 +58,6 @@ static const BIO_METHOD methods_b64 = { b64_callback_ctrl, }; - const BIO_METHOD *BIO_f_base64(void) { return &methods_b64; @@ -68,10 +67,8 @@ static int b64_new(BIO *bi) { BIO_B64_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) return 0; - } ctx->cont = 1; ctx->start = 1; @@ -90,6 +87,7 @@ static int b64_new(BIO *bi) static int b64_free(BIO *a) { BIO_B64_CTX *ctx; + if (a == NULL) return 0; @@ -105,9 +103,17 @@ static int b64_free(BIO *a) return 1; } +/* + * Unless `BIO_FLAGS_BASE64_NO_NL` is set, this BIO ignores leading lines that + * aren't exclusively composed of valid Base64 characters (followed by + * or ). Once a valid Base64 line is found, `ctx->start` is set to 0 and + * lines are processed until EOF or the first line that contains invalid Base64 + * characters. In a nod to PEM, lines that start with a '-' (hyphen) are + * treated as a soft EOF, rather than an error. + */ static int b64_read(BIO *b, char *out, int outl) { - int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; + int ret = 0, i, ii, j, k, x, n, num, ret_code; BIO_B64_CTX *ctx; unsigned char *p, *q; BIO *next; @@ -117,7 +123,7 @@ static int b64_read(BIO *b, char *out, int outl) ctx = (BIO_B64_CTX *)BIO_get_data(b); next = BIO_next(b); - if ((ctx == NULL) || (next == NULL)) + if (ctx == NULL || next == NULL) return 0; BIO_clear_retry_flags(b); @@ -130,7 +136,7 @@ static int b64_read(BIO *b, char *out, int outl) EVP_DecodeInit(ctx->base64); } - /* First check if there are bytes decoded/encoded */ + /* First check if there are buffered bytes already decoded */ if (ctx->buf_len > 0) { OPENSSL_assert(ctx->buf_len >= ctx->buf_off); i = ctx->buf_len - ctx->buf_off; @@ -148,14 +154,17 @@ static int b64_read(BIO *b, char *out, int outl) } } - /* - * At this point, we have room of outl bytes and an empty buffer, so we - * should read in some more. - */ + /* Restore any non-retriable error condition (ctx->cont < 0) */ + ret_code = ctx->cont < 0 ? ctx->cont : 0; - ret_code = 0; + /* + * At this point, we have room of outl bytes and an either an empty buffer, + * or outl == 0, so we'll attempt to read in some more. + */ while (outl > 0) { - if (ctx->cont <= 0) + int again = ctx->cont; + + if (again <= 0) break; i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]), @@ -166,18 +175,22 @@ static int b64_read(BIO *b, char *out, int outl) /* Should we continue next time we are called? */ if (!BIO_should_retry(next)) { - ctx->cont = i; - /* If buffer empty break */ - if (ctx->tmp_len == 0) - break; - /* Fall through and process what we have */ - else - i = 0; + /* Incomplete final Base64 chunk in the decoder is an error */ + if (ctx->tmp_len == 0) { + if (EVP_DecodeFinal(ctx->base64, NULL, &num) < 0) + ret_code = -1; + EVP_DecodeInit(ctx->base64); + } + ctx->cont = ret_code; } - /* else we retry and add more data to buffer */ - else + if (ctx->tmp_len == 0) break; + /* Fall through and process what we have */ + i = 0; + /* But don't loop to top-up even if the buffer is not full! */ + again = 0; } + i += ctx->tmp_len; ctx->tmp_len = i; @@ -185,11 +198,10 @@ static int b64_read(BIO *b, char *out, int outl) * We need to scan, a line at a time until we have a valid line if we * are starting. */ - if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { - /* ctx->start=1; */ + if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) != 0) { ctx->tmp_len = 0; } else if (ctx->start) { - q = p = (unsigned char *)ctx->tmp; + q = p = ctx->tmp; num = 0; for (j = 0; j < i; j++) { if (*(q++) != '\n') @@ -206,50 +218,57 @@ static int b64_read(BIO *b, char *out, int outl) continue; } - k = EVP_DecodeUpdate(ctx->base64, - (unsigned char *)ctx->buf, - &num, p, q - p); - if ((k <= 0) && (num == 0) && (ctx->start)) - EVP_DecodeInit(ctx->base64); - else { - if (p != (unsigned char *) - &(ctx->tmp[0])) { - i -= (p - (unsigned char *) - &(ctx->tmp[0])); - for (x = 0; x < i; x++) - ctx->tmp[x] = p[x]; - } - EVP_DecodeInit(ctx->base64); - ctx->start = 0; - break; + k = EVP_DecodeUpdate(ctx->base64, ctx->buf, &num, p, q - p); + EVP_DecodeInit(ctx->base64); + if (k <= 0 && num == 0) { + p = q; + continue; } - p = q; + + ctx->start = 0; + if (p != ctx->tmp) { + i -= p - ctx->tmp; + for (x = 0; x < i; x++) + ctx->tmp[x] = p[x]; + } + break; } /* we fell off the end without starting */ - if ((j == i) && (num == 0)) { + if (ctx->start) { /* * Is this is one long chunk?, if so, keep on reading until a * new line. */ - if (p == (unsigned char *)&(ctx->tmp[0])) { + if (p == ctx->tmp) { /* Check buffer full */ if (i == B64_BLOCK_SIZE) { ctx->tmp_nl = 1; ctx->tmp_len = 0; } - } else if (p != q) { /* finished on a '\n' */ + } else if (p != q) { + /* Retain partial line at end of buffer */ n = q - p; for (ii = 0; ii < n; ii++) ctx->tmp[ii] = p[ii]; ctx->tmp_len = n; + } else { + /* All we have is newline terminated non-start data */ + ctx->tmp_len = 0; } - /* else finished on a '\n' */ - continue; + /* + * Try to read more if possible, otherwise we can't make + * progress unless the underlying BIO is retriable and may + * produce more data next time we're called. + */ + if (again > 0) + continue; + else + break; } else { ctx->tmp_len = 0; } - } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { + } else if (i < B64_BLOCK_SIZE && again > 0) { /* * If buffer isn't full and we can retry then restart to read in * more data. @@ -257,37 +276,9 @@ static int b64_read(BIO *b, char *out, int outl) continue; } - if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { - int z, jj; - - jj = i & ~3; /* process per 4 */ - z = EVP_DecodeBlock((unsigned char *)ctx->buf, - (unsigned char *)ctx->tmp, jj); - if (jj > 2) { - if (ctx->tmp[jj - 1] == '=') { - z--; - if (ctx->tmp[jj - 2] == '=') - z--; - } - } - /* - * z is now number of output bytes and jj is the number consumed - */ - if (jj != i) { - memmove(ctx->tmp, &ctx->tmp[jj], i - jj); - ctx->tmp_len = i - jj; - } - ctx->buf_len = 0; - if (z > 0) { - ctx->buf_len = z; - } - i = z; - } else { - i = EVP_DecodeUpdate(ctx->base64, - (unsigned char *)ctx->buf, &ctx->buf_len, - (unsigned char *)ctx->tmp, i); - ctx->tmp_len = 0; - } + i = EVP_DecodeUpdate(ctx->base64, ctx->buf, &ctx->buf_len, + ctx->tmp, i); + ctx->tmp_len = 0; /* * If eof or an error was signalled, then the condition * 'ctx->cont <= 0' will prevent b64_read() from reading @@ -298,7 +289,7 @@ static int b64_read(BIO *b, char *out, int outl) ctx->buf_off = 0; if (i < 0) { - ret_code = 0; + ret_code = ctx->start ? 0 : i; ctx->buf_len = 0; break; } @@ -320,7 +311,7 @@ static int b64_read(BIO *b, char *out, int outl) } /* BIO_clear_retry_flags(b); */ BIO_copy_next_retry(b); - return ((ret == 0) ? ret_code : ret); + return ret == 0 ? ret_code : ret; } static int b64_write(BIO *b, const char *in, int inl) @@ -333,7 +324,7 @@ static int b64_write(BIO *b, const char *in, int inl) ctx = (BIO_B64_CTX *)BIO_get_data(b); next = BIO_next(b); - if ((ctx == NULL) || (next == NULL)) + if (ctx == NULL || next == NULL) return 0; BIO_clear_retry_flags(b); @@ -366,13 +357,13 @@ static int b64_write(BIO *b, const char *in, int inl) ctx->buf_off = 0; ctx->buf_len = 0; - if ((in == NULL) || (inl <= 0)) + if (in == NULL || inl <= 0) return 0; while (inl > 0) { - n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; + n = inl > B64_BLOCK_SIZE ? B64_BLOCK_SIZE : inl; - if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { + if ((BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) != 0) { if (ctx->tmp_len > 0) { OPENSSL_assert(ctx->tmp_len <= 3); n = 3 - ctx->tmp_len; @@ -387,8 +378,7 @@ static int b64_write(BIO *b, const char *in, int inl) if (ctx->tmp_len < 3) break; ctx->buf_len = - EVP_EncodeBlock((unsigned char *)ctx->buf, - (unsigned char *)ctx->tmp, ctx->tmp_len); + EVP_EncodeBlock(ctx->buf, ctx->tmp, ctx->tmp_len); OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); OPENSSL_assert(ctx->buf_len >= ctx->buf_off); /* @@ -405,17 +395,15 @@ static int b64_write(BIO *b, const char *in, int inl) } n -= n % 3; ctx->buf_len = - EVP_EncodeBlock((unsigned char *)ctx->buf, - (const unsigned char *)in, n); + EVP_EncodeBlock(ctx->buf, (unsigned char *)in, n); OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); OPENSSL_assert(ctx->buf_len >= ctx->buf_off); ret += n; } } else { - if (!EVP_EncodeUpdate(ctx->base64, - (unsigned char *)ctx->buf, &ctx->buf_len, - (unsigned char *)in, n)) - return ((ret == 0) ? -1 : ret); + if (!EVP_EncodeUpdate(ctx->base64, ctx->buf, &ctx->buf_len, + (unsigned char *)in, n)) + return ret == 0 ? -1 : ret; OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); OPENSSL_assert(ctx->buf_len >= ctx->buf_off); ret += n; @@ -429,7 +417,7 @@ static int b64_write(BIO *b, const char *in, int inl) i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); if (i <= 0) { BIO_copy_next_retry(b); - return ((ret == 0) ? i : ret); + return ret == 0 ? i : ret; } OPENSSL_assert(i <= n); n -= i; @@ -452,7 +440,7 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) ctx = (BIO_B64_CTX *)BIO_get_data(b); next = BIO_next(b); - if ((ctx == NULL) || (next == NULL)) + if (ctx == NULL || next == NULL) return 0; switch (cmd) { @@ -471,8 +459,8 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_WPENDING: /* More to write in buffer */ OPENSSL_assert(ctx->buf_len >= ctx->buf_off); ret = ctx->buf_len - ctx->buf_off; - if ((ret == 0) && (ctx->encode != B64_NONE) - && (EVP_ENCODE_CTX_num(ctx->base64) != 0)) + if (ret == 0 && ctx->encode != B64_NONE + && EVP_ENCODE_CTX_num(ctx->base64) != 0) ret = 1; else if (ret <= 0) ret = BIO_ctrl(next, cmd, num, ptr); @@ -493,9 +481,8 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) } if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { if (ctx->tmp_len != 0) { - ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf, - (unsigned char *)ctx->tmp, - ctx->tmp_len); + ctx->buf_len = EVP_EncodeBlock(ctx->buf, + ctx->tmp, ctx->tmp_len); ctx->buf_off = 0; ctx->tmp_len = 0; goto again; @@ -503,13 +490,13 @@ static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) } else if (ctx->encode != B64_NONE && EVP_ENCODE_CTX_num(ctx->base64) != 0) { ctx->buf_off = 0; - EVP_EncodeFinal(ctx->base64, - (unsigned char *)ctx->buf, &(ctx->buf_len)); + EVP_EncodeFinal(ctx->base64, ctx->buf, &(ctx->buf_len)); /* push out the bytes */ goto again; } /* Finally flush the underlying BIO */ ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); break; case BIO_C_DO_STATE_MACHINE: diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c index 304030bcb3b5..ffe4b5bb02e3 100644 --- a/crypto/evp/bio_enc.c +++ b/crypto/evp/bio_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -65,10 +65,8 @@ static int enc_new(BIO *bi) { BIO_ENC_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) return 0; - } ctx->cipher = EVP_CIPHER_CTX_new(); if (ctx->cipher == NULL) { @@ -134,6 +132,10 @@ static int enc_read(BIO *b, char *out, int outl) } blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); + + if (blocksize == 0) + return 0; + if (blocksize == 1) blocksize = 0; @@ -362,6 +364,7 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) /* Finally flush the underlying BIO */ ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); break; case BIO_C_GET_CIPHER_STATUS: ret = (long)ctx->ok; diff --git a/crypto/evp/bio_ok.c b/crypto/evp/bio_ok.c index 97e67fcb6814..20811ffded6f 100644 --- a/crypto/evp/bio_ok.c +++ b/crypto/evp/bio_ok.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -132,10 +132,8 @@ static int ok_new(BIO *bi) { BIO_OK_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) return 0; - } ctx->cont = 1; ctx->sigio = 1; @@ -374,6 +372,7 @@ static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) /* Finally flush the underlying BIO */ ret = BIO_ctrl(next, cmd, num, ptr); + BIO_copy_next_retry(b); break; case BIO_C_DO_STATE_MACHINE: BIO_clear_retry_flags(b); @@ -444,6 +443,8 @@ static int sig_out(BIO *b) md_size = EVP_MD_get_size(digest); md_data = EVP_MD_CTX_get0_md_data(md); + if (md_size <= 0) + goto berr; if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE) return 1; @@ -486,7 +487,7 @@ static int sig_in(BIO *b) if ((md = ctx->md) == NULL) goto berr; digest = EVP_MD_CTX_get0_md(md); - if ((md_size = EVP_MD_get_size(digest)) < 0) + if ((md_size = EVP_MD_get_size(digest)) <= 0) goto berr; md_data = EVP_MD_CTX_get0_md_data(md); @@ -534,6 +535,8 @@ static int block_out(BIO *b) md = ctx->md; digest = EVP_MD_CTX_get0_md(md); md_size = EVP_MD_get_size(digest); + if (md_size <= 0) + goto berr; tl = ctx->buf_len - OK_BLOCK_BLOCK; ctx->buf[0] = (unsigned char)(tl >> 24); @@ -564,7 +567,7 @@ static int block_in(BIO *b) ctx = BIO_get_data(b); md = ctx->md; md_size = EVP_MD_get_size(EVP_MD_CTX_get0_md(md)); - if (md_size < 0) + if (md_size <= 0) goto berr; assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */ diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 95fea31226b0..80570bdcce46 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -1,7 +1,8 @@ LIBS=../../libcrypto $COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c evp_utils.c \ mac_lib.c mac_meth.c keymgmt_meth.c keymgmt_lib.c kdf_lib.c kdf_meth.c \ - m_sigver.c pmeth_lib.c signature.c p_lib.c pmeth_gn.c exchange.c \ + skeymgmt_meth.c \ + pmeth_lib.c signature.c p_lib.c s_lib.c pmeth_gn.c exchange.c \ evp_rand.c asymcipher.c kem.c dh_support.c ec_support.c pmeth_check.c SOURCE[../../libcrypto]=$COMMON\ @@ -16,7 +17,7 @@ SOURCE[../../libcrypto]=$COMMON\ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ e_chacha20_poly1305.c \ legacy_sha.c ctrl_params_translate.c \ - cmeth_lib.c + cmeth_lib.c m_sigver.c # Diverse type specific ctrl functions. They are kinda sorta legacy, kinda # sorta not. diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c index d556b5ab280a..c74b3dcd753a 100644 --- a/crypto/evp/c_allc.c +++ b/crypto/evp/c_allc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -149,6 +149,7 @@ void openssl_add_all_ciphers_int(void) EVP_add_cipher(EVP_aes_128_wrap()); EVP_add_cipher_alias(SN_id_aes128_wrap, "aes128-wrap"); EVP_add_cipher(EVP_aes_128_wrap_pad()); + EVP_add_cipher_alias(SN_id_aes128_wrap_pad, "aes128-wrap-pad"); EVP_add_cipher_alias(SN_aes_128_cbc, "AES128"); EVP_add_cipher_alias(SN_aes_128_cbc, "aes128"); EVP_add_cipher(EVP_aes_192_ecb()); @@ -166,6 +167,7 @@ void openssl_add_all_ciphers_int(void) EVP_add_cipher(EVP_aes_192_wrap()); EVP_add_cipher_alias(SN_id_aes192_wrap, "aes192-wrap"); EVP_add_cipher(EVP_aes_192_wrap_pad()); + EVP_add_cipher_alias(SN_id_aes192_wrap_pad, "aes192-wrap-pad"); EVP_add_cipher_alias(SN_aes_192_cbc, "AES192"); EVP_add_cipher_alias(SN_aes_192_cbc, "aes192"); EVP_add_cipher(EVP_aes_256_ecb()); @@ -184,6 +186,7 @@ void openssl_add_all_ciphers_int(void) EVP_add_cipher(EVP_aes_256_wrap()); EVP_add_cipher_alias(SN_id_aes256_wrap, "aes256-wrap"); EVP_add_cipher(EVP_aes_256_wrap_pad()); + EVP_add_cipher_alias(SN_id_aes256_wrap_pad, "aes256-wrap-pad"); EVP_add_cipher_alias(SN_aes_256_cbc, "AES256"); EVP_add_cipher_alias(SN_aes_256_cbc, "aes256"); EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); diff --git a/crypto/evp/cmeth_lib.c b/crypto/evp/cmeth_lib.c index a806ec5f9e22..41a1bade2c44 100644 --- a/crypto/evp/cmeth_lib.c +++ b/crypto/evp/cmeth_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -46,10 +46,10 @@ EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher) if ((to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size, cipher->key_len)) != NULL) { - CRYPTO_RWLOCK *lock = to->lock; + CRYPTO_REF_COUNT refcnt = to->refcnt; memcpy(to, cipher, sizeof(*to)); - to->lock = lock; + to->refcnt = refcnt; to->origin = EVP_ORIG_METH; } return to; diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c index 44d0895bcf14..13240db611b3 100644 --- a/crypto/evp/ctrl_params_translate.c +++ b/crypto/evp/ctrl_params_translate.c @@ -1,5 +1,5 @@ /* - * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -458,11 +458,9 @@ static int default_fixup_args(enum state state, 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); + if ((ctx->allocated_buf + = OPENSSL_malloc(ctx->buflen)) == NULL) return 0; - } if (BN_bn2nativepad(ctx->p2, ctx->allocated_buf, ctx->buflen) < 0) { OPENSSL_free(ctx->allocated_buf); @@ -784,7 +782,7 @@ static int fix_cipher_md(enum state state, if (state == POST_CTRL_TO_PARAMS && ctx->action_type == GET) { /* - * Here's how we re-use |ctx->orig_p2| that was set in the + * Here's how we reuse |ctx->orig_p2| that was set in the * PRE_CTRL_TO_PARAMS state above. */ *(void **)ctx->orig_p2 = @@ -1664,6 +1662,64 @@ static int get_payload_public_key(enum state state, return ret; } +static int get_payload_public_key_ec(enum state state, + const struct translation_st *translation, + struct translation_ctx_st *ctx) +{ +#ifndef OPENSSL_NO_EC + EVP_PKEY *pkey = ctx->p2; + const EC_KEY *eckey = EVP_PKEY_get0_EC_KEY(pkey); + BN_CTX *bnctx; + const EC_POINT *point; + const EC_GROUP *ecg; + BIGNUM *x = NULL; + BIGNUM *y = NULL; + int ret = 0; + + ctx->p2 = NULL; + + if (eckey == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE); + return 0; + } + + bnctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(eckey)); + if (bnctx == NULL) + return 0; + + point = EC_KEY_get0_public_key(eckey); + ecg = EC_KEY_get0_group(eckey); + + /* Caller should have requested a BN, fail if not */ + if (ctx->params->data_type != OSSL_PARAM_UNSIGNED_INTEGER) + goto out; + + x = BN_CTX_get(bnctx); + y = BN_CTX_get(bnctx); + if (y == NULL) + goto out; + + if (!EC_POINT_get_affine_coordinates(ecg, point, x, y, bnctx)) + goto out; + + if (strncmp(ctx->params->key, OSSL_PKEY_PARAM_EC_PUB_X, 2) == 0) + ctx->p2 = x; + else if (strncmp(ctx->params->key, OSSL_PKEY_PARAM_EC_PUB_Y, 2) == 0) + ctx->p2 = y; + else + goto out; + + /* Return the payload */ + ret = default_fixup_args(state, translation, ctx); +out: + BN_CTX_free(bnctx); + return ret; +#else + ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE); + return 0; +#endif +} + static int get_payload_bn(enum state state, const struct translation_st *translation, struct translation_ctx_st *ctx, const BIGNUM *bn) @@ -2258,7 +2314,7 @@ static const struct translation_st evp_pkey_ctx_translations[] = { 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 + * This is accommodated by default_fixup_args() above, which mimics that * expectation for any translation item where |ctrl_str| is NULL and * |ctrl_hexstr| is non-NULL. */ @@ -2269,6 +2325,12 @@ static const struct translation_st evp_pkey_ctx_translations[] = { EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, NULL, NULL, OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL, OSSL_PARAM_OCTET_PTR, NULL }, + { SET, EVP_PKEY_RSA, 0, EVP_PKEY_OP_TYPE_CRYPT, + EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION, NULL, + "rsa_pkcs1_implicit_rejection", + OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, OSSL_PARAM_UNSIGNED_INTEGER, + 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 }, @@ -2400,6 +2462,12 @@ static const struct translation_st evp_pkey_translations[] = { OSSL_PKEY_PARAM_PUB_KEY, 0 /* no data type, let get_payload_public_key() handle that */, get_payload_public_key }, + { GET, -1, -1, -1, 0, NULL, NULL, + OSSL_PKEY_PARAM_EC_PUB_X, OSSL_PARAM_UNSIGNED_INTEGER, + get_payload_public_key_ec }, + { GET, -1, -1, -1, 0, NULL, NULL, + OSSL_PKEY_PARAM_EC_PUB_Y, OSSL_PARAM_UNSIGNED_INTEGER, + get_payload_public_key_ec }, /* DH and DSA */ { GET, -1, -1, -1, 0, NULL, NULL, @@ -2590,7 +2658,7 @@ lookup_translation(struct translation_st *tmpl, tmpl->ctrl_hexstr = ctrl_hexstr; } else if (tmpl->param_key != NULL) { /* - * Search criteria that originates from a OSSL_PARAM setter or + * Search criteria that originates from an OSSL_PARAM setter or * getter. * * Ctrls were fundamentally bidirectional, with only the ctrl @@ -2827,11 +2895,15 @@ static int evp_pkey_ctx_setget_params_to_ctrl(EVP_PKEY_CTX *pctx, int evp_pkey_ctx_set_params_to_ctrl(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params) { + if (ctx->keymgmt != NULL) + return 0; 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) { + if (ctx->keymgmt != NULL) + return 0; return evp_pkey_ctx_setget_params_to_ctrl(ctx, GET, params); } diff --git a/crypto/evp/dh_support.c b/crypto/evp/dh_support.c index 87296ffbee2b..d2472874221a 100644 --- a/crypto/evp/dh_support.c +++ b/crypto/evp/dh_support.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,7 +12,7 @@ #include "internal/nelem.h" #include "crypto/dh.h" -typedef struct dh_name2id_st{ +typedef struct dh_name2id_st { const char *name; int id; int type; @@ -28,8 +28,7 @@ typedef struct dh_name2id_st{ # define TYPE_DHX 0 #endif -static const DH_GENTYPE_NAME2ID dhtype2id[] = -{ +static const DH_GENTYPE_NAME2ID dhtype2id[] = { { "group", DH_PARAMGEN_TYPE_GROUP, TYPE_ANY }, { "generator", DH_PARAMGEN_TYPE_GENERATOR, TYPE_DH }, { "fips186_4", DH_PARAMGEN_TYPE_FIPS_186_4, TYPE_DHX }, diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index aca05186ec10..6fc201bcfe25 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,6 +20,7 @@ #include #include #include "internal/cryptlib.h" +#include "internal/nelem.h" #include "internal/provider.h" #include "internal/core.h" #include "crypto/evp.h" @@ -77,7 +78,6 @@ 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 @@ -86,7 +86,6 @@ static int evp_md_ctx_reset_ex(EVP_MD_CTX *ctx, int keep_fetched) EVP_PKEY_CTX_free(ctx->pctx); ctx->pctx = NULL; } -#endif evp_md_ctx_clear_digest(ctx, 0, keep_fetched); if (!keep_fetched) @@ -110,7 +109,7 @@ EVP_MD_CTX *evp_md_ctx_new_ex(EVP_PKEY *pkey, const ASN1_OCTET_STRING *id, 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); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); goto err; } @@ -141,6 +140,20 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx) OPENSSL_free(ctx); } +int evp_md_ctx_free_algctx(EVP_MD_CTX *ctx) +{ + 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; + } + return 1; +} + static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, const OSSL_PARAM params[], ENGINE *impl) { @@ -167,17 +180,8 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, } #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; - } + EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED + | EVP_MD_CTX_FLAG_FINALISED); if (type != NULL) { ctx->reqdigest = type; @@ -197,21 +201,20 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, * 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))) + if (ctx->engine != NULL + && ctx->digest != 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; - } + /* + * 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) + if (impl == NULL) tmpimpl = ENGINE_get_digest_engine(type->type); #endif @@ -219,15 +222,20 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, * 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) + if (impl != NULL +#if !defined(OPENSSL_NO_ENGINE) + || ctx->engine != NULL +# if !defined(FIPS_MODULE) || tmpimpl != NULL +# endif #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 we were using provided hash before, cleanup algctx */ + if (!evp_md_ctx_free_algctx(ctx)) + return 0; if (ctx->digest == ctx->fetched_digest) ctx->digest = NULL; EVP_MD_free(ctx->fetched_digest); @@ -238,6 +246,15 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, cleanup_old_md_data(ctx, 1); /* Start of non-legacy code below */ + if (ctx->digest == type) { + if (!ossl_assert(type->prov != NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } else { + if (!evp_md_ctx_free_algctx(ctx)) + return 0; + } if (type->prov == NULL) { #ifdef FIPS_MODULE @@ -260,11 +277,6 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, #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); @@ -330,10 +342,8 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *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); + if (ctx->md_data == NULL) return 0; - } } } #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) @@ -377,9 +387,15 @@ int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) if (count == 0) return 1; + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); + return 0; + } + if (ctx->pctx != NULL && EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx->pctx) && ctx->pctx->op.sig.algctx != NULL) { +#ifndef FIPS_MODULE /* * Prior to OpenSSL 3.0 EVP_DigestSignUpdate() and * EVP_DigestVerifyUpdate() were just macros for EVP_DigestUpdate(). @@ -392,6 +408,7 @@ int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) return EVP_DigestSignUpdate(ctx, data, count); if (ctx->pctx->operation == EVP_PKEY_OP_VERIFYCTX) return EVP_DigestVerifyUpdate(ctx, data, count); +#endif ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); return 0; } @@ -431,7 +448,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize) if (ctx->digest == NULL) return 0; - sz = EVP_MD_get_size(ctx->digest); + sz = EVP_MD_CTX_get_size(ctx); if (sz < 0) return 0; mdsize = sz; @@ -443,8 +460,15 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize) return 0; } + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } + ret = ctx->digest->dfinal(ctx->algctx, md, &size, mdsize); + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + if (isize != NULL) { if (size <= UINT_MAX) { *isize = (unsigned int)size; @@ -470,6 +494,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize) return ret; } +/* This is a one shot operation */ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size) { int ret = 0; @@ -489,16 +514,28 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size) return 0; } + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } + + /* + * For backward compatibility we pass the XOFLEN via a param here so that + * older providers can use the supplied value. Ideally we should have just + * used the size passed into ctx->digest->dfinal(). + */ 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) + if (EVP_MD_CTX_set_params(ctx, params) >= 0) ret = ctx->digest->dfinal(ctx->algctx, md, &size, size); + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + return ret; legacy: - if (ctx->digest->flags & EVP_MD_FLAG_XOF + if (EVP_MD_xof(ctx->digest) && size <= INT_MAX && ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) { ret = ctx->digest->final(ctx, md); @@ -514,6 +551,38 @@ legacy: return ret; } +/* EVP_DigestSqueeze() can be called multiple times */ +int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *md, size_t size) +{ + if (ctx->digest == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM); + return 0; + } + + if (ctx->digest->prov == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ctx->digest->dsqueeze == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED); + return 0; + } + + return ctx->digest->dsqueeze(ctx->algctx, md, &size, size); +} + +EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in) +{ + EVP_MD_CTX *out = EVP_MD_CTX_new(); + + if (out != NULL && !EVP_MD_CTX_copy_ex(out, in)) { + EVP_MD_CTX_free(out); + out = NULL; + } + return out; +} + int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) { EVP_MD_CTX_reset(out); @@ -548,23 +617,36 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) 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 (out->digest == in->digest && in->digest->copyctx != NULL) { - if (digest_change && in->fetched_digest != NULL) - EVP_MD_up_ref(in->fetched_digest); + in->digest->copyctx(out->algctx, in->algctx); - 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); + EVP_PKEY_CTX_free(out->pctx); + out->pctx = NULL; + cleanup_old_md_data(out, 0); + + out->flags = in->flags; + out->update = in->update; + } else { + evp_md_ctx_reset_ex(out, 1); + digest_change = (out->fetched_digest != in->fetched_digest); + + if (digest_change && in->fetched_digest != NULL + && !EVP_MD_up_ref(in->fetched_digest)) return 0; + 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 (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; + } } } @@ -617,10 +699,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) 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); + if (out->md_data == NULL) return 0; - } } memcpy(out->md_data, in->md_data, out->digest->ctx_size); } @@ -862,13 +942,9 @@ 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; + if (md != NULL && !CRYPTO_NEW_REF(&md->refcnt, 1)) { + OPENSSL_free(md); + return NULL; } return md; } @@ -911,6 +987,11 @@ static int evp_md_cache_constants(EVP_MD *md) size_t mdsize = 0; OSSL_PARAM params[5]; + /* + * Note that these parameters are 'constants' that are only set up + * during the EVP_MD_fetch(). For this reason the XOF functions set the + * md_size to 0, since the output size is unknown. + */ 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); @@ -941,7 +1022,7 @@ static void *evp_md_from_algorithm(int name_id, /* 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); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return NULL; } @@ -950,16 +1031,14 @@ static void *evp_md_from_algorithm(int name_id, 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; + goto err; } #endif md->name_id = name_id; - if ((md->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - EVP_MD_free(md); - return NULL; - } + if ((md->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) + goto err; + md->description = algodef->algorithm_description; for (; fns->function_id != 0; fns++) { @@ -988,6 +1067,12 @@ static void *evp_md_from_algorithm(int name_id, fncnt++; } break; + case OSSL_FUNC_DIGEST_SQUEEZE: + if (md->dsqueeze == NULL) { + md->dsqueeze = OSSL_FUNC_digest_squeeze(fns); + fncnt++; + } + break; case OSSL_FUNC_DIGEST_DIGEST: if (md->digest == NULL) md->digest = OSSL_FUNC_digest_digest(fns); @@ -1029,9 +1114,14 @@ static void *evp_md_from_algorithm(int name_id, md->gettable_ctx_params = OSSL_FUNC_digest_gettable_ctx_params(fns); break; + case OSSL_FUNC_DIGEST_COPYCTX: + if (md->copyctx == NULL) + md->copyctx = + OSSL_FUNC_digest_copyctx(fns); + break; } } - if ((fncnt != 0 && fncnt != 5) + if ((fncnt != 0 && fncnt != 5 && fncnt != 6) || (fncnt == 0 && md->digest == NULL)) { /* * In order to be a consistent set of functions we either need the @@ -1039,21 +1129,24 @@ static void *evp_md_from_algorithm(int name_id, * 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; + goto err; } + if (prov != NULL && !ossl_provider_up_ref(prov)) + goto err; + 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; + goto err; } return md; + +err: + EVP_MD_free(md); + return NULL; } static int evp_md_up_ref(void *md) @@ -1081,7 +1174,7 @@ 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); + CRYPTO_UP_REF(&md->refcnt, &ref); return 1; } @@ -1092,7 +1185,7 @@ void EVP_MD_free(EVP_MD *md) if (md == NULL || md->origin != EVP_ORIG_DYNAMIC) return; - CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock); + CRYPTO_DOWN_REF(&md->refcnt, &i); if (i > 0) return; evp_md_free_int(md); @@ -1106,3 +1199,67 @@ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx, (void (*)(void *, void *))fn, arg, evp_md_from_algorithm, evp_md_up_ref, evp_md_free); } + +EVP_MD *evp_digest_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties) +{ + return evp_generic_fetch_from_prov(prov, OSSL_OP_DIGEST, + algorithm, properties, + evp_md_from_algorithm, + evp_md_up_ref, + evp_md_free); +} + +typedef struct { + int md_nid; + int hmac_nid; +} ossl_hmacmd_pair; + +static const ossl_hmacmd_pair ossl_hmacmd_pairs[] = { + {NID_sha1, NID_hmacWithSHA1}, + {NID_md5, NID_hmacWithMD5}, + {NID_sha224, NID_hmacWithSHA224}, + {NID_sha256, NID_hmacWithSHA256}, + {NID_sha384, NID_hmacWithSHA384}, + {NID_sha512, NID_hmacWithSHA512}, + {NID_id_GostR3411_94, NID_id_HMACGostR3411_94}, + {NID_id_GostR3411_2012_256, NID_id_tc26_hmac_gost_3411_2012_256}, + {NID_id_GostR3411_2012_512, NID_id_tc26_hmac_gost_3411_2012_512}, + {NID_sha3_224, NID_hmac_sha3_224}, + {NID_sha3_256, NID_hmac_sha3_256}, + {NID_sha3_384, NID_hmac_sha3_384}, + {NID_sha3_512, NID_hmac_sha3_512}, + {NID_sha512_224, NID_hmacWithSHA512_224}, + {NID_sha512_256, NID_hmacWithSHA512_256} +}; + +int ossl_hmac2mdnid(int hmac_nid) +{ + int md_nid = NID_undef; + size_t i; + + for (i = 0; i < OSSL_NELEM(ossl_hmacmd_pairs); i++) { + if (ossl_hmacmd_pairs[i].hmac_nid == hmac_nid) { + md_nid = ossl_hmacmd_pairs[i].md_nid; + break; + } + } + + return md_nid; +} + +int ossl_md2hmacnid(int md_nid) +{ + int hmac_nid = NID_undef; + size_t i; + + for (i = 0; i < OSSL_NELEM(ossl_hmacmd_pairs); i++) { + if (ossl_hmacmd_pairs[i].md_nid == md_nid) { + hmac_nid = ossl_hmacmd_pairs[i].hmac_nid; + break; + } + } + + return hmac_nid; +} diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 949de68077ec..10abb7d52cfa 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -8,7 +8,7 @@ */ /* - * This file uses the low level AES functions (which are deprecated for + * This file uses the low-level AES functions (which are deprecated for * non-internal use) in order to implement the EVP AES ciphers. */ #include "internal/deprecated.h" @@ -146,20 +146,21 @@ static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { int ret, mode; EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } mode = EVP_CIPHER_CTX_get_mode(ctx); if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { - ret = aesni_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = aesni_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) aesni_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) aesni_cbc_encrypt : NULL; } else { - ret = aesni_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = aesni_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) aesni_encrypt; if (mode == EVP_CIPH_CBC_MODE) dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; @@ -223,12 +224,19 @@ static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX, ctx); + + if (iv == NULL && key == NULL) return 1; + if (key) { - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &gctx->ks.ks); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + aesni_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt); gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; /* @@ -262,14 +270,19 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); - if (!iv && !key) + if (iv == NULL && key == NULL) return 1; if (key) { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -315,11 +328,18 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + aesni_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) aesni_encrypt); cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks : @@ -342,19 +362,25 @@ static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt * needs both. We could possibly optimise to remove setting the * decrypt for an encryption operation. */ - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + aesni_set_encrypt_key(key, keylen, &octx->ksenc.ks); + aesni_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) aesni_encrypt, @@ -452,6 +478,10 @@ static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, mode = EVP_CIPHER_CTX_get_mode(ctx); bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { ret = 0; @@ -547,10 +577,16 @@ static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; if (key) { - int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aes_t4_encrypt); @@ -603,9 +639,14 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (key) { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -670,10 +711,17 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { - int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (key != NULL) { + const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) aes_t4_encrypt); @@ -696,19 +744,25 @@ static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt * needs both. We could possibly optimise to remove setting the * decrypt for an encryption operation. */ - aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + aes_t4_set_encrypt_key(key, keylen, &octx->ksenc.ks); + aes_t4_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) aes_t4_encrypt, @@ -969,6 +1023,10 @@ static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx, S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx); const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); if (!enc) cctx->fc |= S390X_DECRYPT; @@ -995,6 +1053,14 @@ static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } memcpy(cctx->kmo.param.cv, iv, ivlen); memcpy(cctx->kmo.param.k, key, keylen); cctx->fc = S390X_AES_FC(keylen); @@ -1053,6 +1119,14 @@ static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */ if (!enc) @@ -1075,6 +1149,14 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int rem; unsigned char tmp; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } memcpy(cctx->kmf.param.cv, iv, ivlen); while (n && len) { tmp = *in; @@ -1122,6 +1204,14 @@ static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); cctx->fc |= 1 << 24; /* 1 byte cipher feedback */ if (!enc) @@ -1379,10 +1469,8 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if (gctx->iv != c->iv) OPENSSL_free(gctx->iv); - if ((gctx->iv = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx->iv = OPENSSL_malloc(len)) == NULL) return 0; - } } /* Add padding. */ memset(gctx->iv + arg, 0, len - arg - 8); @@ -1498,10 +1586,8 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) } else { len = S390X_gcm_ivpadlen(gctx->ivlen); - if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) return 0; - } memcpy(gctx_out->iv, gctx->iv, len); } @@ -1527,6 +1613,11 @@ static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, if (key != NULL) { keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + memcpy(&gctx->kma.param.k, key, keylen); gctx->fc = S390X_AES_FC(keylen); @@ -1574,7 +1665,7 @@ static int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, * communication to fail after 2^64 - 1 keys. We do this on the encrypting * side only. */ - if (ctx->encrypt && ++gctx->tls_enc_records == 0) { + if (enc && ++gctx->tls_enc_records == 0) { ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS); goto err; } @@ -1933,6 +2024,11 @@ static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx, if (key != NULL) { keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + cctx->aes.ccm.fc = S390X_AES_FC(keylen); memcpy(cctx->aes.ccm.kmac_param.k, key, keylen); @@ -2143,7 +2239,7 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if (!enc || !cctx->aes.ccm.tag_set) return 0; - if(arg < cctx->aes.ccm.m) + if (arg < cctx->aes.ccm.m) return 0; memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m); @@ -2309,15 +2405,19 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { int ret, mode; EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } mode = EVP_CIPHER_CTX_get_mode(ctx); if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - ret = HWAES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = HWAES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) HWAES_decrypt; dat->stream.cbc = NULL; # ifdef HWAES_cbc_encrypt @@ -2328,27 +2428,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) { - ret = AES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_decrypt; dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt; } else #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - ret = vpaes_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = vpaes_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) vpaes_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) vpaes_cbc_encrypt : NULL; } else #endif { - ret = AES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) AES_cbc_encrypt : NULL; @@ -2356,9 +2450,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, } else #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - ret = HWAES_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = HWAES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) HWAES_encrypt; dat->stream.cbc = NULL; # ifdef HWAES_cbc_encrypt @@ -2376,25 +2468,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) { - ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_encrypt; dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; } else #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - ret = vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = vpaes_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) vpaes_encrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) vpaes_cbc_encrypt : NULL; } else #endif { - ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_encrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) AES_cbc_encrypt : NULL; @@ -2584,10 +2672,8 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { if (gctx->iv != c->iv) OPENSSL_free(gctx->iv); - if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) return 0; - } } gctx->ivlen = arg; return 1; @@ -2686,10 +2772,8 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if (gctx->iv == c->iv) gctx_out->iv = out->iv; else { - if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) return 0; - } memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); } return 1; @@ -2705,13 +2789,21 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + HWAES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) HWAES_encrypt); # ifdef HWAES_ctr32_encrypt_blocks @@ -2724,7 +2816,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE) { - AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + AES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; @@ -2733,7 +2825,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + vpaes_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) vpaes_encrypt); gctx->ctr = NULL; @@ -2742,7 +2834,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif (void)0; /* terminate potentially open 'else' */ - AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + AES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); #ifdef AES_CTR_ASM @@ -2797,7 +2889,7 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, * communication to fail after 2^64 - 1 keys. We do this on the encrypting * side only. */ - if (ctx->encrypt && ++gctx->tls_enc_records == 0) { + if (EVP_CIPHER_CTX_is_encrypting(ctx) && ++gctx->tls_enc_records == 0) { ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_RECORDS); goto err; } @@ -2806,18 +2898,20 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, * Set IV from start of buffer or generate IV and write to start of * buffer. */ - if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN - : EVP_CTRL_GCM_SET_IV_INV, + if (EVP_CIPHER_CTX_ctrl(ctx, + EVP_CIPHER_CTX_is_encrypting(ctx) ? + EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) goto err; /* Use saved AAD */ - if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len)) + if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->tls_aad_len)) goto err; /* Fix buffer and length to point to payload */ in += EVP_GCM_TLS_EXPLICIT_IV_LEN; out += EVP_GCM_TLS_EXPLICIT_IV_LEN; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; - if (ctx->encrypt) { + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { /* Encrypt payload */ if (gctx->ctr) { size_t bulk = 0; @@ -2896,9 +2990,11 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, goto err; } /* Retrieve tag */ - CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN); + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_GCM_TLS_TAG_LEN); /* If tag mismatch wipe buffer */ - if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) { + if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len, + EVP_GCM_TLS_TAG_LEN)) { OPENSSL_cleanse(out, len); goto err; } @@ -2955,7 +3051,7 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, * where setting the IV externally is the only option available. */ if (!gctx->iv_set) { - if (!ctx->encrypt || !aes_gcm_iv_generate(gctx, 0)) + if (!EVP_CIPHER_CTX_is_encrypting(ctx) || !aes_gcm_iv_generate(gctx, 0)) return -1; CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); gctx->iv_set = 1; @@ -2970,7 +3066,7 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (out == NULL) { if (CRYPTO_gcm128_aad(&gctx->gcm, in, len)) return -1; - } else if (ctx->encrypt) { + } else if (EVP_CIPHER_CTX_is_encrypting(ctx)) { if (gctx->ctr) { size_t bulk = 0; #if defined(AES_GCM_ASM) @@ -3061,15 +3157,17 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, } return len; } else { - if (!ctx->encrypt) { + if (!EVP_CIPHER_CTX_is_encrypting(ctx)) { if (gctx->taglen < 0) return -1; - if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0) + if (CRYPTO_gcm128_finish(&gctx->gcm, + EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->taglen) != 0) return -1; gctx->iv_set = 0; return 0; } - CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16); + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16); gctx->taglen = 16; /* Don't reuse the IV */ gctx->iv_set = 0; @@ -3085,9 +3183,9 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM, EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) - BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM, +BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM, EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) - BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM, +BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM, EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) @@ -3122,15 +3220,20 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); - if (!iv && !key) + if (iv == NULL && key == NULL) return 1; - if (key) { + if (key != NULL) { do { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -3269,7 +3372,7 @@ static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | EVP_CIPH_CUSTOM_COPY) BLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS) - BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS) +BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS) static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { @@ -3325,7 +3428,7 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_AEAD_SET_IVLEN: arg = 15 - arg; - /* fall thru */ + /* fall through */ case EVP_CTRL_CCM_SET_L: if (arg < 2 || arg > 8) return 0; @@ -3376,15 +3479,21 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + HWAES_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) HWAES_encrypt); @@ -3395,9 +3504,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + vpaes_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) vpaes_encrypt); cctx->str = NULL; @@ -3405,14 +3512,14 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, break; } #endif - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + AES_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) AES_encrypt); cctx->str = NULL; cctx->key_set = 1; } while (0); - if (iv) { + } + if (iv != NULL) { memcpy(ctx->iv, iv, 15 - cctx->L); cctx->iv_set = 1; } @@ -3567,12 +3674,16 @@ static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (iv == NULL && key == NULL) return 1; if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if (EVP_CIPHER_CTX_is_encrypting(ctx)) - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &wctx->ks.ks); + AES_set_encrypt_key(key, keylen, &wctx->ks.ks); else - AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &wctx->ks.ks); + AES_set_decrypt_key(key, keylen, &wctx->ks.ks); if (iv == NULL) wctx->iv = NULL; } @@ -3800,9 +3911,17 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt @@ -3811,10 +3930,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, */ # ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + HWAES_set_encrypt_key(key, keylen, &octx->ksenc.ks); + HWAES_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) HWAES_encrypt, @@ -3827,12 +3944,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, # endif # ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - vpaes_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + vpaes_set_encrypt_key(key, keylen, &octx->ksenc.ks); + vpaes_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) vpaes_encrypt, @@ -3842,10 +3955,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, break; } # endif - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + AES_set_encrypt_key(key, keylen, &octx->ksenc.ks); + AES_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) AES_encrypt, @@ -3896,7 +4007,7 @@ static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (in != NULL) { /* - * Need to ensure we are only passing full blocks to low level OCB + * Need to ensure we are only passing full blocks to low-level OCB * routines. We do it here rather than in EVP_EncryptUpdate/ * EVP_DecryptUpdate because we need to pass full blocks of AAD too * and those routines don't support that diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c index 4941f98e6483..8843c8ae119f 100644 --- a/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -72,15 +72,16 @@ static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, { EVP_AES_HMAC_SHA1 *key = data(ctx); int ret; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if (enc) - ret = aesni_set_encrypt_key(inkey, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &key->ks); + ret = aesni_set_encrypt_key(inkey, keylen, &key->ks); else - ret = aesni_set_decrypt_key(inkey, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &key->ks); + ret = aesni_set_decrypt_key(inkey, keylen, &key->ks); SHA1_Init(&key->head); /* handy when benchmarking */ key->tail = key->head; @@ -496,6 +497,12 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, # if defined(STITCHED_DECRYPT_CALL) unsigned char tail_iv[AES_BLOCK_SIZE]; int stitch = 0; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } # endif if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) @@ -513,7 +520,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return 0; # if defined(STITCHED_DECRYPT_CALL) - if (len >= 1024 && ctx->key_len == 32) { + if (len >= 1024 && keylen == 32) { /* decrypt last block */ memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE, AES_BLOCK_SIZE); @@ -734,7 +741,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return ret; } else { # if defined(STITCHED_DECRYPT_CALL) - if (len >= 1024 && ctx->key_len == 32) { + if (len >= 1024 && keylen == 32) { if (sha_off %= SHA_CBLOCK) blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK; else diff --git a/crypto/evp/e_aria.c b/crypto/evp/e_aria.c index 7e1fda33e121..5a894fbb9be2 100644 --- a/crypto/evp/e_aria.c +++ b/crypto/evp/e_aria.c @@ -73,7 +73,7 @@ static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, EVP_CIPHER_CTX_get_cipher_data(ctx)); if (ret < 0) { - ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED); + ERR_raise(ERR_LIB_EVP, EVP_R_ARIA_KEY_SETUP_FAILED); return 0; } return 1; @@ -216,7 +216,7 @@ static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ret; - EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx); if (!iv && !key) return 1; @@ -227,7 +227,7 @@ static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) ossl_aria_encrypt); if (ret < 0) { - ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED); + ERR_raise(ERR_LIB_EVP, EVP_R_ARIA_KEY_SETUP_FAILED); return 0; } @@ -255,7 +255,7 @@ static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { - EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,c); + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, c); switch (type) { case EVP_CTRL_INIT: @@ -279,10 +279,8 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { if (gctx->iv != c->iv) OPENSSL_free(gctx->iv); - if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) return 0; - } } gctx->ivlen = arg; return 1; @@ -375,7 +373,7 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_COPY: { EVP_CIPHER_CTX *out = ptr; - EVP_ARIA_GCM_CTX *gctx_out = EVP_C_DATA(EVP_ARIA_GCM_CTX,out); + EVP_ARIA_GCM_CTX *gctx_out = EVP_C_DATA(EVP_ARIA_GCM_CTX, out); if (gctx->gcm.key) { if (gctx->gcm.key != &gctx->ks) return 0; @@ -384,10 +382,8 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) if (gctx->iv == c->iv) gctx_out->iv = out->iv; else { - if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) return 0; - } memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); } return 1; @@ -402,7 +398,7 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx); int rv = -1; /* Encrypt/decrypt must be performed in place */ @@ -458,7 +454,7 @@ static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx); + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx); /* If not set up, return error */ if (!gctx->key_set) @@ -513,7 +509,7 @@ static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ret; - EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX, ctx); if (!iv && !key) return 1; @@ -525,7 +521,7 @@ static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) ossl_aria_encrypt); if (ret < 0) { - ERR_raise(ERR_LIB_EVP,EVP_R_ARIA_KEY_SETUP_FAILED); + ERR_raise(ERR_LIB_EVP, EVP_R_ARIA_KEY_SETUP_FAILED); return 0; } cctx->str = NULL; @@ -540,7 +536,7 @@ static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { - EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,c); + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX, c); switch (type) { case EVP_CTRL_INIT: @@ -593,7 +589,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_AEAD_SET_IVLEN: arg = 15 - arg; - /* fall thru */ + /* fall through */ case EVP_CTRL_CCM_SET_L: if (arg < 2 || arg > 8) return 0; @@ -624,7 +620,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_COPY: { EVP_CIPHER_CTX *out = ptr; - EVP_ARIA_CCM_CTX *cctx_out = EVP_C_DATA(EVP_ARIA_CCM_CTX,out); + EVP_ARIA_CCM_CTX *cctx_out = EVP_C_DATA(EVP_ARIA_CCM_CTX, out); if (cctx->ccm.key) { if (cctx->ccm.key != &cctx->ks) return 0; @@ -641,7 +637,7 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) static int aria_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX, ctx); CCM128_CONTEXT *ccm = &cctx->ccm; /* Encrypt/decrypt must be performed in place */ @@ -689,7 +685,7 @@ static int aria_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx); + EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX, ctx); CCM128_CONTEXT *ccm = &cctx->ccm; /* If not set up, return error */ @@ -765,10 +761,10 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER \ | EVP_CIPH_CUSTOM_IV_LENGTH) -#define BLOCK_CIPHER_aead(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +#define BLOCK_CIPHER_aead(keylen,mode,MODE) \ static const EVP_CIPHER aria_##keylen##_##mode = { \ - nid##_##keylen##_##nmode, \ - blocksize, keylen/8, ivlen, \ + NID_aria_##keylen##_##mode, \ + 1, keylen/8, 12, \ ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \ EVP_ORIG_GLOBAL, \ aria_##mode##_init_key, \ @@ -779,12 +775,12 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \ const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \ { return (EVP_CIPHER*)&aria_##keylen##_##mode; } -BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, gcm, gcm, GCM, 0) -BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, gcm, gcm, GCM, 0) -BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, gcm, gcm, GCM, 0) +BLOCK_CIPHER_aead(128, gcm, GCM) +BLOCK_CIPHER_aead(192, gcm, GCM) +BLOCK_CIPHER_aead(256, gcm, GCM) -BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, ccm, ccm, CCM, 0) -BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, ccm, ccm, CCM, 0) -BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, ccm, ccm, CCM, 0) +BLOCK_CIPHER_aead(128, ccm, CCM) +BLOCK_CIPHER_aead(192, ccm, CCM) +BLOCK_CIPHER_aead(256, ccm, CCM) #endif diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c index 4f1f4822dc92..cb69516bdef0 100644 --- a/crypto/evp/e_camellia.c +++ b/crypto/evp/e_camellia.c @@ -193,7 +193,7 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { int ret, mode; - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); ret = Camellia_set_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, &dat->ks); @@ -220,7 +220,7 @@ static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); if (dat->stream.cbc) (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv, @@ -238,7 +238,7 @@ static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, { size_t bl = EVP_CIPHER_CTX_get_block_size(ctx); size_t i; - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); if (len < bl) return 1; @@ -252,7 +252,7 @@ static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); int num = EVP_CIPHER_CTX_get_num(ctx); CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &num, dat->block); @@ -263,7 +263,7 @@ static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); int num = EVP_CIPHER_CTX_get_num(ctx); CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, ctx->iv, &num, @@ -275,7 +275,7 @@ static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); int num = EVP_CIPHER_CTX_get_num(ctx); CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, ctx->iv, &num, @@ -287,7 +287,7 @@ static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) { int num = EVP_CIPHER_CTX_get_num(ctx); @@ -326,7 +326,7 @@ static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, { int snum = EVP_CIPHER_CTX_get_num(ctx); unsigned int num; - EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY, ctx); if (snum < 0) return 0; diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c index 18e1c0b5ac06..731c1a1dc70c 100644 --- a/crypto/evp/e_chacha20_poly1305.c +++ b/crypto/evp/e_chacha20_poly1305.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -55,7 +55,7 @@ static int chacha_init_key(EVP_CIPHER_CTX *ctx, return 1; } -static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, +static int chacha_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *inp, size_t len) { EVP_CHACHA_KEY *key = data(ctx); @@ -239,7 +239,7 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, actx->len.text = plen; if (plen) { - if (ctx->encrypt) + if (EVP_CIPHER_CTX_is_encrypting(ctx)) ctr = xor128_encrypt_n_pad(out, in, ctr, plen); else ctr = xor128_decrypt_n_pad(out, in, ctr, plen); @@ -263,7 +263,7 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; actx->len.text = plen; - if (ctx->encrypt) { + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { for (i = 0; i < plen; i++) { out[i] = ctr[i] ^= in[i]; } @@ -297,7 +297,7 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, actx->len.aad = EVP_AEAD_TLS1_AAD_LEN; actx->len.text = plen; - if (ctx->encrypt) { + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter); Poly1305_Update(POLY1305_ctx(actx), out, plen); } else { @@ -340,12 +340,12 @@ static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len); OPENSSL_cleanse(buf, buf_len); - Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag - : tohash); + Poly1305_Final(POLY1305_ctx(actx), + EVP_CIPHER_CTX_is_encrypting(ctx) ? actx->tag : tohash); actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; - if (ctx->encrypt) { + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); } else { if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) { @@ -408,7 +408,7 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, else if (len != plen + POLY1305_BLOCK_SIZE) return -1; - if (ctx->encrypt) { /* plaintext */ + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { /* plaintext */ chacha_cipher(ctx, out, in, plen); Poly1305_Update(POLY1305_ctx(actx), out, plen); in += plen; @@ -463,12 +463,12 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE); } - Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag - : temp); + Poly1305_Final(POLY1305_ctx(actx), + EVP_CIPHER_CTX_is_encrypting(ctx) ? actx->tag : temp); actx->mac_inited = 0; if (in != NULL && len != plen) { /* tls mode */ - if (ctx->encrypt) { + if (EVP_CIPHER_CTX_is_encrypting(ctx)) { memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); } else { if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) { @@ -477,7 +477,7 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, } } } - else if (!ctx->encrypt) { + else if (!EVP_CIPHER_CTX_is_encrypting(ctx)) { if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len)) return -1; } @@ -498,7 +498,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, { EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); - switch(type) { + switch (type) { case EVP_CTRL_INIT: if (actx == NULL) actx = ctx->cipher_data @@ -561,7 +561,8 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, return 1; case EVP_CTRL_AEAD_GET_TAG: - if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt) + if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || + !EVP_CIPHER_CTX_is_encrypting(ctx)) return 0; memcpy(ptr, actx->tag, arg); return 1; @@ -577,7 +578,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | aad[EVP_AEAD_TLS1_AAD_LEN - 1]; aad = actx->tls_aad; - if (!ctx->encrypt) { + if (!EVP_CIPHER_CTX_is_encrypting(ctx)) { if (len < POLY1305_BLOCK_SIZE) return 0; len -= POLY1305_BLOCK_SIZE; /* discount attached tag */ diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c index cd6e5af8d0e4..6eb49c033910 100644 --- a/crypto/evp/e_des.c +++ b/crypto/evp/e_des.c @@ -149,7 +149,8 @@ static int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { size_t n, chunk = EVP_MAXCHUNK / 8; - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; /* Appease Coverity */ if (inl < chunk) chunk = inl; diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c index 1e1591834402..8fdf17cdc0d1 100644 --- a/crypto/evp/e_des3.c +++ b/crypto/evp/e_des3.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -165,7 +165,8 @@ static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { size_t n; - unsigned char c[1], d[1]; + unsigned char c[1]; + unsigned char d[1] = { 0 }; /* Appease Coverity */ if (!EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) inl *= 8; @@ -311,8 +312,9 @@ const EVP_CIPHER *EVP_des_ede3(void) # include -static const unsigned char wrap_iv[8] = - { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; +static const unsigned char wrap_iv[8] = { + 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 +}; static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) diff --git a/crypto/evp/e_idea.c b/crypto/evp/e_idea.c index 4a4df4b92510..93da93823d62 100644 --- a/crypto/evp/e_idea.c +++ b/crypto/evp/e_idea.c @@ -42,7 +42,7 @@ static int idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { BLOCK_CIPHER_ecb_loop() - IDEA_ecb_encrypt(in + i, out + i, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + IDEA_ecb_encrypt(in + i, out + i, &EVP_C_DATA(EVP_IDEA_KEY, ctx)->ks); return 1; } @@ -64,12 +64,12 @@ static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, enc = 1; } if (enc) - IDEA_set_encrypt_key(key, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + IDEA_set_encrypt_key(key, &EVP_C_DATA(EVP_IDEA_KEY, ctx)->ks); else { IDEA_KEY_SCHEDULE tmp; IDEA_set_encrypt_key(key, &tmp); - IDEA_set_decrypt_key(&tmp, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); + IDEA_set_decrypt_key(&tmp, &EVP_C_DATA(EVP_IDEA_KEY, ctx)->ks); OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE)); } return 1; diff --git a/crypto/evp/e_seed.c b/crypto/evp/e_seed.c index 98c7385f61da..65ddb573350a 100644 --- a/crypto/evp/e_seed.c +++ b/crypto/evp/e_seed.c @@ -36,6 +36,6 @@ IMPLEMENT_BLOCK_CIPHER(seed, ks, SEED, EVP_SEED_KEY, NID_seed, static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - SEED_set_key(key, &EVP_C_DATA(EVP_SEED_KEY,ctx)->ks); + SEED_set_key(key, &EVP_C_DATA(EVP_SEED_KEY, ctx)->ks); return 1; } diff --git a/crypto/evp/e_sm4.c b/crypto/evp/e_sm4.c index abd603015c71..eeb4fd8e09f8 100644 --- a/crypto/evp/e_sm4.c +++ b/crypto/evp/e_sm4.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2017 Ribose Inc. All Rights Reserved. * Ported from Ribose contributions from Botan. * @@ -17,92 +17,211 @@ # include # include "crypto/sm4.h" # include "crypto/evp.h" +# include "crypto/sm4_platform.h" # include "evp_local.h" typedef struct { - SM4_KEY ks; + union { + OSSL_UNION_ALIGN; + SM4_KEY ks; + } ks; + block128_f block; + union { + ecb128_f ecb; + cbc128_f cbc; + ctr128_f ctr; + } stream; } EVP_SM4_KEY; +# define BLOCK_CIPHER_generic(nid,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER sm4_##mode = { \ + nid##_##nmode,blocksize,128/8,ivlen, \ + flags|EVP_CIPH_##MODE##_MODE, \ + EVP_ORIG_GLOBAL, \ + sm4_init_key, \ + sm4_##mode##_cipher, \ + NULL, \ + sizeof(EVP_SM4_KEY), \ + NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_sm4_##mode(void) \ +{ return &sm4_##mode; } + +#define DEFINE_BLOCK_CIPHERS(nid,flags) \ + BLOCK_CIPHER_generic(nid,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ + BLOCK_CIPHER_generic(nid,1,16,ctr,ctr,CTR,flags) + static int sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx)); + int mode; + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); + + mode = EVP_CIPHER_CTX_get_mode(ctx); + if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) + && !enc) { +#ifdef HWSM4_CAPABLE + if (HWSM4_CAPABLE) { + HWSM4_set_decrypt_key(key, &dat->ks.ks); + dat->block = (block128_f) HWSM4_decrypt; + dat->stream.cbc = NULL; +# ifdef HWSM4_cbc_encrypt + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt; +# endif +# ifdef HWSM4_ecb_encrypt + if (mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt; +# endif + } else +#endif +#ifdef VPSM4_CAPABLE + if (VPSM4_CAPABLE) { + vpsm4_set_decrypt_key(key, &dat->ks.ks); + dat->block = (block128_f) vpsm4_decrypt; + dat->stream.cbc = NULL; + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt; + else if (mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt; + } else +#endif + { + dat->block = (block128_f) ossl_sm4_decrypt; + ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx)); + } + } else +#ifdef HWSM4_CAPABLE + if (HWSM4_CAPABLE) { + HWSM4_set_encrypt_key(key, &dat->ks.ks); + dat->block = (block128_f) HWSM4_encrypt; + dat->stream.cbc = NULL; +# ifdef HWSM4_cbc_encrypt + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) HWSM4_cbc_encrypt; + else +# endif +# ifdef HWSM4_ecb_encrypt + if (mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f) HWSM4_ecb_encrypt; + else +# endif +# ifdef HWSM4_ctr32_encrypt_blocks + if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) HWSM4_ctr32_encrypt_blocks; + else +# endif + (void)0; /* terminate potentially open 'else' */ + } else +#endif +#ifdef VPSM4_CAPABLE + if (VPSM4_CAPABLE) { + vpsm4_set_encrypt_key(key, &dat->ks.ks); + dat->block = (block128_f) vpsm4_encrypt; + dat->stream.cbc = NULL; + if (mode == EVP_CIPH_CBC_MODE) + dat->stream.cbc = (cbc128_f) vpsm4_cbc_encrypt; + else if (mode == EVP_CIPH_ECB_MODE) + dat->stream.ecb = (ecb128_f) vpsm4_ecb_encrypt; + else if (mode == EVP_CIPH_CTR_MODE) + dat->stream.ctr = (ctr128_f) vpsm4_ctr32_encrypt_blocks; + } else +#endif + { + dat->block = (block128_f) ossl_sm4_encrypt; + ossl_sm4_set_key(key, EVP_CIPHER_CTX_get_cipher_data(ctx)); + } return 1; } -static void sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, - size_t len, const SM4_KEY *key, - unsigned char *ivec, const int enc) +static int sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) { - if (enc) - CRYPTO_cbc128_encrypt(in, out, len, key, ivec, - (block128_f)ossl_sm4_encrypt); + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); + + if (dat->stream.cbc) + (*dat->stream.cbc) (in, out, len, &dat->ks.ks, ctx->iv, + EVP_CIPHER_CTX_is_encrypting(ctx)); + else if (EVP_CIPHER_CTX_is_encrypting(ctx)) + CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, + dat->block); else - CRYPTO_cbc128_decrypt(in, out, len, key, ivec, - (block128_f)ossl_sm4_decrypt); + CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, + ctx->iv, dat->block); + return 1; } -static void sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, - size_t length, const SM4_KEY *key, - unsigned char *ivec, int *num, const int enc) +static int sm4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) { - CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc, - (block128_f)ossl_sm4_encrypt); + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); + int num = EVP_CIPHER_CTX_get_num(ctx); + + CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, + ctx->iv, &num, + EVP_CIPHER_CTX_is_encrypting(ctx), dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; } -static void sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, - const SM4_KEY *key, const int enc) +static int sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) { - if (enc) - ossl_sm4_encrypt(in, out, key); + size_t bl = EVP_CIPHER_CTX_get_block_size(ctx); + size_t i; + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); + + if (len < bl) + return 1; + + if (dat->stream.ecb != NULL) + (*dat->stream.ecb) (in, out, len, &dat->ks.ks, + EVP_CIPHER_CTX_is_encrypting(ctx)); else - ossl_sm4_decrypt(in, out, key); + for (i = 0, len -= bl; i <= len; i += bl) + (*dat->block) (in + i, out + i, &dat->ks); + + return 1; } -static void sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, - size_t length, const SM4_KEY *key, - unsigned char *ivec, int *num) +static int sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) { - CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num, - (block128_f)ossl_sm4_encrypt); -} + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); + int num = EVP_CIPHER_CTX_get_num(ctx); -IMPLEMENT_BLOCK_CIPHER(sm4, ks, sm4, EVP_SM4_KEY, NID_sm4, - 16, 16, 16, 128, EVP_CIPH_FLAG_DEFAULT_ASN1, - sm4_init_key, 0, 0, 0, 0) + CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, + ctx->iv, &num, dat->block); + EVP_CIPHER_CTX_set_num(ctx, num); + return 1; +} static int sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t len) { int n = EVP_CIPHER_CTX_get_num(ctx); unsigned int num; - EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY, ctx); + EVP_SM4_KEY *dat = EVP_C_DATA(EVP_SM4_KEY,ctx); if (n < 0) return 0; num = (unsigned int)n; - CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, - EVP_CIPHER_CTX_buf_noconst(ctx), &num, - (block128_f)ossl_sm4_encrypt); + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, + ctx->iv, + EVP_CIPHER_CTX_buf_noconst(ctx), + &num, dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, + ctx->iv, + EVP_CIPHER_CTX_buf_noconst(ctx), &num, + dat->block); EVP_CIPHER_CTX_set_num(ctx, num); return 1; } -static const EVP_CIPHER sm4_ctr_mode = { - NID_sm4_ctr, 1, 16, 16, - EVP_CIPH_CTR_MODE, - EVP_ORIG_GLOBAL, - sm4_init_key, - sm4_ctr_cipher, - NULL, - sizeof(EVP_SM4_KEY), - NULL, NULL, NULL, NULL -}; - -const EVP_CIPHER *EVP_sm4_ctr(void) -{ - return &sm4_ctr_mode; -} - +DEFINE_BLOCK_CIPHERS(NID_sm4, 0) #endif diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c index 2c047fa039ae..9bbb9b43aa42 100644 --- a/crypto/evp/encode.c +++ b/crypto/evp/encode.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,7 +19,7 @@ static unsigned char conv_ascii2bin(unsigned char a, static int evp_encodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, const unsigned char *f, int dlen); static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, - const unsigned char *f, int n); + const unsigned char *f, int n, int eof); #ifndef CHARSET_EBCDIC # define conv_bin2ascii(a, table) ((table)[(a)&0x3f]) @@ -369,14 +369,14 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, } if (n == 64) { - decoded_len = evp_decodeblock_int(ctx, out, d, n); + decoded_len = evp_decodeblock_int(ctx, out, d, n, eof); n = 0; - if (decoded_len < 0 || eof > decoded_len) { + if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) { rv = -1; goto end; } - ret += decoded_len - eof; - out += decoded_len - eof; + ret += decoded_len; + out += decoded_len; } } @@ -388,13 +388,13 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, tail: if (n > 0) { if ((n & 3) == 0) { - decoded_len = evp_decodeblock_int(ctx, out, d, n); + decoded_len = evp_decodeblock_int(ctx, out, d, n, eof); n = 0; - if (decoded_len < 0 || eof > decoded_len) { + if (decoded_len < 0 || (decoded_len == 0 && eof > 0)) { rv = -1; goto end; } - ret += (decoded_len - eof); + ret += decoded_len; } else if (seof) { /* EOF in the middle of a base64 block. */ rv = -1; @@ -411,12 +411,16 @@ end: } static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, - const unsigned char *f, int n) + const unsigned char *f, int n, + int eof) { int i, ret = 0, a, b, c, d; unsigned long l; const unsigned char *table; + if (eof < -1 || eof > 2) + return -1; + if (ctx != NULL && (ctx->flags & EVP_ENCODE_CTX_USE_SRP_ALPHABET) != 0) table = srpdata_ascii2bin; else @@ -437,13 +441,16 @@ static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, if (n % 4 != 0) return -1; + if (n == 0) + return 0; - for (i = 0; i < n; i += 4) { + /* all 4-byte blocks except the last one do not have padding. */ + for (i = 0; i < n - 4; i += 4) { a = conv_ascii2bin(*(f++), table); b = conv_ascii2bin(*(f++), table); c = conv_ascii2bin(*(f++), table); d = conv_ascii2bin(*(f++), table); - if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) + if ((a | b | c | d) & 0x80) return -1; l = ((((unsigned long)a) << 18L) | (((unsigned long)b) << 12L) | @@ -453,12 +460,43 @@ static int evp_decodeblock_int(EVP_ENCODE_CTX *ctx, unsigned char *t, *(t++) = (unsigned char)(l) & 0xff; ret += 3; } + + /* process the last block that may have padding. */ + a = conv_ascii2bin(*(f++), table); + b = conv_ascii2bin(*(f++), table); + c = conv_ascii2bin(*(f++), table); + d = conv_ascii2bin(*(f++), table); + if ((a | b | c | d) & 0x80) + return -1; + l = ((((unsigned long)a) << 18L) | + (((unsigned long)b) << 12L) | + (((unsigned long)c) << 6L) | (((unsigned long)d))); + + if (eof == -1) + eof = (f[2] == '=') + (f[3] == '='); + + switch (eof) { + case 2: + *(t++) = (unsigned char)(l >> 16L) & 0xff; + break; + case 1: + *(t++) = (unsigned char)(l >> 16L) & 0xff; + *(t++) = (unsigned char)(l >> 8L) & 0xff; + break; + case 0: + *(t++) = (unsigned char)(l >> 16L) & 0xff; + *(t++) = (unsigned char)(l >> 8L) & 0xff; + *(t++) = (unsigned char)(l) & 0xff; + break; + } + ret += 3 - eof; + return ret; } int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) { - return evp_decodeblock_int(NULL, t, f, n); + return evp_decodeblock_int(NULL, t, f, n, 0); } int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) @@ -467,7 +505,7 @@ int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) *outl = 0; if (ctx->num != 0) { - i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num); + i = evp_decodeblock_int(ctx, out, ctx->enc_data, ctx->num, -1); if (i < 0) return -1; ctx->num = 0; diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 4e6f83e3d0a9..eee00a07800d 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -24,9 +24,12 @@ #include "internal/cryptlib.h" #include "internal/provider.h" #include "internal/core.h" +#include "internal/safe_math.h" #include "crypto/evp.h" #include "evp_local.h" +OSSL_SAFE_MATH_SIGNED(int, int) + int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) { if (ctx == NULL) @@ -68,7 +71,14 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) { - return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); + EVP_CIPHER_CTX *ctx; + + ctx = OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); + if (ctx == NULL) + return NULL; + + ctx->iv_len = -1; + return ctx; } void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) @@ -83,6 +93,7 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc, + uint8_t is_pipeline, const OSSL_PARAM params[]) { int n; @@ -90,8 +101,6 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, ENGINE *tmpimpl = NULL; #endif - ctx->iv_len = -1; - /* * enc == 1 means we are encrypting. * enc == 0 means we are decrypting. @@ -111,6 +120,8 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, } /* Code below to be removed when legacy support is dropped. */ + if (is_pipeline) + goto nonlegacy; #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) /* @@ -158,7 +169,7 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, } /* Start of non-legacy code below */ - +nonlegacy: /* Ensure a context left lying around from last time is cleared */ if (cipher != NULL && ctx->cipher != NULL) { unsigned long flags = ctx->flags; @@ -203,9 +214,17 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, return 0; } EVP_CIPHER_free(ctx->fetched_cipher); + /* Coverity false positive, the reference counting is confusing it */ + /* coverity[use_after_free] */ ctx->fetched_cipher = (EVP_CIPHER *)cipher; } ctx->cipher = cipher; + + if (is_pipeline && !EVP_CIPHER_can_pipeline(cipher, enc)) { + ERR_raise(ERR_LIB_EVP, EVP_R_PIPELINE_NOT_SUPPORTED); + return 0; + } + if (ctx->algctx == NULL) { ctx->algctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov)); if (ctx->algctx == NULL) { @@ -238,12 +257,12 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, OSSL_PARAM *q = param_lens; const OSSL_PARAM *p; - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); if (p != NULL) memcpy(q++, p, sizeof(*q)); /* - * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for + * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synonym for * OSSL_CIPHER_PARAM_IVLEN so both are covered here. */ p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); @@ -259,8 +278,22 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, } #endif + if (is_pipeline) + return 1; + if (enc) { if (ctx->cipher->einit == NULL) { + /* + * We still should be able to set the IV using the new API + * if the key is not specified and old API is not available + */ + if (key == NULL && ctx->cipher->einit_skey != NULL) { + return ctx->cipher->einit_skey(ctx->algctx, NULL, + iv, + iv == NULL ? 0 + : EVP_CIPHER_CTX_get_iv_length(ctx), + params); + } ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); return 0; } @@ -276,6 +309,17 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, } if (ctx->cipher->dinit == NULL) { + /* + * We still should be able to set the IV using the new API + * if the key is not specified and old API is not available + */ + if (key == NULL && ctx->cipher->dinit_skey != NULL) { + return ctx->cipher->dinit_skey(ctx->algctx, NULL, + iv, + iv == NULL ? 0 + : EVP_CIPHER_CTX_get_iv_length(ctx), + params); + } ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); return 0; } @@ -344,7 +388,6 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size); if (ctx->cipher_data == NULL) { ctx->cipher = NULL; - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return 0; } } else { @@ -431,11 +474,168 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, return 1; } +/* + * This function is basically evp_cipher_init_internal without ENGINE support. + * They should be combined when engines are not supported any longer. + */ +static int evp_cipher_init_skey_internal(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, + const EVP_SKEY *skey, + const unsigned char *iv, size_t iv_len, + int enc, const OSSL_PARAM params[]) +{ + int ret; + + /* + * enc == 1 means we are encrypting. + * enc == 0 means we are decrypting. + * enc == -1 means, use the previously initialised value for encrypt/decrypt + */ + if (enc == -1) + enc = ctx->encrypt; + else + ctx->encrypt = enc != 0; + + if (cipher == NULL && ctx->cipher == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); + return 0; + } + + /* + * If there are engines involved then we throw an error + */ + if (ctx->engine != NULL + || (cipher != NULL && cipher->origin == EVP_ORIG_METH) + || (cipher == NULL && ctx->cipher != NULL + && ctx->cipher->origin == EVP_ORIG_METH)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + /* + * Ensure a context left lying around from last time is cleared + * (legacy code) + */ + if (cipher != NULL && ctx->cipher != NULL) { + if (ctx->cipher->cleanup != NULL && !ctx->cipher->cleanup(ctx)) + return 0; + OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size); + ctx->cipher_data = NULL; + } + + /* Ensure a context left lying around from last time is cleared */ + if (cipher != NULL && ctx->cipher != NULL) { + unsigned long flags = ctx->flags; + + EVP_CIPHER_CTX_reset(ctx); + /* Restore encrypt and flags */ + ctx->encrypt = enc; + ctx->flags = flags; + } + + if (cipher == NULL) + cipher = ctx->cipher; + + if (cipher->prov == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + if (cipher != ctx->fetched_cipher) { + if (!EVP_CIPHER_up_ref((EVP_CIPHER *)cipher)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + EVP_CIPHER_free(ctx->fetched_cipher); + /* Coverity false positive, the reference counting is confusing it */ + /* coverity[use_after_free] */ + ctx->fetched_cipher = (EVP_CIPHER *)cipher; + } + ctx->cipher = cipher; + if (ctx->algctx == NULL) { + ctx->algctx = ctx->cipher->newctx(ossl_provider_ctx(cipher->prov)); + if (ctx->algctx == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + + if (skey != NULL && ctx->cipher->prov != skey->skeymgmt->prov) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) { + /* + * If this ctx was already set up for no padding then we need to tell + * the new cipher about it. + */ + if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) + return 0; + } + + if (iv == NULL) + iv_len = 0; + + /* We have a data managed via key management, using the new callbacks */ + if (enc) { + if (ctx->cipher->einit_skey == NULL) { + /* + * When skey is NULL, it's a multiple-step init as the current API does. + * Otherwise we try to fallback for providers that do not support SKEYs. + */ + const unsigned char *keydata = NULL; + size_t keylen = 0; + + if (skey != NULL && !EVP_SKEY_get0_raw_key(skey, &keydata, &keylen)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + ret = ctx->cipher->einit(ctx->algctx, keydata, keylen, + iv, iv_len, params); + } else { + ret = ctx->cipher->einit_skey(ctx->algctx, + skey == NULL ? NULL : skey->keydata, + iv, iv_len, params); + } + } else { + if (ctx->cipher->dinit_skey == NULL) { + /* + * When skey is NULL, it's a multiple-step init as the current API does. + * Otherwise we try to fallback for providers that do not support SKEYs. + */ + const unsigned char *keydata = NULL; + size_t keylen = 0; + + if (skey != NULL && !EVP_SKEY_get0_raw_key(skey, &keydata, &keylen)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + ret = ctx->cipher->dinit(ctx->algctx, keydata, keylen, + iv, iv_len, params); + } else { + ret = ctx->cipher->dinit_skey(ctx->algctx, + skey == NULL ? NULL : skey->keydata, + iv, iv_len, params); + } + } + + return ret; +} + +int EVP_CipherInit_SKEY(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + EVP_SKEY *skey, const unsigned char *iv, size_t iv_len, + int enc, const OSSL_PARAM params[]) +{ + return evp_cipher_init_skey_internal(ctx, cipher, skey, iv, iv_len, enc, params); +} + int EVP_CipherInit_ex2(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv, int enc, const OSSL_PARAM params[]) { - return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, params); + return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, 0, params); } int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, @@ -443,14 +643,74 @@ int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, { if (cipher != NULL) EVP_CIPHER_CTX_reset(ctx); - return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, NULL); + return evp_cipher_init_internal(ctx, cipher, NULL, key, iv, enc, 0, NULL); } int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc) { - return evp_cipher_init_internal(ctx, cipher, impl, key, iv, enc, NULL); + return evp_cipher_init_internal(ctx, cipher, impl, key, iv, enc, 0, NULL); +} + +int EVP_CipherPipelineEncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + size_t numpipes, + const unsigned char **iv, size_t ivlen) +{ + if (numpipes > EVP_MAX_PIPES) { + ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_PIPES); + return 0; + } + + ctx->numpipes = numpipes; + + if (!evp_cipher_init_internal(ctx, cipher, NULL, NULL, NULL, 1, 1, + NULL)) + return 0; + + if (ctx->cipher->p_einit == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + return ctx->cipher->p_einit(ctx->algctx, + key, + keylen, + numpipes, + iv, + ivlen, + NULL); +} + +int EVP_CipherPipelineDecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + size_t numpipes, + const unsigned char **iv, size_t ivlen) +{ + if (numpipes > EVP_MAX_PIPES) { + ERR_raise(ERR_LIB_EVP, EVP_R_TOO_MANY_PIPES); + return 0; + } + + ctx->numpipes = numpipes; + + if (!evp_cipher_init_internal(ctx, cipher, NULL, NULL, NULL, 0, 1, + NULL)) + return 0; + + if (ctx->cipher->p_dinit == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + return ctx->cipher->p_dinit(ctx->algctx, + key, + keylen, + numpipes, + iv, + ivlen, + NULL); } int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, @@ -462,6 +722,41 @@ int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, return EVP_DecryptUpdate(ctx, out, outl, in, inl); } +int EVP_CipherPipelineUpdate(EVP_CIPHER_CTX *ctx, + unsigned char **out, size_t *outl, + const size_t *outsize, + const unsigned char **in, const size_t *inl) +{ + size_t i; + + if (ossl_unlikely(outl == NULL || inl == NULL)) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ossl_unlikely(ctx->cipher == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); + return 0; + } + + if (ossl_unlikely(ctx->cipher->prov == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ossl_unlikely(ctx->cipher->p_cupdate == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); + return 0; + } + + for (i = 0; i < ctx->numpipes; i++) + outl[i] = 0; + + return ctx->cipher->p_cupdate(ctx->algctx, ctx->numpipes, + out, outl, outsize, + in, inl); +} + int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { if (ctx->encrypt) @@ -478,6 +773,39 @@ int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) return EVP_DecryptFinal(ctx, out, outl); } +int EVP_CipherPipelineFinal(EVP_CIPHER_CTX *ctx, + unsigned char **out, size_t *outl, + const size_t *outsize) +{ + size_t i; + + if (ossl_unlikely(outl == NULL)) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (ossl_unlikely(ctx->cipher == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); + return 0; + } + + if (ossl_unlikely(ctx->cipher->prov == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); + return 0; + } + + if (ossl_unlikely(ctx->cipher->p_cfinal == NULL)) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } + + for (i = 0; i < ctx->numpipes; i++) + outl[i] = 0; + + return ctx->cipher->p_cfinal(ctx->algctx, ctx->numpipes, + out, outl, outsize); +} + int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, const unsigned char *key, const unsigned char *iv) { @@ -562,7 +890,7 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx, int i, j, bl, cmpl = inl; if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) - cmpl = (cmpl + 7) / 8; + cmpl = safe_div_round_up_int(cmpl, 8, NULL); bl = ctx->cipher->block_size; @@ -653,7 +981,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, size_t soutl, inl_ = (size_t)inl; int blocksize; - if (outl != NULL) { + if (ossl_likely(outl != NULL)) { *outl = 0; } else { ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); @@ -661,22 +989,22 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, } /* Prevent accidental use of decryption context when encrypting */ - if (!ctx->encrypt) { + if (ossl_unlikely(!ctx->encrypt)) { ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); return 0; } - if (ctx->cipher == NULL) { + if (ossl_unlikely(ctx->cipher == NULL)) { ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); return 0; } - if (ctx->cipher->prov == NULL) + if (ossl_unlikely(ctx->cipher->prov == NULL)) goto legacy; blocksize = ctx->cipher->block_size; - if (ctx->cipher->cupdate == NULL || blocksize < 1) { + if (ossl_unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) { ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); return 0; } @@ -685,7 +1013,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, inl_ + (size_t)(blocksize == 1 ? 0 : blocksize), in, inl_); - if (ret) { + if (ossl_likely(ret)) { if (soutl > INT_MAX) { ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); return 0; @@ -802,7 +1130,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, size_t soutl, inl_ = (size_t)inl; int blocksize; - if (outl != NULL) { + if (ossl_likely(outl != NULL)) { *outl = 0; } else { ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); @@ -810,21 +1138,21 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, } /* Prevent accidental use of encryption context when decrypting */ - if (ctx->encrypt) { + if (ossl_unlikely(ctx->encrypt)) { ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION); return 0; } - if (ctx->cipher == NULL) { + if (ossl_unlikely(ctx->cipher == NULL)) { ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET); return 0; } - if (ctx->cipher->prov == NULL) + if (ossl_unlikely(ctx->cipher->prov == NULL)) goto legacy; blocksize = EVP_CIPHER_CTX_get_block_size(ctx); - if (ctx->cipher->cupdate == NULL || blocksize < 1) { + if (ossl_unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) { ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); return 0; } @@ -832,7 +1160,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, inl_ + (size_t)(blocksize == 1 ? 0 : blocksize), in, inl_); - if (ret) { + if (ossl_likely(ret)) { if (soutl > INT_MAX) { ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); return 0; @@ -848,7 +1176,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, b = ctx->cipher->block_size; if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) - cmpl = (cmpl + 7) / 8; + cmpl = safe_div_round_up_int(cmpl, 8, NULL); if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { if (b == 1 && ossl_is_partially_overlapping(out, in, cmpl)) { @@ -1025,8 +1353,7 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) for (i = 0; i < n; i++) out[i] = ctx->final[i]; *outl = n; - } else - *outl = 0; + } return 1; } @@ -1035,7 +1362,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) if (c->cipher->prov != NULL) { int ok; OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - size_t len = keylen; + size_t len; if (EVP_CIPHER_CTX_get_key_length(c) == keylen) return 1; @@ -1048,9 +1375,13 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) } params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); + if (!OSSL_PARAM_set_int(params, keylen)) + return 0; ok = evp_do_ciph_ctx_setparams(c->cipher, c->algctx, params); - - return ok > 0 ? 1 : 0; + if (ok <= 0) + return 0; + c->key_len = keylen; + return 1; } /* Code below to be removed when legacy support is dropped. */ @@ -1110,7 +1441,13 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) switch (type) { case EVP_CTRL_SET_KEY_LENGTH: + if (arg < 0) + return 0; + if (ctx->key_len == arg) + /* Skip calling into provider if unchanged. */ + return 1; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz); + ctx->key_len = -1; break; case EVP_CTRL_RAND_KEY: /* Used by DES */ set_params = 0; @@ -1134,6 +1471,9 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) case EVP_CTRL_AEAD_SET_IVLEN: if (arg < 0) return 0; + if (ctx->iv_len == arg) + /* Skip calling into provider if unchanged. */ + return 1; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); ctx->iv_len = -1; break; @@ -1306,11 +1646,27 @@ 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 r = 0; + const OSSL_PARAM *p; + if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) { - ctx->iv_len = -1; - return ctx->cipher->set_ctx_params(ctx->algctx, params); + r = ctx->cipher->set_ctx_params(ctx->algctx, params); + if (r > 0) { + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->key_len)) { + r = 0; + ctx->key_len = -1; + } + } + if (r > 0) { + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->iv_len)) { + r = 0; + ctx->iv_len = -1; + } + } } - return 0; + return r; } int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]) @@ -1406,6 +1762,17 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) #endif /* FIPS_MODULE */ } +EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in) +{ + EVP_CIPHER_CTX *out = EVP_CIPHER_CTX_new(); + + if (out != NULL && !EVP_CIPHER_CTX_copy(out, in)) { + EVP_CIPHER_CTX_free(out); + out = NULL; + } + return out; +} + int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { if ((in == NULL) || (in->cipher == NULL)) { @@ -1457,7 +1824,6 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); if (out->cipher_data == NULL) { out->cipher = NULL; - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return 0; } memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); @@ -1476,13 +1842,9 @@ EVP_CIPHER *evp_cipher_new(void) { EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER)); - if (cipher != NULL) { - cipher->lock = CRYPTO_THREAD_lock_new(); - if (cipher->lock == NULL) { - OPENSSL_free(cipher); - return NULL; - } - cipher->refcnt = 1; + if (cipher != NULL && !CRYPTO_NEW_REF(&cipher->refcnt, 1)) { + OPENSSL_free(cipher); + return NULL; } return cipher; } @@ -1524,10 +1886,10 @@ static void *evp_cipher_from_algorithm(const int name_id, { const OSSL_DISPATCH *fns = algodef->implementation; EVP_CIPHER *cipher = NULL; - int fnciphcnt = 0, fnctxcnt = 0; + int fnciphcnt = 0, encinit = 0, decinit = 0, fnpipecnt = 0, fnctxcnt = 0; if ((cipher = evp_cipher_new()) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return NULL; } @@ -1536,16 +1898,14 @@ static void *evp_cipher_from_algorithm(const int name_id, if (!evp_names_do_all(prov, name_id, set_legacy_nid, &cipher->nid) || cipher->nid == -1) { ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); - EVP_CIPHER_free(cipher); - return NULL; + goto err; } #endif cipher->name_id = name_id; - if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - EVP_CIPHER_free(cipher); - return NULL; - } + if ((cipher->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) + goto err; + cipher->description = algodef->algorithm_description; for (; fns->function_id != 0; fns++) { @@ -1560,13 +1920,25 @@ static void *evp_cipher_from_algorithm(const int name_id, if (cipher->einit != NULL) break; cipher->einit = OSSL_FUNC_cipher_encrypt_init(fns); - fnciphcnt++; + encinit = 1; break; case OSSL_FUNC_CIPHER_DECRYPT_INIT: if (cipher->dinit != NULL) break; cipher->dinit = OSSL_FUNC_cipher_decrypt_init(fns); - fnciphcnt++; + decinit = 1; + break; + case OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT: + if (cipher->einit_skey != NULL) + break; + cipher->einit_skey = OSSL_FUNC_cipher_encrypt_skey_init(fns); + encinit = 1; + break; + case OSSL_FUNC_CIPHER_DECRYPT_SKEY_INIT: + if (cipher->dinit_skey != NULL) + break; + cipher->dinit_skey = OSSL_FUNC_cipher_decrypt_skey_init(fns); + decinit = 1; break; case OSSL_FUNC_CIPHER_UPDATE: if (cipher->cupdate != NULL) @@ -1585,6 +1957,30 @@ static void *evp_cipher_from_algorithm(const int name_id, break; cipher->ccipher = OSSL_FUNC_cipher_cipher(fns); break; + case OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT: + if (cipher->p_einit != NULL) + break; + cipher->p_einit = OSSL_FUNC_cipher_pipeline_encrypt_init(fns); + fnpipecnt++; + break; + case OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT: + if (cipher->p_dinit != NULL) + break; + cipher->p_dinit = OSSL_FUNC_cipher_pipeline_decrypt_init(fns); + fnpipecnt++; + break; + case OSSL_FUNC_CIPHER_PIPELINE_UPDATE: + if (cipher->p_cupdate != NULL) + break; + cipher->p_cupdate = OSSL_FUNC_cipher_pipeline_update(fns); + fnpipecnt++; + break; + case OSSL_FUNC_CIPHER_PIPELINE_FINAL: + if (cipher->p_cfinal != NULL) + break; + cipher->p_cfinal = OSSL_FUNC_cipher_pipeline_final(fns); + fnpipecnt++; + break; case OSSL_FUNC_CIPHER_FREECTX: if (cipher->freectx != NULL) break; @@ -1630,8 +2026,11 @@ static void *evp_cipher_from_algorithm(const int name_id, break; } } + fnciphcnt += encinit + decinit; if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4) - || (fnciphcnt == 0 && cipher->ccipher == NULL) + || (fnciphcnt == 0 && cipher->ccipher == NULL && fnpipecnt == 0) + || (fnpipecnt != 0 && (fnpipecnt < 3 || cipher->p_cupdate == NULL + || cipher->p_cfinal == NULL)) || fnctxcnt != 2) { /* * In order to be a consistent set of functions we must have at least @@ -1639,21 +2038,24 @@ static void *evp_cipher_from_algorithm(const int name_id, * functions, or a single "cipher" function. In all cases we need both * the "newctx" and "freectx" functions. */ - EVP_CIPHER_free(cipher); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); - return NULL; + goto err; } + if (prov != NULL && !ossl_provider_up_ref(prov)) + goto err; + cipher->prov = prov; - if (prov != NULL) - ossl_provider_up_ref(prov); if (!evp_cipher_cache_constants(cipher)) { - EVP_CIPHER_free(cipher); ERR_raise(ERR_LIB_EVP, EVP_R_CACHE_CONSTANTS_FAILED); - cipher = NULL; + goto err; } return cipher; + +err: + EVP_CIPHER_free(cipher); + return NULL; } static int evp_cipher_up_ref(void *cipher) @@ -1677,12 +2079,32 @@ EVP_CIPHER *EVP_CIPHER_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, return cipher; } +EVP_CIPHER *evp_cipher_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties) +{ + return evp_generic_fetch_from_prov(prov, OSSL_OP_CIPHER, + algorithm, properties, + evp_cipher_from_algorithm, + evp_cipher_up_ref, + evp_cipher_free); +} + +int EVP_CIPHER_can_pipeline(const EVP_CIPHER *cipher, int enc) +{ + if (((enc && cipher->p_einit != NULL) || (!enc && cipher->p_dinit != NULL)) + && cipher->p_cupdate != NULL && cipher->p_cfinal != NULL) + return 1; + + return 0; +} + int EVP_CIPHER_up_ref(EVP_CIPHER *cipher) { int ref = 0; if (cipher->origin == EVP_ORIG_DYNAMIC) - CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock); + CRYPTO_UP_REF(&cipher->refcnt, &ref); return 1; } @@ -1690,7 +2112,7 @@ void evp_cipher_free_int(EVP_CIPHER *cipher) { OPENSSL_free(cipher->type_name); ossl_provider_free(cipher->prov); - CRYPTO_THREAD_lock_free(cipher->lock); + CRYPTO_FREE_REF(&cipher->refcnt); OPENSSL_free(cipher); } @@ -1701,7 +2123,7 @@ void EVP_CIPHER_free(EVP_CIPHER *cipher) if (cipher == NULL || cipher->origin != EVP_ORIG_DYNAMIC) return; - CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock); + CRYPTO_DOWN_REF(&cipher->refcnt, &i); if (i > 0) return; evp_cipher_free_int(cipher); diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index c0d92321032f..d8440fc76d13 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,183 +16,196 @@ static const ERR_STRING_DATA EVP_str_reasons[] = { {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_AES_KEY_SETUP_FAILED), - "aes key setup failed"}, + "aes key setup failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ARIA_KEY_SETUP_FAILED), - "aria key setup failed"}, + "aria key setup failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_ALGORITHM_NAME), "bad algorithm name"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_DECRYPT), "bad decrypt"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BAD_KEY_LENGTH), "bad key length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_BUFFER_TOO_SMALL), "buffer too small"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CACHE_CONSTANTS_FAILED), - "cache constants failed"}, + "cache constants failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CAMELLIA_KEY_SETUP_FAILED), - "camellia key setup failed"}, + "camellia key setup failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CANNOT_GET_PARAMETERS), - "cannot get parameters"}, + "cannot get parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CANNOT_SET_PARAMETERS), - "cannot set parameters"}, + "cannot set parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_NOT_GCM_MODE), - "cipher not gcm mode"}, + "cipher not gcm mode"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CIPHER_PARAMETER_ERROR), - "cipher parameter error"}, + "cipher parameter error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COMMAND_NOT_SUPPORTED), - "command not supported"}, + "command not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CONFLICTING_ALGORITHM_NAME), - "conflicting algorithm name"}, + "conflicting algorithm name"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_COPY_ERROR), "copy error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_NOT_IMPLEMENTED), - "ctrl not implemented"}, + "ctrl not implemented"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED), - "ctrl operation not implemented"}, + "ctrl operation not implemented"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), - "data not multiple of block length"}, + "data not multiple of block length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR), "decode error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DEFAULT_QUERY_PARSE_ERROR), - "default query parse error"}, + "default query parse error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_KEY_TYPES), - "different key types"}, + "different key types"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_DIFFERENT_PARAMETERS), - "different parameters"}, + "different parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ERROR_LOADING_SECTION), - "error loading section"}, + "error loading section"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_HMAC_KEY), - "expecting an hmac key"}, + "expecting an hmac key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY), - "expecting an rsa key"}, + "expecting an rsa key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DH_KEY), "expecting a dh key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_DSA_KEY), - "expecting a dsa key"}, + "expecting a dsa key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_ECX_KEY), - "expecting an ecx key"}, + "expecting an ecx key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_EC_KEY), "expecting an ec key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_POLY1305_KEY), - "expecting a poly1305 key"}, + "expecting a poly1305 key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY), - "expecting a siphash key"}, + "expecting a siphash key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GENERATE_ERROR), "generate error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED), + "getting AlgorithmIdentifier not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS), - "illegal scrypt parameters"}, + "illegal scrypt parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS), - "inaccessible domain parameters"}, + "inaccessible domain parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_KEY), "inaccessible key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR), - "initialization error"}, + "initialization error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED), - "input not initialized"}, + "input not initialized"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_CUSTOM_LENGTH), - "invalid custom length"}, + "invalid custom length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_DIGEST), "invalid digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_IV_LENGTH), "invalid iv length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_LENGTH), "invalid length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_NULL_ALGORITHM), - "invalid null algorithm"}, + "invalid null algorithm"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PROVIDER_FUNCTIONS), - "invalid provider functions"}, + "invalid provider functions"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH), - "invalid salt length"}, + "invalid salt length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SECRET_LENGTH), - "invalid secret length"}, + "invalid secret length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SEED_LENGTH), - "invalid seed length"}, + "invalid seed length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_VALUE), "invalid value"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE), - "keymgmt export failure"}, + "keymgmt export failure"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_LOCKING_NOT_SUPPORTED), - "locking not supported"}, + "locking not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED), - "memory limit exceeded"}, + "memory limit exceeded"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MESSAGE_DIGEST_IS_NULL), - "message digest is null"}, + "message digest is null"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED), - "method not supported"}, + "method not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_ABLE_TO_COPY_CTX), - "not able to copy ctx"}, + "not able to copy ctx"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH), - "not XOF or invalid length"}, + "not XOF or invalid length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_IMPORT_FUNCTION), "no import function"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_AVAILABLE), - "no keymgmt available"}, + "no keymgmt available"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEY_SET), "no key set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_OPERATION_SET), "no operation set"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NULL_MAC_PKEY_CTX), "null mac pkey ctx"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ONLY_ONESHOT_SUPPORTED), - "only oneshot supported"}, + "only oneshot supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_INITIALIZED), - "operation not initialized"}, + "operation not initialized"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), - "operation not supported for this keytype"}, + "operation not supported for this keytype"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_SIGNATURE_TYPE), + "operation not supported for this signature type"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OUTPUT_WOULD_OVERFLOW), - "output would overflow"}, + "output would overflow"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE), - "parameter too large"}, + "parameter too large"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING), - "partially overlapping buffers"}, + "partially overlapping buffers"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PIPELINE_NOT_SUPPORTED), + "pipeline not supported"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED), - "pkey application asn1 method already registered"}, + "pkey application asn1 method already registered"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_DECODE_ERROR), - "private key decode error"}, + "private key decode error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PRIVATE_KEY_ENCODE_ERROR), - "private key encode error"}, + "private key encode error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SETTING_XOF_FAILED), "setting xof failed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SET_DEFAULT_PROPERTY_FAILURE), - "set default property failure"}, + "set default property failure"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE), + "signature type and key type incompatible"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_PIPES), "too many pipes"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_ENABLE_LOCKING), - "unable to enable locking"}, + "unable to enable locking"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_MAXIMUM_REQUEST_SIZE), - "unable to get maximum request size"}, + "unable to get maximum request size"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_GET_RANDOM_STRENGTH), - "unable to get random strength"}, + "unable to get random strength"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_LOCK_CONTEXT), - "unable to lock context"}, + "unable to lock context"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNABLE_TO_SET_CALLBACKS), - "unable to set callbacks"}, + "unable to set callbacks"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_BITS), "unknown bits"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_KEY_TYPE), "unknown key type"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_MAX_SIZE), "unknown max size"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_OPTION), "unknown option"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PBE_ALGORITHM), - "unknown pbe algorithm"}, + "unknown pbe algorithm"}, + {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_SECURITY_BITS), + "unknown security bits"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_ALGORITHM), - "unsupported algorithm"}, + "unsupported algorithm"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_CIPHER), "unsupported cipher"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEYLENGTH), - "unsupported keylength"}, + "unsupported keylength"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION), - "unsupported key derivation function"}, + "unsupported key derivation function"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_SIZE), - "unsupported key size"}, + "unsupported key size"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_KEY_TYPE), - "unsupported key type"}, + "unsupported key type"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS), - "unsupported number of rounds"}, + "unsupported number of rounds"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRF), "unsupported prf"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), - "unsupported private key algorithm"}, + "unsupported private key algorithm"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE), - "unsupported salt type"}, + "unsupported salt type"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UPDATE_ERROR), "update error"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED), - "wrap mode not allowed"}, + "wrap mode not allowed"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH), - "wrong final block length"}, + "wrong final block length"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DATA_UNIT_IS_TOO_LARGE), - "xts data unit is too large"}, + "xts data unit is too large"}, {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_XTS_DUPLICATED_KEYS), - "xts duplicated keys"}, + "xts duplicated keys"}, {0, NULL} }; diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 6eeafd948ea1..fbebca1b634c 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,30 +17,12 @@ #include "internal/core.h" #include "internal/provider.h" #include "internal/namemap.h" -#include "internal/property.h" +#include "crypto/decoder.h" #include "crypto/evp.h" /* evp_local.h needs it */ #include "evp_local.h" #define NAME_SEPARATOR ':' -static void evp_method_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *evp_method_store_new(OSSL_LIB_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OSSL_LIB_CTX_METHOD evp_method_store_method = { - /* We want evp_method_store to be cleaned up before the provider store */ - OSSL_LIB_CTX_METHOD_PRIORITY_2, - evp_method_store_new, - evp_method_store_free, -}; - /* Data to be passed through ossl_method_construct() */ struct evp_method_data_st { OSSL_LIB_CTX *libctx; @@ -66,21 +48,25 @@ static void *get_tmp_evp_method_store(void *data) { struct evp_method_data_st *methdata = data; - if (methdata->tmp_store == NULL) + if (methdata->tmp_store == NULL) { methdata->tmp_store = ossl_method_store_new(methdata->libctx); + OSSL_TRACE1(QUERY, "Allocating a new tmp_store %p\n", (void *)methdata->tmp_store); + } else { + OSSL_TRACE1(QUERY, "Using the existing tmp_store %p\n", (void *)methdata->tmp_store); + } return methdata->tmp_store; } static void dealloc_tmp_evp_method_store(void *store) { + OSSL_TRACE1(QUERY, "Deallocating the tmp_store %p\n", store); if (store != NULL) ossl_method_store_free(store); } static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX, - &evp_method_store_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_EVP_METHOD_STORE_INDEX); } static int reserve_evp_method_store(void *store, void *data) @@ -142,7 +128,7 @@ static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov, { struct evp_method_data_st *methdata = data; void *method = NULL; - int name_id = 0; + int name_id; uint32_t meth_id; /* @@ -203,10 +189,15 @@ static int put_evp_method_in_store(void *store, void *method, || (meth_id = evp_method_id(name_id, methdata->operation_id)) == 0) return 0; + OSSL_TRACE1(QUERY, "put_evp_method_in_store: original store: %p\n", store); if (store == NULL && (store = get_evp_method_store(methdata->libctx)) == NULL) return 0; + OSSL_TRACE5(QUERY, + "put_evp_method_in_store: " + "store: %p, names: %s, operation_id %d, method_id: %d, properties: %s\n", + store, names, methdata->operation_id, meth_id, propdef ? propdef : ""); return ossl_method_store_add(store, prov, meth_id, propdef, method, methdata->refcnt_up_method, methdata->destruct_method); @@ -259,8 +250,7 @@ static void destruct_evp_method(void *method, void *data) static void * inner_evp_generic_fetch(struct evp_method_data_st *methdata, OSSL_PROVIDER *prov, int operation_id, - int name_id, const char *name, - const char *properties, + const char *name, ossl_unused const char *properties, void *(*new_method)(int name_id, const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov), @@ -269,10 +259,20 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, { OSSL_METHOD_STORE *store = get_evp_method_store(methdata->libctx); OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); +#ifdef FIPS_MODULE + /* + * The FIPS provider has its own internal library context where only it + * is loaded. Consequently, property queries aren't relevant because + * there is only one fetchable algorithm and it is assumed that the + * FIPS-ness is handled by the using algorithm. + */ + const char *const propq = ""; +#else const char *const propq = properties != NULL ? properties : ""; +#endif /* FIPS_MODULE */ uint32_t meth_id = 0; void *method = NULL; - int unsupported = 0; + int unsupported, name_id; if (store == NULL || namemap == NULL) { ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); @@ -288,18 +288,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, return NULL; } - /* - * If we have been passed both a name_id and a name, we have an - * internal programming error. - */ - if (!ossl_assert(name_id == 0 || name == NULL)) { - ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); - return NULL; - } - /* If we haven't received a name id yet, try to get one for the name */ - if (name_id == 0 && name != NULL) - name_id = ossl_namemap_name2num(namemap, name); + name_id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0; /* * If we have a name id, calculate a method id with evp_method_id(). @@ -318,8 +308,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, * If we haven't found the name yet, chances are that the algorithm to * be fetched is unsupported. */ - if (name_id == 0) - unsupported = 1; + unsupported = name_id == 0; if (meth_id == 0 || !ossl_method_store_cache_get(store, prov, meth_id, propq, &method)) { @@ -354,7 +343,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, * will create a method against all names, but the lookup will fail * as ossl_namemap_name2num treats the name string as a single name * rather than introducing new features where in the EVP__fetch - * parses the string and querys for each, return an error. + * parses the string and queries for each, return an error. */ if (name_id == 0) name_id = ossl_namemap_name2num(namemap, name); @@ -388,6 +377,11 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, ossl_lib_ctx_get_descriptor(methdata->libctx), name == NULL ? "" : name, name_id, properties == NULL ? "" : properties); + } else { + OSSL_TRACE4(QUERY, "%s, Algorithm (%s : %d), Properties (%s)\n", + ossl_lib_ctx_get_descriptor(methdata->libctx), + name == NULL ? "" : name, name_id, + properties == NULL ? "" : properties); } return method; @@ -407,34 +401,7 @@ void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id, methdata.libctx = libctx; methdata.tmp_store = NULL; method = inner_evp_generic_fetch(&methdata, NULL, operation_id, - 0, name, properties, - new_method, up_ref_method, free_method); - dealloc_tmp_evp_method_store(methdata.tmp_store); - return method; -} - -/* - * evp_generic_fetch_by_number() is special, and only returns methods for - * already known names, i.e. it refuses to work if no name_id can be found - * (it's considered an internal programming error). - * This is meant to be used when one method needs to fetch an associated - * method. - */ -void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id, - int name_id, const char *properties, - void *(*new_method)(int name_id, - const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov), - int (*up_ref_method)(void *), - void (*free_method)(void *)) -{ - struct evp_method_data_st methdata; - void *method; - - methdata.libctx = libctx; - methdata.tmp_store = NULL; - method = inner_evp_generic_fetch(&methdata, NULL, operation_id, - name_id, NULL, properties, + name, properties, new_method, up_ref_method, free_method); dealloc_tmp_evp_method_store(methdata.tmp_store); return method; @@ -460,7 +427,7 @@ void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, methdata.libctx = ossl_provider_libctx(prov); methdata.tmp_store = NULL; method = inner_evp_generic_fetch(&methdata, prov, operation_id, - 0, name, properties, + name, properties, new_method, up_ref_method, free_method); dealloc_tmp_evp_method_store(methdata.tmp_store); return method; @@ -494,6 +461,7 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx, OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig); if (plp != NULL && store != NULL) { + int ret; #ifndef FIPS_MODULE char *propstr = NULL; size_t strsz; @@ -527,8 +495,12 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx, #endif ossl_property_free(*plp); *plp = def_prop; - if (store != NULL) - return ossl_method_store_cache_flush_all(store); + + ret = ossl_method_store_cache_flush_all(store); +#ifndef FIPS_MODULE + ossl_decoder_cache_flush(libctx); +#endif + return ret; } ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); return 0; @@ -572,7 +544,7 @@ static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq, pl2 = ossl_property_merge(pl1, *plp); ossl_property_free(pl1); if (pl2 == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); return 0; } if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) { @@ -624,10 +596,8 @@ char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig) } propstr = OPENSSL_malloc(sz); - if (propstr == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (propstr == NULL) return NULL; - } if (ossl_property_list_to_string(libctx, *plp, propstr, sz) == 0) { ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); OPENSSL_free(propstr); @@ -636,6 +606,11 @@ char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig) return propstr; } +char *EVP_get1_default_properties(OSSL_LIB_CTX *libctx) +{ + return evp_get_global_properties_str(libctx, ossl_lib_ctx_is_global_default(libctx)); +} + struct filter_data_st { int operation_id; void (*user_fn)(void *method, void *arg); @@ -664,7 +639,7 @@ void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id, methdata.libctx = libctx; methdata.tmp_store = NULL; - (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, 0, NULL, NULL, + (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, NULL, NULL, new_method, up_ref_method, free_method); data.operation_id = operation_id; diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c index 607d45ee2340..7ef94e44eb53 100644 --- a/crypto/evp/evp_key.c +++ b/crypto/evp/evp_key.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -88,7 +88,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, nkey = EVP_CIPHER_get_key_length(type); niv = EVP_CIPHER_get_iv_length(type); OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH); - OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH); + OPENSSL_assert(niv >= 0 && niv <= EVP_MAX_IV_LENGTH); if (data == NULL) return nkey; diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 4f3d901eba5d..32ada929e1be 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,6 +17,7 @@ #include #include "internal/cryptlib.h" #include +#include #include #include #include @@ -81,8 +82,12 @@ int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type, evp_cipher_aead_asn1_params *asn1_params) { int ret = -1; /* Assume the worst */ - const EVP_CIPHER *cipher = c->cipher; + const EVP_CIPHER *cipher; + if (c == NULL || c->cipher == NULL) + goto err; + + cipher = c->cipher; /* * For legacy implementations, we detect custom AlgorithmIdentifier * parameter handling by checking if the function pointer @@ -123,37 +128,13 @@ int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type, ret = EVP_CIPHER_set_asn1_iv(c, type); } } else if (cipher->prov != NULL) { - OSSL_PARAM params[3], *p = params; - unsigned char *der = NULL, *derp; + /* We cheat, there's no need for an object ID for this use */ + X509_ALGOR alg; - /* - * We make two passes, the first to get the appropriate buffer size, - * and the second to get the actual value. - */ - *p++ = OSSL_PARAM_construct_octet_string( - OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, - NULL, 0); - *p = OSSL_PARAM_construct_end(); + alg.algorithm = NULL; + alg.parameter = type; - if (!EVP_CIPHER_CTX_get_params(c, params)) - goto err; - - /* ... but, we should get a return size too! */ - if (OSSL_PARAM_modified(params) - && params[0].return_size != 0 - && (der = OPENSSL_malloc(params[0].return_size)) != NULL) { - params[0].data = der; - params[0].data_size = params[0].return_size; - OSSL_PARAM_set_all_unmodified(params); - derp = der; - if (EVP_CIPHER_CTX_get_params(c, params) - && OSSL_PARAM_modified(params) - && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp, - params[0].return_size) != NULL) { - ret = 1; - } - OPENSSL_free(der); - } + ret = EVP_CIPHER_CTX_get_algor_params(c, &alg); } else { ret = -2; } @@ -172,8 +153,12 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type, evp_cipher_aead_asn1_params *asn1_params) { int ret = -1; /* Assume the worst */ - const EVP_CIPHER *cipher = c->cipher; + const EVP_CIPHER *cipher; + if (c == NULL || c->cipher == NULL) + goto err; + + cipher = c->cipher; /* * For legacy implementations, we detect custom AlgorithmIdentifier * parameter handling by checking if there the function pointer @@ -212,24 +197,18 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type, ret = EVP_CIPHER_get_asn1_iv(c, type) >= 0 ? 1 : -1; } } else if (cipher->prov != NULL) { - OSSL_PARAM params[3], *p = params; - unsigned char *der = NULL; - int derl = -1; + /* We cheat, there's no need for an object ID for this use */ + X509_ALGOR alg; - if ((derl = i2d_ASN1_TYPE(type, &der)) >= 0) { - *p++ = - OSSL_PARAM_construct_octet_string( - OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS, - der, (size_t)derl); - *p = OSSL_PARAM_construct_end(); - if (EVP_CIPHER_CTX_set_params(c, params)) - ret = 1; - OPENSSL_free(der); - } + alg.algorithm = NULL; + alg.parameter = type; + + ret = EVP_CIPHER_CTX_set_algor_params(c, &alg); } else { ret = -2; } +err: if (ret == -2) ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER); else if (ret <= 0) @@ -387,12 +366,12 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher) int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher) { - return cipher->block_size; + return (cipher == NULL) ? 0 : cipher->block_size; } int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx) { - return EVP_CIPHER_get_block_size(ctx->cipher); + return (ctx == NULL) ? 0 : EVP_CIPHER_get_block_size(ctx->cipher); } int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e) @@ -403,6 +382,9 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e) int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { + if (ctx == NULL || ctx->cipher == NULL) + return 0; + if (ctx->cipher->prov != NULL) { /* * If the provided implementation has a ccipher function, we use it, @@ -415,6 +397,9 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, size_t outl = 0; size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx); + if (blocksize == 0) + return 0; + if (ctx->cipher->ccipher != NULL) ret = ctx->cipher->ccipher(ctx->algctx, out, &outl, inl + (blocksize == 1 ? 0 : blocksize), @@ -454,7 +439,7 @@ EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx) { EVP_CIPHER *cipher; - if (ctx == NULL) + if (ctx == NULL || ctx->cipher == NULL) return NULL; cipher = (EVP_CIPHER *)ctx->cipher; if (!EVP_CIPHER_up_ref(cipher)) @@ -469,7 +454,7 @@ int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx) unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher) { - return cipher->flags; + return cipher == NULL ? 0 : cipher->flags; } void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) @@ -499,11 +484,14 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data) int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher) { - return cipher->iv_len; + return (cipher == NULL) ? 0 : cipher->iv_len; } int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx) { + if (ctx->cipher == NULL) + return 0; + if (ctx->iv_len < 0) { int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); size_t v = len; @@ -652,24 +640,41 @@ int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher) int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx) { - int ok; - size_t v = ctx->key_len; - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + if (ctx->cipher == NULL) + return 0; - params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &v); - ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + if (ctx->key_len <= 0 && ctx->cipher->prov != NULL) { + int ok; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t len; - return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED; + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); + ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + if (ok <= 0) + return EVP_CTRL_RET_UNSUPPORTED; + + /*- + * The if branch should never be taken since EVP_MAX_KEY_LENGTH is + * less than INT_MAX but best to be safe. + * + * Casting away the const is annoying but required here. We need to + * cache the result for performance reasons. + */ + if (!OSSL_PARAM_get_int(params, &((EVP_CIPHER_CTX *)ctx)->key_len)) + return -1; + ((EVP_CIPHER_CTX *)ctx)->key_len = (int)len; + } + return ctx->key_len; } int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher) { - return cipher->nid; + return (cipher == NULL) ? NID_undef : cipher->nid; } int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx) { - return ctx->cipher->nid; + return EVP_CIPHER_get_nid(ctx->cipher); } int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name) @@ -809,6 +814,11 @@ int EVP_MD_get_size(const EVP_MD *md) return md->md_size; } +int EVP_MD_xof(const EVP_MD *md) +{ + return md != NULL && ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0); +} + unsigned long EVP_MD_get_flags(const EVP_MD *md) { return md->flags; @@ -838,10 +848,10 @@ EVP_MD *EVP_MD_meth_dup(const EVP_MD *md) return NULL; if ((to = EVP_MD_meth_new(md->type, md->pkey_type)) != NULL) { - CRYPTO_RWLOCK *lock = to->lock; + CRYPTO_REF_COUNT refcnt = to->refcnt; memcpy(to, md, sizeof(*to)); - to->lock = lock; + to->refcnt = refcnt; to->origin = EVP_ORIG_METH; } return to; @@ -851,7 +861,7 @@ void evp_md_free_int(EVP_MD *md) { OPENSSL_free(md->type_name); ossl_provider_free(md->prov); - CRYPTO_THREAD_lock_free(md->lock); + CRYPTO_FREE_REF(&md->refcnt); OPENSSL_free(md); } @@ -1023,6 +1033,34 @@ EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx) return md; } +int EVP_MD_CTX_get_size_ex(const EVP_MD_CTX *ctx) +{ + EVP_MD_CTX *c = (EVP_MD_CTX *)ctx; + const OSSL_PARAM *gettables; + + gettables = EVP_MD_CTX_gettable_params(c); + if (gettables != NULL + && OSSL_PARAM_locate_const(gettables, + OSSL_DIGEST_PARAM_SIZE) != NULL) { + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t sz = 0; + + /* + * For XOF's EVP_MD_get_size() returns 0 + * So try to get the xoflen instead. This will return -1 if the + * xof length has not been set. + */ + params[0] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE, &sz); + if (EVP_MD_CTX_get_params(c, params) != 1 + || sz == SIZE_MAX + || sz == 0) + return -1; + return sz; + } + /* Normal digests have a constant fixed size output */ + return EVP_MD_get_size(EVP_MD_CTX_get0_md(ctx)); +} + EVP_PKEY_CTX *EVP_MD_CTX_get_pkey_ctx(const EVP_MD_CTX *ctx) { return ctx->pctx; @@ -1155,6 +1193,7 @@ int EVP_PKEY_CTX_get_group_name(EVP_PKEY_CTX *ctx, char *name, size_t namelen) return -1; return 1; } +#endif /* !FIPS_MODULE */ /* * evp_pkey_keygen() abstracts from the explicit use of B @@ -1198,19 +1237,257 @@ EVP_PKEY *EVP_PKEY_Q_keygen(OSSL_LIB_CTX *libctx, const char *propq, name = va_arg(args, char *); params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, name, 0); - } else if (OPENSSL_strcasecmp(type, "ED25519") != 0 - && OPENSSL_strcasecmp(type, "X25519") != 0 - && OPENSSL_strcasecmp(type, "ED448") != 0 - && OPENSSL_strcasecmp(type, "X448") != 0 - && OPENSSL_strcasecmp(type, "SM2") != 0) { - ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); - goto end; } + ret = evp_pkey_keygen(libctx, type, propq, params); - end: va_end(args); return ret; } +#if !defined(FIPS_MODULE) +int EVP_CIPHER_CTX_set_algor_params(EVP_CIPHER_CTX *ctx, const X509_ALGOR *alg) +{ + int ret = -1; /* Assume the worst */ + unsigned char *der = NULL; + int derl = -1; + + if ((derl = i2d_ASN1_TYPE(alg->parameter, &der)) >= 0) { + const char *k_old = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS_OLD; + const char *k_new = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS; + OSSL_PARAM params[3]; + + /* + * Passing the same data with both the old (deprecated) and the + * new AlgID parameters OSSL_PARAM key. + */ + params[0] = OSSL_PARAM_construct_octet_string(k_old, der, (size_t)derl); + params[1] = OSSL_PARAM_construct_octet_string(k_new, der, (size_t)derl); + params[2] = OSSL_PARAM_construct_end(); + ret = EVP_CIPHER_CTX_set_params(ctx, params); + } + OPENSSL_free(der); + return ret; +} + +int EVP_CIPHER_CTX_get_algor_params(EVP_CIPHER_CTX *ctx, X509_ALGOR *alg) +{ + int ret = -1; /* Assume the worst */ + unsigned char *der = NULL; + size_t derl; + ASN1_TYPE *type = NULL; + int i = -1; + const char *k_old = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS_OLD; + const char *k_new = OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS; + const char *derk; + OSSL_PARAM params[3]; + + /* + * We make two passes, the first to get the appropriate buffer size, + * and the second to get the actual value. + * Also, using both the old (deprecated) and the new AlgID parameters + * OSSL_PARAM key, and using whichever the provider responds to. + * Should the provider respond on both, the new key takes priority. + */ + params[0] = OSSL_PARAM_construct_octet_string(k_old, NULL, 0); + params[1] = OSSL_PARAM_construct_octet_string(k_new, NULL, 0); + params[2] = OSSL_PARAM_construct_end(); + + if (!EVP_CIPHER_CTX_get_params(ctx, params)) + goto err; + + /* ... but, we should get a return size too! */ + if (OSSL_PARAM_modified(¶ms[0]) && params[0].return_size != 0) + i = 0; + if (OSSL_PARAM_modified(¶ms[1]) && params[1].return_size != 0) + i = 1; + if (i < 0) + goto err; + + /* + * If alg->parameter is non-NULL, it will be changed by d2i_ASN1_TYPE() + * below. If it is NULL, the d2i_ASN1_TYPE() call will allocate new + * space for it. Either way, alg->parameter can be safely assigned + * with type after the d2i_ASN1_TYPE() call, with the safety that it + * will be ok. + */ + type = alg->parameter; + + derk = params[i].key; + derl = params[i].return_size; + if ((der = OPENSSL_malloc(derl)) != NULL) { + unsigned char *derp = der; + + params[i] = OSSL_PARAM_construct_octet_string(derk, der, derl); + if (EVP_CIPHER_CTX_get_params(ctx, params) + && OSSL_PARAM_modified(¶ms[i]) + && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp, + (int)derl) != NULL) { + /* + * Don't free alg->parameter, see comment further up. + * Worst case, alg->parameter gets assigned its own value. + */ + alg->parameter = type; + ret = 1; + } + } + err: + OPENSSL_free(der); + return ret; +} + +int EVP_CIPHER_CTX_get_algor(EVP_CIPHER_CTX *ctx, X509_ALGOR **alg) +{ + int ret = -1; /* Assume the worst */ + OSSL_PARAM params[2]; + size_t aid_len = 0; + const char *k_aid = OSSL_SIGNATURE_PARAM_ALGORITHM_ID; + + params[0] = OSSL_PARAM_construct_octet_string(k_aid, NULL, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (EVP_CIPHER_CTX_get_params(ctx, params) <= 0) + goto err; + + if (OSSL_PARAM_modified(¶ms[0])) + aid_len = params[0].return_size; + if (aid_len == 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED); + ret = -2; + goto err; + } + if (alg != NULL) { + unsigned char *aid = NULL; + const unsigned char *pp = NULL; + + if ((aid = OPENSSL_malloc(aid_len)) != NULL) { + params[0] = OSSL_PARAM_construct_octet_string(k_aid, aid, aid_len); + pp = aid; + if (EVP_CIPHER_CTX_get_params(ctx, params) + && OSSL_PARAM_modified(¶ms[0]) + && d2i_X509_ALGOR(alg, &pp, aid_len) != NULL) + ret = 1; + } + OPENSSL_free(aid); + } + err: + return ret; +} + +int EVP_PKEY_CTX_set_algor_params(EVP_PKEY_CTX *ctx, const X509_ALGOR *alg) +{ + int ret = -1; /* Assume the worst */ + unsigned char *der = NULL; + int derl = -1; + + if ((derl = i2d_ASN1_TYPE(alg->parameter, &der)) >= 0) { + const char *k = OSSL_PKEY_PARAM_ALGORITHM_ID_PARAMS; + OSSL_PARAM params[2]; + + /* + * Passing the same data with both the old (deprecated) and the + * new AlgID parameters OSSL_PARAM key. + */ + params[0] = OSSL_PARAM_construct_octet_string(k, der, (size_t)derl); + params[1] = OSSL_PARAM_construct_end(); + ret = EVP_PKEY_CTX_set_params(ctx, params); + } + OPENSSL_free(der); + return ret; +} + +int EVP_PKEY_CTX_get_algor_params(EVP_PKEY_CTX *ctx, X509_ALGOR *alg) +{ + int ret = -1; /* Assume the worst */ + OSSL_PARAM params[2]; + unsigned char *der = NULL; + size_t derl; + ASN1_TYPE *type = NULL; + const char *k = OSSL_PKEY_PARAM_ALGORITHM_ID_PARAMS; + + /* + * We make two passes, the first to get the appropriate buffer size, + * and the second to get the actual value. + * Also, using both the old (deprecated) and the new AlgID parameters + * OSSL_PARAM key, and using whichever the provider responds to. + * Should the provider respond on both, the new key takes priority. + */ + params[0] = OSSL_PARAM_construct_octet_string(k, NULL, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_PKEY_CTX_get_params(ctx, params)) + goto err; + + /* + * If alg->parameter is non-NULL, it will be changed by d2i_ASN1_TYPE() + * below. If it is NULL, the d2i_ASN1_TYPE() call will allocate new + * space for it. Either way, alg->parameter can be safely assigned + * with type after the d2i_ASN1_TYPE() call, with the safety that it + * will be ok. + */ + type = alg->parameter; + + derl = params[0].return_size; + if (OSSL_PARAM_modified(¶ms[0]) + /* ... but, we should get a return size too! */ + && derl != 0 + && (der = OPENSSL_malloc(derl)) != NULL) { + unsigned char *derp = der; + + params[0] = OSSL_PARAM_construct_octet_string(k, der, derl); + if (EVP_PKEY_CTX_get_params(ctx, params) + && OSSL_PARAM_modified(¶ms[0]) + && d2i_ASN1_TYPE(&type, (const unsigned char **)&derp, + derl) != NULL) { + /* + * Don't free alg->parameter, see comment further up. + * Worst case, alg->parameter gets assigned its own value. + */ + alg->parameter = type; + ret = 1; + } + } + err: + OPENSSL_free(der); + return ret; +} + +int EVP_PKEY_CTX_get_algor(EVP_PKEY_CTX *ctx, X509_ALGOR **alg) +{ + int ret = -1; /* Assume the worst */ + OSSL_PARAM params[2]; + size_t aid_len = 0; + const char *k_aid = OSSL_SIGNATURE_PARAM_ALGORITHM_ID; + + params[0] = OSSL_PARAM_construct_octet_string(k_aid, NULL, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (EVP_PKEY_CTX_get_params(ctx, params) <= 0) + goto err; + + if (OSSL_PARAM_modified(¶ms[0])) + aid_len = params[0].return_size; + if (aid_len == 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_GETTING_ALGORITHMIDENTIFIER_NOT_SUPPORTED); + ret = -2; + goto err; + } + if (alg != NULL) { + unsigned char *aid = NULL; + const unsigned char *pp = NULL; + + if ((aid = OPENSSL_malloc(aid_len)) != NULL) { + params[0] = OSSL_PARAM_construct_octet_string(k_aid, aid, aid_len); + pp = aid; + if (EVP_PKEY_CTX_get_params(ctx, params) + && OSSL_PARAM_modified(¶ms[0]) + && d2i_X509_ALGOR(alg, &pp, aid_len) != NULL) + ret = 1; + } + OPENSSL_free(aid); + } + err: + return ret; +} + #endif /* !defined(FIPS_MODULE) */ diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 3ccfaeb37cd9..9a216c30c849 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -52,6 +52,7 @@ struct evp_cipher_ctx_st { int final_used; int block_mask; unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ + size_t numpipes; /* * Opaque ctx returned from a providers cipher algorithm implementation @@ -95,11 +96,12 @@ struct evp_keymgmt_st { int id; /* libcrypto internal */ int name_id; + /* NID for the legacy alg if there is one */ + int legacy_alg; char *type_name; const char *description; OSSL_PROVIDER *prov; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; /* Constructor(s), destructor, information */ OSSL_FUNC_keymgmt_new_fn *new; @@ -112,6 +114,8 @@ struct evp_keymgmt_st { /* Generation, a complex constructor */ OSSL_FUNC_keymgmt_gen_init_fn *gen_init; OSSL_FUNC_keymgmt_gen_set_template_fn *gen_set_template; + OSSL_FUNC_keymgmt_gen_get_params_fn *gen_get_params; + OSSL_FUNC_keymgmt_gen_gettable_params_fn *gen_gettable_params; OSSL_FUNC_keymgmt_gen_set_params_fn *gen_set_params; OSSL_FUNC_keymgmt_gen_settable_params_fn *gen_settable_params; OSSL_FUNC_keymgmt_gen_fn *gen; @@ -128,8 +132,10 @@ struct evp_keymgmt_st { /* Import and export routines */ OSSL_FUNC_keymgmt_import_fn *import; OSSL_FUNC_keymgmt_import_types_fn *import_types; + OSSL_FUNC_keymgmt_import_types_ex_fn *import_types_ex; OSSL_FUNC_keymgmt_export_fn *export; OSSL_FUNC_keymgmt_export_types_fn *export_types; + OSSL_FUNC_keymgmt_export_types_ex_fn *export_types_ex; OSSL_FUNC_keymgmt_dup_fn *dup; } /* EVP_KEYMGMT */ ; @@ -139,7 +145,6 @@ struct evp_keyexch_st { const char *description; OSSL_PROVIDER *prov; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; OSSL_FUNC_keyexch_newctx_fn *newctx; OSSL_FUNC_keyexch_init_fn *init; @@ -159,13 +164,18 @@ struct evp_signature_st { const char *description; OSSL_PROVIDER *prov; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; OSSL_FUNC_signature_newctx_fn *newctx; OSSL_FUNC_signature_sign_init_fn *sign_init; OSSL_FUNC_signature_sign_fn *sign; + OSSL_FUNC_signature_sign_message_init_fn *sign_message_init; + OSSL_FUNC_signature_sign_message_update_fn *sign_message_update; + OSSL_FUNC_signature_sign_message_final_fn *sign_message_final; OSSL_FUNC_signature_verify_init_fn *verify_init; OSSL_FUNC_signature_verify_fn *verify; + OSSL_FUNC_signature_verify_message_init_fn *verify_message_init; + OSSL_FUNC_signature_verify_message_update_fn *verify_message_update; + OSSL_FUNC_signature_verify_message_final_fn *verify_message_final; OSSL_FUNC_signature_verify_recover_init_fn *verify_recover_init; OSSL_FUNC_signature_verify_recover_fn *verify_recover; OSSL_FUNC_signature_digest_sign_init_fn *digest_sign_init; @@ -186,15 +196,40 @@ struct evp_signature_st { OSSL_FUNC_signature_gettable_ctx_md_params_fn *gettable_ctx_md_params; OSSL_FUNC_signature_set_ctx_md_params_fn *set_ctx_md_params; OSSL_FUNC_signature_settable_ctx_md_params_fn *settable_ctx_md_params; + + /* Signature object checking */ + OSSL_FUNC_signature_query_key_types_fn *query_key_types; } /* EVP_SIGNATURE */; +struct evp_skeymgmt_st { + int name_id; + char *type_name; + const char *description; + OSSL_PROVIDER *prov; + CRYPTO_REF_COUNT refcnt; + + /* Import and export routines */ + OSSL_FUNC_skeymgmt_imp_settable_params_fn *imp_params; + OSSL_FUNC_skeymgmt_import_fn *import; + OSSL_FUNC_skeymgmt_export_fn *export; + + /* Key generation */ + OSSL_FUNC_skeymgmt_gen_settable_params_fn *gen_params; + OSSL_FUNC_skeymgmt_generate_fn *generate; + + /* Key identifier */ + OSSL_FUNC_skeymgmt_get_key_id_fn *get_key_id; + + /* destructor */ + OSSL_FUNC_skeymgmt_free_fn *free; +} /* EVP_SKEYMGMT */; + struct evp_asym_cipher_st { int name_id; char *type_name; const char *description; OSSL_PROVIDER *prov; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; OSSL_FUNC_asym_cipher_newctx_fn *newctx; OSSL_FUNC_asym_cipher_encrypt_init_fn *encrypt_init; @@ -215,7 +250,6 @@ struct evp_kem_st { const char *description; OSSL_PROVIDER *prov; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; OSSL_FUNC_kem_newctx_fn *newctx; OSSL_FUNC_kem_encapsulate_init_fn *encapsulate_init; @@ -228,6 +262,8 @@ struct evp_kem_st { OSSL_FUNC_kem_gettable_ctx_params_fn *gettable_ctx_params; OSSL_FUNC_kem_set_ctx_params_fn *set_ctx_params; OSSL_FUNC_kem_settable_ctx_params_fn *settable_ctx_params; + OSSL_FUNC_kem_auth_encapsulate_init_fn *auth_encapsulate_init; + OSSL_FUNC_kem_auth_decapsulate_init_fn *auth_decapsulate_init; } /* EVP_KEM */; int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, @@ -270,13 +306,6 @@ void *evp_generic_fetch(OSSL_LIB_CTX *ctx, int operation_id, OSSL_PROVIDER *prov), int (*up_ref_method)(void *), void (*free_method)(void *)); -void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id, - int name_id, const char *properties, - void *(*new_method)(int name_id, - const OSSL_ALGORITHM *algodef, - OSSL_PROVIDER *prov), - int (*up_ref_method)(void *), - void (*free_method)(void *)); void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, const char *name, const char *properties, void *(*new_method)(int name_id, @@ -311,6 +340,15 @@ EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov, EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *name, const char *properties); +EVP_CIPHER *evp_cipher_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties); +EVP_MD *evp_digest_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties); +EVP_MAC *evp_mac_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties); /* Internal structure constructors for fetched methods */ EVP_MD *evp_md_new(void); diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c index 56ee69865c9e..5478dfcd3b6d 100644 --- a/crypto/evp/evp_pbe.c +++ b/crypto/evp/evp_pbe.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -40,7 +40,8 @@ static const EVP_PBE_CTL builtin_pbe[] = { {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_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen, + PKCS5_v2_PBKDF2_keyivgen_ex}, {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4, NID_rc4, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex}, @@ -77,8 +78,15 @@ static const EVP_PBE_CTL builtin_pbe[] = { 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_hmac_sha3_224, -1, NID_sha3_224, 0}, + {EVP_PBE_TYPE_PRF, NID_hmac_sha3_256, -1, NID_sha3_256, 0}, + {EVP_PBE_TYPE_PRF, NID_hmac_sha3_384, -1, NID_sha3_384, 0}, + {EVP_PBE_TYPE_PRF, NID_hmac_sha3_512, -1, NID_sha3_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}, +#ifndef OPENSSL_NO_SM3 + {EVP_PBE_TYPE_PRF, NID_hmacWithSM3, -1, NID_sm3, 0}, +#endif {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} @@ -192,12 +200,14 @@ static int pbe_cmp(const EVP_PBE_CTL *const *a, const EVP_PBE_CTL *const *b) 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; + EVP_PBE_CTL *pbe_tmp = NULL; if (pbe_algs == NULL) { pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp); - if (pbe_algs == NULL) + if (pbe_algs == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); goto err; + } } if ((pbe_tmp = OPENSSL_zalloc(sizeof(*pbe_tmp))) == NULL) @@ -210,13 +220,13 @@ int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, pbe_tmp->keygen = keygen; if (!sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp)) { - OPENSSL_free(pbe_tmp); + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); goto err; } return 1; err: - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + OPENSSL_free(pbe_tmp); return 0; } @@ -250,6 +260,8 @@ int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid, pbelu.pbe_nid = pbe_nid; if (pbe_algs != NULL) { + /* Ideally, this would be done under lock */ + sk_EVP_PBE_CTL_sort(pbe_algs); i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu); pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i); } diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c index 8f3f1503756c..a4505a9d036c 100644 --- a/crypto/evp/evp_pkey.c +++ b/crypto/evp/evp_pkey.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -15,6 +15,7 @@ #include #include #include "internal/provider.h" +#include "internal/sizes.h" #include "crypto/asn1.h" #include "crypto/evp.h" #include "crypto/x509.h" @@ -32,7 +33,7 @@ EVP_PKEY *evp_pkcs82pkey_legacy(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *lib return NULL; if ((pkey = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return NULL; } @@ -73,6 +74,13 @@ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, int selection; size_t len; OSSL_DECODER_CTX *dctx = NULL; + const ASN1_OBJECT *algoid = NULL; + char keytype[OSSL_MAX_NAME_SIZE]; + + if (p8 == NULL + || !PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8) + || !OBJ_obj2txt(keytype, sizeof(keytype), algoid, 0)) + return NULL; if ((encoded_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &encoded_data)) <= 0 || encoded_data == NULL) @@ -82,7 +90,20 @@ EVP_PKEY *EVP_PKCS82PKEY_ex(const PKCS8_PRIV_KEY_INFO *p8, OSSL_LIB_CTX *libctx, len = encoded_len; selection = EVP_PKEY_KEYPAIR | EVP_PKEY_KEY_PARAMETERS; dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", - NULL, selection, libctx, propq); + keytype, selection, libctx, propq); + + if (dctx != NULL && OSSL_DECODER_CTX_get_num_decoders(dctx) == 0) { + OSSL_DECODER_CTX_free(dctx); + + /* + * This could happen if OBJ_obj2txt() returned a text OID and the + * decoder has not got that OID as an alias. We fall back to a NULL + * keytype + */ + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "PrivateKeyInfo", + NULL, selection, libctx, propq); + } + if (dctx == NULL || !OSSL_DECODER_from_data(dctx, &p8_data, &len)) /* try legacy */ @@ -130,7 +151,7 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(const EVP_PKEY *pkey) } else { p8 = PKCS8_PRIV_KEY_INFO_new(); if (p8 == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_ASN1_LIB); return NULL; } diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c index c36dbdc56c77..50334042a9cc 100644 --- a/crypto/evp/evp_rand.c +++ b/crypto/evp/evp_rand.c @@ -1,5 +1,5 @@ /* - * 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 @@ -27,7 +27,6 @@ struct evp_rand_st { char *type_name; const char *description; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *refcnt_lock; const OSSL_DISPATCH *dispatch; OSSL_FUNC_rand_newctx_fn *newctx; @@ -47,6 +46,8 @@ struct evp_rand_st { OSSL_FUNC_rand_get_ctx_params_fn *get_ctx_params; OSSL_FUNC_rand_set_ctx_params_fn *set_ctx_params; OSSL_FUNC_rand_verify_zeroization_fn *verify_zeroization; + OSSL_FUNC_rand_get_seed_fn *get_seed; + OSSL_FUNC_rand_clear_seed_fn *clear_seed; } /* EVP_RAND */ ; static int evp_rand_up_ref(void *vrand) @@ -55,7 +56,7 @@ static int evp_rand_up_ref(void *vrand) int ref = 0; if (rand != NULL) - return CRYPTO_UP_REF(&rand->refcnt, &ref, rand->refcnt_lock); + return CRYPTO_UP_REF(&rand->refcnt, &ref); return 1; } @@ -66,12 +67,12 @@ static void evp_rand_free(void *vrand) if (rand == NULL) return; - CRYPTO_DOWN_REF(&rand->refcnt, &ref, rand->refcnt_lock); + CRYPTO_DOWN_REF(&rand->refcnt, &ref); if (ref > 0) return; OPENSSL_free(rand->type_name); ossl_provider_free(rand->prov); - CRYPTO_THREAD_lock_free(rand->refcnt_lock); + CRYPTO_FREE_REF(&rand->refcnt); OPENSSL_free(rand); } @@ -79,12 +80,13 @@ static void *evp_rand_new(void) { EVP_RAND *rand = OPENSSL_zalloc(sizeof(*rand)); - if (rand == NULL - || (rand->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) { + if (rand == NULL) + return NULL; + + if (!CRYPTO_NEW_REF(&rand->refcnt, 1)) { OPENSSL_free(rand); return NULL; } - rand->refcnt = 1; return rand; } @@ -124,7 +126,7 @@ static void *evp_rand_from_algorithm(int name_id, #endif if ((rand = evp_rand_new()) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return NULL; } rand->name_id = name_id; @@ -236,6 +238,16 @@ static void *evp_rand_from_algorithm(int name_id, fnzeroizecnt++; #endif break; + case OSSL_FUNC_RAND_GET_SEED: + if (rand->get_seed != NULL) + break; + rand->get_seed = OSSL_FUNC_rand_get_seed(fns); + break; + case OSSL_FUNC_RAND_CLEAR_SEED: + if (rand->clear_seed != NULL) + break; + rand->clear_seed = OSSL_FUNC_rand_clear_seed(fns); + break; } } /* @@ -320,11 +332,11 @@ int EVP_RAND_get_params(EVP_RAND *rand, OSSL_PARAM params[]) return 1; } -static int evp_rand_ctx_up_ref(EVP_RAND_CTX *ctx) +int EVP_RAND_CTX_up_ref(EVP_RAND_CTX *ctx) { int ref = 0; - return CRYPTO_UP_REF(&ctx->refcnt, &ref, ctx->refcnt_lock); + return CRYPTO_UP_REF(&ctx->refcnt, &ref); } EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) @@ -339,15 +351,16 @@ EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) } ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL || (ctx->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL) { + if (ctx == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&ctx->refcnt, 1)) { OPENSSL_free(ctx); - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return NULL; } if (parent != NULL) { - if (!evp_rand_ctx_up_ref(parent)) { + if (!EVP_RAND_CTX_up_ref(parent)) { ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); - CRYPTO_THREAD_lock_free(ctx->refcnt_lock); + CRYPTO_FREE_REF(&ctx->refcnt); OPENSSL_free(ctx); return NULL; } @@ -357,16 +370,15 @@ EVP_RAND_CTX *EVP_RAND_CTX_new(EVP_RAND *rand, EVP_RAND_CTX *parent) if ((ctx->algctx = rand->newctx(ossl_provider_ctx(rand->prov), parent_ctx, parent_dispatch)) == NULL || !EVP_RAND_up_ref(rand)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); rand->freectx(ctx->algctx); - CRYPTO_THREAD_lock_free(ctx->refcnt_lock); + CRYPTO_FREE_REF(&ctx->refcnt); OPENSSL_free(ctx); EVP_RAND_CTX_free(parent); return NULL; } ctx->meth = rand; ctx->parent = parent; - ctx->refcnt = 1; return ctx; } @@ -378,14 +390,14 @@ void EVP_RAND_CTX_free(EVP_RAND_CTX *ctx) if (ctx == NULL) return; - CRYPTO_DOWN_REF(&ctx->refcnt, &ref, ctx->refcnt_lock); + CRYPTO_DOWN_REF(&ctx->refcnt, &ref); if (ref > 0) return; parent = ctx->parent; ctx->meth->freectx(ctx->algctx); ctx->algctx = NULL; EVP_RAND_free(ctx->meth); - CRYPTO_THREAD_lock_free(ctx->refcnt_lock); + CRYPTO_FREE_REF(&ctx->refcnt); OPENSSL_free(ctx); EVP_RAND_CTX_free(parent); } @@ -680,3 +692,59 @@ int EVP_RAND_verify_zeroization(EVP_RAND_CTX *ctx) evp_rand_unlock(ctx); return res; } + +int evp_rand_can_seed(EVP_RAND_CTX *ctx) +{ + return ctx->meth->get_seed != NULL; +} + +static size_t evp_rand_get_seed_locked(EVP_RAND_CTX *ctx, + unsigned char **buffer, + int entropy, + size_t min_len, size_t max_len, + int prediction_resistance, + const unsigned char *adin, + size_t adin_len) +{ + if (ctx->meth->get_seed != NULL) + return ctx->meth->get_seed(ctx->algctx, buffer, + entropy, min_len, max_len, + prediction_resistance, + adin, adin_len); + return 0; +} + +size_t evp_rand_get_seed(EVP_RAND_CTX *ctx, + unsigned char **buffer, + int entropy, size_t min_len, size_t max_len, + int prediction_resistance, + const unsigned char *adin, size_t adin_len) +{ + int res; + + if (!evp_rand_lock(ctx)) + return 0; + res = evp_rand_get_seed_locked(ctx, + buffer, + entropy, min_len, max_len, + prediction_resistance, + adin, adin_len); + evp_rand_unlock(ctx); + return res; +} + +static void evp_rand_clear_seed_locked(EVP_RAND_CTX *ctx, + unsigned char *buffer, size_t b_len) +{ + if (ctx->meth->clear_seed != NULL) + ctx->meth->clear_seed(ctx->algctx, buffer, b_len); +} + +void evp_rand_clear_seed(EVP_RAND_CTX *ctx, + unsigned char *buffer, size_t b_len) +{ + if (!evp_rand_lock(ctx)) + return; + evp_rand_clear_seed_locked(ctx, buffer, b_len); + evp_rand_unlock(ctx); +} diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index d7a4ad142aa7..dae3a2c5a85c 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,24 +18,30 @@ #include "crypto/evp.h" #include "evp_local.h" +static void evp_keyexch_free(void *data) +{ + EVP_KEYEXCH_free(data); +} + +static int evp_keyexch_up_ref(void *data) +{ + return EVP_KEYEXCH_up_ref(data); +} + static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov) { EVP_KEYEXCH *exchange = OPENSSL_zalloc(sizeof(EVP_KEYEXCH)); - if (exchange == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (exchange == NULL) return NULL; - } - exchange->lock = CRYPTO_THREAD_lock_new(); - if (exchange->lock == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&exchange->refcnt, 1) + || !ossl_provider_up_ref(prov)) { + CRYPTO_FREE_REF(&exchange->refcnt); OPENSSL_free(exchange); return NULL; } exchange->prov = prov; - ossl_provider_up_ref(prov); - exchange->refcnt = 1; return exchange; } @@ -49,7 +55,7 @@ static void *evp_keyexch_from_algorithm(int name_id, int fncnt = 0, sparamfncnt = 0, gparamfncnt = 0; if ((exchange = evp_keyexch_new(prov)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } @@ -150,12 +156,12 @@ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange) if (exchange == NULL) return; - CRYPTO_DOWN_REF(&exchange->refcnt, &i, exchange->lock); + CRYPTO_DOWN_REF(&exchange->refcnt, &i); if (i > 0) return; OPENSSL_free(exchange->type_name); ossl_provider_free(exchange->prov); - CRYPTO_THREAD_lock_free(exchange->lock); + CRYPTO_FREE_REF(&exchange->refcnt); OPENSSL_free(exchange); } @@ -163,7 +169,7 @@ int EVP_KEYEXCH_up_ref(EVP_KEYEXCH *exchange) { int ref = 0; - CRYPTO_UP_REF(&exchange->refcnt, &ref, exchange->lock); + CRYPTO_UP_REF(&exchange->refcnt, &ref); return 1; } @@ -177,8 +183,8 @@ EVP_KEYEXCH *EVP_KEYEXCH_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, { return evp_generic_fetch(ctx, OSSL_OP_KEYEXCH, algorithm, properties, evp_keyexch_from_algorithm, - (int (*)(void *))EVP_KEYEXCH_up_ref, - (void (*)(void *))EVP_KEYEXCH_free); + evp_keyexch_up_ref, + evp_keyexch_free); } EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov, @@ -188,8 +194,8 @@ EVP_KEYEXCH *evp_keyexch_fetch_from_prov(OSSL_PROVIDER *prov, return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYEXCH, algorithm, properties, evp_keyexch_from_algorithm, - (int (*)(void *))EVP_KEYEXCH_up_ref, - (void (*)(void *))EVP_KEYEXCH_free); + evp_keyexch_up_ref, + evp_keyexch_free); } int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) @@ -332,7 +338,11 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) /* No more legacy from here down to legacy: */ + /* A Coverity false positive with up_ref/down_ref and free */ + /* coverity[use_after_free] */ ctx->op.kex.exchange = exchange; + /* A Coverity false positive with up_ref/down_ref and free */ + /* coverity[deref_arg] */ ctx->op.kex.algctx = exchange->newctx(ossl_provider_ctx(exchange->prov)); if (ctx->op.kex.algctx == NULL) { /* The provider key can stay in the cache */ @@ -420,6 +430,8 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer, EVP_KEYMGMT_get0_name(ctx->keymgmt), ctx->propquery); if (tmp_keymgmt != NULL) + /* A Coverity issue with up_ref/down_ref and free */ + /* coverity[pass_freed_arg] */ provkey = evp_pkey_export_to_provider(peer, ctx->libctx, &tmp_keymgmt, ctx->propquery); EVP_KEYMGMT_free(tmp_keymgmt_tofree); @@ -430,7 +442,10 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer, */ if (provkey == NULL) goto legacy; - return ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey); + ret = ctx->op.kex.exchange->set_peer(ctx->op.kex.algctx, provkey); + if (ret <= 0) + return ret; + goto common; legacy: #ifdef FIPS_MODULE @@ -482,19 +497,19 @@ int EVP_PKEY_derive_set_peer_ex(EVP_PKEY_CTX *ctx, EVP_PKEY *peer, return -1; } + ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); + if (ret <= 0) + return ret; +#endif + + common: + if (!EVP_PKEY_up_ref(peer)) + return -1; + EVP_PKEY_free(ctx->peerkey); ctx->peerkey = peer; - ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); - - if (ret <= 0) { - ctx->peerkey = NULL; - return ret; - } - - EVP_PKEY_up_ref(peer); return 1; -#endif } int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) @@ -561,8 +576,8 @@ void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx, evp_generic_do_all(libctx, OSSL_OP_KEYEXCH, (void (*)(void *, void *))fn, arg, evp_keyexch_from_algorithm, - (int (*)(void *))EVP_KEYEXCH_up_ref, - (void (*)(void *))EVP_KEYEXCH_free); + evp_keyexch_up_ref, + evp_keyexch_free); } int EVP_KEYEXCH_names_do_all(const EVP_KEYEXCH *keyexch, diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c index 6a6bb31e6372..1093aac29e91 100644 --- a/crypto/evp/kdf_lib.c +++ b/crypto/evp/kdf_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2021 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 @@ -31,7 +31,7 @@ EVP_KDF_CTX *EVP_KDF_CTX_new(EVP_KDF *kdf) if (ctx == NULL || (ctx->algctx = kdf->newctx(ossl_provider_ctx(kdf->prov))) == NULL || !EVP_KDF_up_ref(kdf)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); if (ctx != NULL) kdf->freectx(ctx->algctx); OPENSSL_free(ctx); @@ -60,14 +60,12 @@ EVP_KDF_CTX *EVP_KDF_CTX_dup(const EVP_KDF_CTX *src) return NULL; dst = OPENSSL_malloc(sizeof(*dst)); - if (dst == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (dst == NULL) return NULL; - } memcpy(dst, src, sizeof(*dst)); if (!EVP_KDF_up_ref(dst->meth)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); OPENSSL_free(dst); return NULL; } diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c index 94af5d40a091..ad02b3381fa4 100644 --- a/crypto/evp/kdf_meth.c +++ b/crypto/evp/kdf_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -22,7 +22,7 @@ static int evp_kdf_up_ref(void *vkdf) EVP_KDF *kdf = (EVP_KDF *)vkdf; int ref = 0; - CRYPTO_UP_REF(&kdf->refcnt, &ref, kdf->lock); + CRYPTO_UP_REF(&kdf->refcnt, &ref); return 1; } @@ -34,12 +34,12 @@ static void evp_kdf_free(void *vkdf) if (kdf == NULL) return; - CRYPTO_DOWN_REF(&kdf->refcnt, &ref, kdf->lock); + CRYPTO_DOWN_REF(&kdf->refcnt, &ref); if (ref > 0) return; OPENSSL_free(kdf->type_name); ossl_provider_free(kdf->prov); - CRYPTO_THREAD_lock_free(kdf->lock); + CRYPTO_FREE_REF(&kdf->refcnt); OPENSSL_free(kdf); } @@ -48,11 +48,10 @@ static void *evp_kdf_new(void) EVP_KDF *kdf = NULL; if ((kdf = OPENSSL_zalloc(sizeof(*kdf))) == NULL - || (kdf->lock = CRYPTO_THREAD_lock_new()) == NULL) { + || !CRYPTO_NEW_REF(&kdf->refcnt, 1)) { OPENSSL_free(kdf); return NULL; } - kdf->refcnt = 1; return kdf; } @@ -65,14 +64,13 @@ static void *evp_kdf_from_algorithm(int name_id, int fnkdfcnt = 0, fnctxcnt = 0; if ((kdf = evp_kdf_new()) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return NULL; } kdf->name_id = name_id; - if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - evp_kdf_free(kdf); - return NULL; - } + if ((kdf->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) + goto err; + kdf->description = algodef->algorithm_description; for (; fns->function_id != 0; fns++) { @@ -146,15 +144,19 @@ static void *evp_kdf_from_algorithm(int name_id, * a derive function, and a complete set of context management * functions. */ - evp_kdf_free(kdf); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); - return NULL; + goto err; } + if (prov != NULL && !ossl_provider_up_ref(prov)) + goto err; + kdf->prov = prov; - if (prov != NULL) - ossl_provider_up_ref(prov); return kdf; + +err: + evp_kdf_free(kdf); + return NULL; } EVP_KDF *EVP_KDF_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c index 1786ae6553bf..2bc03e1d4e03 100644 --- a/crypto/evp/kem.c +++ b/crypto/evp/kem.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,14 +17,24 @@ #include "crypto/evp.h" #include "evp_local.h" +static void evp_kem_free(void *data) +{ + EVP_KEM_free(data); +} + +static int evp_kem_up_ref(void *data) +{ + return EVP_KEM_up_ref(data); +} + static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, - const OSSL_PARAM params[]) + const OSSL_PARAM params[], EVP_PKEY *authkey) { int ret = 0; EVP_KEM *kem = NULL; EVP_KEYMGMT *tmp_keymgmt = NULL; const OSSL_PROVIDER *tmp_prov = NULL; - void *provkey = NULL; + void *provkey = NULL, *provauthkey = NULL; const char *supported_kem = NULL; int iter; @@ -40,7 +50,10 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); goto err; } - + if (authkey != NULL && authkey->type != ctx->pkey->type) { + ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); + return 0; + } /* * Try to derive the supported kem from |ctx->keymgmt|. */ @@ -114,16 +127,26 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, * same property query as when fetching the kem method. * With the keymgmt we found (if we did), we try to export |ctx->pkey| * to it (evp_pkey_export_to_provider() is smart enough to only actually - * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) */ tmp_keymgmt_tofree = tmp_keymgmt = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, EVP_KEYMGMT_get0_name(ctx->keymgmt), ctx->propquery); - if (tmp_keymgmt != NULL) + if (tmp_keymgmt != NULL) { provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, &tmp_keymgmt, ctx->propquery); + if (provkey != NULL && authkey != NULL) { + provauthkey = evp_pkey_export_to_provider(authkey, ctx->libctx, + &tmp_keymgmt, + ctx->propquery); + if (provauthkey == NULL) { + EVP_KEM_free(kem); + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + } + } if (tmp_keymgmt == NULL) EVP_KEYMGMT_free(tmp_keymgmt_tofree); } @@ -144,20 +167,28 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, switch (operation) { case EVP_PKEY_OP_ENCAPSULATE: - if (kem->encapsulate_init == NULL) { + if (provauthkey != NULL && kem->auth_encapsulate_init != NULL) { + ret = kem->auth_encapsulate_init(ctx->op.encap.algctx, provkey, + provauthkey, params); + } else if (provauthkey == NULL && kem->encapsulate_init != NULL) { + ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params); + } else { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); ret = -2; goto err; } - ret = kem->encapsulate_init(ctx->op.encap.algctx, provkey, params); break; case EVP_PKEY_OP_DECAPSULATE: - if (kem->decapsulate_init == NULL) { + if (provauthkey != NULL && kem->auth_decapsulate_init != NULL) { + ret = kem->auth_decapsulate_init(ctx->op.encap.algctx, provkey, + provauthkey, params); + } else if (provauthkey == NULL && kem->encapsulate_init != NULL) { + ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params); + } else { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); ret = -2; goto err; } - ret = kem->decapsulate_init(ctx->op.encap.algctx, provkey, params); break; default: ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); @@ -178,9 +209,17 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, return ret; } +int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv, + const OSSL_PARAM params[]) +{ + if (authpriv == NULL) + return 0; + return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, authpriv); +} + int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) { - return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params); + return evp_kem_init(ctx, EVP_PKEY_OP_ENCAPSULATE, params, NULL); } int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, @@ -209,7 +248,15 @@ int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) { - return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params); + return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, NULL); +} + +int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpub, + const OSSL_PARAM params[]) +{ + if (authpub == NULL) + return 0; + return evp_kem_init(ctx, EVP_PKEY_OP_DECAPSULATE, params, authpub); } int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, @@ -238,20 +285,16 @@ static EVP_KEM *evp_kem_new(OSSL_PROVIDER *prov) { EVP_KEM *kem = OPENSSL_zalloc(sizeof(EVP_KEM)); - if (kem == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (kem == NULL) return NULL; - } - kem->lock = CRYPTO_THREAD_lock_new(); - if (kem->lock == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&kem->refcnt, 1) + || !ossl_provider_up_ref(prov)) { + CRYPTO_FREE_REF(&kem->refcnt); OPENSSL_free(kem); return NULL; } kem->prov = prov; - ossl_provider_up_ref(prov); - kem->refcnt = 1; return kem; } @@ -265,7 +308,7 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, int gparamfncnt = 0, sparamfncnt = 0; if ((kem = evp_kem_new(prov)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } @@ -288,6 +331,12 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, kem->encapsulate_init = OSSL_FUNC_kem_encapsulate_init(fns); encfncnt++; break; + case OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT: + if (kem->auth_encapsulate_init != NULL) + break; + kem->auth_encapsulate_init = OSSL_FUNC_kem_auth_encapsulate_init(fns); + encfncnt++; + break; case OSSL_FUNC_KEM_ENCAPSULATE: if (kem->encapsulate != NULL) break; @@ -300,6 +349,12 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, kem->decapsulate_init = OSSL_FUNC_kem_decapsulate_init(fns); decfncnt++; break; + case OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT: + if (kem->auth_decapsulate_init != NULL) + break; + kem->auth_decapsulate_init = OSSL_FUNC_kem_auth_decapsulate_init(fns); + decfncnt++; + break; case OSSL_FUNC_KEM_DECAPSULATE: if (kem->decapsulate != NULL) break; @@ -348,19 +403,21 @@ static void *evp_kem_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, } } if (ctxfncnt != 2 - || (encfncnt != 0 && encfncnt != 2) - || (decfncnt != 0 && decfncnt != 2) - || (encfncnt != 2 && decfncnt != 2) + || (encfncnt != 0 && encfncnt != 2 && encfncnt != 3) + || (decfncnt != 0 && decfncnt != 2 && decfncnt != 3) + || (encfncnt != decfncnt) || (gparamfncnt != 0 && gparamfncnt != 2) || (sparamfncnt != 0 && sparamfncnt != 2)) { /* * In order to be a consistent set of functions we must have at least - * a set of context functions (newctx and freectx) as well as a pair of - * "kem" functions: (encapsulate_init, encapsulate) or - * (decapsulate_init, decapsulate). set_ctx_params and settable_ctx_params are - * optional, but if one of them is present then the other one must also - * be present. The same applies to get_ctx_params and - * gettable_ctx_params. The dupctx function is optional. + * a set of context functions (newctx and freectx) as well as a pair + * (or triplet) of "kem" functions: + * (encapsulate_init, (and/or auth_encapsulate_init), encapsulate) or + * (decapsulate_init, (and/or auth_decapsulate_init), decapsulate). + * set_ctx_params and settable_ctx_params are optional, but if one of + * them is present then the other one must also be present. The same + * applies to get_ctx_params and gettable_ctx_params. + * The dupctx function is optional. */ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); goto err; @@ -379,12 +436,12 @@ void EVP_KEM_free(EVP_KEM *kem) if (kem == NULL) return; - CRYPTO_DOWN_REF(&kem->refcnt, &i, kem->lock); + CRYPTO_DOWN_REF(&kem->refcnt, &i); if (i > 0) return; OPENSSL_free(kem->type_name); ossl_provider_free(kem->prov); - CRYPTO_THREAD_lock_free(kem->lock); + CRYPTO_FREE_REF(&kem->refcnt); OPENSSL_free(kem); } @@ -392,7 +449,7 @@ int EVP_KEM_up_ref(EVP_KEM *kem) { int ref = 0; - CRYPTO_UP_REF(&kem->refcnt, &ref, kem->lock); + CRYPTO_UP_REF(&kem->refcnt, &ref); return 1; } @@ -406,8 +463,8 @@ EVP_KEM *EVP_KEM_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, { return evp_generic_fetch(ctx, OSSL_OP_KEM, algorithm, properties, evp_kem_from_algorithm, - (int (*)(void *))EVP_KEM_up_ref, - (void (*)(void *))EVP_KEM_free); + evp_kem_up_ref, + evp_kem_free); } EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm, @@ -415,8 +472,8 @@ EVP_KEM *evp_kem_fetch_from_prov(OSSL_PROVIDER *prov, const char *algorithm, { return evp_generic_fetch_from_prov(prov, OSSL_OP_KEM, algorithm, properties, evp_kem_from_algorithm, - (int (*)(void *))EVP_KEM_up_ref, - (void (*)(void *))EVP_KEM_free); + evp_kem_up_ref, + evp_kem_free); } int EVP_KEM_is_a(const EVP_KEM *kem, const char *name) @@ -445,8 +502,8 @@ void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx, { evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg, evp_kem_from_algorithm, - (int (*)(void *))EVP_KEM_up_ref, - (void (*)(void *))EVP_KEM_free); + evp_kem_up_ref, + evp_kem_free); } int EVP_KEM_names_do_all(const EVP_KEM *kem, diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c index 9512cc9cf0f7..9ed0ba3caea9 100644 --- a/crypto/evp/keymgmt_lib.c +++ b/crypto/evp/keymgmt_lib.c @@ -34,7 +34,7 @@ int evp_keymgmt_util_try_import(const OSSL_PARAM params[], void *arg) /* Just in time creation of keydata */ if (data->keydata == NULL) { if ((data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return 0; } delete_on_error = 1; @@ -194,7 +194,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt, * operation cache. In that case, we know that |i| is zero. */ if (pk->dirty_cnt != pk->dirty_cnt_copy) - evp_keymgmt_util_clear_operation_cache(pk, 0); + evp_keymgmt_util_clear_operation_cache(pk); /* Add the new export to the operation cache */ if (!evp_keymgmt_util_cache_keydata(pk, keymgmt, import_data.keydata, @@ -219,15 +219,11 @@ static void op_cache_free(OP_CACHE_ELEM *e) OPENSSL_free(e); } -int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking) +int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk) { if (pk != NULL) { - if (locking && pk->lock != NULL && !CRYPTO_THREAD_write_lock(pk->lock)) - return 0; sk_OP_CACHE_ELEM_pop_free(pk->operation_cache, op_cache_free); pk->operation_cache = NULL; - if (locking && pk->lock != NULL) - CRYPTO_THREAD_unlock(pk->lock); } return 1; diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c index b1e8870e36ac..108bbf957973 100644 --- a/crypto/evp/keymgmt_meth.c +++ b/crypto/evp/keymgmt_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,22 +17,49 @@ #include "crypto/evp.h" #include "evp_local.h" +static void evp_keymgmt_free(void *data) +{ + EVP_KEYMGMT_free(data); +} + +static int evp_keymgmt_up_ref(void *data) +{ + return EVP_KEYMGMT_up_ref(data); +} + static void *keymgmt_new(void) { EVP_KEYMGMT *keymgmt = NULL; - if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL - || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) { + if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&keymgmt->refcnt, 1)) { EVP_KEYMGMT_free(keymgmt); - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return NULL; } - - keymgmt->refcnt = 1; - return keymgmt; } +#ifndef FIPS_MODULE +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 + static void *keymgmt_from_algorithm(int name_id, const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov) @@ -42,6 +69,8 @@ static void *keymgmt_from_algorithm(int name_id, int setparamfncnt = 0, getparamfncnt = 0; int setgenparamfncnt = 0; int importfncnt = 0, exportfncnt = 0; + int importtypesfncnt = 0, exporttypesfncnt = 0; + int getgenparamfncnt = 0; if ((keymgmt = keymgmt_new()) == NULL) return NULL; @@ -82,6 +111,20 @@ static void *keymgmt_from_algorithm(int name_id, OSSL_FUNC_keymgmt_gen_settable_params(fns); } break; + case OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS: + if (keymgmt->gen_get_params == NULL) { + getgenparamfncnt++; + keymgmt->gen_get_params = + OSSL_FUNC_keymgmt_gen_get_params(fns); + } + break; + case OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS: + if (keymgmt->gen_gettable_params == NULL) { + getgenparamfncnt++; + keymgmt->gen_gettable_params = + OSSL_FUNC_keymgmt_gen_gettable_params(fns); + } + break; case OSSL_FUNC_KEYMGMT_GEN: if (keymgmt->gen == NULL) keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns); @@ -153,10 +196,20 @@ static void *keymgmt_from_algorithm(int name_id, break; case OSSL_FUNC_KEYMGMT_IMPORT_TYPES: if (keymgmt->import_types == NULL) { - importfncnt++; + if (importtypesfncnt == 0) + importfncnt++; + importtypesfncnt++; keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns); } break; + case OSSL_FUNC_KEYMGMT_IMPORT_TYPES_EX: + if (keymgmt->import_types_ex == NULL) { + if (importtypesfncnt == 0) + importfncnt++; + importtypesfncnt++; + keymgmt->import_types_ex = OSSL_FUNC_keymgmt_import_types_ex(fns); + } + break; case OSSL_FUNC_KEYMGMT_EXPORT: if (keymgmt->export == NULL) { exportfncnt++; @@ -165,10 +218,20 @@ static void *keymgmt_from_algorithm(int name_id, break; case OSSL_FUNC_KEYMGMT_EXPORT_TYPES: if (keymgmt->export_types == NULL) { - exportfncnt++; + if (exporttypesfncnt == 0) + exportfncnt++; + exporttypesfncnt++; keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns); } break; + case OSSL_FUNC_KEYMGMT_EXPORT_TYPES_EX: + if (keymgmt->export_types_ex == NULL) { + if (exporttypesfncnt == 0) + exportfncnt++; + exporttypesfncnt++; + keymgmt->export_types_ex = OSSL_FUNC_keymgmt_export_types_ex(fns); + } + break; } } /* @@ -187,6 +250,7 @@ static void *keymgmt_from_algorithm(int name_id, || (getparamfncnt != 0 && getparamfncnt != 2) || (setparamfncnt != 0 && setparamfncnt != 2) || (setgenparamfncnt != 0 && setgenparamfncnt != 2) + || (getgenparamfncnt != 0 && getgenparamfncnt != 2) || (importfncnt != 0 && importfncnt != 2) || (exportfncnt != 0 && exportfncnt != 2) || (keymgmt->gen != NULL @@ -200,17 +264,11 @@ static void *keymgmt_from_algorithm(int name_id, if (prov != NULL) ossl_provider_up_ref(prov); - return keymgmt; -} +#ifndef FIPS_MODULE + keymgmt->legacy_alg = get_legacy_alg_type_from_keymgmt(keymgmt); +#endif -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); + return keymgmt; } EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov, @@ -220,8 +278,8 @@ EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov, 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_up_ref, + evp_keymgmt_free); } EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, @@ -229,15 +287,15 @@ EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, { return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties, keymgmt_from_algorithm, - (int (*)(void *))EVP_KEYMGMT_up_ref, - (void (*)(void *))EVP_KEYMGMT_free); + evp_keymgmt_up_ref, + evp_keymgmt_free); } int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt) { int ref = 0; - CRYPTO_UP_REF(&keymgmt->refcnt, &ref, keymgmt->lock); + CRYPTO_UP_REF(&keymgmt->refcnt, &ref); return 1; } @@ -248,12 +306,12 @@ void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt) if (keymgmt == NULL) return; - CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref, keymgmt->lock); + CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref); if (ref > 0) return; OPENSSL_free(keymgmt->type_name); ossl_provider_free(keymgmt->prov); - CRYPTO_THREAD_lock_free(keymgmt->lock); + CRYPTO_FREE_REF(&keymgmt->refcnt); OPENSSL_free(keymgmt); } @@ -267,6 +325,11 @@ int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt) return keymgmt->name_id; } +int evp_keymgmt_get_legacy_alg(const EVP_KEYMGMT *keymgmt) +{ + return keymgmt->legacy_alg; +} + const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt) { return keymgmt->description; @@ -290,8 +353,8 @@ void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx, 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); + evp_keymgmt_up_ref, + evp_keymgmt_free); } int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt, @@ -338,7 +401,7 @@ void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection, } int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx, - void *template) + void *templ) { /* * It's arguable if we actually should return success in this case, as @@ -348,7 +411,7 @@ int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx, */ if (keymgmt->gen_set_template == NULL) return 1; - return keymgmt->gen_set_template(genctx, template); + return keymgmt->gen_set_template(genctx, templ); } int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx, @@ -368,6 +431,23 @@ const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt) return keymgmt->gen_settable_params(NULL, provctx); } +int evp_keymgmt_gen_get_params(const EVP_KEYMGMT *keymgmt, void *genctx, + OSSL_PARAM params[]) +{ + if (keymgmt->gen_get_params == NULL) + return 0; + return keymgmt->gen_get_params(genctx, params); +} + +const OSSL_PARAM *EVP_KEYMGMT_gen_gettable_params(const EVP_KEYMGMT *keymgmt) +{ + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt)); + + if (keymgmt->gen_gettable_params == NULL) + return NULL; + return keymgmt->gen_gettable_params(NULL, provctx); +} + void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx, OSSL_CALLBACK *cb, void *cbarg) { @@ -465,6 +545,10 @@ int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata, const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt, int selection) { + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt)); + + if (keymgmt->import_types_ex != NULL) + return keymgmt->import_types_ex(provctx, selection); if (keymgmt->import_types == NULL) return NULL; return keymgmt->import_types(selection); @@ -481,6 +565,10 @@ int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata, const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt, int selection) { + void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt)); + + if (keymgmt->export_types_ex != NULL) + return keymgmt->export_types_ex(provctx, selection); if (keymgmt->export_types == NULL) return NULL; return keymgmt->export_types(selection); diff --git a/crypto/evp/legacy_blake2.c b/crypto/evp/legacy_blake2.c index 6a18e5fe01b6..5a5f05044cee 100644 --- a/crypto/evp/legacy_blake2.c +++ b/crypto/evp/legacy_blake2.c @@ -1,5 +1,5 @@ /* - * 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 @@ -11,11 +11,31 @@ #include "prov/blake2.h" /* diverse BLAKE2 macros */ #include "legacy_meth.h" -#define ossl_blake2b_init ossl_blake2b512_init -#define ossl_blake2s_init ossl_blake2s256_init +/* + * Local hack to adapt the BLAKE2 init functions to what the + * legacy function signatures demand. + */ +static int blake2s_init(BLAKE2S_CTX *C) +{ + BLAKE2S_PARAM P; -IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2s_int, ossl_blake2s) -IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2b_int, ossl_blake2b) + ossl_blake2s_param_init(&P); + return ossl_blake2s_init(C, &P); +} +static int blake2b_init(BLAKE2B_CTX *C) +{ + BLAKE2B_PARAM P; + + ossl_blake2b_param_init(&P); + return ossl_blake2b_init(C, &P); +} +#define blake2s_update ossl_blake2s_update +#define blake2b_update ossl_blake2b_update +#define blake2s_final ossl_blake2s_final +#define blake2b_final ossl_blake2b_final + +IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2s_int, blake2s) +IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2b_int, blake2b) static const EVP_MD blake2b_md = { NID_blake2b512, diff --git a/crypto/evp/legacy_sha.c b/crypto/evp/legacy_sha.c index ca9a3264978a..38423ff540f5 100644 --- a/crypto/evp/legacy_sha.c +++ b/crypto/evp/legacy_sha.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -37,7 +37,8 @@ static int nm##_update(EVP_MD_CTX *ctx, const void *data, size_t count) \ } \ static int nm##_final(EVP_MD_CTX *ctx, unsigned char *md) \ { \ - return fn##_final(md, EVP_MD_CTX_get0_md_data(ctx)); \ + KECCAK1600_CTX *kctx = EVP_MD_CTX_get0_md_data(ctx); \ + return fn##_final(kctx, md, kctx->md_size); \ } #define IMPLEMENT_LEGACY_EVP_MD_METH_SHAKE(nm, fn, tag) \ static int nm##_init(EVP_MD_CTX *ctx) \ diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c index efd2c05c85cf..2d1839fedb2f 100644 --- a/crypto/evp/m_sigver.c +++ b/crypto/evp/m_sigver.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,8 +16,6 @@ #include "internal/numbers.h" /* includes SIZE_MAX */ #include "evp_local.h" -#ifndef FIPS_MODULE - static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) { ERR_raise(ERR_LIB_EVP, EVP_R_ONLY_ONESHOT_SUPPORTED); @@ -51,15 +49,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, void *provkey = NULL; int ret, iter, reinit = 1; - if (ctx->algctx != NULL) { - if (!ossl_assert(ctx->digest != NULL)) { - ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); - return 0; - } - if (ctx->digest->freectx != NULL) - ctx->digest->freectx(ctx->algctx); - ctx->algctx = NULL; - } + if (!evp_md_ctx_free_algctx(ctx)) + return 0; if (ctx->pctx == NULL) { reinit = 0; @@ -71,6 +62,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, if (ctx->pctx == NULL) return 0; + EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_FINALISED); + locpctx = ctx->pctx; ERR_set_mark(); @@ -239,7 +232,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, * This might be requested by a later call to EVP_MD_CTX_get0_md(). * In that case the "explicit fetch" rules apply for that * function (as per man pages), i.e. the ref count is not updated - * so the EVP_MD should not be used beyound the lifetime of the + * so the EVP_MD should not be used beyond the lifetime of the * EVP_MD_CTX. */ ctx->fetched_digest = EVP_MD_fetch(locpctx->libctx, mdname, props); @@ -360,12 +353,9 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, ctx->pctx->flag_call_digest_custom = 1; ret = 1; - end: -#ifndef FIPS_MODULE if (ret > 0) ret = evp_pkey_ctx_use_cached_data(locpctx); -#endif EVP_KEYMGMT_free(tmp_keymgmt); return ret > 0 ? 1 : 0; @@ -402,12 +392,16 @@ int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 1, NULL); } -#endif /* FIPS_MDOE */ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) { EVP_PKEY_CTX *pctx = ctx->pctx; + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); + return 0; + } + if (pctx == NULL || pctx->operation != EVP_PKEY_OP_SIGNCTX || pctx->op.sig.algctx == NULL @@ -438,6 +432,11 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) { EVP_PKEY_CTX *pctx = ctx->pctx; + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR); + return 0; + } + if (pctx == NULL || pctx->operation != EVP_PKEY_OP_VERIFYCTX || pctx->op.sig.algctx == NULL @@ -464,12 +463,17 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) return EVP_DigestUpdate(ctx, data, dsize); } -#ifndef FIPS_MODULE int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen) { - int sctx = 0, r = 0; - EVP_PKEY_CTX *dctx, *pctx = ctx->pctx; + int sctx = 0; + int r = 0; + EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx; + + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } if (pctx == NULL || pctx->operation != EVP_PKEY_OP_SIGNCTX @@ -477,18 +481,19 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, || pctx->op.sig.signature == NULL) goto legacy; - if (sigret == NULL || (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) - return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx, - sigret, siglen, - sigret == NULL ? 0 : *siglen); - dctx = EVP_PKEY_CTX_dup(pctx); - if (dctx == NULL) - return 0; - - r = dctx->op.sig.signature->digest_sign_final(dctx->op.sig.algctx, + if (sigret != NULL && (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) { + /* try dup */ + dctx = EVP_PKEY_CTX_dup(pctx); + if (dctx != NULL) + pctx = dctx; + } + r = pctx->op.sig.signature->digest_sign_final(pctx->op.sig.algctx, sigret, siglen, - *siglen); - EVP_PKEY_CTX_free(dctx); + sigret == NULL ? 0 : *siglen); + if (dctx == NULL && sigret != NULL) + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + else + EVP_PKEY_CTX_free(dctx); return r; legacy: @@ -506,9 +511,10 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) { if (sigret == NULL) return pctx->pmeth->signctx(pctx, sigret, siglen, ctx); - if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) { r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); - else { + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + } else { dctx = EVP_PKEY_CTX_dup(pctx); if (dctx == NULL) return 0; @@ -557,7 +563,7 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, } else { int s = EVP_MD_get_size(ctx->digest); - if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0) + if (s <= 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0) return 0; } } @@ -569,19 +575,31 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, { EVP_PKEY_CTX *pctx = ctx->pctx; - if (pctx != NULL - && pctx->operation == EVP_PKEY_OP_SIGNCTX + if (pctx == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + return 0; + } + + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } + + if (pctx->operation == EVP_PKEY_OP_SIGNCTX && pctx->op.sig.algctx != NULL && pctx->op.sig.signature != NULL) { - if (pctx->op.sig.signature->digest_sign != NULL) + if (pctx->op.sig.signature->digest_sign != NULL) { + if (sigret != NULL) + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; return pctx->op.sig.signature->digest_sign(pctx->op.sig.algctx, sigret, siglen, sigret == NULL ? 0 : *siglen, tbs, tbslen); + } } else { /* legacy */ - if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) - return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); + if (pctx->pmeth != NULL && pctx->pmeth->digestsign != NULL) + return pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); } if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) @@ -592,11 +610,16 @@ int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen) { + int vctx = 0; + unsigned int mdlen = 0; unsigned char md[EVP_MAX_MD_SIZE]; int r = 0; - unsigned int mdlen = 0; - int vctx = 0; - EVP_PKEY_CTX *dctx, *pctx = ctx->pctx; + EVP_PKEY_CTX *dctx = NULL, *pctx = ctx->pctx; + + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } if (pctx == NULL || pctx->operation != EVP_PKEY_OP_VERIFYCTX @@ -604,16 +627,18 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, || pctx->op.sig.signature == NULL) goto legacy; - if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) != 0) - return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx, - sig, siglen); - dctx = EVP_PKEY_CTX_dup(pctx); - if (dctx == NULL) - return 0; - - r = dctx->op.sig.signature->digest_verify_final(dctx->op.sig.algctx, + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISE) == 0) { + /* try dup */ + dctx = EVP_PKEY_CTX_dup(pctx); + if (dctx != NULL) + pctx = dctx; + } + r = pctx->op.sig.signature->digest_verify_final(pctx->op.sig.algctx, sig, siglen); - EVP_PKEY_CTX_free(dctx); + if (dctx == NULL) + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + else + EVP_PKEY_CTX_free(dctx); return r; legacy: @@ -633,9 +658,10 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, else vctx = 0; if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { - if (vctx) + if (vctx) { r = pctx->pmeth->verifyctx(pctx, sig, siglen, ctx); - else + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; + } else r = EVP_DigestFinal_ex(ctx, md, &mdlen); } else { EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); @@ -667,21 +693,26 @@ int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, return -1; } + if ((ctx->flags & EVP_MD_CTX_FLAG_FINALISED) != 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); + return 0; + } + if (pctx->operation == EVP_PKEY_OP_VERIFYCTX && pctx->op.sig.algctx != NULL && pctx->op.sig.signature != NULL) { - if (pctx->op.sig.signature->digest_verify != NULL) + if (pctx->op.sig.signature->digest_verify != NULL) { + ctx->flags |= EVP_MD_CTX_FLAG_FINALISED; return pctx->op.sig.signature->digest_verify(pctx->op.sig.algctx, sigret, siglen, tbs, tbslen); + } } else { /* legacy */ if (pctx->pmeth != NULL && pctx->pmeth->digestverify != NULL) return pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); } - if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) return -1; return EVP_DigestVerifyFinal(ctx, sigret, siglen); } -#endif /* FIPS_MODULE */ diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c index 90c79715d757..58ddf76151d3 100644 --- a/crypto/evp/mac_lib.c +++ b/crypto/evp/mac_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,16 +23,15 @@ EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac) { EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX)); - if (ctx == NULL - || (ctx->algctx = mac->newctx(ossl_provider_ctx(mac->prov))) == NULL - || !EVP_MAC_up_ref(mac)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - if (ctx != NULL) - mac->freectx(ctx->algctx); - OPENSSL_free(ctx); - ctx = NULL; - } else { + if (ctx != NULL) { ctx->meth = mac; + if ((ctx->algctx = mac->newctx(ossl_provider_ctx(mac->prov))) == NULL + || !EVP_MAC_up_ref(mac)) { + mac->freectx(ctx->algctx); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); + OPENSSL_free(ctx); + ctx = NULL; + } } return ctx; } @@ -56,14 +55,12 @@ EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src) return NULL; dst = OPENSSL_malloc(sizeof(*dst)); - if (dst == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (dst == NULL) return NULL; - } *dst = *src; if (!EVP_MAC_up_ref(dst->meth)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); OPENSSL_free(dst); return NULL; } @@ -118,9 +115,24 @@ size_t EVP_MAC_CTX_get_block_size(EVP_MAC_CTX *ctx) int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen, const OSSL_PARAM params[]) { + if (ctx->meth->init == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return 0; + } return ctx->meth->init(ctx->algctx, key, keylen, params); } +int EVP_MAC_init_SKEY(EVP_MAC_CTX *ctx, EVP_SKEY *skey, const OSSL_PARAM params[]) +{ + if (ctx->meth->init_skey == NULL + || skey->skeymgmt->prov != ctx->meth->prov + || ctx->meth->init_skey == NULL) { + ERR_raise(ERR_R_EVP_LIB, ERR_R_UNSUPPORTED); + return 0; + } + return ctx->meth->init_skey(ctx->algctx, skey->keydata, params); +} + int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen) { return ctx->meth->update(ctx->algctx, data, datalen); diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c index 85fe7704fde2..3c7a1365fdd8 100644 --- a/crypto/evp/mac_meth.c +++ b/crypto/evp/mac_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,7 +21,7 @@ static int evp_mac_up_ref(void *vmac) EVP_MAC *mac = vmac; int ref = 0; - CRYPTO_UP_REF(&mac->refcnt, &ref, mac->lock); + CRYPTO_UP_REF(&mac->refcnt, &ref); return 1; } @@ -33,12 +33,12 @@ static void evp_mac_free(void *vmac) if (mac == NULL) return; - CRYPTO_DOWN_REF(&mac->refcnt, &ref, mac->lock); + CRYPTO_DOWN_REF(&mac->refcnt, &ref); if (ref > 0) return; OPENSSL_free(mac->type_name); ossl_provider_free(mac->prov); - CRYPTO_THREAD_lock_free(mac->lock); + CRYPTO_FREE_REF(&mac->refcnt); OPENSSL_free(mac); } @@ -47,13 +47,10 @@ static void *evp_mac_new(void) EVP_MAC *mac = NULL; if ((mac = OPENSSL_zalloc(sizeof(*mac))) == NULL - || (mac->lock = CRYPTO_THREAD_lock_new()) == NULL) { + || !CRYPTO_NEW_REF(&mac->refcnt, 1)) { evp_mac_free(mac); return NULL; } - - mac->refcnt = 1; - return mac; } @@ -63,17 +60,17 @@ static void *evp_mac_from_algorithm(int name_id, { const OSSL_DISPATCH *fns = algodef->implementation; EVP_MAC *mac = NULL; - int fnmaccnt = 0, fnctxcnt = 0; + int fnmaccnt = 0, fnctxcnt = 0, mac_init_found = 0; if ((mac = evp_mac_new()) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); - return NULL; + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); + goto err; } mac->name_id = name_id; - if ((mac->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) { - evp_mac_free(mac); - return NULL; - } + + if ((mac->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) + goto err; + mac->description = algodef->algorithm_description; for (; fns->function_id != 0; fns++) { @@ -99,7 +96,7 @@ static void *evp_mac_from_algorithm(int name_id, if (mac->init != NULL) break; mac->init = OSSL_FUNC_mac_init(fns); - fnmaccnt++; + mac_init_found = 1; break; case OSSL_FUNC_MAC_UPDATE: if (mac->update != NULL) @@ -146,8 +143,15 @@ static void *evp_mac_from_algorithm(int name_id, break; mac->set_ctx_params = OSSL_FUNC_mac_set_ctx_params(fns); break; + case OSSL_FUNC_MAC_INIT_SKEY: + if (mac->init_skey != NULL) + break; + mac->init_skey = OSSL_FUNC_mac_init_skey(fns); + mac_init_found = 1; + break; } } + fnmaccnt += mac_init_found; if (fnmaccnt != 3 || fnctxcnt != 2) { /* @@ -155,15 +159,20 @@ static void *evp_mac_from_algorithm(int name_id, * a complete set of "mac" functions, and a complete set of context * management functions, as well as the size function. */ - evp_mac_free(mac); ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); - return NULL; + goto err; } + + if (prov != NULL && !ossl_provider_up_ref(prov)) + goto err; + mac->prov = prov; - if (prov != NULL) - ossl_provider_up_ref(prov); return mac; + +err: + evp_mac_free(mac); + return NULL; } EVP_MAC *EVP_MAC_fetch(OSSL_LIB_CTX *libctx, const char *algorithm, @@ -244,3 +253,14 @@ void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx, (void (*)(void *, void *))fn, arg, evp_mac_from_algorithm, evp_mac_up_ref, evp_mac_free); } + +EVP_MAC *evp_mac_fetch_from_prov(OSSL_PROVIDER *prov, + const char *algorithm, + const char *properties) +{ + return evp_generic_fetch_from_prov(prov, OSSL_OP_MAC, + algorithm, properties, + evp_mac_from_algorithm, + evp_mac_up_ref, + evp_mac_free); +} diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c index f3ac675ff2e3..eb8fbc09fb2b 100644 --- a/crypto/evp/p5_crpt.c +++ b/crypto/evp/p5_crpt.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -78,7 +78,7 @@ int PKCS5_PBE_keyivgen_ex(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, passlen = strlen(pass); mdsize = EVP_MD_get_size(md); - if (mdsize < 0) + if (mdsize <= 0) goto err; kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF1, propq); diff --git a/crypto/evp/p_dec.c b/crypto/evp/p_dec.c index d77eed14284f..29ea3f5fbcb3 100644 --- a/crypto/evp/p_dec.c +++ b/crypto/evp/p_dec.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/evp/p_enc.c b/crypto/evp/p_enc.c index 433c1a9e1710..64e67514561c 100644 --- a/crypto/evp/p_enc.c +++ b/crypto/evp/p_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/evp/p_legacy.c b/crypto/evp/p_legacy.c index 6c65e7e1947a..0b95fc4b2116 100644 --- a/crypto/evp/p_legacy.c +++ b/crypto/evp/p_legacy.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -24,10 +24,16 @@ int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) { - int ret = EVP_PKEY_assign_RSA(pkey, key); + int ret; + + if (!RSA_up_ref(key)) + return 0; + + ret = EVP_PKEY_assign_RSA(pkey, key); + + if (!ret) + RSA_free(key); - if (ret) - RSA_up_ref(key); return ret; } @@ -49,8 +55,9 @@ RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) { RSA *ret = evp_pkey_get0_RSA_int(pkey); - if (ret != NULL) - RSA_up_ref(ret); + if (ret != NULL && !RSA_up_ref(ret)) + ret = NULL; + return ret; } diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 6ff7eb7e02cf..7f4508169dfa 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -54,11 +54,10 @@ 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 +#ifndef FIPS_MODULE int EVP_PKEY_get_bits(const EVP_PKEY *pkey) { int size = 0; @@ -68,7 +67,11 @@ int EVP_PKEY_get_bits(const EVP_PKEY *pkey) if (pkey->ameth != NULL && pkey->ameth->pkey_bits != NULL) size = pkey->ameth->pkey_bits(pkey); } - return size < 0 ? 0 : size; + if (size <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_BITS); + return 0; + } + return size; } int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey) @@ -80,7 +83,11 @@ int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey) if (pkey->ameth != NULL && pkey->ameth->pkey_security_bits != NULL) size = pkey->ameth->pkey_security_bits(pkey); } - return size < 0 ? 0 : size; + if (size <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_SECURITY_BITS); + return 0; + } + return size; } int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) @@ -115,6 +122,7 @@ void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx) { return CRYPTO_get_ex_data(&key->ex_data, idx); } +#endif /* !FIPS_MODULE */ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) { @@ -125,6 +133,7 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) EVP_PKEY *downgraded_from = NULL; int ok = 0; +#ifndef FIPS_MODULE /* * If |to| is a legacy key and |from| isn't, we must make a downgraded * copy of |from|. If that fails, this function fails. @@ -134,6 +143,7 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) goto end; from = downgraded_from; } +#endif /* !FIPS_MODULE */ /* * Make sure |to| is typed. Content is less important at this early @@ -148,19 +158,25 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) * further down help us find out if they are the same or not. */ if (evp_pkey_is_blank(to)) { +#ifndef FIPS_MODULE if (evp_pkey_is_legacy(from)) { if (EVP_PKEY_set_type(to, from->type) == 0) goto end; - } else { + } else +#endif /* !FIPS_MODULE */ + { if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0) goto end; } - } else if (evp_pkey_is_legacy(to)) { + } +#ifndef FIPS_MODULE + else if (evp_pkey_is_legacy(to)) { if (to->type != from->type) { ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES); goto end; } } +#endif /* !FIPS_MODULE */ if (EVP_PKEY_missing_parameters(from)) { ERR_raise(ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS); @@ -181,6 +197,7 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) goto end; } +#ifndef FIPS_MODULE /* * 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() @@ -210,6 +227,7 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) /* Both keys are legacy */ if (from->ameth != NULL && from->ameth->param_copy != NULL) ok = from->ameth->param_copy(to, from); +#endif /* !FIPS_MODULE */ end: EVP_PKEY_free(downgraded_from); return ok; @@ -218,10 +236,14 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) { if (pkey != NULL) { +#ifdef FIPS_MODULE + return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS); +#else if (pkey->keymgmt != NULL) return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS); - else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL) + if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL) return pkey->ameth->param_missing(pkey); +#endif /* FIPS_MODULE */ } return 0; } @@ -234,6 +256,9 @@ int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b, int selection) { +#ifdef FIPS_MODULE + return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection); +#else EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL; void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL; @@ -292,17 +317,23 @@ static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b, return -2; return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection); +#endif /* FIPS_MODULE */ } +#ifndef FIPS_MODULE # 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 +# endif +#endif /* FIPS_MODULE */ int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b) { +#ifdef FIPS_MODULE + return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS); +#else /* * This will just call evp_keymgmt_util_match when legacy support * is gone. @@ -317,14 +348,17 @@ int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b) if (a->ameth != NULL && a->ameth->param_cmp != NULL) return a->ameth->param_cmp(a, b); return -2; +#endif /* !FIPS_MODULE */ } +#ifndef FIPS_MODULE # 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 +# endif +#endif /* !FIPS_MODULE */ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) { @@ -339,7 +373,10 @@ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) if (a == NULL || b == NULL) return 0; - if (a->keymgmt != NULL || b->keymgmt != NULL) { +#ifndef FIPS_MODULE + if (a->keymgmt != NULL || b->keymgmt != NULL) +#endif /* !FIPS_MODULE */ + { int selection = SELECT_PARAMETERS; if (evp_keymgmt_util_has((EVP_PKEY *)a, OSSL_KEYMGMT_SELECT_PUBLIC_KEY) @@ -350,6 +387,7 @@ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) return evp_pkey_cmp_any(a, b, selection); } +#ifndef FIPS_MODULE /* All legacy keys */ if (a->type != b->type) return -1; @@ -368,9 +406,10 @@ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) } return -2; +#endif /* !FIPS_MODULE */ } - +#ifndef FIPS_MODULE static EVP_PKEY *new_raw_key_int(OSSL_LIB_CTX *libctx, const char *strtype, const char *propq, @@ -442,12 +481,12 @@ static EVP_PKEY *new_raw_key_int(OSSL_LIB_CTX *libctx, pkey = EVP_PKEY_new(); if (pkey == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) { - /* EVPerr already called */ + /* ERR_raise(ERR_LIB_EVP, ...) already called */ goto err; } @@ -517,8 +556,7 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e, return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0); } -struct raw_key_details_st -{ +struct raw_key_details_st { unsigned char **key; size_t *len; int selection; @@ -859,22 +897,30 @@ const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *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); + int ret; + + if (!DSA_up_ref(key)) + return 0; + + ret = EVP_PKEY_assign_DSA(pkey, key); + + if (!ret) + DSA_free(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); + if (ret != NULL && !DSA_up_ref(ret)) + return NULL; + return ret; } # endif /* OPENSSL_NO_DSA */ -# ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_ECX static const ECX_KEY *evp_pkey_get0_ECX_KEY(const EVP_PKEY *pkey, int type) { if (EVP_PKEY_get_base_id(pkey) != type) { @@ -903,7 +949,7 @@ IMPLEMENT_ECX_VARIANT(X448) IMPLEMENT_ECX_VARIANT(ED25519) IMPLEMENT_ECX_VARIANT(ED448) -# endif +# endif /* OPENSSL_NO_ECX */ # if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0) @@ -935,10 +981,14 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey) else type = DH_get0_q(dhkey) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX; + if (!DH_up_ref(dhkey)) + return 0; + ret = EVP_PKEY_assign(pkey, type, dhkey); - if (ret) - DH_up_ref(dhkey); + if (!ret) + DH_free(dhkey); + return ret; } @@ -960,8 +1010,9 @@ DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) { DH *ret = evp_pkey_get0_DH_int(pkey); - if (ret != NULL) - DH_up_ref(ret); + if (ret != NULL && !DH_up_ref(ret)) + ret = NULL; + return ret; } # endif @@ -1375,18 +1426,22 @@ int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx, EVP_MD_CTX_free(ctx); return rv; } +#endif /* !FIPS_MODULE */ int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey, const unsigned char *pub, size_t publen) { if (pkey == NULL) return 0; +#ifndef FIPS_MODULE if (evp_pkey_is_provided(pkey)) +#endif /* !FIPS_MODULE */ return EVP_PKEY_set_octet_string_param(pkey, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, (unsigned char *)pub, publen); +#ifndef FIPS_MODULE if (publen > INT_MAX) return 0; /* Historically this function was EVP_PKEY_set1_tls_encodedpoint */ @@ -1394,15 +1449,17 @@ int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey, const unsigned char *pub, (void *)pub) <= 0) return 0; return 1; +#endif /* !FIPS_MODULE */ } size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub) { - int rv; - if (pkey == NULL) return 0; - if (evp_pkey_is_provided(pkey)) { +#ifndef FIPS_MODULE + if (evp_pkey_is_provided(pkey)) +#endif + { size_t return_size = OSSL_PARAM_UNMODIFIED; unsigned char *buf; @@ -1431,46 +1488,48 @@ size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub) return return_size; } - - rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppub); - if (rv <= 0) - return 0; - return rv; +#ifndef FIPS_MODULE + { + int rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppub); + if (rv <= 0) + return 0; + return rv; + } +#endif /* !FIPS_MODULE */ } -#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); + if (ret == NULL) return NULL; - } ret->type = EVP_PKEY_NONE; ret->save_type = EVP_PKEY_NONE; - ret->references = 1; + + if (!CRYPTO_NEW_REF(&ret->references, 1)) + goto err; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - EVPerr(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); 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); + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); goto err; } #endif return ret; err: + CRYPTO_FREE_REF(&ret->references); CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; @@ -1660,15 +1719,14 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey) { int i; - if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0) + if (CRYPTO_UP_REF(&pkey->references, &i) <= 0) return 0; - REF_PRINT_COUNT("EVP_PKEY", pkey); + REF_PRINT_COUNT("EVP_PKEY", i, 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; @@ -1684,13 +1742,17 @@ EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey) if (evp_pkey_is_blank(pkey)) goto done; - if (evp_pkey_is_provided(pkey)) { +#ifndef FIPS_MODULE + if (evp_pkey_is_provided(pkey)) +#endif /* !FIPS_MODULE */ + { if (!evp_keymgmt_util_copy(dup_pk, pkey, OSSL_KEYMGMT_SELECT_ALL)) goto err; goto done; } +#ifndef FIPS_MODULE if (evp_pkey_is_legacy(pkey)) { const EVP_PKEY_ASN1_METHOD *ameth = pkey->ameth; @@ -1705,9 +1767,11 @@ EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey) goto err; goto done; } +#endif /* !FIPS_MODULE */ goto err; done: +#ifndef FIPS_MODULE /* copy auxiliary data */ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, &dup_pk->ex_data, &pkey->ex_data)) @@ -1717,12 +1781,14 @@ done: if ((dup_pk->attributes = ossl_x509at_dup(pkey->attributes)) == NULL) goto err; } +#endif /* !FIPS_MODULE */ return dup_pk; err: EVP_PKEY_free(dup_pk); return NULL; } +#ifndef FIPS_MODULE void evp_pkey_free_legacy(EVP_PKEY *x) { const EVP_PKEY_ASN1_METHOD *ameth = x->ameth; @@ -1762,7 +1828,7 @@ void evp_pkey_free_legacy(EVP_PKEY *x) static void evp_pkey_free_it(EVP_PKEY *x) { /* internal function; x is never NULL */ - evp_keymgmt_util_clear_operation_cache(x, 1); + evp_keymgmt_util_clear_operation_cache(x); #ifndef FIPS_MODULE evp_pkey_free_legacy(x); #endif @@ -1783,8 +1849,8 @@ void EVP_PKEY_free(EVP_PKEY *x) if (x == NULL) return; - CRYPTO_DOWN_REF(&x->references, &i, x->lock); - REF_PRINT_COUNT("EVP_PKEY", x); + CRYPTO_DOWN_REF(&x->references, &i); + REF_PRINT_COUNT("EVP_PKEY", i, x); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1793,6 +1859,7 @@ void EVP_PKEY_free(EVP_PKEY *x) CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data); #endif CRYPTO_THREAD_lock_free(x->lock); + CRYPTO_FREE_REF(&x->references); #ifndef FIPS_MODULE sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); #endif @@ -1810,7 +1877,11 @@ int EVP_PKEY_get_size(const EVP_PKEY *pkey) size = pkey->ameth->pkey_size(pkey); #endif } - return size < 0 ? 0 : size; + if (size <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_MAX_SIZE); + return 0; + } + return size; } const char *EVP_PKEY_get0_description(const EVP_PKEY *pkey) @@ -1949,7 +2020,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx, 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)) { + && !evp_keymgmt_util_clear_operation_cache(pk)) { CRYPTO_THREAD_unlock(pk->lock); evp_keymgmt_freedata(tmp_keymgmt, keydata); keydata = NULL; @@ -2043,7 +2114,7 @@ int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src) if (*dest == NULL) { allocpkey = *dest = EVP_PKEY_new(); if (*dest == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return 0; } } else { @@ -2069,7 +2140,7 @@ int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src) EVP_PKEY_CTX_new_from_pkey(libctx, *dest, NULL); if (pctx == NULL) - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); if (pctx != NULL && evp_keymgmt_export(keymgmt, keydata, diff --git a/crypto/evp/p_open.c b/crypto/evp/p_open.c index 8ee8b7a0276b..8630553e7963 100644 --- a/crypto/evp/p_open.c +++ b/crypto/evp/p_open.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -34,7 +34,7 @@ int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, return 1; if ((pctx = EVP_PKEY_CTX_new(priv, NULL)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } @@ -42,10 +42,8 @@ int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, || EVP_PKEY_decrypt(pctx, NULL, &keylen, ek, ekl) <= 0) goto err; - if ((key = OPENSSL_malloc(keylen)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if ((key = OPENSSL_malloc(keylen)) == NULL) goto err; - } if (EVP_PKEY_decrypt(pctx, key, &keylen, ek, ekl) <= 0) goto err; diff --git a/crypto/evp/p_seal.c b/crypto/evp/p_seal.c index 475082d43116..94c8462ab457 100644 --- a/crypto/evp/p_seal.c +++ b/crypto/evp/p_seal.c @@ -15,7 +15,6 @@ #include #include #include -#include int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, unsigned char **ek, int *ekl, unsigned char *iv, @@ -59,7 +58,7 @@ int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pubk[i], NULL); if (pctx == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c index 8e430f4704b2..e5555281a6b0 100644 --- a/crypto/evp/p_sign.c +++ b/crypto/evp/p_sign.c @@ -1,5 +1,5 @@ /* - * 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 @@ -33,12 +33,14 @@ int EVP_SignFinal_ex(EVP_MD_CTX *ctx, unsigned char *sigret, EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); if (tmp_ctx == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return 0; } rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); if (rv) rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); + else + rv = EVP_DigestFinal_ex(ctx, m, &m_len); EVP_MD_CTX_free(tmp_ctx); if (!rv) return 0; diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c index e5667afb7cca..02db143d1324 100644 --- a/crypto/evp/p_verify.c +++ b/crypto/evp/p_verify.c @@ -1,5 +1,5 @@ /* - * 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 @@ -31,12 +31,14 @@ int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf, EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); if (tmp_ctx == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return 0; } rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); if (rv) rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); + else + rv = EVP_DigestFinal_ex(ctx, m, &m_len); EVP_MD_CTX_free(tmp_ctx); if (!rv) return 0; diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index 8e4940ed5956..74cca96f4d78 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -1,5 +1,5 @@ /* - * 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 @@ -145,7 +145,7 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) *ppkey = allocated_pkey = EVP_PKEY_new(); if (*ppkey == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return -1; } @@ -153,7 +153,7 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) goto legacy; /* - * Asssigning gentmp to ctx->keygen_info is something our legacy + * Assigning gentmp to ctx->keygen_info is something our legacy * implementations do. Because the provider implementations aren't * allowed to reach into our EVP_PKEY_CTX, we need to provide similar * space for backward compatibility. It's ok that we attach a local @@ -378,7 +378,7 @@ int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection, allocated_pkey = *ppkey = EVP_PKEY_new(); if (*ppkey == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); return -1; } diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 5cd0c4b27f6d..665cafbc21a7 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -66,11 +66,9 @@ static pmeth_fn standard_methods[] = { # ifndef OPENSSL_NO_DH ossl_dhx_pkey_method, # endif -# ifndef OPENSSL_NO_EC +# ifndef OPENSSL_NO_ECX ossl_ecx25519_pkey_method, ossl_ecx448_pkey_method, -# endif -# ifndef OPENSSL_NO_EC ossl_ed25519_pkey_method, ossl_ed448_pkey_method, # endif @@ -128,33 +126,13 @@ 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); + if (pmeth == NULL) 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) @@ -292,7 +270,7 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, * directly. */ if (keymgmt != NULL) { - int tmp_id = get_legacy_alg_type_from_keymgmt(keymgmt); + int tmp_id = evp_keymgmt_get_legacy_alg(keymgmt); if (tmp_id != NID_undef) { if (id == -1) { @@ -317,8 +295,6 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, 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) @@ -345,9 +321,13 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, ret->engine = e; ret->pmeth = pmeth; ret->operation = EVP_PKEY_OP_UNDEFINED; + + if (pkey != NULL && !EVP_PKEY_up_ref(pkey)) { + EVP_PKEY_CTX_free(ret); + return NULL; + } + ret->pkey = pkey; - if (pkey != NULL) - EVP_PKEY_up_ref(pkey); if (pmeth != NULL && pmeth->init != NULL) { if (pmeth->init(ret) <= 0) { @@ -482,13 +462,12 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) } # endif rctx = OPENSSL_zalloc(sizeof(*rctx)); - if (rctx == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (rctx == NULL) return NULL; - } - if (pctx->pkey != NULL) - EVP_PKEY_up_ref(pctx->pkey); + if (pctx->pkey != NULL && !EVP_PKEY_up_ref(pctx->pkey)) + goto err; + rctx->pkey = pctx->pkey; rctx->operation = pctx->operation; rctx->libctx = pctx->libctx; @@ -595,8 +574,9 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_dup(const EVP_PKEY_CTX *pctx) rctx->engine = pctx->engine; # endif - if (pctx->peerkey != NULL) - EVP_PKEY_up_ref(pctx->peerkey); + if (pctx->peerkey != NULL && !EVP_PKEY_up_ref(pctx->peerkey)) + goto err; + rctx->peerkey = pctx->peerkey; if (pctx->pmeth == NULL) { @@ -627,13 +607,13 @@ 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); + if (app_pkey_methods == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); return 0; } } if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB); return 0; } sk_EVP_PKEY_METHOD_sort(app_pkey_methods); @@ -721,8 +701,9 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, const OSSL_PARAM *params) ctx->op.encap.kem->set_ctx_params(ctx->op.encap.algctx, params); break; -#ifndef FIPS_MODULE case EVP_PKEY_STATE_UNKNOWN: + break; +#ifndef FIPS_MODULE case EVP_PKEY_STATE_LEGACY: return evp_pkey_ctx_set_params_to_ctrl(ctx, params); #endif @@ -758,9 +739,16 @@ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) return ctx->op.encap.kem->get_ctx_params(ctx->op.encap.algctx, params); + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_get_params != NULL) + return + evp_keymgmt_gen_get_params(ctx->keymgmt, ctx->op.keymgmt.genctx, + params); + break; + case EVP_PKEY_STATE_UNKNOWN: 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 @@ -803,6 +791,13 @@ const OSSL_PARAM *EVP_PKEY_CTX_gettable_params(const EVP_PKEY_CTX *ctx) return ctx->op.encap.kem->gettable_ctx_params(ctx->op.encap.algctx, provctx); } + if (EVP_PKEY_CTX_IS_GEN_OP(ctx) + && ctx->keymgmt != NULL + && ctx->keymgmt->gen_gettable_params != NULL) { + provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(ctx->keymgmt)); + return ctx->keymgmt->gen_gettable_params(ctx->op.keymgmt.genctx, + provctx); + } return NULL; } @@ -879,7 +874,7 @@ int evp_pkey_ctx_set_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) for (p = params; p->key != NULL; p++) { /* Check the ctx actually understands this parameter */ - if (OSSL_PARAM_locate_const(settable, p->key) == NULL ) + if (OSSL_PARAM_locate_const(settable, p->key) == NULL) return -2; } } @@ -902,9 +897,9 @@ int evp_pkey_ctx_get_params_strict(EVP_PKEY_CTX *ctx, OSSL_PARAM *params) const OSSL_PARAM *gettable = EVP_PKEY_CTX_gettable_params(ctx); const OSSL_PARAM *p; - for (p = params; p->key != NULL; p++ ) { + for (p = params; p->key != NULL; p++) { /* Check the ctx actually understands this parameter */ - if (OSSL_PARAM_locate_const(gettable, p->key) == NULL ) + if (OSSL_PARAM_locate_const(gettable, p->key) == NULL) return -2; } } @@ -1284,77 +1279,12 @@ int EVP_PKEY_CTX_set_kem_op(EVP_PKEY_CTX *ctx, const char *op) 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); @@ -1570,17 +1500,13 @@ static int evp_pkey_ctx_store_cached_data(EVP_PKEY_CTX *ctx, 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); + if (ctx->cached_parameters.dist_id_name == NULL) 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); + if (ctx->cached_parameters.dist_id == NULL) return 0; - } } ctx->cached_parameters.dist_id_set = 1; ctx->cached_parameters.dist_id_len = data_len; diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 8adf254d5eec..e5bb7da255f3 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,8 +7,10 @@ * https://www.openssl.org/source/license.html */ +#include #include #include +#include #include #include #include "internal/numbers.h" /* includes SIZE_MAX */ @@ -18,24 +20,31 @@ #include "crypto/evp.h" #include "evp_local.h" +static void evp_signature_free(void *data) +{ + EVP_SIGNATURE_free(data); +} + +static int evp_signature_up_ref(void *data) +{ + return EVP_SIGNATURE_up_ref(data); +} + static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov) { EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE)); - if (signature == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (signature == NULL) return NULL; - } - signature->lock = CRYPTO_THREAD_lock_new(); - if (signature->lock == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&signature->refcnt, 1) + || !ossl_provider_up_ref(prov)) { + CRYPTO_FREE_REF(&signature->refcnt); OPENSSL_free(signature); return NULL; } + signature->prov = prov; - ossl_provider_up_ref(prov); - signature->refcnt = 1; return signature; } @@ -46,12 +55,16 @@ static void *evp_signature_from_algorithm(int name_id, { const OSSL_DISPATCH *fns = algodef->implementation; EVP_SIGNATURE *signature = NULL; - int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0; - int digsignfncnt = 0, digverifyfncnt = 0; + /* Counts newctx / freectx */ + int ctxfncnt = 0; + /* Counts all init functions */ + int initfncnt = 0; + /* Counts all parameter functions */ int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0; + int valid = 0; if ((signature = evp_signature_new(prov)) == NULL) { - ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB); goto err; } @@ -72,59 +85,93 @@ static void *evp_signature_from_algorithm(int name_id, if (signature->sign_init != NULL) break; signature->sign_init = OSSL_FUNC_signature_sign_init(fns); - signfncnt++; + initfncnt++; break; case OSSL_FUNC_SIGNATURE_SIGN: if (signature->sign != NULL) break; signature->sign = OSSL_FUNC_signature_sign(fns); - signfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT: + if (signature->sign_message_init != NULL) + break; + signature->sign_message_init + = OSSL_FUNC_signature_sign_message_init(fns); + initfncnt++; + break; + case OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE: + if (signature->sign_message_update != NULL) + break; + signature->sign_message_update + = OSSL_FUNC_signature_sign_message_update(fns); + break; + case OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL: + if (signature->sign_message_final != NULL) + break; + signature->sign_message_final + = OSSL_FUNC_signature_sign_message_final(fns); break; case OSSL_FUNC_SIGNATURE_VERIFY_INIT: if (signature->verify_init != NULL) break; signature->verify_init = OSSL_FUNC_signature_verify_init(fns); - verifyfncnt++; + initfncnt++; break; case OSSL_FUNC_SIGNATURE_VERIFY: if (signature->verify != NULL) break; signature->verify = OSSL_FUNC_signature_verify(fns); - verifyfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT: + if (signature->verify_message_init != NULL) + break; + signature->verify_message_init + = OSSL_FUNC_signature_verify_message_init(fns); + initfncnt++; + break; + case OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE: + if (signature->verify_message_update != NULL) + break; + signature->verify_message_update + = OSSL_FUNC_signature_verify_message_update(fns); + break; + case OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL: + if (signature->verify_message_final != NULL) + break; + signature->verify_message_final + = OSSL_FUNC_signature_verify_message_final(fns); break; case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT: if (signature->verify_recover_init != NULL) break; signature->verify_recover_init = OSSL_FUNC_signature_verify_recover_init(fns); - verifyrecfncnt++; + initfncnt++; break; case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER: if (signature->verify_recover != NULL) break; signature->verify_recover = OSSL_FUNC_signature_verify_recover(fns); - verifyrecfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT: if (signature->digest_sign_init != NULL) break; signature->digest_sign_init = OSSL_FUNC_signature_digest_sign_init(fns); + initfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE: if (signature->digest_sign_update != NULL) break; signature->digest_sign_update = OSSL_FUNC_signature_digest_sign_update(fns); - digsignfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL: if (signature->digest_sign_final != NULL) break; signature->digest_sign_final = OSSL_FUNC_signature_digest_sign_final(fns); - digsignfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_SIGN: if (signature->digest_sign != NULL) @@ -137,20 +184,19 @@ static void *evp_signature_from_algorithm(int name_id, break; signature->digest_verify_init = OSSL_FUNC_signature_digest_verify_init(fns); + initfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE: if (signature->digest_verify_update != NULL) break; signature->digest_verify_update = OSSL_FUNC_signature_digest_verify_update(fns); - digverifyfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL: if (signature->digest_verify_final != NULL) break; signature->digest_verify_final = OSSL_FUNC_signature_digest_verify_final(fns); - digverifyfncnt++; break; case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY: if (signature->digest_verify != NULL) @@ -225,48 +271,107 @@ static void *evp_signature_from_algorithm(int name_id, = OSSL_FUNC_signature_settable_ctx_md_params(fns); smdparamfncnt++; break; + case OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES: + if (signature->query_key_types != NULL) + break; + signature->query_key_types + = OSSL_FUNC_signature_query_key_types(fns); + break; } } - if (ctxfncnt != 2 - || (signfncnt == 0 - && verifyfncnt == 0 - && verifyrecfncnt == 0 - && digsignfncnt == 0 - && digverifyfncnt == 0 - && signature->digest_sign == NULL - && signature->digest_verify == NULL) - || (signfncnt != 0 && signfncnt != 2) - || (verifyfncnt != 0 && verifyfncnt != 2) - || (verifyrecfncnt != 0 && verifyrecfncnt != 2) - || (digsignfncnt != 0 && digsignfncnt != 2) - || (digsignfncnt == 2 && signature->digest_sign_init == NULL) - || (digverifyfncnt != 0 && digverifyfncnt != 2) - || (digverifyfncnt == 2 && signature->digest_verify_init == NULL) - || (signature->digest_sign != NULL - && signature->digest_sign_init == NULL) - || (signature->digest_verify != NULL - && signature->digest_verify_init == NULL) - || (gparamfncnt != 0 && gparamfncnt != 2) - || (sparamfncnt != 0 && sparamfncnt != 2) - || (gmdparamfncnt != 0 && gmdparamfncnt != 2) - || (smdparamfncnt != 0 && smdparamfncnt != 2)) { + /* + * In order to be a consistent set of functions we must have at least + * a set of context functions (newctx and freectx) as well as a set of + * "signature" functions. Because there's an overlap between some sets + * of functions, counters don't always cut it, we must test known + * combinations. + * We start by assuming the implementation is valid, and then look for + * reasons it's not. + */ + valid = 1; + /* Start with the ones where counters say enough */ + if (ctxfncnt != 2) + /* newctx or freectx missing */ + valid = 0; + if (valid + && ((gparamfncnt != 0 && gparamfncnt != 2) + || (sparamfncnt != 0 && sparamfncnt != 2) + || (gmdparamfncnt != 0 && gmdparamfncnt != 2) + || (smdparamfncnt != 0 && smdparamfncnt != 2))) /* - * In order to be a consistent set of functions we must have at least - * a set of context functions (newctx and freectx) as well as a set of - * "signature" functions: - * (sign_init, sign) or - * (verify_init verify) or - * (verify_recover_init, verify_recover) or - * (digest_sign_init, digest_sign_update, digest_sign_final) or - * (digest_verify_init, digest_verify_update, digest_verify_final) or - * (digest_sign_init, digest_sign) or - * (digest_verify_init, digest_verify). - * - * set_ctx_params and settable_ctx_params are optional, but if one of - * them is present then the other one must also be present. The same - * applies to get_ctx_params and gettable_ctx_params. The same rules - * apply to the "md_params" functions. The dupctx function is optional. + * Params functions are optional, but if defined, they must + * be pairwise complete sets, i.e. a getter must have an + * associated gettable, etc */ + valid = 0; + if (valid && initfncnt == 0) + /* No init functions */ + valid = 0; + + /* Now we check for function combinations */ + if (valid + && ((signature->sign_init != NULL + && signature->sign == NULL) + || (signature->sign_message_init != NULL + && signature->sign == NULL + && (signature->sign_message_update == NULL + || signature->sign_message_final == NULL)))) + /* sign_init functions with no signing function? That's weird */ + valid = 0; + if (valid + && (signature->sign != NULL + || signature->sign_message_update != NULL + || signature->sign_message_final != NULL) + && signature->sign_init == NULL + && signature->sign_message_init == NULL) + /* signing functions with no sign_init? That's odd */ + valid = 0; + + if (valid + && ((signature->verify_init != NULL + && signature->verify == NULL) + || (signature->verify_message_init != NULL + && signature->verify == NULL + && (signature->verify_message_update == NULL + || signature->verify_message_final == NULL)))) + /* verify_init functions with no verification function? That's weird */ + valid = 0; + if (valid + && (signature->verify != NULL + || signature->verify_message_update != NULL + || signature->verify_message_final != NULL) + && signature->verify_init == NULL + && signature->verify_message_init == NULL) + /* verification functions with no verify_init? That's odd */ + valid = 0; + + if (valid + && (signature->verify_recover_init != NULL) + && (signature->verify_recover == NULL)) + /* verify_recover_init functions with no verify_recover? How quaint */ + valid = 0; + + if (valid + && (signature->digest_sign_init != NULL + && signature->digest_sign == NULL + && (signature->digest_sign_update == NULL + || signature->digest_sign_final == NULL))) + /* + * You can't have a digest_sign_init without *some* performing functions + */ + valid = 0; + + if (valid + && ((signature->digest_verify_init != NULL + && signature->digest_verify == NULL + && (signature->digest_verify_update == NULL + || signature->digest_verify_final == NULL)))) + /* + * You can't have a digest_verify_init without *some* performing functions + */ + valid = 0; + + if (!valid) { ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS); goto err; } @@ -283,12 +388,12 @@ void EVP_SIGNATURE_free(EVP_SIGNATURE *signature) if (signature == NULL) return; - CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock); + CRYPTO_DOWN_REF(&signature->refcnt, &i); if (i > 0) return; OPENSSL_free(signature->type_name); ossl_provider_free(signature->prov); - CRYPTO_THREAD_lock_free(signature->lock); + CRYPTO_FREE_REF(&signature->refcnt); OPENSSL_free(signature); } @@ -296,7 +401,7 @@ int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature) { int ref = 0; - CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock); + CRYPTO_UP_REF(&signature->refcnt, &ref); return 1; } @@ -310,8 +415,8 @@ EVP_SIGNATURE *EVP_SIGNATURE_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, { return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties, evp_signature_from_algorithm, - (int (*)(void *))EVP_SIGNATURE_up_ref, - (void (*)(void *))EVP_SIGNATURE_free); + evp_signature_up_ref, + evp_signature_free); } EVP_SIGNATURE *evp_signature_fetch_from_prov(OSSL_PROVIDER *prov, @@ -321,8 +426,8 @@ EVP_SIGNATURE *evp_signature_fetch_from_prov(OSSL_PROVIDER *prov, return evp_generic_fetch_from_prov(prov, OSSL_OP_SIGNATURE, algorithm, properties, evp_signature_from_algorithm, - (int (*)(void *))EVP_SIGNATURE_up_ref, - (void (*)(void *))EVP_SIGNATURE_free); + evp_signature_up_ref, + evp_signature_free); } int EVP_SIGNATURE_is_a(const EVP_SIGNATURE *signature, const char *name) @@ -354,8 +459,8 @@ void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx, evp_generic_do_all(libctx, OSSL_OP_SIGNATURE, (void (*)(void *, void *))fn, arg, evp_signature_from_algorithm, - (int (*)(void *))EVP_SIGNATURE_up_ref, - (void (*)(void *))EVP_SIGNATURE_free); + evp_signature_up_ref, + evp_signature_free); } @@ -391,12 +496,11 @@ const OSSL_PARAM *EVP_SIGNATURE_settable_ctx_params(const EVP_SIGNATURE *sig) return sig->settable_ctx_params(NULL, provctx); } -static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, - const OSSL_PARAM params[]) +static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature, + int operation, const OSSL_PARAM params[]) { int ret = 0; void *provkey = NULL; - EVP_SIGNATURE *signature = NULL; EVP_KEYMGMT *tmp_keymgmt = NULL; const OSSL_PROVIDER *tmp_prov = NULL; const char *supported_sig = NULL; @@ -410,91 +514,30 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, evp_pkey_ctx_free_old_ops(ctx); ctx->operation = operation; - ERR_set_mark(); + if (signature != NULL) { + /* + * It's important to figure out what the key type should be, and if + * that is what we have in ctx. + */ - if (evp_pkey_ctx_is_legacy(ctx)) - goto legacy; - - if (ctx->pkey == NULL) { - ERR_clear_last_mark(); - ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); - goto err; - } - - /* - * Try to derive the supported signature from |ctx->keymgmt|. - */ - if (!ossl_assert(ctx->pkey->keymgmt == NULL - || ctx->pkey->keymgmt == ctx->keymgmt)) { - ERR_clear_last_mark(); - ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); - goto err; - } - supported_sig = evp_keymgmt_util_query_operation_name(ctx->keymgmt, - OSSL_OP_SIGNATURE); - if (supported_sig == NULL) { - ERR_clear_last_mark(); - ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); - goto err; - } - - /* - * We perform two iterations: - * - * 1. Do the normal signature fetch, using the fetching data given by - * the EVP_PKEY_CTX. - * 2. Do the provider specific signature fetch, from the same provider - * as |ctx->keymgmt| - * - * We then try to fetch the keymgmt from the same provider as the - * signature, and try to export |ctx->pkey| to that keymgmt (when - * this keymgmt happens to be the same as |ctx->keymgmt|, the export - * is a no-op, but we call it anyway to not complicate the code even - * more). - * If the export call succeeds (returns a non-NULL provider key pointer), - * we're done and can perform the operation itself. If not, we perform - * the second iteration, or jump to legacy. - */ - for (iter = 1; iter < 3 && provkey == NULL; iter++) { EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; - /* - * If we're on the second iteration, free the results from the first. - * They are NULL on the first iteration, so no need to check what - * iteration we're on. - */ - EVP_SIGNATURE_free(signature); - EVP_KEYMGMT_free(tmp_keymgmt); - - switch (iter) { - case 1: - signature = - EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery); - if (signature != NULL) - tmp_prov = EVP_SIGNATURE_get0_provider(signature); - break; - case 2: - tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt); - signature = - evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, - supported_sig, ctx->propquery); - if (signature == NULL) - goto legacy; - break; + if (ctx->pkey == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); + goto err; } - if (signature == NULL) - continue; /* - * Ensure that the key is provided, either natively, or as a cached - * export. We start by fetching the keymgmt with the same name as - * |ctx->pkey|, but from the provider of the signature method, using - * the same property query as when fetching the signature method. - * With the keymgmt we found (if we did), we try to export |ctx->pkey| - * to it (evp_pkey_export_to_provider() is smart enough to only actually - - * export it if |tmp_keymgmt| is different from |ctx->pkey|'s keymgmt) + * Ensure that the key is provided, either natively, or as a + * cached export. We start by fetching the keymgmt with the same + * name as |ctx->pkey|, but from the provider of the signature + * method, using the same property query as when fetching the + * signature method. With the keymgmt we found (if we did), we + * try to export |ctx->pkey| to it (evp_pkey_export_to_provider() + * is smart enough to only actually export it if |tmp_keymgmt| + * is different from |ctx->pkey|'s keymgmt) */ + tmp_prov = EVP_SIGNATURE_get0_provider(signature); tmp_keymgmt_tofree = tmp_keymgmt = evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, EVP_KEYMGMT_get0_name(ctx->keymgmt), @@ -504,14 +547,163 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, &tmp_keymgmt, ctx->propquery); if (tmp_keymgmt == NULL) EVP_KEYMGMT_free(tmp_keymgmt_tofree); - } - if (provkey == NULL) { - EVP_SIGNATURE_free(signature); - goto legacy; - } + if (provkey == NULL) + goto end; - ERR_pop_to_mark(); + /* + * Check that the signature matches the given key. This is not + * designed to work with legacy keys, so has to be done after we've + * ensured that the key is at least exported to a provider (above). + */ + if (signature->query_key_types != NULL) { + /* This is expect to be a NULL terminated array */ + const char **keytypes; + + keytypes = signature->query_key_types(); + for (; *keytypes != NULL; keytypes++) + if (EVP_PKEY_CTX_is_a(ctx, *keytypes)) + break; + if (*keytypes == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE); + return -2; + } + } else { + /* + * Fallback 1: + * check if the keytype is the same as the signature algorithm name + */ + const char *keytype = EVP_KEYMGMT_get0_name(ctx->keymgmt); + int ok = EVP_SIGNATURE_is_a(signature, keytype); + + /* + * Fallback 2: + * query the pkey for a default signature algorithm name, and check + * if it matches the signature implementation + */ + if (!ok) { + const char *signame + = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_SIGNATURE); + + ok = EVP_SIGNATURE_is_a(signature, signame); + } + + /* If none of the fallbacks helped, we're lost */ + if (!ok) { + ERR_raise(ERR_LIB_EVP, EVP_R_SIGNATURE_TYPE_AND_KEY_TYPE_INCOMPATIBLE); + return -2; + } + } + + if (!EVP_SIGNATURE_up_ref(signature)) + return 0; + } else { + /* Without a pre-fetched signature, it must be figured out somehow */ + ERR_set_mark(); + + if (evp_pkey_ctx_is_legacy(ctx)) + goto legacy; + + if (ctx->pkey == NULL) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEY_SET); + goto err; + } + + /* + * Try to derive the supported signature from |ctx->keymgmt|. + */ + if (!ossl_assert(ctx->pkey->keymgmt == NULL + || ctx->pkey->keymgmt == ctx->keymgmt)) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + goto err; + } + supported_sig + = evp_keymgmt_util_query_operation_name(ctx->keymgmt, + OSSL_OP_SIGNATURE); + if (supported_sig == NULL) { + ERR_clear_last_mark(); + ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); + goto err; + } + + /* + * We perform two iterations: + * + * 1. Do the normal signature fetch, using the fetching data given by + * the EVP_PKEY_CTX. + * 2. Do the provider specific signature fetch, from the same provider + * as |ctx->keymgmt| + * + * We then try to fetch the keymgmt from the same provider as the + * signature, and try to export |ctx->pkey| to that keymgmt (when + * this keymgmt happens to be the same as |ctx->keymgmt|, the export + * is a no-op, but we call it anyway to not complicate the code even + * more). + * If the export call succeeds (returns a non-NULL provider key pointer), + * we're done and can perform the operation itself. If not, we perform + * the second iteration, or jump to legacy. + */ + for (iter = 1; iter < 3 && provkey == NULL; iter++) { + EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; + + /* + * If we're on the second iteration, free the results from the first. + * They are NULL on the first iteration, so no need to check what + * iteration we're on. + */ + EVP_SIGNATURE_free(signature); + EVP_KEYMGMT_free(tmp_keymgmt); + + switch (iter) { + case 1: + signature = + EVP_SIGNATURE_fetch(ctx->libctx, supported_sig, ctx->propquery); + if (signature != NULL) + tmp_prov = EVP_SIGNATURE_get0_provider(signature); + break; + case 2: + tmp_prov = EVP_KEYMGMT_get0_provider(ctx->keymgmt); + signature = + evp_signature_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, + supported_sig, ctx->propquery); + if (signature == NULL) + goto legacy; + break; + } + if (signature == NULL) + continue; + + /* + * Ensure that the key is provided, either natively, or as a + * cached export. We start by fetching the keymgmt with the same + * name as |ctx->pkey|, but from the provider of the signature + * method, using the same property query as when fetching the + * signature method. With the keymgmt we found (if we did), we + * try to export |ctx->pkey| to it (evp_pkey_export_to_provider() + * is smart enough to only actually export it if |tmp_keymgmt| + * is different from |ctx->pkey|'s keymgmt) + */ + tmp_keymgmt_tofree = tmp_keymgmt = + evp_keymgmt_fetch_from_prov((OSSL_PROVIDER *)tmp_prov, + EVP_KEYMGMT_get0_name(ctx->keymgmt), + ctx->propquery); + if (tmp_keymgmt != NULL) + provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, + &tmp_keymgmt, ctx->propquery); + if (tmp_keymgmt == NULL) + EVP_KEYMGMT_free(tmp_keymgmt_tofree); + } + + if (provkey == NULL) { + EVP_SIGNATURE_free(signature); + goto legacy; + } + + ERR_pop_to_mark(); + } /* No more legacy from here down to legacy: */ @@ -533,6 +725,14 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, } ret = signature->sign_init(ctx->op.sig.algctx, provkey, params); break; + case EVP_PKEY_OP_SIGNMSG: + if (signature->sign_message_init == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = signature->sign_message_init(ctx->op.sig.algctx, provkey, params); + break; case EVP_PKEY_OP_VERIFY: if (signature->verify_init == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); @@ -541,14 +741,21 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, } ret = signature->verify_init(ctx->op.sig.algctx, provkey, params); break; + case EVP_PKEY_OP_VERIFYMSG: + if (signature->verify_message_init == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + ret = -2; + goto err; + } + ret = signature->verify_message_init(ctx->op.sig.algctx, provkey, params); + break; case EVP_PKEY_OP_VERIFYRECOVER: if (signature->verify_recover_init == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); ret = -2; goto err; } - ret = signature->verify_recover_init(ctx->op.sig.algctx, provkey, - params); + ret = signature->verify_recover_init(ctx->op.sig.algctx, provkey, params); break; default: ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); @@ -619,12 +826,69 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN, NULL); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_SIGN, NULL); } int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_SIGN, params); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_SIGN, params); +} + +int EVP_PKEY_sign_init_ex2(EVP_PKEY_CTX *ctx, + EVP_SIGNATURE *algo, const OSSL_PARAM params[]) +{ + return evp_pkey_signature_init(ctx, algo, EVP_PKEY_OP_SIGN, params); +} + +int EVP_PKEY_sign_message_init(EVP_PKEY_CTX *ctx, + EVP_SIGNATURE *algo, const OSSL_PARAM params[]) +{ + return evp_pkey_signature_init(ctx, algo, EVP_PKEY_OP_SIGNMSG, params); +} + +int EVP_PKEY_sign_message_update(EVP_PKEY_CTX *ctx, + const unsigned char *in, size_t inlen) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (ctx->operation != EVP_PKEY_OP_SIGNMSG) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.signature->sign_message_update == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return ctx->op.sig.signature->sign_message_update(ctx->op.sig.algctx, + in, inlen); +} + +int EVP_PKEY_sign_message_final(EVP_PKEY_CTX *ctx, + unsigned char *sig, size_t *siglen) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (ctx->operation != EVP_PKEY_OP_SIGNMSG) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.signature->sign_message_final == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return ctx->op.sig.signature->sign_message_final(ctx->op.sig.algctx, + sig, siglen, + (sig == NULL) ? 0 : *siglen); } int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, @@ -638,7 +902,8 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, return -1; } - if (ctx->operation != EVP_PKEY_OP_SIGN) { + if (ctx->operation != EVP_PKEY_OP_SIGN + && ctx->operation != EVP_PKEY_OP_SIGNMSG) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); return -1; } @@ -668,12 +933,88 @@ int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY, NULL); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFY, NULL); } int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFY, params); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFY, params); +} + +int EVP_PKEY_verify_init_ex2(EVP_PKEY_CTX *ctx, + EVP_SIGNATURE *algo, const OSSL_PARAM params[]) +{ + return evp_pkey_signature_init(ctx, algo, EVP_PKEY_OP_VERIFY, params); +} + +int EVP_PKEY_verify_message_init(EVP_PKEY_CTX *ctx, + EVP_SIGNATURE *algo, const OSSL_PARAM params[]) +{ + return evp_pkey_signature_init(ctx, algo, EVP_PKEY_OP_VERIFYMSG, params); +} + +int EVP_PKEY_CTX_set_signature(EVP_PKEY_CTX *ctx, + const unsigned char *sig, size_t siglen) +{ + OSSL_PARAM sig_params[2], *p = sig_params; + + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + *p++ = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, + /* + * Cast away the const. This is + * read only so should be safe + */ + (char *)sig, siglen); + *p = OSSL_PARAM_construct_end(); + + return EVP_PKEY_CTX_set_params(ctx, sig_params); +} + +int EVP_PKEY_verify_message_update(EVP_PKEY_CTX *ctx, + const unsigned char *in, size_t inlen) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (ctx->operation != EVP_PKEY_OP_VERIFYMSG) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.signature->verify_message_update == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + return ctx->op.sig.signature->verify_message_update(ctx->op.sig.algctx, + in, inlen); +} + +int EVP_PKEY_verify_message_final(EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + + if (ctx->operation != EVP_PKEY_OP_VERIFYMSG) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); + return -1; + } + + if (ctx->op.sig.signature->verify_message_final == NULL) { + ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); + return -2; + } + + /* The signature must have been set with EVP_PKEY_CTX_set_signature() */ + return ctx->op.sig.signature->verify_message_final(ctx->op.sig.algctx); } int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, @@ -687,7 +1028,8 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, return -1; } - if (ctx->operation != EVP_PKEY_OP_VERIFY) { + if (ctx->operation != EVP_PKEY_OP_VERIFY + && ctx->operation != EVP_PKEY_OP_VERIFYMSG) { ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); return -1; } @@ -715,13 +1057,19 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER, NULL); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFYRECOVER, NULL); } int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) { - return evp_pkey_signature_init(ctx, EVP_PKEY_OP_VERIFYRECOVER, params); + return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFYRECOVER, params); +} + +int EVP_PKEY_verify_recover_init_ex2(EVP_PKEY_CTX *ctx, + EVP_SIGNATURE *algo, const OSSL_PARAM params[]) +{ + return evp_pkey_signature_init(ctx, algo, EVP_PKEY_OP_VERIFYRECOVER, params); } int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, diff --git a/crypto/ex_data.c b/crypto/ex_data.c index 13b928899456..0412f38e9baa 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -26,8 +26,10 @@ int ossl_do_ex_data_init(OSSL_LIB_CTX *ctx) * Return the EX_CALLBACKS from the |ex_data| array that corresponds to * a given class. On success, *holds the lock.* * The |global| parameter is assumed to be non null (checked by the caller). + * If |read| is 1 then a read lock is obtained. Otherwise it is a write lock. */ -static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index) +static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index, + int read) { EX_CALLBACKS *ip; @@ -44,8 +46,14 @@ static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index) return NULL; } - if (!CRYPTO_THREAD_write_lock(global->ex_data_lock)) - return NULL; + if (read) { + if (!CRYPTO_THREAD_read_lock(global->ex_data_lock)) + return NULL; + } else { + if (!CRYPTO_THREAD_write_lock(global->ex_data_lock)) + return NULL; + } + ip = &global->ex_data[class_index]; return ip; } @@ -112,7 +120,7 @@ int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx) if (global == NULL) return 0; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 0); if (ip == NULL) return 0; @@ -153,7 +161,7 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, if (global == NULL) return -1; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 0); if (ip == NULL) return -1; @@ -165,16 +173,14 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, || !sk_EX_CALLBACK_push(ip->meth, NULL)) { sk_EX_CALLBACK_free(ip->meth); ip->meth = NULL; - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); goto err; } } a = (EX_CALLBACK *)OPENSSL_malloc(sizeof(*a)); - if (a == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (a == NULL) goto err; - } a->argl = argl; a->argp = argp; a->new_func = new_func; @@ -183,7 +189,7 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, a->priority = priority; if (!sk_EX_CALLBACK_push(ip->meth, NULL)) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); OPENSSL_free(a); goto err; } @@ -223,7 +229,7 @@ int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj, if (global == NULL) return 0; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 1); if (ip == NULL) return 0; @@ -241,10 +247,8 @@ int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj, } CRYPTO_THREAD_unlock(global->ex_data_lock); - if (mx > 0 && storage == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (mx > 0 && storage == NULL) return 0; - } for (i = 0; i < mx; i++) { if (storage[i] != NULL && storage[i]->new_func != NULL) { ptr = CRYPTO_get_ex_data(ad, i); @@ -286,7 +290,7 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, if (global == NULL) return 0; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 1); if (ip == NULL) return 0; @@ -307,10 +311,8 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, if (mx == 0) return 1; - if (storage == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (storage == NULL) return 0; - } /* * Make sure the ex_data stack is at least |mx| elements long to avoid * issues in the for loop that follows; so go get the |mx|'th element @@ -375,7 +377,7 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) if (global == NULL) goto err; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 1); if (ip == NULL) goto err; @@ -442,7 +444,7 @@ int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj, if (global == NULL) return 0; - ip = get_and_lock(global, class_index); + ip = get_and_lock(global, class_index, 1); if (ip == NULL) return 0; f = sk_EX_CALLBACK_value(ip->meth, idx); @@ -470,14 +472,14 @@ int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) if (ad->sk == NULL) { if ((ad->sk = sk_void_new_null()) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); return 0; } } for (i = sk_void_num(ad->sk); i <= idx; ++i) { if (!sk_void_push(ad->sk, NULL)) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); return 0; } } diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c index fe0a82eac8a6..c12a88148fc8 100644 --- a/crypto/ffc/ffc_backend.c +++ b/crypto/ffc/ffc_backend.c @@ -24,9 +24,6 @@ int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) 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) { /* @@ -76,9 +73,8 @@ int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) } 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)) + if (prm->data_type != OSSL_PARAM_OCTET_STRING + || !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); @@ -113,10 +109,8 @@ int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) goto err; props = p1->data; } - if (!ossl_ffc_set_digest(ffc, prm->data, props)) - goto err; + ossl_ffc_set_digest(ffc, prm->data, props); } - ossl_ffc_params_set0_pqg(ffc, p, q, g); ossl_ffc_params_set0_j(ffc, j); return 1; diff --git a/crypto/ffc/ffc_key_generate.c b/crypto/ffc/ffc_key_generate.c index d02c6575274d..cb895f2abd53 100644 --- a/crypto/ffc/ffc_key_generate.c +++ b/crypto/ffc/ffc_key_generate.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c index 3536efd1ad85..4101682a9a6d 100644 --- a/crypto/ffc/ffc_params.c +++ b/crypto/ffc/ffc_params.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -27,11 +27,19 @@ void ossl_ffc_params_init(FFC_PARAMS *params) void ossl_ffc_params_cleanup(FFC_PARAMS *params) { +#ifdef OPENSSL_PEDANTIC_ZEROIZATION + BN_clear_free(params->p); + BN_clear_free(params->q); + BN_clear_free(params->g); + BN_clear_free(params->j); + OPENSSL_clear_free(params->seed, params->seedlen); +#else BN_free(params->p); BN_free(params->q); BN_free(params->g); BN_free(params->j); OPENSSL_free(params->seed); +#endif ossl_ffc_params_init(params); } @@ -75,9 +83,6 @@ void ossl_ffc_params_set0_j(FFC_PARAMS *d, BIGNUM *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; @@ -125,11 +130,10 @@ void ossl_ffc_params_enable_flags(FFC_PARAMS *params, unsigned int flags, params->flags &= ~flags; } -int ossl_ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props) +void 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, @@ -214,9 +218,6 @@ int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, { 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; diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 6b018edfffce..f6dc57fc9980 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -322,9 +322,12 @@ static int generate_q_fips186_4(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd, unsigned char *pmd; OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx); + if (mdsize <= 0) + goto err; + /* find q */ for (;;) { - if(!BN_GENCB_call(cb, 0, m++)) + if (!BN_GENCB_call(cb, 0, m++)) goto err; /* A.1.1.2 Step (5) : generate seed with size seed_len */ @@ -435,7 +438,7 @@ static int generate_q_fips186_2(BN_CTX *ctx, BIGNUM *q, const EVP_MD *evpmd, } if (r != 0) goto err; /* Exit if error */ - /* Try another iteration if it wasnt prime - was in old code.. */ + /* Try another iteration if it wasn't prime - was in old code.. */ generate_seed = 1; } err: @@ -621,7 +624,7 @@ int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, p = params->p; q = params->q; goto g_only; - /* otherwise fall thru to validate p & q */ + /* otherwise fall through to validate p & q */ } /* p & q will be used for generation and validation */ @@ -673,7 +676,7 @@ int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, * A.1.1.3 Step (10) * n = floor(L / hash_outlen) - 1 */ - n = (L - 1 ) / (mdsize << 3); + n = (L - 1) / (mdsize << 3); /* Calculate 2^(L-1): Used in step A.1.1.2 Step (11.3) */ if (!BN_lshift(test, BN_value_one(), L - 1)) @@ -688,9 +691,9 @@ int ossl_ffc_params_FIPS186_4_gen_verify(OSSL_LIB_CTX *libctx, *res = FFC_CHECK_Q_MISMATCH; goto err; } - if(!BN_GENCB_call(cb, 2, 0)) + if (!BN_GENCB_call(cb, 2, 0)) goto err; - if(!BN_GENCB_call(cb, 3, 0)) + if (!BN_GENCB_call(cb, 3, 0)) goto err; memcpy(seed_tmp, seed, seedlen); @@ -814,6 +817,7 @@ int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx, BIGNUM *r0, *test, *tmp, *g = NULL, *q = NULL, *p = NULL; BN_MONT_CTX *mont = NULL; EVP_MD *md = NULL; + int md_size; size_t qsize; int n = 0, m = 0; int counter = 0, pcounter = 0, use_random_seed; @@ -842,8 +846,11 @@ int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx, } if (md == NULL) goto err; + md_size = EVP_MD_get_size(md); + if (md_size <= 0) + goto err; if (N == 0) - N = EVP_MD_get_size(md) * 8; + N = md_size * 8; qsize = N >> 3; /* @@ -922,7 +929,7 @@ int ossl_ffc_params_FIPS186_2_gen_verify(OSSL_LIB_CTX *libctx, p = params->p; q = params->q; goto g_only; - /* otherwise fall thru to validate p and q */ + /* otherwise fall through to validate p and q */ } use_random_seed = (seed_in == NULL); diff --git a/crypto/getenv.c b/crypto/getenv.c index e79b6cc1618f..fe8444f417f7 100644 --- a/crypto/getenv.c +++ b/crypto/getenv.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,7 +13,7 @@ #include #include "internal/cryptlib.h" -#include "e_os.h" +#include "internal/e_os.h" char *ossl_safe_getenv(const char *name) { diff --git a/crypto/hmac/build.info b/crypto/hmac/build.info index b828ab122e49..90b43cf42b3a 100644 --- a/crypto/hmac/build.info +++ b/crypto/hmac/build.info @@ -2,5 +2,22 @@ LIBS=../../libcrypto $COMMON=hmac.c -SOURCE[../../libcrypto]=$COMMON -SOURCE[../../providers/libfips.a]=$COMMON +IF[{- !$disabled{asm} -}] + IF[{- ($target{perlasm_scheme} // '') ne '31' -}] + $HMACASM_s390x=hmac_s390x.c + $HMACDEF_s390x=OPENSSL_HMAC_S390X + ENDIF + + # Now that we have defined all the arch specific variables, use the + # appropriate ones, and define the appropriate macros + IF[$HMACASM_{- $target{asm_arch} -}] + $HMACASM=$HMACASM_{- $target{asm_arch} -} + $HMACDEF=$HMACDEF_{- $target{asm_arch} -} + ENDIF +ENDIF + +DEFINE[../../libcrypto]=$HMACDEF +DEFINE[../../providers/libfips.a]=$HMACDEF + +SOURCE[../../libcrypto]=$COMMON $HMACASM +SOURCE[../../providers/libfips.a]=$COMMON $HMACASM diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c index 940d867ca652..19fc7d3b4f6a 100644 --- a/crypto/hmac/hmac.c +++ b/crypto/hmac/hmac.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -46,9 +46,15 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, * The HMAC construction is not allowed to be used with the * extendable-output functions (XOF) shake128 and shake256. */ - if ((EVP_MD_get_flags(md) & EVP_MD_FLAG_XOF) != 0) + if (EVP_MD_xof(md)) return 0; +#ifdef OPENSSL_HMAC_S390X + rv = s390x_HMAC_init(ctx, key, len, impl); + if (rv >= 1) + return rv; +#endif + if (key != NULL) { reset = 1; @@ -111,6 +117,12 @@ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) { if (!ctx->md) return 0; + +#ifdef OPENSSL_HMAC_S390X + if (ctx->plat.s390x.fc) + return s390x_HMAC_update(ctx, data, len); +#endif + return EVP_DigestUpdate(ctx->md_ctx, data, len); } @@ -122,6 +134,11 @@ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) if (!ctx->md) goto err; +#ifdef OPENSSL_HMAC_S390X + if (ctx->plat.s390x.fc) + return s390x_HMAC_final(ctx, md, len); +#endif + if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i)) goto err; if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx)) @@ -161,6 +178,10 @@ static void hmac_ctx_cleanup(HMAC_CTX *ctx) EVP_MD_CTX_reset(ctx->o_ctx); EVP_MD_CTX_reset(ctx->md_ctx); ctx->md = NULL; + +#ifdef OPENSSL_HMAC_S390X + s390x_HMAC_CTX_cleanup(ctx); +#endif } void HMAC_CTX_free(HMAC_CTX *ctx) @@ -212,6 +233,12 @@ int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx)) goto err; dctx->md = sctx->md; + +#ifdef OPENSSL_HMAC_S390X + if (s390x_HMAC_CTX_copy(dctx, sctx) == 0) + goto err; +#endif + return 1; err: hmac_ctx_cleanup(dctx); @@ -227,7 +254,7 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, size_t temp_md_len = 0; unsigned char *ret = NULL; - if (size >= 0) { + if (size > 0) { ret = EVP_Q_mac(NULL, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, key, key_len, data, data_len, md == NULL ? static_md : md, size, &temp_md_len); diff --git a/crypto/hmac/hmac_local.h b/crypto/hmac/hmac_local.h index 495b8593ffc6..1b871e732053 100644 --- a/crypto/hmac/hmac_local.h +++ b/crypto/hmac/hmac_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,6 +10,10 @@ #ifndef OSSL_CRYPTO_HMAC_LOCAL_H # define OSSL_CRYPTO_HMAC_LOCAL_H +# include "internal/common.h" +# include "internal/numbers.h" +# include "openssl/sha.h" + /* The current largest case is for SHA3-224 */ #define HMAC_MAX_MD_CBLOCK_SIZE 144 @@ -18,6 +22,45 @@ struct hmac_ctx_st { EVP_MD_CTX *md_ctx; EVP_MD_CTX *i_ctx; EVP_MD_CTX *o_ctx; + + /* Platform specific data */ + union { + int dummy; +# ifdef OPENSSL_HMAC_S390X + struct { + unsigned int fc; /* 0 if not supported by kmac instruction */ + int blk_size; + int ikp; + int iimp; + unsigned char *buf; + size_t size; /* must be multiple of digest block size */ + size_t num; + union { + OSSL_UNION_ALIGN; + struct { + uint32_t h[8]; + uint64_t imbl; + unsigned char key[64]; + } hmac_224_256; + struct { + uint64_t h[8]; + uint128_t imbl; + unsigned char key[128]; + } hmac_384_512; + } param; + } s390x; +# endif /* OPENSSL_HMAC_S390X */ + } plat; }; +# ifdef OPENSSL_HMAC_S390X +# define HMAC_S390X_BUF_NUM_BLOCKS 64 + +int s390x_HMAC_init(HMAC_CTX *ctx, const void *key, int key_len, ENGINE *impl); +int s390x_HMAC_update(HMAC_CTX *ctx, const unsigned char *data, size_t len); +int s390x_HMAC_final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); +int s390x_HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx); +int s390x_HMAC_CTX_cleanup(HMAC_CTX *ctx); +# endif /* OPENSSL_HMAC_S390X */ + #endif diff --git a/crypto/http/build.info b/crypto/http/build.info index b4626b13de7f..656bc29841e3 100644 --- a/crypto/http/build.info +++ b/crypto/http/build.info @@ -1,2 +1,6 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=http_client.c http_err.c http_lib.c +SOURCE[../../libcrypto]=http_lib.c + +IF[{- !$disabled{http} -}] + SOURCE[../../libcrypto]=http_client.c http_err.c +ENDIF diff --git a/crypto/http/http_client.c b/crypto/http/http_client.c index c86db4405b8f..dea69ffc64d4 100644 --- a/crypto/http/http_client.c +++ b/crypto/http/http_client.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2025 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 @@ -8,7 +8,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include "crypto/ctype.h" @@ -20,10 +20,10 @@ #include #include #include +#include #include "internal/sockets.h" -#include "internal/cryptlib.h" /* for ossl_assert() */ +#include "internal/common.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") */ @@ -35,6 +35,7 @@ #define HTTP_STATUS_CODE_OK 200 #define HTTP_STATUS_CODE_MOVED_PERMANENTLY 301 #define HTTP_STATUS_CODE_FOUND 302 +#define HTTP_STATUS_CODES_NONFATAL_ERROR 400 /* Stateful HTTP request code, supporting blocking and non-blocking I/O */ @@ -51,13 +52,14 @@ struct ossl_http_req_ctx_st { 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 *server; /* Optional server hostname */ 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) */ + int text; /* Request content type is (likely) text */ char *expected_ct; /* Optional expected Content-Type */ - int expect_asn1; /* Response must be ASN.1-encoded */ + int expect_asn1; /* Response content 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 */ @@ -66,24 +68,29 @@ struct ossl_http_req_ctx_st { 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 */ + size_t max_hdr_lines; /* Max. number of response header lines, or 0 */ }; -/* HTTP states */ +/* HTTP client OSSL_HTTP_REQ_CTX_nbio() internal states, in typical order */ #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_WRITE_HDR1 (3 | OHS_NOREAD) /* Request header to be sent */ +#define OHS_WRITE_HDR (4 | OHS_NOREAD) /* Request header being sent */ +#define OHS_WRITE_REQ (5 | OHS_NOREAD) /* Request content (body) being sent */ +#define OHS_FLUSH (6 | 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 */ +#define OHS_HEADERS_ERROR 3 /* MIME headers of response being read after fatal error */ +#define OHS_REDIRECT 4 /* MIME headers being read, expecting Location */ +#define OHS_ASN1_HEADER 5 /* ASN1 sequence header (tag+length) being read */ +#define OHS_ASN1_CONTENT 6 /* ASN1 content octets being read */ +#define OHS_ASN1_DONE 7 /* ASN1 content read completed */ +#define OHS_STREAM 8 /* HTTP content stream to be read by caller */ +#define OHS_ERROR_CONTENT 9 /* response content (body) being read after fatal error */ /* Low-level HTTP API implementation */ @@ -103,6 +110,7 @@ OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size) rctx->buf = OPENSSL_malloc(rctx->buf_size); rctx->wbio = wbio; rctx->rbio = rbio; + rctx->max_hdr_lines = OSSL_HTTP_DEFAULT_MAX_RESP_HDR_LINES; if (rctx->buf == NULL) { OPENSSL_free(rctx); return NULL; @@ -296,9 +304,14 @@ static int set1_content(OSSL_HTTP_REQ_CTX *rctx, return 0; } - if (content_type != NULL - && BIO_printf(rctx->mem, "Content-Type: %s\r\n", content_type) <= 0) - return 0; + if (content_type == NULL) { + rctx->text = 1; /* assuming request to be text by default, used just for tracing */ + } else { + if (HAS_CASE_PREFIX(content_type, "text/")) + rctx->text = 1; + if (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 @@ -347,6 +360,16 @@ int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type return res; } +void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx, + size_t count) +{ + if (rctx == NULL) { + ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); + return; + } + rctx->max_hdr_lines = count; +} + static int add1_headers(OSSL_HTTP_REQ_CTX *rctx, const STACK_OF(CONF_VALUE) *headers, const char *host) { @@ -409,13 +432,13 @@ static OSSL_HTTP_REQ_CTX *http_req_ctx_new(int free_wbio, BIO *wbio, BIO *rbio, static int parse_http_line1(char *line, int *found_keep_alive) { - int i, retcode, err; + int i, retcode; char *code, *reason, *end; - if (!HAS_PREFIX(line, HTTP_PREFIX_VERSION)) + if (!CHECK_AND_SKIP_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'; + *found_keep_alive = *line > '0'; /* Skip to first whitespace (past protocol info) */ for (code = line; *code != '\0' && !ossl_isspace(*code); code++) @@ -465,14 +488,11 @@ static int parse_http_line1(char *line, int *found_keep_alive) 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); + if (retcode < HTTP_STATUS_CODES_NONFATAL_ERROR) { + ERR_raise_data(ERR_LIB_HTTP, HTTP_R_STATUS_CODE_UNSUPPORTED, "code=%s", code); + if (*reason != '\0') + ERR_add_error_data(2, ", reason=", reason); + } /* must return content normally if status >= 400 */ return retcode; } @@ -485,17 +505,23 @@ static int parse_http_line1(char *line, int *found_keep_alive) return 0; } -static int check_set_resp_len(OSSL_HTTP_REQ_CTX *rctx, size_t len) +static int check_max_len(const char *desc, size_t max_len, size_t len) { - if (rctx->max_resp_len != 0 && len > rctx->max_resp_len) { + if (max_len != 0 && len > max_len) { ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MAX_RESP_LEN_EXCEEDED, - "length=%zu, max=%zu", len, rctx->max_resp_len); + "%s length=%zu, max=%zu", desc, len, max_len); return 0; } + return 1; +} + +static int check_set_resp_len(const char *desc, OSSL_HTTP_REQ_CTX *rctx, size_t len) +{ + if (!check_max_len(desc, rctx->max_resp_len, len)) + return 0; if (rctx->resp_len != 0 && rctx->resp_len != len) { ERR_raise_data(ERR_LIB_HTTP, HTTP_R_INCONSISTENT_CONTENT_LENGTH, - "ASN.1 length=%zu, Content-Length=%zu", - len, rctx->resp_len); + "%s length=%zu, Content-Length=%zu", desc, len, rctx->resp_len); return 0; } rctx->resp_len = len; @@ -524,10 +550,12 @@ static int may_still_retry(time_t max_time, int *ptimeout) int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) { int i, found_expected_ct = 0, found_keep_alive = 0; + int got_text = 1; long n; - size_t resp_len; + size_t resp_len = 0; const unsigned char *p; char *buf, *key, *value, *line_end = NULL; + size_t resp_hdr_lines = 0; if (rctx == NULL) { ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER); @@ -542,12 +570,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) 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 { + if (rctx->expect_asn1 && (rctx->state == OHS_ASN1_HEADER + || rctx->state == OHS_ASN1_CONTENT)) { + n = BIO_read(rctx->rbio, buf, rctx->buf_size); + } else { /* read one text line */ (void)ERR_set_mark(); n = BIO_gets(rctx->rbio, buf, rctx->buf_size); - if (n == -2) { /* unsupported method */ + if (n == -2) { /* some BIOs, such as SSL, do not support "gets" */ (void)ERR_pop_to_mark(); n = BIO_get_line(rctx->rbio, buf, rctx->buf_size); } else { @@ -555,6 +584,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } } if (n <= 0) { + if (rctx->state == OHS_ERROR_CONTENT) { + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "]\n"); /* end of error response content */ + /* in addition, throw error on inconsistent length: */ + (void)check_set_resp_len("error response content", rctx, resp_len); + return 0; + } if (BIO_should_retry(rctx->rbio)) return -1; ERR_raise(ERR_LIB_HTTP, HTTP_R_FAILED_READING_DATA); @@ -562,11 +598,15 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } /* Write data to memory BIO */ - if (BIO_write(rctx->mem, rctx->buf, n) != n) + if (BIO_write(rctx->mem, buf, n) != n) return 0; } switch (rctx->state) { + case OHS_ERROR: + default: + return 0; + case OHS_ADD_HEADERS: /* Last operation was adding headers: need a final \r\n */ if (BIO_write(rctx->mem, "\r\n", 2) != 2) { @@ -575,27 +615,39 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } rctx->state = OHS_WRITE_INIT; - /* fall thru */ + /* fall through */ case OHS_WRITE_INIT: rctx->len_to_send = BIO_get_mem_data(rctx->mem, &rctx->pos); - rctx->state = OHS_WRITE_HDR; + rctx->state = OHS_WRITE_HDR1; - /* fall thru */ + /* fall through */ + case OHS_WRITE_HDR1: 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) { + size_t sz; + + if (!BIO_write_ex(rctx->wbio, rctx->pos, rctx->len_to_send, &sz)) { if (BIO_should_retry(rctx->wbio)) return -1; rctx->state = OHS_ERROR; return 0; } - rctx->pos += i; - rctx->len_to_send -= i; + if (OSSL_TRACE_ENABLED(HTTP)) { + if (rctx->state == OHS_WRITE_HDR1) + OSSL_TRACE(HTTP, "Sending request header: [\n"); + /* for request headers, this usually traces several lines at once: */ + OSSL_TRACE_STRING(HTTP, rctx->state != OHS_WRITE_REQ || rctx->text, + rctx->state != OHS_WRITE_REQ, rctx->pos, sz); + OSSL_TRACE(HTTP, "]\n"); /* end of request header or content */ + } + if (rctx->state == OHS_WRITE_HDR1) + rctx->state = OHS_WRITE_HDR; + rctx->pos += sz; + rctx->len_to_send -= sz; goto next_io; } if (rctx->state == OHS_WRITE_HDR) { @@ -603,6 +655,9 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) rctx->state = OHS_WRITE_REQ; } if (rctx->req != NULL && !BIO_eof(rctx->req)) { + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE1(HTTP, "Sending request content (likely %s)\n", + rctx->text ? "text" : "ASN.1"); n = BIO_read(rctx->req, rctx->buf, rctx->buf_size); if (n <= 0) { if (BIO_should_retry(rctx->req)) @@ -616,7 +671,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } rctx->state = OHS_FLUSH; - /* fall thru */ + /* fall through */ case OHS_FLUSH: i = BIO_flush(rctx->wbio); @@ -632,12 +687,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) rctx->state = OHS_ERROR; return 0; - case OHS_ERROR: - return 0; + /* State machine could be broken up at this point and bulky code sections factorized out. */ case OHS_FIRSTLINE: case OHS_HEADERS: + case OHS_HEADERS_ERROR: case OHS_REDIRECT: + case OHS_ERROR_CONTENT: /* Attempt to read a line in */ next_line: @@ -663,6 +719,22 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) return 0; } + if (rctx->state == OHS_ERROR_CONTENT) { + resp_len += n; + if (!check_max_len("error response content", rctx->max_resp_len, resp_len)) + return 0; + if (OSSL_TRACE_ENABLED(HTTP)) /* dump response content line */ + OSSL_TRACE_STRING(HTTP, got_text, 1, (unsigned char *)buf, n); + goto next_line; + } + + resp_hdr_lines++; + if (rctx->max_hdr_lines != 0 && rctx->max_hdr_lines < resp_hdr_lines) { + ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES); + 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); @@ -670,9 +742,17 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) return 0; } - /* First line */ + if (OSSL_TRACE_ENABLED(HTTP)) { + /* dump all response header line */ + if (rctx->state == OHS_FIRSTLINE) + OSSL_TRACE(HTTP, "Receiving response header: [\n"); + OSSL_TRACE_STRING(HTTP, 1, 1, (unsigned char *)buf, n); + } + + /* First line in response header */ if (rctx->state == OHS_FIRSTLINE) { - switch (parse_http_line1(buf, &found_keep_alive)) { + i = parse_http_line1(buf, &found_keep_alive); + switch (i) { case HTTP_STATUS_CODE_OK: rctx->state = OHS_HEADERS; goto next_line; @@ -686,8 +766,10 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) /* redirection is not supported/recommended for POST */ /* fall through */ default: - rctx->state = OHS_ERROR; - goto next_line; + /* must return content if status >= 400 */ + rctx->state = i < HTTP_STATUS_CODES_NONFATAL_ERROR + ? OHS_HEADERS_ERROR : OHS_HEADERS; + goto next_line; /* continue parsing, also on HTTP error */ } } key = buf; @@ -706,17 +788,33 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) if (rctx->state == OHS_REDIRECT && OPENSSL_strcasecmp(key, "Location") == 0) { rctx->redirection_url = value; + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "]\n"); + /* stop reading due to redirect */ + (void)BIO_reset(rctx->rbio); 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; + if (OPENSSL_strcasecmp(key, "Content-Type") == 0) { + got_text = HAS_CASE_PREFIX(value, "text/"); + if (rctx->state == OHS_HEADERS + && rctx->expected_ct != NULL) { + const char *semicolon; + + if (OPENSSL_strcasecmp(rctx->expected_ct, value) != 0 + /* ignore past ';' unless expected_ct contains ';' */ + && (strchr(rctx->expected_ct, ';') != NULL + || (semicolon = strchr(value, ';')) == NULL + || (size_t)(semicolon - value) != strlen(rctx->expected_ct) + || OPENSSL_strncasecmp(rctx->expected_ct, value, + semicolon - 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; } - found_expected_ct = 1; } /* https://tools.ietf.org/html/rfc7230#section-6.3 Persistence */ @@ -726,14 +824,15 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) 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); + size_t content_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)) + if (!check_set_resp_len("response content-length", rctx, content_len)) return 0; } } @@ -743,9 +842,13 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) if (*p != '\r' && *p != '\n') break; } - if (*p != '\0') /* not end of headers */ + if (*p != '\0') /* not end of headers or not end of error reponse content */ goto next_line; + /* Found blank line(s) indicating end of headers */ + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "]\n"); /* end of response header */ + 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) { @@ -756,8 +859,17 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) rctx->keep_alive = 0; } - if (rctx->state == OHS_ERROR) + if (rctx->state == OHS_HEADERS_ERROR) { + rctx->state = OHS_ERROR_CONTENT; + if (OSSL_TRACE_ENABLED(HTTP)) { + OSSL_TRACE1(HTTP, "Receiving error response content (likely %s): [\n", + got_text ? "text" : "ASN.1"); + goto next_line; + } + /* discard response content when trace not enabled */ + (void)BIO_reset(rctx->rbio); return 0; + } if (rctx->expected_ct != NULL && !found_expected_ct) { ERR_raise_data(ERR_LIB_HTTP, HTTP_R_MISSING_CONTENT_TYPE, @@ -770,11 +882,16 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) return 0; } + /* Note: in non-error situations cannot trace response content */ if (!rctx->expect_asn1) { + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "Receiving response text content\n"); rctx->state = OHS_STREAM; return 1; } + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "Receiving response ASN.1 content\n"); rctx->state = OHS_ASN1_HEADER; /* Fall thru */ @@ -818,18 +935,21 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx) } else { resp_len = *p + 2; } - if (!check_set_resp_len(rctx, resp_len)) + if (!check_set_resp_len("ASN.1 DER content", rctx, resp_len)) return 0; + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE1(HTTP, "Expected response ASN.1 DER content length: %zd\n", resp_len); 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; + if (OSSL_TRACE_ENABLED(HTTP)) + OSSL_TRACE(HTTP, "Finished receiving response ASN.1 content\n"); rctx->state = OHS_ASN1_DONE; return 1; } @@ -1090,7 +1210,7 @@ BIO *OSSL_HTTP_exchange(OSSL_HTTP_REQ_CTX *rctx, char **redirection_url) && reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE) #endif ) { - if (rctx->server != NULL) { + if (rctx->server != NULL && *rctx->server != '\0') { BIO_snprintf(buf, sizeof(buf), "server=http%s://%s%s%s", rctx->use_ssl ? "s" : "", rctx->server, rctx->port != NULL ? ":" : "", @@ -1138,13 +1258,12 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, const char *expected_ct, int expect_asn1, size_t max_resp_len, int timeout) { - char *current_url, *redirection_url = NULL; + char *current_url; int n_redirs = 0; char *host; char *port; char *path; int use_ssl; - OSSL_HTTP_REQ_CTX *rctx = NULL; BIO *resp = NULL; time_t max_time = timeout > 0 ? time(NULL) + timeout : 0; @@ -1156,6 +1275,9 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, return NULL; for (;;) { + OSSL_HTTP_REQ_CTX *rctx; + char *redirection_url; + if (!OSSL_HTTP_parse_url(current_url, &use_ssl, NULL /* user */, &host, &port, NULL /* port_num */, &path, NULL, NULL)) break; @@ -1164,6 +1286,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, use_ssl, bio, rbio, bio_update_fn, arg, buf_size, timeout); new_rpath: + redirection_url = NULL; if (rctx != NULL) { if (!OSSL_HTTP_set1_request(rctx, path, headers, NULL /* content_type */, @@ -1173,9 +1296,9 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, 0 /* no keep_alive */)) { OSSL_HTTP_REQ_CTX_free(rctx); rctx = NULL; - } else { + } else { resp = OSSL_HTTP_exchange(rctx, &redirection_url); - } + } } OPENSSL_free(path); if (resp == NULL && redirection_url != NULL) { @@ -1190,7 +1313,6 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, OPENSSL_free(host); OPENSSL_free(port); (void)OSSL_HTTP_close(rctx, 1); - rctx = NULL; BIO_free(resp); OPENSSL_free(current_url); return NULL; @@ -1200,7 +1322,6 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, OPENSSL_free(host); OPENSSL_free(port); (void)OSSL_HTTP_close(rctx, 1); - rctx = NULL; continue; } /* if redirection not allowed, ignore it */ @@ -1210,7 +1331,6 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy, OPENSSL_free(port); if (!OSSL_HTTP_close(rctx, resp != NULL)) { BIO_free(resp); - rctx = NULL; resp = NULL; } break; @@ -1395,15 +1515,15 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, continue; /* Check for HTTP/1.x */ - if (!HAS_PREFIX(mbuf, HTTP_PREFIX) != 0) { + mbufp = mbuf; + if (!CHECK_AND_SKIP_PREFIX(mbufp, HTTP_PREFIX)) { 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) { + if (!HAS_PREFIX(mbufp, HTTP_VERSION_PATT)) { ERR_raise(ERR_LIB_HTTP, HTTP_R_RECEIVED_WRONG_HTTP_VERSION); BIO_printf(bio_err, "%s: HTTP CONNECT failed, bad HTTP version %.*s\n", @@ -1414,6 +1534,8 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, /* RFC 7231 4.3.6: any 2xx status code is valid */ if (!HAS_PREFIX(mbufp, " 2")) { + if (ossl_isspace(*mbufp)) + mbufp++; /* chop any trailing whitespace */ while (read_len > 0 && ossl_isspace(mbuf[read_len - 1])) read_len--; @@ -1432,7 +1554,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port, do { /* * This does not necessarily catch the case when the full - * HTTP response came in in more than a single TCP message. + * HTTP response came in more than a single TCP message. */ read_len = BIO_gets(fbio, mbuf, BUF_SIZE); } while (read_len > 2); diff --git a/crypto/http/http_err.c b/crypto/http/http_err.c index 332ad926d367..22c2b40e619a 100644 --- a/crypto/http/http_err.c +++ b/crypto/http/http_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,7 +12,9 @@ #include #include "crypto/httperr.h" -#ifndef OPENSSL_NO_ERR +#ifndef OPENSSL_NO_HTTP + +# ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA HTTP_str_reasons[] = { {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN), @@ -55,6 +57,8 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = { "response line too long"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR), "response parse error"}, + {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_TOO_MANY_HDRLINES), + "response too many hdrlines"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RETRY_TIMEOUT), "retry timeout"}, {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_CANCELED_CONNECTION), "server canceled connection"}, @@ -70,13 +74,16 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = { {0, NULL} }; -#endif +# endif int ossl_err_load_HTTP_strings(void) { -#ifndef OPENSSL_NO_ERR +# ifndef OPENSSL_NO_ERR if (ERR_reason_error_string(HTTP_str_reasons[0].error) == NULL) ERR_load_strings_const(HTTP_str_reasons); -#endif +# endif return 1; } +#else +NON_EMPTY_TRANSLATION_UNIT +#endif diff --git a/crypto/http/http_lib.c b/crypto/http/http_lib.c index 9c41f57541d7..725ec1908499 100644 --- a/crypto/http/http_lib.c +++ b/crypto/http/http_lib.c @@ -9,14 +9,14 @@ #include /* for sscanf() */ #include -#ifndef OPENSSL_NO_SOCK -# include "../bio/bio_local.h" /* for NI_MAXHOST */ -#endif #include #include #include /* for BIO_snprintf() */ #include #include "internal/cryptlib.h" /* for ossl_assert() */ +#ifndef OPENSSL_NO_SOCK +# include "internal/bio_addr.h" /* for NI_MAXHOST */ +#endif #ifndef NI_MAXHOST # define NI_MAXHOST 255 #endif @@ -98,9 +98,9 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, else host = p; - /* parse host name/address as far as needed here */ + /* parse hostname/address as far as needed here */ if (host[0] == '[') { - /* ipv6 literal, which may include ':' */ + /* IPv6 literal, which may include ':' */ host_end = strchr(host + 1, ']'); if (host_end == NULL) goto parse_err; @@ -196,6 +196,8 @@ int OSSL_parse_url(const char *url, char **pscheme, char **puser, char **phost, return 0; } +#ifndef OPENSSL_NO_HTTP + 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) @@ -305,3 +307,5 @@ const char *OSSL_HTTP_adapt_proxy(const char *proxy, const char *no_proxy, return NULL; return proxy; } + +#endif /* !defined(OPENSSL_NO_HTTP) */ diff --git a/crypto/idea/idea_local.h b/crypto/idea/idea_local.h index 3c9ffa0827d0..29836a84ba5f 100644 --- a/crypto/idea/idea_local.h +++ b/crypto/idea/idea_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,13 +9,12 @@ #define idea_mul(r,a,b,ul) \ ul=(unsigned long)a*b; \ -if (ul != 0) \ - { \ +if (ul != 0) { \ r=(ul&0xffff)-(ul>>16); \ r-=((r)>>16); \ - } \ -else \ - r=(-(int)a-b+1); /* assuming a or b is 0 and in range */ +} else { \ + r=(-(int)a-b+1); /* assuming a or b is 0 and in range */ \ +} /* NOTE - c is not incremented as per n2l */ #define n2ln(c,l1,l2,n) { \ @@ -23,19 +22,19 @@ else \ l1=l2=0; \ switch (n) { \ case 8: l2 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((unsigned long)(*(--(c))))<<24; \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((unsigned long)(*(--(c))))<<24; \ } \ } @@ -45,19 +44,19 @@ else \ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ } \ } diff --git a/crypto/info.c b/crypto/info.c index a0dc2e80136f..4d70471be255 100644 --- a/crypto/info.c +++ b/crypto/info.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,17 +12,25 @@ #include "crypto/dso_conf.h" #include "internal/thread_once.h" #include "internal/cryptlib.h" -#include "e_os.h" +#include "internal/e_os.h" #include "buildinf.h" +#ifndef OPENSSL_NO_JITTER +# include +# include +#endif + #if defined(__arm__) || defined(__arm) || defined(__aarch64__) # include "arm_arch.h" # define CPU_INFO_STR_LEN 128 #elif defined(__s390__) || defined(__s390x__) # include "s390x_arch.h" # define CPU_INFO_STR_LEN 2048 +#elif defined(__riscv) +# include "crypto/riscv_arch.h" +# define CPU_INFO_STR_LEN 2048 #else -# define CPU_INFO_STR_LEN 128 +# define CPU_INFO_STR_LEN 256 #endif /* extern declaration to avoid warning */ @@ -44,11 +52,18 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) const char *env; BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), - CPUINFO_PREFIX "OPENSSL_ia32cap=0x%llx:0x%llx", + CPUINFO_PREFIX "OPENSSL_ia32cap=0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx:0x%.16llx", (unsigned long long)OPENSSL_ia32cap_P[0] | (unsigned long long)OPENSSL_ia32cap_P[1] << 32, (unsigned long long)OPENSSL_ia32cap_P[2] | - (unsigned long long)OPENSSL_ia32cap_P[3] << 32); + (unsigned long long)OPENSSL_ia32cap_P[3] << 32, + (unsigned long long)OPENSSL_ia32cap_P[4] | + (unsigned long long)OPENSSL_ia32cap_P[5] << 32, + (unsigned long long)OPENSSL_ia32cap_P[6] | + (unsigned long long)OPENSSL_ia32cap_P[7] << 32, + (unsigned long long)OPENSSL_ia32cap_P[8] | + (unsigned long long)OPENSSL_ia32cap_P[9] << 32); + if ((env = getenv("OPENSSL_ia32cap")) != NULL) BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), @@ -98,6 +113,33 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), " env:%s", env); +# elif defined(__riscv) + const char *env; + char sep = '='; + + BIO_snprintf(ossl_cpu_info_str, sizeof(ossl_cpu_info_str), + CPUINFO_PREFIX "OPENSSL_riscvcap"); + for (size_t i = 0; i < kRISCVNumCaps; ++i) { + if (OPENSSL_riscvcap_P[RISCV_capabilities[i].index] + & (1 << RISCV_capabilities[i].bit_offset)) { + /* Match, display the name */ + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + "%c%s", sep, RISCV_capabilities[i].name); + /* Only the first sep is '=' */ + sep = '_'; + } + } + /* If no capability is found, add back the = */ + if (sep == '=') { + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + "%c", sep); + } + if ((env = getenv("OPENSSL_riscvcap")) != NULL) + BIO_snprintf(ossl_cpu_info_str + strlen(ossl_cpu_info_str), + sizeof(ossl_cpu_info_str) - strlen(ossl_cpu_info_str), + " env:%s", env); # endif #endif @@ -135,10 +177,11 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) add_seeds_string("rdtsc"); #endif #ifdef OPENSSL_RAND_SEED_RDCPU +# ifdef __aarch64__ + add_seeds_string("rndr ( rndrrs rndr )"); +# else add_seeds_string("rdrand ( rdseed rdrand )"); -#endif -#ifdef OPENSSL_RAND_SEED_LIBRANDOM - add_seeds_string("C-library-random"); +# endif #endif #ifdef OPENSSL_RAND_SEED_GETRANDOM add_seeds_string("getrandom-syscall"); @@ -151,6 +194,14 @@ DEFINE_RUN_ONCE_STATIC(init_info_strings) #endif #ifdef OPENSSL_RAND_SEED_OS add_seeds_string("os-specific"); +#endif +#ifndef OPENSSL_NO_JITTER + { + char buf[32]; + + BIO_snprintf(buf, sizeof(buf), "JITTER (%d)", jent_version()); + add_seeds_string(buf); + } #endif seed_sources = seeds; } @@ -168,11 +219,11 @@ const char *OPENSSL_info(int t) switch (t) { case OPENSSL_INFO_CONFIG_DIR: - return OPENSSLDIR; + return ossl_get_openssldir(); case OPENSSL_INFO_ENGINES_DIR: - return ENGINESDIR; + return ossl_get_enginesdir(); case OPENSSL_INFO_MODULES_DIR: - return MODULESDIR; + return ossl_get_modulesdir(); case OPENSSL_INFO_DSO_EXTENSION: return DSO_EXTENSION; case OPENSSL_INFO_DIR_FILENAME_SEPARATOR: @@ -199,6 +250,8 @@ const char *OPENSSL_info(int t) if (ossl_cpu_info_str[0] != '\0') return ossl_cpu_info_str + strlen(CPUINFO_PREFIX); break; + case OPENSSL_INFO_WINDOWS_CONTEXT: + return ossl_get_wininstallcontext(); default: break; } diff --git a/crypto/init.c b/crypto/init.c index 659a660eeced..2da4914707b1 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,7 +10,7 @@ /* We need to use some engine deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED -#include "e_os.h" +#include "internal/e_os.h" #include "crypto/cryptlib.h" #include #include "crypto/rand.h" @@ -32,7 +32,9 @@ #include "crypto/store.h" #include /* for OSSL_CMP_log_close() */ #include +#include /* for OPENSSL_INIT_(NO_)?LOAD_SSL_STRINGS */ #include "crypto/ctype.h" +#include "sslerr.h" static int stopped = 0; static uint64_t optsdone = 0; @@ -188,8 +190,15 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) * pulling in all the error strings during static linking */ #if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT) + void *err; + + if (!err_shelve_state(&err)) + return 0; + OSSL_TRACE(INIT, "ossl_err_load_crypto_strings()\n"); ret = ossl_err_load_crypto_strings(); + + err_unshelve_state(err); #endif return ret; } @@ -201,6 +210,28 @@ DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings, return 1; } +static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings) +{ + /* + * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time + * pulling in all the error strings during static linking + */ +#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT) + OSSL_TRACE(INIT, "ossl_init_load_ssl_strings: ossl_err_load_SSL_strings()\n"); + ossl_err_load_SSL_strings(); +#endif + return 1; +} + +DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings) +{ + /* Do nothing in this case */ + return 1; +} + static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) { @@ -391,6 +422,10 @@ void OPENSSL_cleanup(void) #ifndef OPENSSL_NO_COMP OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n"); ossl_comp_zlib_cleanup(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_brotli_cleanup()\n"); + ossl_comp_brotli_cleanup(); + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zstd_cleanup()\n"); + ossl_comp_zstd_cleanup(); #endif if (async_inited) { @@ -551,6 +586,15 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) && !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings)) return 0; + if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS) + && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings, + ossl_init_load_ssl_strings)) + return 0; + + if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS) + && !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings)) + return 0; + if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers, ossl_init_add_all_ciphers)) @@ -708,10 +752,8 @@ int OPENSSL_atexit(void (*handler)(void)) } #endif - if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) return 0; - } newhand->handler = handler; newhand->next = stop_handlers; diff --git a/crypto/initthread.c b/crypto/initthread.c index 1bdaeda9fc8e..27b460009e1d 100644 --- a/crypto/initthread.c +++ b/crypto/initthread.c @@ -1,5 +1,5 @@ /* - * 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 @@ -12,6 +12,7 @@ #include "crypto/cryptlib.h" #include "prov/providercommon.h" #include "internal/thread_once.h" +#include "crypto/context.h" #ifdef FIPS_MODULE #include "prov/provider_ctx.h" @@ -26,7 +27,7 @@ * * The FIPS provider tells libcrypto about which threads it is interested in * by calling "c_thread_start" which is a function pointer created during - * provider initialisation (i.e. OSSL_init_provider). + * provider initialisation (i.e. OSSL_provider_init). */ extern OSSL_FUNC_core_thread_start_fn *c_thread_start; #endif @@ -248,7 +249,16 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) #else -static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) +static void ossl_arg_thread_stop(void *arg); + +/* Register the current thread so that we are informed if it gets stopped */ +int ossl_thread_register_fips(OSSL_LIB_CTX *libctx) +{ + return c_thread_start(FIPS_get_core_handle(libctx), ossl_arg_thread_stop, + libctx); +} + +void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx) { THREAD_EVENT_HANDLER **hands = NULL; CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal)); @@ -256,9 +266,8 @@ static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) if (tlocal == NULL) return NULL; - if (!CRYPTO_THREAD_init_local(tlocal, NULL)) { - goto err; - } + if (!CRYPTO_THREAD_init_local(tlocal, NULL)) + goto deinit; hands = OPENSSL_zalloc(sizeof(*hands)); if (hands == NULL) @@ -267,24 +276,31 @@ static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) if (!CRYPTO_THREAD_set_local(tlocal, hands)) goto err; + /* + * We should ideally call ossl_thread_register_fips() here. This function + * is called during the startup of the FIPS provider and we need to ensure + * that the main thread is registered to receive thread callbacks in order + * to free |hands| that we allocated above. However we are too early in + * the FIPS provider initialisation that FIPS_get_core_handle() doesn't work + * yet. So we defer this to the main provider OSSL_provider_init_int() + * function. + */ + return tlocal; err: OPENSSL_free(hands); + CRYPTO_THREAD_cleanup_local(tlocal); + deinit: OPENSSL_free(tlocal); return NULL; } -static void thread_event_ossl_ctx_free(void *tlocal) +void ossl_thread_event_ctx_free(void *tlocal) { + CRYPTO_THREAD_cleanup_local(tlocal); OPENSSL_free(tlocal); } -static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - thread_event_ossl_ctx_new, - thread_event_ossl_ctx_free, -}; - static void ossl_arg_thread_stop(void *arg) { ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg); @@ -294,8 +310,7 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) { THREAD_EVENT_HANDLER **hands; CRYPTO_THREAD_LOCAL *local - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, - &thread_event_ossl_ctx_method); + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX); if (local == NULL) return; @@ -363,8 +378,7 @@ int ossl_init_thread_start(const void *index, void *arg, * OSSL_LIB_CTX gets informed about thread stop events individually. */ CRYPTO_THREAD_LOCAL *local - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, - &thread_event_ossl_ctx_method); + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX); #else /* * Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per @@ -386,8 +400,7 @@ int ossl_init_thread_start(const void *index, void *arg, * libcrypto to tell us about later thread stop events. c_thread_start * is a callback to libcrypto defined in fipsprov.c */ - if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop, - ctx)) + if (!ossl_thread_register_fips(ctx)) return 0; } #endif diff --git a/crypto/lhash/lh_stats.c b/crypto/lhash/lh_stats.c index ba4d4ea89708..ea0a3252a6ba 100644 --- a/crypto/lhash/lh_stats.c +++ b/crypto/lhash/lh_stats.c @@ -7,6 +7,8 @@ * https://www.openssl.org/source/license.html */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include @@ -21,6 +23,7 @@ #include "lhash_local.h" # ifndef OPENSSL_NO_STDIO +# ifndef OPENSSL_NO_DEPRECATED_3_1 void OPENSSL_LH_stats(const OPENSSL_LHASH *lh, FILE *fp) { BIO *bp; @@ -56,9 +59,15 @@ void OPENSSL_LH_node_usage_stats(const OPENSSL_LHASH *lh, FILE *fp) OPENSSL_LH_node_usage_stats_bio(lh, bp); BIO_free(bp); } - +# endif # endif +# ifndef OPENSSL_NO_DEPRECATED_3_1 +/* + * These functions are implemented as separate static functions as they are + * called from the stdio functions above and calling deprecated functions will + * generate a warning. + */ void OPENSSL_LH_stats_bio(const OPENSSL_LHASH *lh, BIO *out) { BIO_printf(out, "num_items = %lu\n", lh->num_items); @@ -115,3 +124,4 @@ void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out) (int)((total % lh->num_nodes) * 100 / lh->num_nodes), (int)(total / n_used), (int)((total % n_used) * 100 / n_used)); } +# endif diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c index a01cfa725e38..e0234ccbffe4 100644 --- a/crypto/lhash/lhash.c +++ b/crypto/lhash/lhash.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,18 +44,28 @@ static int expand(OPENSSL_LHASH *lh); static void contract(OPENSSL_LHASH *lh); static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, const void *data, unsigned long *rhash); +OPENSSL_LHASH *OPENSSL_LH_set_thunks(OPENSSL_LHASH *lh, + OPENSSL_LH_HASHFUNCTHUNK hw, + OPENSSL_LH_COMPFUNCTHUNK cw, + OPENSSL_LH_DOALL_FUNC_THUNK daw, + OPENSSL_LH_DOALL_FUNCARG_THUNK daaw) +{ + + if (lh == NULL) + return NULL; + lh->compw = cw; + lh->hashw = hw; + lh->daw = daw; + lh->daaw = daaw; + return lh; +} + OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c) { OPENSSL_LHASH *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { - /* - * Do not set the error code, because the ERR code uses LHASH - * and we want to avoid possible endless error loop. - * ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); - */ + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) return NULL; - } if ((ret->b = OPENSSL_zalloc(sizeof(*ret->b) * MIN_NODES)) == NULL) goto err; ret->comp = ((c == NULL) ? (OPENSSL_LH_COMPFUNC)strcmp : c); @@ -174,8 +184,11 @@ void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data) } static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg, + OPENSSL_LH_DOALL_FUNC_THUNK wfunc, OPENSSL_LH_DOALL_FUNC func, - OPENSSL_LH_DOALL_FUNCARG func_arg, void *arg) + OPENSSL_LH_DOALL_FUNCARG func_arg, + OPENSSL_LH_DOALL_FUNCARG_THUNK wfunc_arg, + void *arg) { int i; OPENSSL_LH_NODE *a, *n; @@ -192,9 +205,9 @@ static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg, while (a != NULL) { n = a->next; if (use_arg) - func_arg(a->data, arg); + wfunc_arg(a->data, arg, func_arg); else - func(a->data); + wfunc(a->data, func); a = n; } } @@ -202,12 +215,29 @@ static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg, void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func) { - doall_util_fn(lh, 0, func, (OPENSSL_LH_DOALL_FUNCARG)0, NULL); + if (lh == NULL) + return; + + doall_util_fn(lh, 0, lh->daw, func, (OPENSSL_LH_DOALL_FUNCARG)NULL, + (OPENSSL_LH_DOALL_FUNCARG_THUNK)NULL, NULL); } -void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg) +void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, + OPENSSL_LH_DOALL_FUNCARG func, void *arg) { - doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC)0, func, arg); + if (lh == NULL) + return; + + doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC_THUNK)NULL, + (OPENSSL_LH_DOALL_FUNC)NULL, func, lh->daaw, arg); +} + +void OPENSSL_LH_doall_arg_thunk(OPENSSL_LHASH *lh, + OPENSSL_LH_DOALL_FUNCARG_THUNK daaw, + OPENSSL_LH_DOALL_FUNCARG fn, void *arg) +{ + doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC_THUNK)NULL, + (OPENSSL_LH_DOALL_FUNC)NULL, fn, daaw, arg); } static int expand(OPENSSL_LHASH *lh) @@ -264,7 +294,7 @@ static void contract(OPENSSL_LHASH *lh) n = OPENSSL_realloc(lh->b, (unsigned int)(sizeof(OPENSSL_LH_NODE *) * lh->pmax)); if (n == NULL) { - /* fputs("realloc error in lhash",stderr); */ + /* fputs("realloc error in lhash", stderr); */ lh->error++; } else { lh->b = n; @@ -292,24 +322,32 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, { OPENSSL_LH_NODE **ret, *n1; unsigned long hash, nn; - OPENSSL_LH_COMPFUNC cf; - hash = (*(lh->hash)) (data); + if (lh->hashw != NULL) + hash = lh->hashw(data, lh->hash); + else + hash = lh->hash(data); + *rhash = hash; nn = hash % lh->pmax; if (nn < lh->p) nn = hash % lh->num_alloc_nodes; - cf = lh->comp; ret = &(lh->b[(int)nn]); for (n1 = *ret; n1 != NULL; n1 = n1->next) { if (n1->hash != hash) { ret = &(n1->next); continue; } - if (cf(n1->data, data) == 0) - break; + + if (lh->compw != NULL) { + if (lh->compw(n1->data, data, lh->comp) == 0) + break; + } else { + if (lh->comp(n1->data, data) == 0) + break; + } ret = &(n1->next); } return ret; @@ -344,18 +382,37 @@ unsigned long OPENSSL_LH_strhash(const char *c) return (ret >> 16) ^ ret; } +/* + * Case insensitive string hashing. + * + * The lower/upper case bit is masked out (forcing all letters to be capitals). + * The major side effect on non-alpha characters is mapping the symbols and + * digits into the control character range (which should be harmless). + * The duplication (with respect to the hash value) of printable characters + * are that '`', '{', '|', '}' and '~' map to '@', '[', '\', ']' and '^' + * respectively (which seems tolerable). + * + * For EBCDIC, the alpha mapping is to lower case, most symbols go to control + * characters. The only duplication is '0' mapping to '^', which is better + * than for ASCII. + */ unsigned long ossl_lh_strcasehash(const char *c) { unsigned long ret = 0; long n; unsigned long v; int r; +#if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST) + const long int case_adjust = ~0x40; +#else + const long int case_adjust = ~0x20; +#endif if (c == NULL || *c == '\0') return ret; for (n = 0x100; *c != '\0'; n += 0x100) { - v = n | ossl_tolower(*c); + v = n | (case_adjust & *c); r = (int)((v >> 2) ^ v) & 0x0f; /* cast to uint64_t to avoid 32 bit shift of 32 bit value */ ret = (ret << r) | (unsigned long)((uint64_t)ret >> (32 - r)); diff --git a/crypto/lhash/lhash_local.h b/crypto/lhash/lhash_local.h index 088ac94d2e63..8da63b9adda2 100644 --- a/crypto/lhash/lhash_local.h +++ b/crypto/lhash/lhash_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,6 +20,10 @@ struct lhash_st { OPENSSL_LH_NODE **b; OPENSSL_LH_COMPFUNC comp; OPENSSL_LH_HASHFUNC hash; + OPENSSL_LH_HASHFUNCTHUNK hashw; + OPENSSL_LH_COMPFUNCTHUNK compw; + OPENSSL_LH_DOALL_FUNC_THUNK daw; + OPENSSL_LH_DOALL_FUNCARG_THUNK daaw; unsigned int num_nodes; unsigned int num_alloc_nodes; unsigned int p; diff --git a/crypto/md5/asm/md5-x86_64.pl b/crypto/md5/asm/md5-x86_64.pl index 6625fb7d08aa..4fde03ecabc8 100755 --- a/crypto/md5/asm/md5-x86_64.pl +++ b/crypto/md5/asm/md5-x86_64.pl @@ -1,6 +1,6 @@ #! /usr/bin/env perl # Author: Marc Bevand -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -41,7 +41,6 @@ EOF # %r10d = X[k_next] # %r11d = z' (copy of z for the next step) # %r12d = z' (copy of z for the next step) -# Each round2_step() takes about 5.4 clocks (11 instructions, 2.0 IPC) sub round2_step { my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_; @@ -53,9 +52,9 @@ sub round2_step lea $T_i($dst,%r10d),$dst /* Const + dst + ... */ and $y, %r11d /* y & (not z) */ mov $k_next*4(%rsi),%r10d /* (NEXT STEP) X[$k_next] */ - or %r11d, %r12d /* (y & (not z)) | (x & z) */ + add %r11d, $dst /* dst += (y & (not z)) */ mov $y, %r11d /* (NEXT STEP) z' = $y */ - add %r12d, $dst /* dst += ... */ + add %r12d, $dst /* dst += (x & z) */ mov $y, %r12d /* (NEXT STEP) z' = $y */ rol \$$s, $dst /* dst <<< s */ add $x, $dst /* dst += x */ diff --git a/crypto/md5/build.info b/crypto/md5/build.info index 9a325386065b..307e5037ee6e 100644 --- a/crypto/md5/build.info +++ b/crypto/md5/build.info @@ -4,6 +4,8 @@ $MD5ASM= IF[{- !$disabled{asm} -}] $MD5ASM_x86=md5-586.S $MD5ASM_x86_64=md5-x86_64.s + $MD5ASM_aarch64=md5-aarch64.S + $MD5ASM_loongarch64=md5-loongarch64.S $MD5ASM_sparcv9=md5-sparcv9.S # Now that we have defined all the arch specific variables, use the @@ -35,6 +37,11 @@ DEFINE[../../providers/liblegacy.a]=$MD5DEF GENERATE[md5-586.S]=asm/md5-586.pl GENERATE[md5-x86_64.s]=asm/md5-x86_64.pl +GENERATE[md5-aarch64.S]=asm/md5-aarch64.pl +INCLUDE[md5-aarch64.o]=.. + +GENERATE[md5-loongarch64.S]=asm/md5-loongarch64.pl +INCLUDE[md5-loongarch64.o]=.. GENERATE[md5-sparcv9.S]=asm/md5-sparcv9.pl INCLUDE[md5-sparcv9.o]=.. diff --git a/crypto/md5/md5_local.h b/crypto/md5/md5_local.h index 22a0e0f62aed..fab8bb9dae63 100644 --- a/crypto/md5/md5_local.h +++ b/crypto/md5/md5_local.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,7 +14,9 @@ #ifdef MD5_ASM # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) + defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ + defined(_M_X64) || defined(__aarch64__) || \ + (defined(__loongarch__) && __loongarch_grlen == 64) # define md5_block_data_order ossl_md5_block_asm_data_order # elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) # define md5_block_data_order ossl_md5_block_asm_data_order diff --git a/crypto/mem.c b/crypto/mem.c index 34128616e270..c6cdfb36e1e6 100644 --- a/crypto/mem.c +++ b/crypto/mem.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include "crypto/cryptlib.h" #include @@ -38,7 +38,8 @@ static TSAN_QUALIFIER int free_count; # define LOAD(x) tsan_load(&x) # endif /* TSAN_REQUIRES_LOCKING */ -static char *md_failstring; +static char md_failbuf[CRYPTO_MEM_CHECK_MAX_FS + 1]; +static char *md_failstring = NULL; static long md_count; static int md_fail_percent = 0; static int md_tracefd = -1; @@ -164,9 +165,17 @@ static int shouldfail(void) void ossl_malloc_setup_failures(void) { const char *cp = getenv("OPENSSL_MALLOC_FAILURES"); + size_t cplen = 0; - if (cp != NULL && (md_failstring = strdup(cp)) != NULL) - parseit(); + if (cp != NULL) { + /* if the value is too long we'll just ignore it */ + cplen = strlen(cp); + if (cplen <= CRYPTO_MEM_CHECK_MAX_FS) { + strncpy(md_failbuf, cp, CRYPTO_MEM_CHECK_MAX_FS); + md_failstring = md_failbuf; + parseit(); + } + } if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL) md_tracefd = atoi(cp); if ((cp = getenv("OPENSSL_MALLOC_SEED")) != NULL) @@ -176,9 +185,15 @@ void ossl_malloc_setup_failures(void) void *CRYPTO_malloc(size_t num, const char *file, int line) { + void *ptr; + INCREMENT(malloc_count); - if (malloc_impl != CRYPTO_malloc) - return malloc_impl(num, file, line); + if (malloc_impl != CRYPTO_malloc) { + ptr = malloc_impl(num, file, line); + if (ptr != NULL || num == 0) + return ptr; + goto err; + } if (num == 0) return NULL; @@ -193,7 +208,20 @@ void *CRYPTO_malloc(size_t num, const char *file, int line) allow_customize = 0; } - return malloc(num); + ptr = malloc(num); + if (ptr != NULL) + return ptr; + err: + /* + * ossl_err_get_state_int() in err.c uses CRYPTO_zalloc(num, NULL, 0) for + * ERR_STATE allocation. Prevent mem alloc error loop while reporting error. + */ + if (file != NULL || line != 0) { + ERR_new(); + ERR_set_debug(file, line, NULL); + ERR_set_error(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE, NULL); + } + return NULL; } void *CRYPTO_zalloc(size_t num, const char *file, int line) @@ -207,6 +235,68 @@ void *CRYPTO_zalloc(size_t num, const char *file, int line) return ret; } +void *CRYPTO_aligned_alloc(size_t num, size_t alignment, void **freeptr, + const char *file, int line) +{ + void *ret; + + *freeptr = NULL; + +#if defined(OPENSSL_SMALL_FOOTPRINT) + ret = freeptr = NULL; + return ret; +#endif + + /* Allow non-malloc() allocations as long as no malloc_impl is provided. */ + if (malloc_impl == CRYPTO_malloc) { +#if defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) + if (posix_memalign(&ret, alignment, num)) + return NULL; + *freeptr = ret; + return ret; +#elif defined(_ISOC11_SOURCE) + ret = *freeptr = aligned_alloc(alignment, num); + return ret; +#endif + } + + /* we have to do this the hard way */ + + /* + * Note: Windows supports an _aligned_malloc call, but we choose + * not to use it here, because allocations from that function + * require that they be freed via _aligned_free. Given that + * we can't differentiate plain malloc blocks from blocks obtained + * via _aligned_malloc, just avoid its use entirely + */ + + /* + * Step 1: Allocate an amount of memory that is + * bytes bigger than requested + */ + *freeptr = CRYPTO_malloc(num + alignment, file, line); + if (*freeptr == NULL) + return NULL; + + /* + * Step 2: Add bytes to the pointer + * This will cross the alignment boundary that is + * requested + */ + ret = (void *)((char *)*freeptr + (alignment - 1)); + + /* + * Step 3: Use the alignment as a mask to translate the + * least significant bits of the allocation at the alignment + * boundary to 0. ret now holds a pointer to the memory + * buffer at the requested alignment + * NOTE: It is a documented requirement that alignment be a + * power of 2, which is what allows this to work + */ + ret = (void *)((uintptr_t)ret & (uintptr_t)(~(alignment - 1))); + return ret; +} + void *CRYPTO_realloc(void *str, size_t num, const char *file, int line) { INCREMENT(realloc_count); diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c index 5cdeedb8d127..e8700ebaa42b 100644 --- a/crypto/mem_sec.c +++ b/crypto/mem_sec.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2004-2014, Akamai Technologies. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -15,8 +15,9 @@ * For details on that implementation, see below (look for uppercase * "SECURE HEAP IMPLEMENTATION"). */ -#include "e_os.h" +#include "internal/e_os.h" #include +#include #include @@ -65,6 +66,18 @@ VirtualLock( # include # include #endif +#ifndef HAVE_MADVISE +# if defined(MADV_DONTDUMP) +# define HAVE_MADVISE 1 +# else +# define HAVE_MADVISE 0 +# endif +#endif +#if HAVE_MADVISE +# undef NO_MADVISE +#else +# define NO_MADVISE +#endif #define CLEAR(p, s) OPENSSL_cleanse(p, s) #ifndef PAGE_SIZE @@ -141,18 +154,27 @@ int CRYPTO_secure_malloc_initialized(void) void *CRYPTO_secure_malloc(size_t num, const char *file, int line) { #ifndef OPENSSL_NO_SECURE_MEMORY - void *ret; + void *ret = NULL; size_t actual_size; + int reason = CRYPTO_R_SECURE_MALLOC_FAILURE; if (!secure_mem_initialized) { return CRYPTO_malloc(num, file, line); } - if (!CRYPTO_THREAD_write_lock(sec_malloc_lock)) - return NULL; + if (!CRYPTO_THREAD_write_lock(sec_malloc_lock)) { + reason = ERR_R_CRYPTO_LIB; + goto err; + } ret = sh_malloc(num); actual_size = ret ? sh_actual_size(ret) : 0; secure_mem_used += actual_size; CRYPTO_THREAD_unlock(sec_malloc_lock); + err: + if (ret == NULL && (file != NULL || line != 0)) { + ERR_new(); + ERR_set_debug(file, line, NULL); + ERR_set_error(ERR_LIB_CRYPTO, reason, NULL); + } return ret; #else return CRYPTO_malloc(num, file, line); @@ -299,14 +321,12 @@ size_t CRYPTO_secure_actual_size(void *ptr) ((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size]) -typedef struct sh_list_st -{ +typedef struct sh_list_st { struct sh_list_st *next; struct sh_list_st **p_next; } SH_LIST; -typedef struct sh_st -{ +typedef struct sh_st { char* map_result; size_t map_size; char *arena; @@ -563,7 +583,7 @@ static int sh_init(size_t size, size_t minsize) if (mlock(sh.arena, sh.arena_size) < 0) ret = 2; #endif -#ifdef MADV_DONTDUMP +#ifndef NO_MADVISE if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0) ret = 2; #endif diff --git a/crypto/modes/asm/aes-gcm-armv8_64.pl b/crypto/modes/asm/aes-gcm-armv8_64.pl index 302b6f5a8ec8..95491fd08e5e 100755 --- a/crypto/modes/asm/aes-gcm-armv8_64.pl +++ b/crypto/modes/asm/aes-gcm-armv8_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -245,18 +245,19 @@ $code.=<<___ if ($flavour !~ /64/); ___ ######################################################################################### -# size_t aes_gcm_enc_128_kernel(const unsigned char *in, -# size_t len, -# unsigned char *out, -# const void *key, +# size_t aes_gcm_enc_128_kernel(const uint8_t * plaintext, +# uint64_t plaintext_length, +# uint8_t * ciphertext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_enc_128_kernel .type aes_gcm_enc_128_kernel,%function .align 4 aes_gcm_enc_128_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L128_enc_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -1130,18 +1131,19 @@ 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, +# size_t aes_gcm_dec_128_kernel(const uint8_t * ciphertext, +# uint64_t plaintext_length, +# uint8_t * plaintext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_dec_128_kernel .type aes_gcm_dec_128_kernel,%function .align 4 aes_gcm_dec_128_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L128_dec_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -2087,18 +2089,19 @@ 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, +# size_t aes_gcm_enc_192_kernel(const uint8_t * plaintext, +# uint64_t plaintext_length, +# uint8_t * ciphertext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_enc_192_kernel .type aes_gcm_enc_192_kernel,%function .align 4 aes_gcm_enc_192_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L192_enc_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -3023,18 +3026,19 @@ 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, +# size_t aes_gcm_dec_192_kernel(const uint8_t * ciphertext, +# uint64_t plaintext_length, +# uint8_t * plaintext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_dec_192_kernel .type aes_gcm_dec_192_kernel,%function .align 4 aes_gcm_dec_192_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L192_dec_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -4030,18 +4034,19 @@ 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, +# size_t aes_gcm_enc_256_kernel(const uint8_t * plaintext, +# uint64_t plaintext_length, +# uint8_t * ciphertext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_enc_256_kernel .type aes_gcm_enc_256_kernel,%function .align 4 aes_gcm_enc_256_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L256_enc_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -5014,18 +5019,19 @@ 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, +# size_t aes_gcm_dec_256_kernel(const uint8_t * ciphertext, +# uint64_t plaintext_length, +# uint8_t * plaintext, +# uint64_t *Xi, # unsigned char ivec[16], -# u64 *Xi); +# const void *key); # $code.=<<___; .global aes_gcm_dec_256_kernel .type aes_gcm_dec_256_kernel,%function .align 4 aes_gcm_dec_256_kernel: + AARCH64_VALID_CALL_TARGET cbz x1, .L256_dec_ret stp x19, x20, [sp, #-112]! mov x16, x4 @@ -6029,6 +6035,7 @@ ___ } $code.=<<___; +.rodata .asciz "GHASH for ARMv8, CRYPTOGAMS by " .align 2 #endif diff --git a/crypto/modes/asm/aesni-gcm-x86_64.pl b/crypto/modes/asm/aesni-gcm-x86_64.pl index eaf4d9c755fb..872e13f8f1a1 100644 --- a/crypto/modes/asm/aesni-gcm-x86_64.pl +++ b/crypto/modes/asm/aesni-gcm-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -943,6 +943,7 @@ $code.=<<___; ___ $code.=<<___; +.section .rodata align=64 .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -955,6 +956,7 @@ $code.=<<___; .Lone_lsb: .byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 .asciz "AES-NI GCM module for x86_64, CRYPTOGAMS by " +.previous .align 64 ___ if ($win64) { diff --git a/crypto/modes/asm/ghash-s390x.pl b/crypto/modes/asm/ghash-s390x.pl index ba9c5b4a4f4f..0ae6adbf6146 100644 --- a/crypto/modes/asm/ghash-s390x.pl +++ b/crypto/modes/asm/ghash-s390x.pl @@ -90,25 +90,6 @@ $code.=<<___; .align 32 gcm_gmult_4bit: ___ -$code.=<<___ if(!$softonly && 0); # hardware is slow for single block... - larl %r1,OPENSSL_s390xcap_P - lghi %r0,0 - lg %r1,S390X_KIMD+8(%r1) # load second word of kimd capabilities - # vector - tmhh %r1,0x4000 # check for function 65 - jz .Lsoft_gmult - stg %r0,16($sp) # arrange 16 bytes of zero input - stg %r0,24($sp) - lghi %r0,S390X_GHASH # function 65 - la %r1,0($Xi) # H lies right after Xi in gcm128_context - la $inp,16($sp) - lghi $len,16 - .long 0xb93e0004 # kimd %r0,$inp - brc 1,.-4 # pay attention to "partial completion" - br %r14 -.align 32 -.Lsoft_gmult: -___ $code.=<<___; stm${g} %r6,%r14,6*$SIZE_T($sp) @@ -132,10 +113,21 @@ $code.=<<___ if(!$softonly); # vector tmhh %r0,0x4000 # check for function 65 jz .Lsoft_ghash + # Do not assume this function is called from a gcm128_context. + # This is not true, e.g., for AES-GCM-SIV. + # Parameter Block: + # Chaining Value (XI) 128byte + # Key (Htable[8]) 128byte + lmg %r0,%r1,0($Xi) + stmg %r0,%r1,8($sp) + lmg %r0,%r1,8*16($Htbl) + stmg %r0,%r1,24($sp) + la %r1,8($sp) lghi %r0,S390X_GHASH # function 65 - la %r1,0($Xi) # H lies right after Xi in gcm128_context .long 0xb93e0004 # kimd %r0,$inp brc 1,.-4 # pay attention to "partial completion" + lmg %r0,%r1,8($sp) + stmg %r0,%r1,0($Xi) br %r14 .align 32 .Lsoft_ghash: diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl index 6709f96492ed..6ef8e555d0a2 100644 --- a/crypto/modes/asm/ghash-x86_64.pl +++ b/crypto/modes/asm/ghash-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -534,6 +534,7 @@ $code.=<<___; .align 16 gcm_init_clmul: .cfi_startproc + endbranch .L_init_clmul: ___ $code.=<<___ if ($win64); @@ -1027,6 +1028,7 @@ $code.=<<___; .align 32 gcm_init_avx: .cfi_startproc + endbranch ___ if ($avx) { my ($Htbl,$Xip)=@_4args; @@ -1609,6 +1611,7 @@ ___ } $code.=<<___; +.section .rodata align=64 .align 64 .Lbswap_mask: .byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 @@ -1662,6 +1665,7 @@ $code.=<<___; .asciz "GHASH for x86_64, CRYPTOGAMS by " .align 64 +.previous ___ # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame, diff --git a/crypto/modes/asm/ghashv8-armx.pl b/crypto/modes/asm/ghashv8-armx.pl index b3d94041729e..8ab7c03df160 100644 --- a/crypto/modes/asm/ghashv8-armx.pl +++ b/crypto/modes/asm/ghashv8-armx.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -107,6 +107,11 @@ $code.=<<___; .type gcm_init_v8,%function .align 4 gcm_init_v8: +___ +$code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET +___ +$code.=<<___; vld1.64 {$t1},[x1] @ load input H vmov.i8 $xC2,#0xe1 vshl.i64 $xC2,$xC2,#57 @ 0xc2.0 @@ -153,6 +158,7 @@ gcm_init_v8: ___ if ($flavour =~ /64/) { my ($t3,$Yl,$Ym,$Yh) = map("q$_",(4..7)); +my ($H3,$H34k,$H4,$H5,$H56k,$H6,$H7,$H78k,$H8) = map("q$_",(15..23)); $code.=<<___; @ calculate H^3 and H^4 @@ -187,15 +193,103 @@ $code.=<<___; vpmull.p64 $Yl,$Yl,$xC2 veor $t2,$t2,$Xh veor $t3,$t3,$Yh - veor $H, $Xl,$t2 @ H^3 - veor $H2,$Yl,$t3 @ H^4 + veor $H3, $Xl,$t2 @ H^3 + veor $H4,$Yl,$t3 @ H^4 - vext.8 $t0,$H, $H,#8 @ Karatsuba pre-processing - vext.8 $t1,$H2,$H2,#8 - veor $t0,$t0,$H - veor $t1,$t1,$H2 - vext.8 $Hhl,$t0,$t1,#8 @ pack Karatsuba pre-processed - vst1.64 {$H-$H2},[x0] @ store Htable[3..5] + vext.8 $t0,$H3, $H3,#8 @ Karatsuba pre-processing + vext.8 $t1,$H4,$H4,#8 + vext.8 $t2,$H2,$H2,#8 + veor $t0,$t0,$H3 + veor $t1,$t1,$H4 + veor $t2,$t2,$H2 + vext.8 $H34k,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$H3-$H4},[x0],#48 @ store Htable[3..5] + + @ calculate H^5 and H^6 + vpmull.p64 $Xl,$H2, $H3 + vpmull.p64 $Yl,$H3,$H3 + vpmull2.p64 $Xh,$H2, $H3 + vpmull2.p64 $Yh,$H3,$H3 + vpmull.p64 $Xm,$t0,$t2 + vpmull.p64 $Ym,$t0,$t0 + + vext.8 $t0,$Xl,$Xh,#8 @ Karatsuba post-processing + vext.8 $t1,$Yl,$Yh,#8 + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t0 + veor $t3,$Yl,$Yh + veor $Ym,$Ym,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + veor $Ym,$Ym,$t3 + vpmull.p64 $t3,$Yl,$xC2 + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Yh#lo,$Ym#hi + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vmov $Ym#hi,$Yl#lo + veor $Xl,$Xm,$t2 + veor $Yl,$Ym,$t3 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vext.8 $t3,$Yl,$Yl,#8 + vpmull.p64 $Xl,$Xl,$xC2 + vpmull.p64 $Yl,$Yl,$xC2 + veor $t2,$t2,$Xh + veor $t3,$t3,$Yh + veor $H5,$Xl,$t2 @ H^5 + veor $H6,$Yl,$t3 @ H^6 + + vext.8 $t0,$H5, $H5,#8 @ Karatsuba pre-processing + vext.8 $t1,$H6,$H6,#8 + vext.8 $t2,$H2,$H2,#8 + veor $t0,$t0,$H5 + veor $t1,$t1,$H6 + veor $t2,$t2,$H2 + vext.8 $H56k,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$H5-$H6},[x0],#48 @ store Htable[6..8] + + @ calculate H^7 and H^8 + vpmull.p64 $Xl,$H2,$H5 + vpmull.p64 $Yl,$H2,$H6 + vpmull2.p64 $Xh,$H2,$H5 + vpmull2.p64 $Yh,$H2,$H6 + vpmull.p64 $Xm,$t0,$t2 + vpmull.p64 $Ym,$t1,$t2 + + vext.8 $t0,$Xl,$Xh,#8 @ Karatsuba post-processing + vext.8 $t1,$Yl,$Yh,#8 + veor $t2,$Xl,$Xh + veor $Xm,$Xm,$t0 + veor $t3,$Yl,$Yh + veor $Ym,$Ym,$t1 + veor $Xm,$Xm,$t2 + vpmull.p64 $t2,$Xl,$xC2 @ 1st phase + veor $Ym,$Ym,$t3 + vpmull.p64 $t3,$Yl,$xC2 + + vmov $Xh#lo,$Xm#hi @ Xh|Xm - 256-bit result + vmov $Yh#lo,$Ym#hi + vmov $Xm#hi,$Xl#lo @ Xm is rotated Xl + vmov $Ym#hi,$Yl#lo + veor $Xl,$Xm,$t2 + veor $Yl,$Ym,$t3 + + vext.8 $t2,$Xl,$Xl,#8 @ 2nd phase + vext.8 $t3,$Yl,$Yl,#8 + vpmull.p64 $Xl,$Xl,$xC2 + vpmull.p64 $Yl,$Yl,$xC2 + veor $t2,$t2,$Xh + veor $t3,$t3,$Yh + veor $H7,$Xl,$t2 @ H^7 + veor $H8,$Yl,$t3 @ H^8 + + vext.8 $t0,$H7,$H7,#8 @ Karatsuba pre-processing + vext.8 $t1,$H8,$H8,#8 + veor $t0,$t0,$H7 + veor $t1,$t1,$H8 + vext.8 $H78k,$t0,$t1,#8 @ pack Karatsuba pre-processed + vst1.64 {$H7-$H8},[x0] @ store Htable[9..11] ___ } $code.=<<___; @@ -214,6 +308,11 @@ $code.=<<___; .type gcm_gmult_v8,%function .align 4 gcm_gmult_v8: +___ +$code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET +___ +$code.=<<___; vld1.64 {$t1},[$Xi] @ load Xi vmov.i8 $xC2,#0xe1 vld1.64 {$H-$Hhl},[$Htbl] @ load twisted H, ... @@ -268,6 +367,7 @@ $code.=<<___; gcm_ghash_v8: ___ $code.=<<___ if ($flavour =~ /64/); + AARCH64_VALID_CALL_TARGET cmp $len,#64 b.hs .Lgcm_ghash_v8_4x ___ @@ -710,6 +810,7 @@ ___ } $code.=<<___; +.rodata .asciz "GHASH for ARMv8, CRYPTOGAMS by " .align 2 #endif diff --git a/crypto/modes/build.info b/crypto/modes/build.info index f3558fa1a465..52d2df19c6d9 100644 --- a/crypto/modes/build.info +++ b/crypto/modes/build.info @@ -4,7 +4,7 @@ $MODESASM= IF[{- !$disabled{asm} -}] $MODESASM_x86=ghash-x86.S $MODESDEF_x86=GHASH_ASM - $MODESASM_x86_64=ghash-x86_64.s aesni-gcm-x86_64.s + $MODESASM_x86_64=ghash-x86_64.s aesni-gcm-x86_64.s aes-gcm-avx512.s $MODESDEF_x86_64=GHASH_ASM # ghash-ia64.s doesn't work on VMS @@ -24,7 +24,7 @@ IF[{- !$disabled{asm} -}] $MODESASM_armv4=ghash-armv4.S ghashv8-armx.S $MODESDEF_armv4=GHASH_ASM - $MODESASM_aarch64=ghashv8-armx.S aes-gcm-armv8_64.S + $MODESASM_aarch64=ghashv8-armx.S aes-gcm-armv8_64.S aes-gcm-armv8-unroll8_64.S $MODESDEF_aarch64= $MODESASM_parisc11=ghash-parisc.s @@ -35,11 +35,17 @@ IF[{- !$disabled{asm} -}] $MODESASM_ppc32=ghashp8-ppc.s $MODESDEF_ppc32= $MODESASM_ppc64=$MODESASM_ppc32 + IF[{- $target{sys_id} ne "AIX" && $target{sys_id} ne "MACOSX" -}] + $MODESASM_ppc64=$MODESASM_ppc32 aes-gcm-ppc.s + ENDIF $MODESDEF_ppc64=$MODESDEF_ppc32 $MODESASM_c64xplus=ghash-c64xplus.s $MODESDEF_c64xplus=GHASH_ASM + $MODESASM_riscv64=ghash-riscv64.s ghash-riscv64-zvkb-zvbc.s ghash-riscv64-zvkg.s aes-gcm-riscv64-zvkb-zvkg-zvkned.s + $MODESDEF_riscv64=GHASH_ASM + # Now that we have defined all the arch specific variables, use the # appropriate one, and define the appropriate macros IF[$MODESASM_{- $target{asm_arch} -}] @@ -49,7 +55,7 @@ IF[{- !$disabled{asm} -}] ENDIF $COMMON=cbc128.c ctr128.c cfb128.c ofb128.c gcm128.c ccm128.c xts128.c \ - wrap128.c $MODESASM + wrap128.c xts128gb.c $MODESASM SOURCE[../../libcrypto]=$COMMON \ cts128.c ocb128.c siv128.c SOURCE[../../providers/libfips.a]=$COMMON @@ -66,17 +72,25 @@ GENERATE[ghash-ia64.s]=asm/ghash-ia64.pl GENERATE[ghash-x86.S]=asm/ghash-x86.pl GENERATE[ghash-x86_64.s]=asm/ghash-x86_64.pl GENERATE[aesni-gcm-x86_64.s]=asm/aesni-gcm-x86_64.pl +GENERATE[aes-gcm-avx512.s]=asm/aes-gcm-avx512.pl GENERATE[ghash-sparcv9.S]=asm/ghash-sparcv9.pl INCLUDE[ghash-sparcv9.o]=.. GENERATE[ghash-alpha.S]=asm/ghash-alpha.pl GENERATE[ghash-parisc.s]=asm/ghash-parisc.pl GENERATE[ghashp8-ppc.s]=asm/ghashp8-ppc.pl +GENERATE[aes-gcm-ppc.s]=asm/aes-gcm-ppc.pl GENERATE[ghash-armv4.S]=asm/ghash-armv4.pl INCLUDE[ghash-armv4.o]=.. GENERATE[ghashv8-armx.S]=asm/ghashv8-armx.pl INCLUDE[ghashv8-armx.o]=.. GENERATE[aes-gcm-armv8_64.S]=asm/aes-gcm-armv8_64.pl INCLUDE[aes-gcm-armv8_64.o]=.. +GENERATE[aes-gcm-armv8-unroll8_64.S]=asm/aes-gcm-armv8-unroll8_64.pl +INCLUDE[aes-gcm-armv8-unroll8_64.o]=.. GENERATE[ghash-s390x.S]=asm/ghash-s390x.pl INCLUDE[ghash-s390x.o]=.. GENERATE[ghash-c64xplus.S]=asm/ghash-c64xplus.pl +GENERATE[ghash-riscv64.s]=asm/ghash-riscv64.pl +GENERATE[ghash-riscv64-zvkb-zvbc.s]=asm/ghash-riscv64-zvkb-zvbc.pl +GENERATE[ghash-riscv64-zvkg.s]=asm/ghash-riscv64-zvkg.pl +GENERATE[aes-gcm-riscv64-zvkb-zvkg-zvkned.s]=asm/aes-gcm-riscv64-zvkb-zvkg-zvkned.pl diff --git a/crypto/modes/gcm128.c b/crypto/modes/gcm128.c index e7e719fc0e26..366fe11215ac 100644 --- a/crypto/modes/gcm128.c +++ b/crypto/modes/gcm128.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -27,6 +27,12 @@ typedef size_t size_t_aX; # define PUTU32(p,v) *(u32 *)(p) = BSWAP4(v) #endif +/* RISC-V uses C implementation as a fallback. */ +#if defined(__riscv) +# define INCLUDE_C_GMULT_4BIT +# define INCLUDE_C_GHASH_4BIT +#endif + #define PACK(s) ((size_t)(s)<<(sizeof(size_t)*8-16)) #define REDUCE1BIT(V) do { \ if (sizeof(size_t)==8) { \ @@ -42,6 +48,9 @@ typedef size_t size_t_aX; } while(0) /*- + * + * NOTE: TABLE_BITS and all non-4bit implementations have been removed in 3.1. + * * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should * never be set to 8. 8 is effectively reserved for testing purposes. * TABLE_BITS>1 are lookup-table-driven implementations referred to as @@ -75,150 +84,8 @@ typedef size_t size_t_aX; * * Value of 1 is not appropriate for performance reasons. */ -#if TABLE_BITS==8 -static void gcm_init_8bit(u128 Htable[256], u64 H[2]) -{ - int i, j; - u128 V; - - Htable[0].hi = 0; - Htable[0].lo = 0; - V.hi = H[0]; - V.lo = H[1]; - - for (Htable[128] = V, i = 64; i > 0; i >>= 1) { - REDUCE1BIT(V); - Htable[i] = V; - } - - for (i = 2; i < 256; i <<= 1) { - u128 *Hi = Htable + i, H0 = *Hi; - for (j = 1; j < i; ++j) { - Hi[j].hi = H0.hi ^ Htable[j].hi; - Hi[j].lo = H0.lo ^ Htable[j].lo; - } - } -} - -static void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256]) -{ - u128 Z = { 0, 0 }; - const u8 *xi = (const u8 *)Xi + 15; - size_t rem, n = *xi; - DECLARE_IS_ENDIAN; - static const size_t rem_8bit[256] = { - PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246), - PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E), - PACK(0x0E10), PACK(0x0FD2), PACK(0x0D94), PACK(0x0C56), - PACK(0x0918), PACK(0x08DA), PACK(0x0A9C), PACK(0x0B5E), - PACK(0x1C20), PACK(0x1DE2), PACK(0x1FA4), PACK(0x1E66), - PACK(0x1B28), PACK(0x1AEA), PACK(0x18AC), PACK(0x196E), - PACK(0x1230), PACK(0x13F2), PACK(0x11B4), PACK(0x1076), - PACK(0x1538), PACK(0x14FA), PACK(0x16BC), PACK(0x177E), - PACK(0x3840), PACK(0x3982), PACK(0x3BC4), PACK(0x3A06), - PACK(0x3F48), PACK(0x3E8A), PACK(0x3CCC), PACK(0x3D0E), - PACK(0x3650), PACK(0x3792), PACK(0x35D4), PACK(0x3416), - PACK(0x3158), PACK(0x309A), PACK(0x32DC), PACK(0x331E), - PACK(0x2460), PACK(0x25A2), PACK(0x27E4), PACK(0x2626), - PACK(0x2368), PACK(0x22AA), PACK(0x20EC), PACK(0x212E), - PACK(0x2A70), PACK(0x2BB2), PACK(0x29F4), PACK(0x2836), - PACK(0x2D78), PACK(0x2CBA), PACK(0x2EFC), PACK(0x2F3E), - PACK(0x7080), PACK(0x7142), PACK(0x7304), PACK(0x72C6), - PACK(0x7788), PACK(0x764A), PACK(0x740C), PACK(0x75CE), - PACK(0x7E90), PACK(0x7F52), PACK(0x7D14), PACK(0x7CD6), - PACK(0x7998), PACK(0x785A), PACK(0x7A1C), PACK(0x7BDE), - PACK(0x6CA0), PACK(0x6D62), PACK(0x6F24), PACK(0x6EE6), - PACK(0x6BA8), PACK(0x6A6A), PACK(0x682C), PACK(0x69EE), - PACK(0x62B0), PACK(0x6372), PACK(0x6134), PACK(0x60F6), - PACK(0x65B8), PACK(0x647A), PACK(0x663C), PACK(0x67FE), - PACK(0x48C0), PACK(0x4902), PACK(0x4B44), PACK(0x4A86), - PACK(0x4FC8), PACK(0x4E0A), PACK(0x4C4C), PACK(0x4D8E), - PACK(0x46D0), PACK(0x4712), PACK(0x4554), PACK(0x4496), - PACK(0x41D8), PACK(0x401A), PACK(0x425C), PACK(0x439E), - PACK(0x54E0), PACK(0x5522), PACK(0x5764), PACK(0x56A6), - PACK(0x53E8), PACK(0x522A), PACK(0x506C), PACK(0x51AE), - PACK(0x5AF0), PACK(0x5B32), PACK(0x5974), PACK(0x58B6), - PACK(0x5DF8), PACK(0x5C3A), PACK(0x5E7C), PACK(0x5FBE), - PACK(0xE100), PACK(0xE0C2), PACK(0xE284), PACK(0xE346), - PACK(0xE608), PACK(0xE7CA), PACK(0xE58C), PACK(0xE44E), - PACK(0xEF10), PACK(0xEED2), PACK(0xEC94), PACK(0xED56), - PACK(0xE818), PACK(0xE9DA), PACK(0xEB9C), PACK(0xEA5E), - PACK(0xFD20), PACK(0xFCE2), PACK(0xFEA4), PACK(0xFF66), - PACK(0xFA28), PACK(0xFBEA), PACK(0xF9AC), PACK(0xF86E), - PACK(0xF330), PACK(0xF2F2), PACK(0xF0B4), PACK(0xF176), - PACK(0xF438), PACK(0xF5FA), PACK(0xF7BC), PACK(0xF67E), - PACK(0xD940), PACK(0xD882), PACK(0xDAC4), PACK(0xDB06), - PACK(0xDE48), PACK(0xDF8A), PACK(0xDDCC), PACK(0xDC0E), - PACK(0xD750), PACK(0xD692), PACK(0xD4D4), PACK(0xD516), - PACK(0xD058), PACK(0xD19A), PACK(0xD3DC), PACK(0xD21E), - PACK(0xC560), PACK(0xC4A2), PACK(0xC6E4), PACK(0xC726), - PACK(0xC268), PACK(0xC3AA), PACK(0xC1EC), PACK(0xC02E), - PACK(0xCB70), PACK(0xCAB2), PACK(0xC8F4), PACK(0xC936), - PACK(0xCC78), PACK(0xCDBA), PACK(0xCFFC), PACK(0xCE3E), - PACK(0x9180), PACK(0x9042), PACK(0x9204), PACK(0x93C6), - PACK(0x9688), PACK(0x974A), PACK(0x950C), PACK(0x94CE), - PACK(0x9F90), PACK(0x9E52), PACK(0x9C14), PACK(0x9DD6), - PACK(0x9898), PACK(0x995A), PACK(0x9B1C), PACK(0x9ADE), - PACK(0x8DA0), PACK(0x8C62), PACK(0x8E24), PACK(0x8FE6), - PACK(0x8AA8), PACK(0x8B6A), PACK(0x892C), PACK(0x88EE), - PACK(0x83B0), PACK(0x8272), PACK(0x8034), PACK(0x81F6), - PACK(0x84B8), PACK(0x857A), PACK(0x873C), PACK(0x86FE), - PACK(0xA9C0), PACK(0xA802), PACK(0xAA44), PACK(0xAB86), - PACK(0xAEC8), PACK(0xAF0A), PACK(0xAD4C), PACK(0xAC8E), - PACK(0xA7D0), PACK(0xA612), PACK(0xA454), PACK(0xA596), - PACK(0xA0D8), PACK(0xA11A), PACK(0xA35C), PACK(0xA29E), - PACK(0xB5E0), PACK(0xB422), PACK(0xB664), PACK(0xB7A6), - PACK(0xB2E8), PACK(0xB32A), PACK(0xB16C), PACK(0xB0AE), - PACK(0xBBF0), PACK(0xBA32), PACK(0xB874), PACK(0xB9B6), - PACK(0xBCF8), PACK(0xBD3A), PACK(0xBF7C), PACK(0xBEBE) - }; - - while (1) { - Z.hi ^= Htable[n].hi; - Z.lo ^= Htable[n].lo; - - if ((u8 *)Xi == xi) - break; - - n = *(--xi); - - rem = (size_t)Z.lo & 0xff; - Z.lo = (Z.hi << 56) | (Z.lo >> 8); - Z.hi = (Z.hi >> 8); - if (sizeof(size_t) == 8) - Z.hi ^= rem_8bit[rem]; - else - Z.hi ^= (u64)rem_8bit[rem] << 32; - } - - if (IS_LITTLE_ENDIAN) { -# ifdef BSWAP8 - Xi[0] = BSWAP8(Z.hi); - Xi[1] = BSWAP8(Z.lo); -# else - u8 *p = (u8 *)Xi; - u32 v; - v = (u32)(Z.hi >> 32); - PUTU32(p, v); - v = (u32)(Z.hi); - PUTU32(p + 4, v); - v = (u32)(Z.lo >> 32); - PUTU32(p + 8, v); - v = (u32)(Z.lo); - PUTU32(p + 12, v); -# endif - } else { - Xi[0] = Z.hi; - Xi[1] = Z.lo; - } -} - -# define GCM_MUL(ctx) gcm_gmult_8bit(ctx->Xi.u,ctx->Htable) - -#elif TABLE_BITS==4 - -static void gcm_init_4bit(u128 Htable[16], u64 H[2]) +static void gcm_init_4bit(u128 Htable[16], const u64 H[2]) { u128 V; # if defined(OPENSSL_SMALL_FOOTPRINT) @@ -289,7 +156,7 @@ static void gcm_init_4bit(u128 Htable[16], u64 H[2]) # endif } -# ifndef GHASH_ASM +# if !defined(GHASH_ASM) || defined(INCLUDE_C_GMULT_4BIT) static const size_t rem_4bit[16] = { PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460), PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0), @@ -364,6 +231,9 @@ static void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]) } } +# endif + +# if !defined(GHASH_ASM) || defined(INCLUDE_C_GHASH_4BIT) # if !defined(OPENSSL_SMALL_FOOTPRINT) /* * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for @@ -380,7 +250,6 @@ static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], size_t rem, nlo, nhi; DECLARE_IS_ENDIAN; -# if 1 do { cnt = 15; nlo = ((const u8 *)Xi)[15]; @@ -422,100 +291,6 @@ static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], Z.hi ^= Htable[nlo].hi; Z.lo ^= Htable[nlo].lo; } -# else - /* - * Extra 256+16 bytes per-key plus 512 bytes shared tables - * [should] give ~50% improvement... One could have PACK()-ed - * the rem_8bit even here, but the priority is to minimize - * cache footprint... - */ - u128 Hshr4[16]; /* Htable shifted right by 4 bits */ - u8 Hshl4[16]; /* Htable shifted left by 4 bits */ - static const unsigned short rem_8bit[256] = { - 0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E, - 0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E, - 0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E, - 0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E, - 0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E, - 0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E, - 0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E, - 0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E, - 0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE, - 0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE, - 0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE, - 0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE, - 0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E, - 0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E, - 0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE, - 0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE, - 0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E, - 0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E, - 0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E, - 0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E, - 0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E, - 0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E, - 0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E, - 0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E, - 0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE, - 0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE, - 0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE, - 0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE, - 0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E, - 0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E, - 0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE, - 0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE - }; - /* - * This pre-processing phase slows down procedure by approximately - * same time as it makes each loop spin faster. In other words - * single block performance is approximately same as straightforward - * "4-bit" implementation, and then it goes only faster... - */ - for (cnt = 0; cnt < 16; ++cnt) { - Z.hi = Htable[cnt].hi; - Z.lo = Htable[cnt].lo; - Hshr4[cnt].lo = (Z.hi << 60) | (Z.lo >> 4); - Hshr4[cnt].hi = (Z.hi >> 4); - Hshl4[cnt] = (u8)(Z.lo << 4); - } - - do { - for (Z.lo = 0, Z.hi = 0, cnt = 15; cnt; --cnt) { - nlo = ((const u8 *)Xi)[cnt]; - nlo ^= inp[cnt]; - nhi = nlo >> 4; - nlo &= 0xf; - - Z.hi ^= Htable[nlo].hi; - Z.lo ^= Htable[nlo].lo; - - rem = (size_t)Z.lo & 0xff; - - Z.lo = (Z.hi << 56) | (Z.lo >> 8); - Z.hi = (Z.hi >> 8); - - Z.hi ^= Hshr4[nhi].hi; - Z.lo ^= Hshr4[nhi].lo; - Z.hi ^= (u64)rem_8bit[rem ^ Hshl4[nhi]] << 48; - } - - nlo = ((const u8 *)Xi)[0]; - nlo ^= inp[0]; - nhi = nlo >> 4; - nlo &= 0xf; - - Z.hi ^= Htable[nlo].hi; - Z.lo ^= Htable[nlo].lo; - - rem = (size_t)Z.lo & 0xf; - - Z.lo = (Z.hi << 60) | (Z.lo >> 4); - Z.hi = (Z.hi >> 4); - - Z.hi ^= Htable[nhi].hi; - Z.lo ^= Htable[nhi].lo; - Z.hi ^= ((u64)rem_8bit[rem << 4]) << 48; -# endif if (IS_LITTLE_ENDIAN) { # ifdef BSWAP8 @@ -537,7 +312,11 @@ static void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], Xi[0] = Z.hi; Xi[1] = Z.lo; } - } while (inp += 16, len -= 16); + + inp += 16; + /* Block size is 128 bits so len is a multiple of 16 */ + len -= 16; + } while (len > 0); } # endif # else @@ -546,9 +325,9 @@ void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], const u8 *inp, size_t len); # endif -# define GCM_MUL(ctx) gcm_gmult_4bit(ctx->Xi.u,ctx->Htable) +# define GCM_MUL(ctx) ctx->funcs.gmult(ctx->Xi.u,ctx->Htable) # if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT) -# define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len) +# define GHASH(ctx,in,len) ctx->funcs.ghash((ctx)->Xi.u,(ctx)->Htable,in,len) /* * GHASH_CHUNK is "stride parameter" missioned to mitigate cache trashing * effect. In other words idea is to hash data while it's still in L1 cache @@ -557,77 +336,12 @@ void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], const u8 *inp, # define GHASH_CHUNK (3*1024) # endif -#else /* TABLE_BITS */ - -static void gcm_gmult_1bit(u64 Xi[2], const u64 H[2]) -{ - u128 V, Z = { 0, 0 }; - long X; - int i, j; - const long *xi = (const long *)Xi; - DECLARE_IS_ENDIAN; - - V.hi = H[0]; /* H is in host byte order, no byte swapping */ - V.lo = H[1]; - - for (j = 0; j < 16 / sizeof(long); ++j) { - if (IS_LITTLE_ENDIAN) { - if (sizeof(long) == 8) { -# ifdef BSWAP8 - X = (long)(BSWAP8(xi[j])); -# else - const u8 *p = (const u8 *)(xi + j); - X = (long)((u64)GETU32(p) << 32 | GETU32(p + 4)); -# endif - } else { - const u8 *p = (const u8 *)(xi + j); - X = (long)GETU32(p); - } - } else - X = xi[j]; - - for (i = 0; i < 8 * sizeof(long); ++i, X <<= 1) { - u64 M = (u64)(X >> (8 * sizeof(long) - 1)); - Z.hi ^= V.hi & M; - Z.lo ^= V.lo & M; - - REDUCE1BIT(V); - } - } - - if (IS_LITTLE_ENDIAN) { -# ifdef BSWAP8 - Xi[0] = BSWAP8(Z.hi); - Xi[1] = BSWAP8(Z.lo); -# else - u8 *p = (u8 *)Xi; - u32 v; - v = (u32)(Z.hi >> 32); - PUTU32(p, v); - v = (u32)(Z.hi); - PUTU32(p + 4, v); - v = (u32)(Z.lo >> 32); - PUTU32(p + 8, v); - v = (u32)(Z.lo); - PUTU32(p + 12, v); -# endif - } else { - Xi[0] = Z.hi; - Xi[1] = Z.lo; - } -} - -# define GCM_MUL(ctx) gcm_gmult_1bit(ctx->Xi.u,ctx->H.u) - -#endif - -#if TABLE_BITS==4 && (defined(GHASH_ASM) || defined(OPENSSL_CPUID_OBJ)) +#if (defined(GHASH_ASM) || defined(OPENSSL_CPUID_OBJ)) # if !defined(I386_ONLY) && \ (defined(__i386) || defined(__i386__) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) # define GHASH_ASM_X86_OR_64 -# define GCM_FUNCREF_4BIT void gcm_init_clmul(u128 Htable[16], const u64 Xi[2]); void gcm_gmult_clmul(u64 Xi[2], const u128 Htable[16]); @@ -655,11 +369,10 @@ void gcm_gmult_4bit_x86(u64 Xi[2], const u128 Htable[16]); void gcm_ghash_4bit_x86(u64 Xi[2], const u128 Htable[16], const u8 *inp, size_t len); # endif -# elif defined(__arm__) || defined(__arm) || defined(__aarch64__) +# elif defined(__arm__) || defined(__arm) || defined(__aarch64__) || defined(_M_ARM64) # include "arm_arch.h" # if __ARM_MAX_ARCH__>=7 # define GHASH_ASM_ARM -# define GCM_FUNCREF_4BIT # define PMULL_CAPABLE (OPENSSL_armcap_P & ARMV8_PMULL) # if defined(__arm__) || defined(__arm) # define NEON_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) @@ -676,30 +389,215 @@ void gcm_ghash_v8(u64 Xi[2], const u128 Htable[16], const u8 *inp, # elif defined(__sparc__) || defined(__sparc) # include "crypto/sparc_arch.h" # define GHASH_ASM_SPARC -# define GCM_FUNCREF_4BIT void gcm_init_vis3(u128 Htable[16], const u64 Xi[2]); void gcm_gmult_vis3(u64 Xi[2], const u128 Htable[16]); void gcm_ghash_vis3(u64 Xi[2], const u128 Htable[16], const u8 *inp, size_t len); -# elif defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)) +# elif defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)) # include "crypto/ppc_arch.h" # define GHASH_ASM_PPC -# define GCM_FUNCREF_4BIT void gcm_init_p8(u128 Htable[16], const u64 Xi[2]); void gcm_gmult_p8(u64 Xi[2], const u128 Htable[16]); void gcm_ghash_p8(u64 Xi[2], const u128 Htable[16], const u8 *inp, size_t len); +# elif defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +# include "crypto/riscv_arch.h" +# define GHASH_ASM_RV64I +/* Zbc/Zbkc (scalar crypto with clmul) based routines. */ +void gcm_init_rv64i_zbc(u128 Htable[16], const u64 Xi[2]); +void gcm_init_rv64i_zbc__zbb(u128 Htable[16], const u64 Xi[2]); +void gcm_init_rv64i_zbc__zbkb(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_rv64i_zbc(u64 Xi[2], const u128 Htable[16]); +void gcm_gmult_rv64i_zbc__zbkb(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_rv64i_zbc(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len); +void gcm_ghash_rv64i_zbc__zbkb(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len); +/* zvkb/Zvbc (vector crypto with vclmul) based routines. */ +void gcm_init_rv64i_zvkb_zvbc(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_rv64i_zvkb_zvbc(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_rv64i_zvkb_zvbc(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len); +/* Zvkg (vector crypto with vgmul.vv and vghsh.vv). */ +void gcm_init_rv64i_zvkg(u128 Htable[16], const u64 Xi[2]); +void gcm_init_rv64i_zvkg_zvkb(u128 Htable[16], const u64 Xi[2]); +void gcm_gmult_rv64i_zvkg(u64 Xi[2], const u128 Htable[16]); +void gcm_ghash_rv64i_zvkg(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len); # endif #endif -#ifdef GCM_FUNCREF_4BIT -# undef GCM_MUL -# define GCM_MUL(ctx) (*gcm_gmult_p)(ctx->Xi.u,ctx->Htable) -# ifdef GHASH -# undef GHASH -# define GHASH(ctx,in,len) (*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len) -# endif +static void gcm_get_funcs(struct gcm_funcs_st *ctx) +{ + /* set defaults -- overridden below as needed */ + ctx->ginit = gcm_init_4bit; +#if !defined(GHASH_ASM) + ctx->gmult = gcm_gmult_4bit; +#else + ctx->gmult = NULL; #endif +#if !defined(GHASH_ASM) && !defined(OPENSSL_SMALL_FOOTPRINT) + ctx->ghash = gcm_ghash_4bit; +#else + ctx->ghash = NULL; +#endif + +#if defined(GHASH_ASM_X86_OR_64) +# if !defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2) + /* x86_64 */ + if (OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */ + if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */ + ctx->ginit = gcm_init_avx; + ctx->gmult = gcm_gmult_avx; + ctx->ghash = gcm_ghash_avx; + } else { + ctx->ginit = gcm_init_clmul; + ctx->gmult = gcm_gmult_clmul; + ctx->ghash = gcm_ghash_clmul; + } + return; + } +# endif +# if defined(GHASH_ASM_X86) + /* x86 only */ +# if defined(OPENSSL_IA32_SSE2) + if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */ + ctx->gmult = gcm_gmult_4bit_mmx; + ctx->ghash = gcm_ghash_4bit_mmx; + return; + } +# else + if (OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */ + ctx->gmult = gcm_gmult_4bit_mmx; + ctx->ghash = gcm_ghash_4bit_mmx; + return; + } +# endif + ctx->gmult = gcm_gmult_4bit_x86; + ctx->ghash = gcm_ghash_4bit_x86; + return; +# else + /* x86_64 fallback defaults */ + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; + return; +# endif +#elif defined(GHASH_ASM_ARM) + /* ARM defaults */ + ctx->gmult = gcm_gmult_4bit; +# if !defined(OPENSSL_SMALL_FOOTPRINT) + ctx->ghash = gcm_ghash_4bit; +# else + ctx->ghash = NULL; +# endif +# ifdef PMULL_CAPABLE + if (PMULL_CAPABLE) { + ctx->ginit = (gcm_init_fn)gcm_init_v8; + ctx->gmult = gcm_gmult_v8; + ctx->ghash = gcm_ghash_v8; + } +# elif defined(NEON_CAPABLE) + if (NEON_CAPABLE) { + ctx->ginit = gcm_init_neon; + ctx->gmult = gcm_gmult_neon; + ctx->ghash = gcm_ghash_neon; + } +# endif + return; +#elif defined(GHASH_ASM_SPARC) + /* SPARC defaults */ + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; + if (OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) { + ctx->ginit = gcm_init_vis3; + ctx->gmult = gcm_gmult_vis3; + ctx->ghash = gcm_ghash_vis3; + } + return; +#elif defined(GHASH_ASM_PPC) + /* PowerPC does not define GHASH_ASM; defaults set above */ + if (OPENSSL_ppccap_P & PPC_CRYPTO207) { + ctx->ginit = gcm_init_p8; + ctx->gmult = gcm_gmult_p8; + ctx->ghash = gcm_ghash_p8; + } + return; +#elif defined(GHASH_ASM_RV64I) + /* RISCV defaults */ + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; + + if (RISCV_HAS_ZVKG() && riscv_vlen() >= 128) { + if (RISCV_HAS_ZVKB()) + ctx->ginit = gcm_init_rv64i_zvkg_zvkb; + else + ctx->ginit = gcm_init_rv64i_zvkg; + ctx->gmult = gcm_gmult_rv64i_zvkg; + ctx->ghash = gcm_ghash_rv64i_zvkg; + } else if (RISCV_HAS_ZVKB() && RISCV_HAS_ZVBC() && riscv_vlen() >= 128) { + ctx->ginit = gcm_init_rv64i_zvkb_zvbc; + ctx->gmult = gcm_gmult_rv64i_zvkb_zvbc; + ctx->ghash = gcm_ghash_rv64i_zvkb_zvbc; + } else if (RISCV_HAS_ZBC()) { + if (RISCV_HAS_ZBKB()) { + ctx->ginit = gcm_init_rv64i_zbc__zbkb; + ctx->gmult = gcm_gmult_rv64i_zbc__zbkb; + ctx->ghash = gcm_ghash_rv64i_zbc__zbkb; + } else if (RISCV_HAS_ZBB()) { + ctx->ginit = gcm_init_rv64i_zbc__zbb; + ctx->gmult = gcm_gmult_rv64i_zbc; + ctx->ghash = gcm_ghash_rv64i_zbc; + } else { + ctx->ginit = gcm_init_rv64i_zbc; + ctx->gmult = gcm_gmult_rv64i_zbc; + ctx->ghash = gcm_ghash_rv64i_zbc; + } + } + return; +#elif defined(GHASH_ASM) + /* all other architectures use the generic names */ + ctx->gmult = gcm_gmult_4bit; + ctx->ghash = gcm_ghash_4bit; + return; +#endif +} + +void ossl_gcm_init_4bit(u128 Htable[16], const u64 H[2]) +{ + struct gcm_funcs_st funcs; + + gcm_get_funcs(&funcs); + funcs.ginit(Htable, H); +} + +void ossl_gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]) +{ + struct gcm_funcs_st funcs; + + gcm_get_funcs(&funcs); + funcs.gmult(Xi, Htable); +} + +void ossl_gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], + const u8 *inp, size_t len) +{ + struct gcm_funcs_st funcs; + u64 tmp[2]; + size_t i; + + gcm_get_funcs(&funcs); + if (funcs.ghash != NULL) { + funcs.ghash(Xi, Htable, inp, len); + } else { + /* Emulate ghash if needed */ + for (i = 0; i < len; i += 16) { + memcpy(tmp, &inp[i], sizeof(tmp)); + Xi[0] ^= tmp[0]; + Xi[1] ^= tmp[1]; + funcs.gmult(Xi, Htable); + } + } +} void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block) { @@ -725,91 +623,9 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block) ctx->H.u[1] = lo; #endif } -#if TABLE_BITS==8 - gcm_init_8bit(ctx->Htable, ctx->H.u); -#elif TABLE_BITS==4 -# if defined(GHASH) -# define CTX__GHASH(f) (ctx->ghash = (f)) -# else -# define CTX__GHASH(f) (ctx->ghash = NULL) -# endif -# if defined(GHASH_ASM_X86_OR_64) -# if !defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2) - if (OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */ - if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */ - gcm_init_avx(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_avx; - CTX__GHASH(gcm_ghash_avx); - } else { - gcm_init_clmul(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_clmul; - CTX__GHASH(gcm_ghash_clmul); - } - return; - } -# endif - gcm_init_4bit(ctx->Htable, ctx->H.u); -# if defined(GHASH_ASM_X86) /* x86 only */ -# if defined(OPENSSL_IA32_SSE2) - if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */ -# else - if (OPENSSL_ia32cap_P[0] & (1 << 23)) { /* check MMX bit */ -# endif - ctx->gmult = gcm_gmult_4bit_mmx; - CTX__GHASH(gcm_ghash_4bit_mmx); - } else { - ctx->gmult = gcm_gmult_4bit_x86; - CTX__GHASH(gcm_ghash_4bit_x86); - } -# else - ctx->gmult = gcm_gmult_4bit; - CTX__GHASH(gcm_ghash_4bit); -# endif -# elif defined(GHASH_ASM_ARM) -# ifdef PMULL_CAPABLE - if (PMULL_CAPABLE) { - gcm_init_v8(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_v8; - CTX__GHASH(gcm_ghash_v8); - } else -# endif -# ifdef NEON_CAPABLE - if (NEON_CAPABLE) { - gcm_init_neon(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_neon; - CTX__GHASH(gcm_ghash_neon); - } else -# endif - { - gcm_init_4bit(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_4bit; - CTX__GHASH(gcm_ghash_4bit); - } -# elif defined(GHASH_ASM_SPARC) - if (OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3) { - gcm_init_vis3(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_vis3; - CTX__GHASH(gcm_ghash_vis3); - } else { - gcm_init_4bit(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_4bit; - CTX__GHASH(gcm_ghash_4bit); - } -# elif defined(GHASH_ASM_PPC) - if (OPENSSL_ppccap_P & PPC_CRYPTO207) { - gcm_init_p8(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_p8; - CTX__GHASH(gcm_ghash_p8); - } else { - gcm_init_4bit(ctx->Htable, ctx->H.u); - ctx->gmult = gcm_gmult_4bit; - CTX__GHASH(gcm_ghash_4bit); - } -# else - gcm_init_4bit(ctx->Htable, ctx->H.u); -# endif -# undef CTX__GHASH -#endif + + gcm_get_funcs(&ctx->funcs); + ctx->funcs.ginit(ctx->Htable, ctx->H.u); } void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, @@ -817,9 +633,6 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, { DECLARE_IS_ENDIAN; unsigned int ctr; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -#endif ctx->len.u[0] = 0; /* AAD length */ ctx->len.u[1] = 0; /* message length */ @@ -908,13 +721,6 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, size_t i; unsigned int n; u64 alen = ctx->len.u[0]; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# ifdef GHASH - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -#endif if (ctx->len.u[1]) return -2; @@ -973,13 +779,6 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, u64 mlen = ctx->len.u[1]; block128_f block = ctx->block; void *key = ctx->key; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -#endif mlen += len; if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) @@ -1205,13 +1004,6 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, u64 mlen = ctx->len.u[1]; block128_f block = ctx->block; void *key = ctx->key; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -#endif mlen += len; if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) @@ -1447,13 +1239,6 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, size_t i; u64 mlen = ctx->len.u[1]; void *key = ctx->key; -# ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# ifdef GHASH - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -# endif mlen += len; if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) @@ -1608,13 +1393,6 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, size_t i; u64 mlen = ctx->len.u[1]; void *key = ctx->key; -# ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# ifdef GHASH - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -# endif mlen += len; if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) @@ -1770,13 +1548,6 @@ int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, DECLARE_IS_ENDIAN; u64 alen = ctx->len.u[0] << 3; u64 clen = ctx->len.u[1] << 3; -#ifdef GCM_FUNCREF_4BIT - void (*gcm_gmult_p) (u64 Xi[2], const u128 Htable[16]) = ctx->gmult; -# if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) - void (*gcm_ghash_p) (u64 Xi[2], const u128 Htable[16], - const u8 *inp, size_t len) = ctx->ghash; -# endif -#endif #if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT) u128 bitlen; diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c index b5202ba5bd56..1ae807c100d0 100644 --- a/crypto/modes/ocb128.c +++ b/crypto/modes/ocb128.c @@ -155,10 +155,8 @@ int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, memset(ctx, 0, sizeof(*ctx)); ctx->l_index = 0; ctx->max_l_index = 5; - if ((ctx->l = OPENSSL_malloc(ctx->max_l_index * 16)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((ctx->l = OPENSSL_malloc(ctx->max_l_index * 16)) == NULL) return 0; - } /* * We set both the encryption and decryption key schedules - decryption @@ -202,10 +200,8 @@ int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src, if (keydec) dest->keydec = keydec; if (src->l) { - if ((dest->l = OPENSSL_malloc(src->max_l_index * 16)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((dest->l = OPENSSL_malloc(src->max_l_index * 16)) == NULL) return 0; - } memcpy(dest->l, src->l, (src->l_index + 1) * 16); } return 1; diff --git a/crypto/modes/siv128.c b/crypto/modes/siv128.c index e6348a8d3753..72526b849eaf 100644 --- a/crypto/modes/siv128.c +++ b/crypto/modes/siv128.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -291,7 +291,7 @@ int ossl_siv128_encrypt(SIV128_CONTEXT *ctx, if (!siv128_do_encrypt(ctx->cipher_ctx, out, in, len, &q)) return 0; ctx->final_ret = 0; - return len; + return 1; } /* @@ -327,7 +327,7 @@ int ossl_siv128_decrypt(SIV128_CONTEXT *ctx, return 0; } ctx->final_ret = 0; - return len; + return 1; } /* diff --git a/crypto/o_dir.c b/crypto/o_dir.c index 6857a2e17d4f..d7f5d64d064f 100644 --- a/crypto/o_dir.c +++ b/crypto/o_dir.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include /* diff --git a/crypto/o_fopen.c b/crypto/o_fopen.c index 8095fffbe0c9..cee4eee8a9e2 100644 --- a/crypto/o_fopen.c +++ b/crypto/o_fopen.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ /* * Following definition aliases fopen to fopen64 on above mentioned * platforms. This makes it possible to open and sequentially access files - * larger than 2GB from 32-bit application. It does not allow to traverse + * larger than 2GB from 32-bit application. It does not allow one to traverse * them beyond 2GB with fseek/ftell, but on the other hand *no* 32-bit * platform permits that, not with fseek/ftell. Not to mention that breaking * 2GB limit for seeking would require surgery to *our* API. But sequential @@ -25,7 +25,7 @@ # endif # endif -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #if !defined(OPENSSL_NO_STDIO) @@ -39,8 +39,14 @@ FILE *openssl_fopen(const char *filename, const char *mode) { FILE *file = NULL; # if defined(_WIN32) && defined(CP_UTF8) - int sz, len_0 = (int)strlen(filename) + 1; + int sz, len_0; DWORD flags; +# endif + + if (filename == NULL) + return NULL; +# if defined(_WIN32) && defined(CP_UTF8) + len_0 = (int)strlen(filename) + 1; /* * Basically there are three cases to cover: a) filename is @@ -87,10 +93,8 @@ FILE *openssl_fopen(const char *filename, const char *mode) char *iterator; char lastchar; - if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((newname = OPENSSL_malloc(strlen(filename) + 1)) == NULL) return NULL; - } for (iterator = newname, lastchar = '\0'; *filename; filename++, iterator++) { diff --git a/crypto/o_init.c b/crypto/o_init.c index a0b4256f78f6..faa67071a713 100644 --- a/crypto/o_init.c +++ b/crypto/o_init.c @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include /* diff --git a/crypto/o_str.c b/crypto/o_str.c index a6598171535e..93af73561f97 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -7,13 +7,14 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include #include "crypto/ctype.h" #include "internal/cryptlib.h" #include "internal/thread_once.h" +#include "internal/to_hex.h" #define DEFAULT_SEPARATOR ':' #define CH_ZERO '\0' @@ -56,10 +57,8 @@ void *CRYPTO_memdup(const void *data, size_t siz, const char* file, int line) return NULL; ret = CRYPTO_malloc(siz, file, line); - if (ret == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } return memcpy(ret, data, siz); } @@ -92,6 +91,74 @@ size_t OPENSSL_strlcat(char *dst, const char *src, size_t size) return l + OPENSSL_strlcpy(dst, src, size); } +/** + * @brief Converts a string to an unsigned long integer. + * + * This function attempts to convert a string representation of a number + * to an unsigned long integer, given a specified base. It also provides + * error checking and reports whether the conversion was successful. + * This function is just a wrapper around the POSIX strtoul function with + * additional error checking. This implies that errno for the caller is set + * on calls to this function. + * + * @param str The string containing the representation of the number. + * @param endptr A pointer to a pointer to character. If not NULL, it is set + * to the character immediately following the number in the + * string. + * @param base The base to use for the conversion, which must be between 2, + * and 36 inclusive, or be the special value 0. If the base is 0, + * the actual base is determined by the format of the initial + * characters of the string. + * @param num A pointer to an unsigned long where the result of the + * conversion is stored. + * + * @return 1 if the conversion was successful, 0 otherwise. Conversion is + * considered unsuccessful if no digits were consumed or if an error + * occurred during conversion. + * + * @note It is the caller's responsibility to check if the conversion is + * correct based on the expected consumption of the string as reported + * by endptr. + */ +int OPENSSL_strtoul(const char *str, char **endptr, int base, + unsigned long *num) +{ + char *tmp_endptr; + char **internal_endptr = endptr == NULL ? &tmp_endptr : endptr; + + errno = 0; + + *internal_endptr = (char *)str; + + if (num == NULL) + return 0; + + if (str == NULL) + return 0; + + /* Fail on negative input */ + if (*str == '-') + return 0; + + *num = strtoul(str, internal_endptr, base); + /* + * We return error from this function under the following conditions + * 1) If strtoul itself returned an error in translation + * 2) If the caller didn't pass in an endptr value, and **internal_endptr + * doesn't point to '\0'. The implication here is that if the caller + * doesn't care how much of a string is consumed, they expect the entire + * string to be consumed. As such, no pointing to the NULL terminator + * means there was some part of the string left over after translation + * 3) If no bytes of the string were consumed + */ + if (errno != 0 || + (endptr == NULL && **internal_endptr != '\0') || + (str == *internal_endptr)) + return 0; + + return 1; +} + int OPENSSL_hexchar2int(unsigned char c) { #ifdef CHARSET_EBCDIC @@ -196,10 +263,8 @@ unsigned char *ossl_hexstr2buf_sep(const char *str, long *buflen, return NULL; } buf_n /= 2; - if ((buf = OPENSSL_malloc(buf_n)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(buf_n)) == NULL) return NULL; - } if (buflen != NULL) *buflen = 0; @@ -222,12 +287,9 @@ static int buf2hexstr_sep(char *str, size_t str_n, size_t *strlength, const unsigned char *buf, size_t buflen, const char sep) { - static const char hexdig[] = "0123456789ABCDEF"; - const unsigned char *p; char *q; - size_t i; int has_sep = (sep != CH_ZERO); - size_t len = has_sep ? buflen * 3 : 1 + buflen * 2; + size_t i, len = has_sep ? buflen * 3 : 1 + buflen * 2; if (len == 0) ++len; @@ -242,9 +304,8 @@ static int buf2hexstr_sep(char *str, size_t str_n, size_t *strlength, } q = str; - for (i = 0, p = buf; i < buflen; i++, p++) { - *q++ = hexdig[(*p >> 4) & 0xf]; - *q++ = hexdig[*p & 0xf]; + for (i = 0; i < buflen; i++) { + q += ossl_to_hex(q, buf[i]); if (has_sep) *q++ = sep; } @@ -274,10 +335,8 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep) return OPENSSL_zalloc(1); tmp_n = (sep != CH_ZERO) ? buflen * 3 : 1 + buflen * 2; - if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((tmp = OPENSSL_malloc(tmp_n)) == NULL) return NULL; - } if (buf2hexstr_sep(tmp, tmp_n, NULL, buf, buflen, sep)) return tmp; @@ -287,13 +346,13 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep) /* - * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its - * hex representation @@@ (Contents of buffer are always kept in ASCII, also - * on EBCDIC machines) + * Given a buffer of length 'buflen' return a OPENSSL_malloc'ed string with + * its hex representation @@@ (Contents of buffer are always kept in ASCII, + * also on EBCDIC machines) */ char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen) { - return ossl_buf2hexstr_sep(buf, buflen, ':'); + return ossl_buf2hexstr_sep(buf, buflen, DEFAULT_SEPARATOR); } int openssl_strerror_r(int errnum, char *buf, size_t buflen) @@ -366,3 +425,10 @@ int OPENSSL_strncasecmp(const char *s1, const char *s2, size_t n) return 0; return 0; } + +size_t ossl_to_hex(char *buf, uint8_t n) +{ + static const char hexdig[] = "0123456789ABCDEF"; + + return to_hex(buf, n, hexdig); +} diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c index 791f2b011e35..5a468bba3a2b 100644 --- a/crypto/objects/o_names.c +++ b/crypto/objects/o_names.c @@ -19,7 +19,7 @@ #include "internal/thread_once.h" #include "crypto/lhash.h" #include "obj_local.h" -#include "e_os.h" +#include "internal/e_os.h" /* * I use the ex_data stuff to manage the identifiers for the obj_name_types @@ -89,7 +89,6 @@ int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) { name_funcs = OPENSSL_zalloc(sizeof(*name_funcs)); if (name_funcs == NULL) { - ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); ret = 0; goto out; } @@ -98,7 +97,7 @@ int OBJ_NAME_new_index(unsigned long (*hash_func) (const char *), push = sk_NAME_FUNCS_push(name_funcs_stack, name_funcs); if (!push) { - ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB); OPENSSL_free(name_funcs); ret = 0; goto out; diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c index dc501cbb8b22..8bc4fa8ec2d5 100644 --- a/crypto/objects/obj_dat.c +++ b/crypto/objects/obj_dat.c @@ -11,6 +11,8 @@ #include "crypto/ctype.h" #include #include "internal/cryptlib.h" +#include "internal/thread_once.h" +#include "internal/tsan_assist.h" #include #include #include "crypto/objects.h" @@ -18,7 +20,7 @@ #include "crypto/asn1.h" #include "obj_local.h" -/* obj_dat.h is generated from objects.h by obj_dat.pl */ +/* obj_dat.h is generated from objects.txt and obj_mac.{num,h} by obj_dat.pl */ #include "obj_dat.h" DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); @@ -35,8 +37,72 @@ struct added_obj_st { ASN1_OBJECT *obj; }; -static int new_nid = NUM_NID; static LHASH_OF(ADDED_OBJ) *added = NULL; +static CRYPTO_RWLOCK *ossl_obj_lock = NULL; +#ifdef TSAN_REQUIRES_LOCKING +static CRYPTO_RWLOCK *ossl_obj_nid_lock = NULL; +#endif + +static CRYPTO_ONCE ossl_obj_lock_init = CRYPTO_ONCE_STATIC_INIT; + +static ossl_inline void objs_free_locks(void) +{ + CRYPTO_THREAD_lock_free(ossl_obj_lock); + ossl_obj_lock = NULL; +#ifdef TSAN_REQUIRES_LOCKING + CRYPTO_THREAD_lock_free(ossl_obj_nid_lock); + ossl_obj_nid_lock = NULL; +#endif +} + +DEFINE_RUN_ONCE_STATIC(obj_lock_initialise) +{ + ossl_obj_lock = CRYPTO_THREAD_lock_new(); + if (ossl_obj_lock == NULL) + return 0; + +#ifdef TSAN_REQUIRES_LOCKING + ossl_obj_nid_lock = CRYPTO_THREAD_lock_new(); + if (ossl_obj_nid_lock == NULL) { + objs_free_locks(); + return 0; + } +#endif + return 1; +} + +static ossl_inline int ossl_init_added_lock(void) +{ +#ifndef OPENSSL_NO_AUTOLOAD_CONFIG + /* Make sure we've loaded config before checking for any "added" objects */ + OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); +#endif + return RUN_ONCE(&ossl_obj_lock_init, obj_lock_initialise); +} + +static ossl_inline int ossl_obj_write_lock(int lock) +{ + if (!lock) + return 1; + if (!ossl_init_added_lock()) + return 0; + return CRYPTO_THREAD_write_lock(ossl_obj_lock); +} + +static ossl_inline int ossl_obj_read_lock(int lock) +{ + if (!lock) + return 1; + if (!ossl_init_added_lock()) + return 0; + return CRYPTO_THREAD_read_lock(ossl_obj_lock); +} + +static ossl_inline void ossl_obj_unlock(int lock) +{ + if (lock) + CRYPTO_THREAD_unlock(ossl_obj_lock); +} static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b) { @@ -123,14 +189,6 @@ static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb) } } -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; @@ -152,65 +210,117 @@ static void cleanup3_doall(ADDED_OBJ *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; + if (added != NULL) { + 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; + } + objs_free_locks(); } -int OBJ_new_nid(int num) +/* + * Requires that the ossl_obj_lock be held + * if TSAN_REQUIRES_LOCKING defined + */ +static int obj_new_nid_unlocked(int num) { + static TSAN_QUALIFIER int new_nid = NUM_NID; +#ifdef TSAN_REQUIRES_LOCKING int i; i = new_nid; new_nid += num; + return i; +#else + return tsan_add(&new_nid, num); +#endif } -int OBJ_add_object(const ASN1_OBJECT *obj) +int OBJ_new_nid(int num) { - ASN1_OBJECT *o; - ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop; +#ifdef TSAN_REQUIRES_LOCKING + int i; + + if (!ossl_obj_write_lock(1)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); + return NID_undef; + } + + i = obj_new_nid_unlocked(num); + + ossl_obj_unlock(1); + + return i; +#else + return obj_new_nid_unlocked(num); +#endif +} + +static int ossl_obj_add_object(const ASN1_OBJECT *obj, int lock) +{ + ASN1_OBJECT *o = NULL; + ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop[4]; 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) + return NID_undef; + if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL + || (o->length != 0 + && obj->data != NULL + && (ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + || (o->sn != NULL + && (ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL) + || (o->ln != NULL + && (ao[ADDED_LNAME] = 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; + + if (!ossl_obj_write_lock(lock)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); + goto err2; + } + if (added == NULL) { + added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp); + if (added == NULL) { + ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB); + goto err; + } + } 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); + aop[i] = lh_ADDED_OBJ_retrieve(added, ao[i]); + if (aop[i] != NULL) + aop[i]->type = -1; + (void)lh_ADDED_OBJ_insert(added, ao[i]); + if (lh_ADDED_OBJ_error(added)) { + if (aop[i] != NULL) + aop[i]->type = i; + while (i-- > ADDED_DATA) { + lh_ADDED_OBJ_delete(added, ao[i]); + if (aop[i] != NULL) + aop[i]->type = i; + } + ERR_raise(ERR_LIB_OBJ, ERR_R_CRYPTO_LIB); + goto err; + } } } o->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA); + ossl_obj_unlock(lock); return o->nid; - err2: - ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); + err: + ossl_obj_unlock(lock); + err2: for (i = ADDED_DATA; i <= ADDED_NID; i++) OPENSSL_free(ao[i]); ASN1_OBJECT_free(o); @@ -219,27 +329,23 @@ int OBJ_add_object(const ASN1_OBJECT *obj) ASN1_OBJECT *OBJ_nid2obj(int n) { - ADDED_OBJ ad, *adp; + ADDED_OBJ ad, *adp = NULL; 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; - } + if (n == NID_undef + || (n > 0 && n < NUM_NID && nid_objs[n].nid != NID_undef)) 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 (!ossl_obj_read_lock(1)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return NULL; + } + if (added != NULL) + adp = lh_ADDED_OBJ_retrieve(added, &ad); + ossl_obj_unlock(1); if (adp != NULL) return adp->obj; @@ -249,62 +355,16 @@ ASN1_OBJECT *OBJ_nid2obj(int n) const char *OBJ_nid2sn(int n) { - ADDED_OBJ ad, *adp; - ASN1_OBJECT ob; + ASN1_OBJECT *ob = OBJ_nid2obj(n); - 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; + return ob == NULL ? NULL : ob->sn; } const char *OBJ_nid2ln(int n) { - ADDED_OBJ ad, *adp; - ASN1_OBJECT ob; + ASN1_OBJECT *ob = OBJ_nid2obj(n); - 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; + return ob == NULL ? NULL : ob->ln; } static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp) @@ -323,33 +383,35 @@ static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp) IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); -int OBJ_obj2nid(const ASN1_OBJECT *a) +static int ossl_obj_obj2nid(const ASN1_OBJECT *a, const int lock) { + int nid = NID_undef; const unsigned int *op; ADDED_OBJ ad, *adp; if (a == NULL) return NID_undef; - if (a->nid != 0) + if (a->nid != NID_undef) 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); - + op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ); + if (op != NULL) + return nid_objs[*op].nid; + if (!ossl_obj_read_lock(lock)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return NID_undef; + } if (added != NULL) { ad.type = ADDED_DATA; - ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */ + ad.obj = (ASN1_OBJECT *)a; /* casting away const is harmless here */ adp = lh_ADDED_OBJ_retrieve(added, &ad); if (adp != NULL) - return adp->obj->nid; + nid = adp->obj->nid; } - op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ); - if (op == NULL) - return NID_undef; - return nid_objs[*op].nid; + ossl_obj_unlock(lock); + return nid; } /* @@ -358,20 +420,20 @@ int OBJ_obj2nid(const ASN1_OBJECT *a) * 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; + ASN1_OBJECT *op = NULL; 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)) + 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; @@ -380,22 +442,16 @@ ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name) /* 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(); - */ + if (i <= 0) 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); + if ((buf = OPENSSL_malloc(j)) == NULL) return NULL; - } p = buf; /* Write out tag+length */ @@ -416,24 +472,23 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) unsigned long l; const unsigned char *p; char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2]; + const char *s; /* Ensure that, at every state, |buf| is NUL-terminated. */ - if (buf && buf_len > 0) + if (buf != NULL && buf_len > 0) buf[0] = '\0'; - if ((a == NULL) || (a->data == NULL)) + 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) + if (s != NULL) { + if (buf != NULL) OPENSSL_strlcpy(buf, s, buf_len); - n = strlen(s); - return n; + return (int)strlen(s); } } @@ -467,17 +522,19 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) use_bn = 0; for (;;) { unsigned char c = *p++; + len--; - if ((len == 0) && (c & 0x80)) + if (len == 0 && (c & 0x80) != 0) goto err; if (use_bn) { if (!BN_add_word(bl, c & 0x7f)) goto err; - } else + } else { l |= c & 0x7f; - if (!(c & 0x80)) + } + if ((c & 0x80) == 0) break; - if (!use_bn && (l > (ULONG_MAX >> 7L))) { + if (!use_bn && l > (ULONG_MAX >> 7L)) { if (bl == NULL && (bl = BN_new()) == NULL) goto err; if (!BN_set_word(bl, l)) @@ -487,8 +544,9 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) if (use_bn) { if (!BN_lshift(bl, bl, 7)) goto err; - } else + } else { l <<= 7L; + } } if (first) { @@ -498,13 +556,14 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) if (use_bn) { if (!BN_sub_word(bl, 80)) goto err; - } else + } else { l -= 80; + } } else { i = (int)(l / 40); l -= (long)(i * 40); } - if (buf && (buf_len > 1)) { + if (buf != NULL && buf_len > 1) { *buf++ = i + '0'; *buf = '\0'; buf_len--; @@ -518,7 +577,7 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) if (!bndec) goto err; i = strlen(bndec); - if (buf) { + if (buf != NULL) { if (buf_len > 1) { *buf++ = '.'; *buf = '\0'; @@ -539,7 +598,7 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) } else { BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l); i = strlen(tbuf); - if (buf && (buf_len > 0)) { + if (buf && buf_len > 0) { OPENSSL_strlcpy(buf, tbuf, buf_len); if (i > buf_len) { buf += buf_len; @@ -564,11 +623,13 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) int OBJ_txt2nid(const char *s) { - ASN1_OBJECT *obj; - int nid; - obj = OBJ_txt2obj(s, 0); - nid = OBJ_obj2nid(obj); - ASN1_OBJECT_free(obj); + ASN1_OBJECT *obj = OBJ_txt2obj(s, 0); + int nid = NID_undef; + + if (obj != NULL) { + nid = OBJ_obj2nid(obj); + ASN1_OBJECT_free(obj); + } return nid; } @@ -578,22 +639,25 @@ int OBJ_ln2nid(const char *s) 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); + int nid = NID_undef; o.ln = s; + op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN); + if (op != NULL) + return nid_objs[*op].nid; + if (!ossl_obj_read_lock(1)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return NID_undef; + } if (added != NULL) { ad.type = ADDED_LNAME; ad.obj = &o; adp = lh_ADDED_OBJ_retrieve(added, &ad); if (adp != NULL) - return adp->obj->nid; + nid = adp->obj->nid; } - op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN); - if (op == NULL) - return NID_undef; - return nid_objs[*op].nid; + ossl_obj_unlock(1); + return nid; } int OBJ_sn2nid(const char *s) @@ -602,22 +666,25 @@ int OBJ_sn2nid(const char *s) 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); + int nid = NID_undef; o.sn = s; + op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN); + if (op != NULL) + return nid_objs[*op].nid; + if (!ossl_obj_read_lock(1)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return NID_undef; + } if (added != NULL) { ad.type = ADDED_SNAME; ad.obj = &o; adp = lh_ADDED_OBJ_retrieve(added, &ad); if (adp != NULL) - return adp->obj->nid; + nid = adp->obj->nid; } - op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN); - if (op == NULL) - return NID_undef; - return nid_objs[*op].nid; + ossl_obj_unlock(1); + return nid; } const void *OBJ_bsearch_(const void *key, const void *base, int num, int size, @@ -714,6 +781,12 @@ int OBJ_create(const char *oid, const char *sn, const char *ln) ASN1_OBJECT *tmpoid = NULL; int ok = 0; + /* With no arguments at all, nothing can be done */ + if (oid == NULL && sn == NULL && ln == NULL) { + ERR_raise(ERR_LIB_OBJ, ERR_R_PASSED_INVALID_ARGUMENT); + return 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)) { @@ -721,30 +794,48 @@ int OBJ_create(const char *oid, const char *sn, const char *ln) return 0; } - /* Convert numerical OID string to an ASN1_OBJECT structure */ - tmpoid = OBJ_txt2obj(oid, 1); - if (tmpoid == NULL) + if (oid != NULL) { + /* Convert numerical OID string to an ASN1_OBJECT structure */ + tmpoid = OBJ_txt2obj(oid, 1); + if (tmpoid == NULL) + return 0; + } else { + /* Create a no-OID ASN1_OBJECT */ + tmpoid = ASN1_OBJECT_new(); + if (tmpoid == NULL) { + ERR_raise(ERR_LIB_OBJ, ERR_R_ASN1_LIB); + return 0; + } + } + + if (!ossl_obj_write_lock(1)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); + ASN1_OBJECT_free(tmpoid); return 0; + } /* If NID is not NID_undef then object already exists */ - if (OBJ_obj2nid(tmpoid) != NID_undef) { + if (oid != NULL + && ossl_obj_obj2nid(tmpoid, 0) != NID_undef) { ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS); goto err; } - tmpoid->nid = OBJ_new_nid(1); + tmpoid->nid = obj_new_nid_unlocked(1); + if (tmpoid->nid == NID_undef) goto err; tmpoid->sn = (char *)sn; tmpoid->ln = (char *)ln; - ok = OBJ_add_object(tmpoid); + ok = ossl_obj_add_object(tmpoid, 0); tmpoid->sn = NULL; tmpoid->ln = NULL; err: + ossl_obj_unlock(1); ASN1_OBJECT_free(tmpoid); return ok; } @@ -762,3 +853,13 @@ const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj) return NULL; return obj->data; } + +int OBJ_add_object(const ASN1_OBJECT *obj) +{ + return ossl_obj_add_object(obj, 1); +} + +int OBJ_obj2nid(const ASN1_OBJECT *a) +{ + return ossl_obj_obj2nid(a, 1); +} diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index 59d156117a00..8790de50dd6a 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by crypto/objects/obj_dat.pl * - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at @@ -10,7 +10,7 @@ */ /* Serialized OID's */ -static const unsigned char so[8076] = { +static const unsigned char so[9517] = { 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ @@ -268,7 +268,7 @@ static const unsigned char so[8076] = { 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x10, /* [ 2075] OBJ_id_mod_cmp2000 */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x02, /* [ 2083] OBJ_biometricInfo */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x03, /* [ 2091] OBJ_qcStatements */ - 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04, /* [ 2099] OBJ_ac_auditEntity */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04, /* [ 2099] OBJ_ac_auditIdentity */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x05, /* [ 2107] OBJ_ac_targeting */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x06, /* [ 2115] OBJ_aaControls */ 0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x07, /* [ 2123] OBJ_sbgp_ipAddrBlock */ @@ -1115,9 +1115,242 @@ static const unsigned char so[8076] = { 0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0D, /* [ 8045] OBJ_rpkiNotify */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x2F, /* [ 8053] OBJ_id_ct_geofeedCSVwithCRLF */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x30, /* [ 8064] OBJ_id_ct_signedChecklist */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x08, /* [ 8075] OBJ_sm4_gcm */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x09, /* [ 8083] OBJ_sm4_ccm */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x31, /* [ 8091] OBJ_id_ct_ASPA */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x32, /* [ 8102] OBJ_id_mod_cmp2000_02 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x63, /* [ 8110] OBJ_id_mod_cmp2021_88 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x64, /* [ 8118] OBJ_id_mod_cmp2021_02 */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x14, /* [ 8126] OBJ_id_it_rootCaCert */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x15, /* [ 8134] OBJ_id_it_certProfile */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x16, /* [ 8142] OBJ_id_it_crlStatusList */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x17, /* [ 8150] OBJ_id_it_crls */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x07, /* [ 8158] OBJ_id_regCtrl_altCertTemplate */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x0B, /* [ 8167] OBJ_id_regCtrl_algId */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x0C, /* [ 8176] OBJ_id_regCtrl_rsaKeyLen */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x2C, /* [ 8185] OBJ_id_aa_ets_attrCertificateRefs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x2D, /* [ 8196] OBJ_id_aa_ets_attrRevocationRefs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x34, /* [ 8207] OBJ_id_aa_CMSAlgorithmProtection */ + 0x04, /* [ 8216] OBJ_itu_t_identified_organization */ + 0x04,0x00, /* [ 8217] OBJ_etsi */ + 0x04,0x00,0x8D,0x45, /* [ 8219] OBJ_electronic_signature_standard */ + 0x04,0x00,0x8D,0x45,0x02, /* [ 8223] OBJ_ess_attributes */ + 0x04,0x00,0x8D,0x45,0x02,0x01, /* [ 8228] OBJ_id_aa_ets_mimeType */ + 0x04,0x00,0x8D,0x45,0x02,0x02, /* [ 8234] OBJ_id_aa_ets_longTermValidation */ + 0x04,0x00,0x8D,0x45,0x02,0x03, /* [ 8240] OBJ_id_aa_ets_SignaturePolicyDocument */ + 0x04,0x00,0x8D,0x45,0x02,0x04, /* [ 8246] OBJ_id_aa_ets_archiveTimestampV3 */ + 0x04,0x00,0x8D,0x45,0x02,0x05, /* [ 8252] OBJ_id_aa_ATSHashIndex */ + 0x04,0x00,0x81,0x95,0x32, /* [ 8258] OBJ_cades */ + 0x04,0x00,0x81,0x95,0x32,0x01, /* [ 8263] OBJ_cades_attributes */ + 0x04,0x00,0x81,0x95,0x32,0x01,0x01, /* [ 8269] OBJ_id_aa_ets_signerAttrV2 */ + 0x04,0x00,0x81,0x95,0x32,0x01,0x03, /* [ 8276] OBJ_id_aa_ets_sigPolicyStore */ + 0x04,0x00,0x81,0x95,0x32,0x01,0x04, /* [ 8283] OBJ_id_aa_ATSHashIndex_v2 */ + 0x04,0x00,0x81,0x95,0x32,0x01,0x05, /* [ 8290] OBJ_id_aa_ATSHashIndex_v3 */ + 0x04,0x00,0x81,0x95,0x32,0x01,0x06, /* [ 8297] OBJ_signedAssertion */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x30, /* [ 8304] OBJ_id_aa_ets_archiveTimestampV2 */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11,0x03,0x01, /* [ 8315] OBJ_hmacWithSM3 */ + 0x60,0x86,0x48,0x01,0x86,0xF9,0x66, /* [ 8325] OBJ_oracle */ + 0x60,0x86,0x48,0x01,0x86,0xF9,0x66,0xAD,0xCA,0x7B,0x01,0x01, /* [ 8332] OBJ_oracle_jdk_trustedkeyusage */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x32, /* [ 8344] OBJ_id_ct_signedTAL */ + 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x0A, /* [ 8355] OBJ_sm4_xts */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x19,0x02,0x01, /* [ 8363] OBJ_ms_ntds_obj_sid */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x19,0x02, /* [ 8373] OBJ_ms_ntds_sec_ext */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x07, /* [ 8382] OBJ_ms_cert_templ */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x15,0x0A, /* [ 8391] OBJ_ms_app_policies */ + 0x55,0x1D,0x26, /* [ 8400] OBJ_authority_attribute_identifier */ + 0x55,0x1D,0x27, /* [ 8403] OBJ_role_spec_cert_identifier */ + 0x55,0x1D,0x29, /* [ 8406] OBJ_basic_att_constraints */ + 0x55,0x1D,0x2A, /* [ 8409] OBJ_delegated_name_constraints */ + 0x55,0x1D,0x2B, /* [ 8412] OBJ_time_specification */ + 0x55,0x1D,0x30, /* [ 8415] OBJ_attribute_descriptor */ + 0x55,0x1D,0x31, /* [ 8418] OBJ_user_notice */ + 0x55,0x1D,0x32, /* [ 8421] OBJ_soa_identifier */ + 0x55,0x1D,0x34, /* [ 8424] OBJ_acceptable_cert_policies */ + 0x55,0x1D,0x39, /* [ 8427] OBJ_acceptable_privilege_policies */ + 0x55,0x1D,0x3D, /* [ 8430] OBJ_indirect_issuer */ + 0x55,0x1D,0x3E, /* [ 8433] OBJ_no_assertion */ + 0x55,0x1D,0x3F, /* [ 8436] OBJ_id_aa_issuing_distribution_point */ + 0x55,0x1D,0x40, /* [ 8439] OBJ_issued_on_behalf_of */ + 0x55,0x1D,0x41, /* [ 8442] OBJ_single_use */ + 0x55,0x1D,0x42, /* [ 8445] OBJ_group_ac */ + 0x55,0x1D,0x43, /* [ 8448] OBJ_allowed_attribute_assignments */ + 0x55,0x1D,0x44, /* [ 8451] OBJ_attribute_mappings */ + 0x55,0x1D,0x45, /* [ 8454] OBJ_holder_name_constraints */ + 0x55,0x1D,0x46, /* [ 8457] OBJ_authorization_validation */ + 0x55,0x1D,0x47, /* [ 8460] OBJ_prot_restrict */ + 0x55,0x1D,0x48, /* [ 8463] OBJ_subject_alt_public_key_info */ + 0x55,0x1D,0x49, /* [ 8466] OBJ_alt_signature_algorithm */ + 0x55,0x1D,0x4A, /* [ 8469] OBJ_alt_signature_value */ + 0x55,0x1D,0x4B, /* [ 8472] OBJ_associated_information */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x33, /* [ 8475] OBJ_id_ct_rpkiSignedPrefixList */ + 0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x04, /* [ 8486] OBJ_id_on_hardwareModuleName */ + 0x2B,0x06,0x01,0x04,0x01,0x82,0xE4,0x25,0x01, /* [ 8494] OBJ_id_kp_wisun_fan_device */ + 0x67,0x81,0x05, /* [ 8503] OBJ_tcg */ + 0x67,0x81,0x05,0x01, /* [ 8506] OBJ_tcg_tcpaSpecVersion */ + 0x67,0x81,0x05,0x02, /* [ 8510] OBJ_tcg_attribute */ + 0x67,0x81,0x05,0x03, /* [ 8514] OBJ_tcg_protocol */ + 0x67,0x81,0x05,0x04, /* [ 8518] OBJ_tcg_algorithm */ + 0x67,0x81,0x05,0x05, /* [ 8522] OBJ_tcg_platformClass */ + 0x67,0x81,0x05,0x06, /* [ 8526] OBJ_tcg_ce */ + 0x67,0x81,0x05,0x08, /* [ 8530] OBJ_tcg_kp */ + 0x67,0x81,0x05,0x0B, /* [ 8534] OBJ_tcg_ca */ + 0x67,0x81,0x05,0x11, /* [ 8538] OBJ_tcg_address */ + 0x67,0x81,0x05,0x12, /* [ 8542] OBJ_tcg_registry */ + 0x67,0x81,0x05,0x13, /* [ 8546] OBJ_tcg_traits */ + 0x67,0x81,0x05,0x05,0x01, /* [ 8550] OBJ_tcg_common */ + 0x67,0x81,0x05,0x05,0x01,0x01, /* [ 8555] OBJ_tcg_at_platformManufacturerStr */ + 0x67,0x81,0x05,0x05,0x01,0x02, /* [ 8561] OBJ_tcg_at_platformManufacturerId */ + 0x67,0x81,0x05,0x05,0x01,0x03, /* [ 8567] OBJ_tcg_at_platformConfigUri */ + 0x67,0x81,0x05,0x05,0x01,0x04, /* [ 8573] OBJ_tcg_at_platformModel */ + 0x67,0x81,0x05,0x05,0x01,0x05, /* [ 8579] OBJ_tcg_at_platformVersion */ + 0x67,0x81,0x05,0x05,0x01,0x06, /* [ 8585] OBJ_tcg_at_platformSerial */ + 0x67,0x81,0x05,0x05,0x01,0x07, /* [ 8591] OBJ_tcg_at_platformConfiguration */ + 0x67,0x81,0x05,0x05,0x01,0x08, /* [ 8597] OBJ_tcg_at_platformIdentifier */ + 0x67,0x81,0x05,0x02,0x01, /* [ 8603] OBJ_tcg_at_tpmManufacturer */ + 0x67,0x81,0x05,0x02,0x02, /* [ 8608] OBJ_tcg_at_tpmModel */ + 0x67,0x81,0x05,0x02,0x03, /* [ 8613] OBJ_tcg_at_tpmVersion */ + 0x67,0x81,0x05,0x02,0x0A, /* [ 8618] OBJ_tcg_at_securityQualities */ + 0x67,0x81,0x05,0x02,0x0B, /* [ 8623] OBJ_tcg_at_tpmProtectionProfile */ + 0x67,0x81,0x05,0x02,0x0C, /* [ 8628] OBJ_tcg_at_tpmSecurityTarget */ + 0x67,0x81,0x05,0x02,0x0D, /* [ 8633] OBJ_tcg_at_tbbProtectionProfile */ + 0x67,0x81,0x05,0x02,0x0E, /* [ 8638] OBJ_tcg_at_tbbSecurityTarget */ + 0x67,0x81,0x05,0x02,0x0F, /* [ 8643] OBJ_tcg_at_tpmIdLabel */ + 0x67,0x81,0x05,0x02,0x10, /* [ 8648] OBJ_tcg_at_tpmSpecification */ + 0x67,0x81,0x05,0x02,0x11, /* [ 8653] OBJ_tcg_at_tcgPlatformSpecification */ + 0x67,0x81,0x05,0x02,0x12, /* [ 8658] OBJ_tcg_at_tpmSecurityAssertions */ + 0x67,0x81,0x05,0x02,0x13, /* [ 8663] OBJ_tcg_at_tbbSecurityAssertions */ + 0x67,0x81,0x05,0x02,0x17, /* [ 8668] OBJ_tcg_at_tcgCredentialSpecification */ + 0x67,0x81,0x05,0x02,0x19, /* [ 8673] OBJ_tcg_at_tcgCredentialType */ + 0x67,0x81,0x05,0x02,0x1A, /* [ 8678] OBJ_tcg_at_previousPlatformCertificates */ + 0x67,0x81,0x05,0x02,0x1B, /* [ 8683] OBJ_tcg_at_tbbSecurityAssertions_v3 */ + 0x67,0x81,0x05,0x02,0x1C, /* [ 8688] OBJ_tcg_at_cryptographicAnchors */ + 0x67,0x81,0x05,0x05,0x01,0x07,0x01, /* [ 8693] OBJ_tcg_at_platformConfiguration_v1 */ + 0x67,0x81,0x05,0x05,0x01,0x07,0x02, /* [ 8700] OBJ_tcg_at_platformConfiguration_v2 */ + 0x67,0x81,0x05,0x05,0x01,0x07,0x03, /* [ 8707] OBJ_tcg_at_platformConfiguration_v3 */ + 0x67,0x81,0x05,0x05,0x01,0x07,0x04, /* [ 8714] OBJ_tcg_at_platformConfigUri_v3 */ + 0x67,0x81,0x05,0x04,0x01, /* [ 8721] OBJ_tcg_algorithm_null */ + 0x67,0x81,0x05,0x08,0x01, /* [ 8726] OBJ_tcg_kp_EKCertificate */ + 0x67,0x81,0x05,0x08,0x02, /* [ 8731] OBJ_tcg_kp_PlatformAttributeCertificate */ + 0x67,0x81,0x05,0x08,0x03, /* [ 8736] OBJ_tcg_kp_AIKCertificate */ + 0x67,0x81,0x05,0x08,0x04, /* [ 8741] OBJ_tcg_kp_PlatformKeyCertificate */ + 0x67,0x81,0x05,0x08,0x05, /* [ 8746] OBJ_tcg_kp_DeltaPlatformAttributeCertificate */ + 0x67,0x81,0x05,0x08,0x06, /* [ 8751] OBJ_tcg_kp_DeltaPlatformKeyCertificate */ + 0x67,0x81,0x05,0x08,0x07, /* [ 8756] OBJ_tcg_kp_AdditionalPlatformAttributeCertificate */ + 0x67,0x81,0x05,0x08,0x08, /* [ 8761] OBJ_tcg_kp_AdditionalPlatformKeyCertificate */ + 0x67,0x81,0x05,0x06,0x02, /* [ 8766] OBJ_tcg_ce_relevantCredentials */ + 0x67,0x81,0x05,0x06,0x03, /* [ 8771] OBJ_tcg_ce_relevantManifests */ + 0x67,0x81,0x05,0x06,0x04, /* [ 8776] OBJ_tcg_ce_virtualPlatformAttestationService */ + 0x67,0x81,0x05,0x06,0x05, /* [ 8781] OBJ_tcg_ce_migrationControllerAttestationService */ + 0x67,0x81,0x05,0x06,0x06, /* [ 8786] OBJ_tcg_ce_migrationControllerRegistrationService */ + 0x67,0x81,0x05,0x06,0x07, /* [ 8791] OBJ_tcg_ce_virtualPlatformBackupService */ + 0x67,0x81,0x05,0x03,0x01, /* [ 8796] OBJ_tcg_prt_tpmIdProtocol */ + 0x67,0x81,0x05,0x11,0x01, /* [ 8801] OBJ_tcg_address_ethernetmac */ + 0x67,0x81,0x05,0x11,0x02, /* [ 8806] OBJ_tcg_address_wlanmac */ + 0x67,0x81,0x05,0x11,0x03, /* [ 8811] OBJ_tcg_address_bluetoothmac */ + 0x67,0x81,0x05,0x12,0x03, /* [ 8816] OBJ_tcg_registry_componentClass */ + 0x67,0x81,0x05,0x12,0x03,0x01, /* [ 8821] OBJ_tcg_registry_componentClass_tcg */ + 0x67,0x81,0x05,0x12,0x03,0x02, /* [ 8827] OBJ_tcg_registry_componentClass_ietf */ + 0x67,0x81,0x05,0x12,0x03,0x03, /* [ 8833] OBJ_tcg_registry_componentClass_dmtf */ + 0x67,0x81,0x05,0x12,0x03,0x04, /* [ 8839] OBJ_tcg_registry_componentClass_pcie */ + 0x67,0x81,0x05,0x12,0x03,0x05, /* [ 8845] OBJ_tcg_registry_componentClass_disk */ + 0x67,0x81,0x05,0x0B,0x04, /* [ 8851] OBJ_tcg_cap_verifiedPlatformCertificate */ + 0x67,0x81,0x05,0x13,0x01, /* [ 8856] OBJ_tcg_tr_ID */ + 0x67,0x81,0x05,0x13,0x02, /* [ 8861] OBJ_tcg_tr_category */ + 0x67,0x81,0x05,0x13,0x03, /* [ 8866] OBJ_tcg_tr_registry */ + 0x67,0x81,0x05,0x13,0x01,0x01, /* [ 8871] OBJ_tcg_tr_ID_Boolean */ + 0x67,0x81,0x05,0x13,0x01,0x02, /* [ 8877] OBJ_tcg_tr_ID_CertificateIdentifier */ + 0x67,0x81,0x05,0x13,0x01,0x03, /* [ 8883] OBJ_tcg_tr_ID_CommonCriteria */ + 0x67,0x81,0x05,0x13,0x01,0x04, /* [ 8889] OBJ_tcg_tr_ID_componentClass */ + 0x67,0x81,0x05,0x13,0x01,0x05, /* [ 8895] OBJ_tcg_tr_ID_componentIdentifierV11 */ + 0x67,0x81,0x05,0x13,0x01,0x06, /* [ 8901] OBJ_tcg_tr_ID_FIPSLevel */ + 0x67,0x81,0x05,0x13,0x01,0x07, /* [ 8907] OBJ_tcg_tr_ID_ISO9000Level */ + 0x67,0x81,0x05,0x13,0x01,0x08, /* [ 8913] OBJ_tcg_tr_ID_networkMAC */ + 0x67,0x81,0x05,0x13,0x01,0x09, /* [ 8919] OBJ_tcg_tr_ID_OID */ + 0x67,0x81,0x05,0x13,0x01,0x0A, /* [ 8925] OBJ_tcg_tr_ID_PEN */ + 0x67,0x81,0x05,0x13,0x01,0x0B, /* [ 8931] OBJ_tcg_tr_ID_platformFirmwareCapabilities */ + 0x67,0x81,0x05,0x13,0x01,0x0C, /* [ 8937] OBJ_tcg_tr_ID_platformFirmwareSignatureVerification */ + 0x67,0x81,0x05,0x13,0x01,0x0D, /* [ 8943] OBJ_tcg_tr_ID_platformFirmwareUpdateCompliance */ + 0x67,0x81,0x05,0x13,0x01,0x0E, /* [ 8949] OBJ_tcg_tr_ID_platformHardwareCapabilities */ + 0x67,0x81,0x05,0x13,0x01,0x0F, /* [ 8955] OBJ_tcg_tr_ID_RTM */ + 0x67,0x81,0x05,0x13,0x01,0x10, /* [ 8961] OBJ_tcg_tr_ID_status */ + 0x67,0x81,0x05,0x13,0x01,0x11, /* [ 8967] OBJ_tcg_tr_ID_URI */ + 0x67,0x81,0x05,0x13,0x01,0x12, /* [ 8973] OBJ_tcg_tr_ID_UTF8String */ + 0x67,0x81,0x05,0x13,0x01,0x13, /* [ 8979] OBJ_tcg_tr_ID_IA5String */ + 0x67,0x81,0x05,0x13,0x01,0x14, /* [ 8985] OBJ_tcg_tr_ID_PEMCertString */ + 0x67,0x81,0x05,0x13,0x01,0x15, /* [ 8991] OBJ_tcg_tr_ID_PublicKey */ + 0x67,0x81,0x05,0x13,0x02,0x01, /* [ 8997] OBJ_tcg_tr_cat_platformManufacturer */ + 0x67,0x81,0x05,0x13,0x02,0x02, /* [ 9003] OBJ_tcg_tr_cat_platformModel */ + 0x67,0x81,0x05,0x13,0x02,0x03, /* [ 9009] OBJ_tcg_tr_cat_platformVersion */ + 0x67,0x81,0x05,0x13,0x02,0x04, /* [ 9015] OBJ_tcg_tr_cat_platformSerial */ + 0x67,0x81,0x05,0x13,0x02,0x05, /* [ 9021] OBJ_tcg_tr_cat_platformManufacturerIdentifier */ + 0x67,0x81,0x05,0x13,0x02,0x06, /* [ 9027] OBJ_tcg_tr_cat_platformOwnership */ + 0x67,0x81,0x05,0x13,0x02,0x07, /* [ 9033] OBJ_tcg_tr_cat_componentClass */ + 0x67,0x81,0x05,0x13,0x02,0x08, /* [ 9039] OBJ_tcg_tr_cat_componentManufacturer */ + 0x67,0x81,0x05,0x13,0x02,0x09, /* [ 9045] OBJ_tcg_tr_cat_componentModel */ + 0x67,0x81,0x05,0x13,0x02,0x0A, /* [ 9051] OBJ_tcg_tr_cat_componentSerial */ + 0x67,0x81,0x05,0x13,0x02,0x0B, /* [ 9057] OBJ_tcg_tr_cat_componentStatus */ + 0x67,0x81,0x05,0x13,0x02,0x0C, /* [ 9063] OBJ_tcg_tr_cat_componentLocation */ + 0x67,0x81,0x05,0x13,0x02,0x0D, /* [ 9069] OBJ_tcg_tr_cat_componentRevision */ + 0x67,0x81,0x05,0x13,0x02,0x0E, /* [ 9075] OBJ_tcg_tr_cat_componentFieldReplaceable */ + 0x67,0x81,0x05,0x13,0x02,0x0F, /* [ 9081] OBJ_tcg_tr_cat_EKCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x10, /* [ 9087] OBJ_tcg_tr_cat_IAKCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x11, /* [ 9093] OBJ_tcg_tr_cat_IDevIDCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x12, /* [ 9099] OBJ_tcg_tr_cat_DICECertificate */ + 0x67,0x81,0x05,0x13,0x02,0x13, /* [ 9105] OBJ_tcg_tr_cat_SPDMCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x14, /* [ 9111] OBJ_tcg_tr_cat_PEMCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x15, /* [ 9117] OBJ_tcg_tr_cat_PlatformCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x16, /* [ 9123] OBJ_tcg_tr_cat_DeltaPlatformCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x17, /* [ 9129] OBJ_tcg_tr_cat_RebasePlatformCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x18, /* [ 9135] OBJ_tcg_tr_cat_genericCertificate */ + 0x67,0x81,0x05,0x13,0x02,0x19, /* [ 9141] OBJ_tcg_tr_cat_CommonCriteria */ + 0x67,0x81,0x05,0x13,0x02,0x1A, /* [ 9147] OBJ_tcg_tr_cat_componentIdentifierV11 */ + 0x67,0x81,0x05,0x13,0x02,0x1B, /* [ 9153] OBJ_tcg_tr_cat_FIPSLevel */ + 0x67,0x81,0x05,0x13,0x02,0x1C, /* [ 9159] OBJ_tcg_tr_cat_ISO9000 */ + 0x67,0x81,0x05,0x13,0x02,0x1D, /* [ 9165] OBJ_tcg_tr_cat_networkMAC */ + 0x67,0x81,0x05,0x13,0x02,0x1E, /* [ 9171] OBJ_tcg_tr_cat_attestationProtocol */ + 0x67,0x81,0x05,0x13,0x02,0x1F, /* [ 9177] OBJ_tcg_tr_cat_PEN */ + 0x67,0x81,0x05,0x13,0x02,0x20, /* [ 9183] OBJ_tcg_tr_cat_platformFirmwareCapabilities */ + 0x67,0x81,0x05,0x13,0x02,0x21, /* [ 9189] OBJ_tcg_tr_cat_platformHardwareCapabilities */ + 0x67,0x81,0x05,0x13,0x02,0x22, /* [ 9195] OBJ_tcg_tr_cat_platformFirmwareSignatureVerification */ + 0x67,0x81,0x05,0x13,0x02,0x23, /* [ 9201] OBJ_tcg_tr_cat_platformFirmwareUpdateCompliance */ + 0x67,0x81,0x05,0x13,0x02,0x24, /* [ 9207] OBJ_tcg_tr_cat_RTM */ + 0x67,0x81,0x05,0x13,0x02,0x25, /* [ 9213] OBJ_tcg_tr_cat_PublicKey */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x04,0x01, /* [ 9219] OBJ_ML_KEM_512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x04,0x02, /* [ 9228] OBJ_ML_KEM_768 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x04,0x03, /* [ 9237] OBJ_ML_KEM_1024 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x11, /* [ 9246] OBJ_ML_DSA_44 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x12, /* [ 9255] OBJ_ML_DSA_65 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x13, /* [ 9264] OBJ_ML_DSA_87 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x14, /* [ 9273] OBJ_SLH_DSA_SHA2_128s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x15, /* [ 9282] OBJ_SLH_DSA_SHA2_128f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x16, /* [ 9291] OBJ_SLH_DSA_SHA2_192s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x17, /* [ 9300] OBJ_SLH_DSA_SHA2_192f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x18, /* [ 9309] OBJ_SLH_DSA_SHA2_256s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x19, /* [ 9318] OBJ_SLH_DSA_SHA2_256f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1A, /* [ 9327] OBJ_SLH_DSA_SHAKE_128s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1B, /* [ 9336] OBJ_SLH_DSA_SHAKE_128f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1C, /* [ 9345] OBJ_SLH_DSA_SHAKE_192s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1D, /* [ 9354] OBJ_SLH_DSA_SHAKE_192f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1E, /* [ 9363] OBJ_SLH_DSA_SHAKE_256s */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x1F, /* [ 9372] OBJ_SLH_DSA_SHAKE_256f */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x20, /* [ 9381] OBJ_HASH_ML_DSA_44_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x21, /* [ 9390] OBJ_HASH_ML_DSA_65_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x22, /* [ 9399] OBJ_HASH_ML_DSA_87_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x23, /* [ 9408] OBJ_SLH_DSA_SHA2_128s_WITH_SHA256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x24, /* [ 9417] OBJ_SLH_DSA_SHA2_128f_WITH_SHA256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x25, /* [ 9426] OBJ_SLH_DSA_SHA2_192s_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x26, /* [ 9435] OBJ_SLH_DSA_SHA2_192f_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x27, /* [ 9444] OBJ_SLH_DSA_SHA2_256s_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x28, /* [ 9453] OBJ_SLH_DSA_SHA2_256f_WITH_SHA512 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x29, /* [ 9462] OBJ_SLH_DSA_SHAKE_128s_WITH_SHAKE128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2A, /* [ 9471] OBJ_SLH_DSA_SHAKE_128f_WITH_SHAKE128 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2B, /* [ 9480] OBJ_SLH_DSA_SHAKE_192s_WITH_SHAKE256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2C, /* [ 9489] OBJ_SLH_DSA_SHAKE_192f_WITH_SHAKE256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2D, /* [ 9498] OBJ_SLH_DSA_SHAKE_256s_WITH_SHAKE256 */ + 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2E, /* [ 9507] OBJ_SLH_DSA_SHAKE_256f_WITH_SHAKE256 */ }; -#define NUM_NID 1248 +#define NUM_NID 1487 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -1406,7 +1639,7 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"id-mod-cmp2000", "id-mod-cmp2000", NID_id_mod_cmp2000, 8, &so[2075]}, {"biometricInfo", "Biometric Info", NID_biometricInfo, 8, &so[2083]}, {"qcStatements", "qcStatements", NID_qcStatements, 8, &so[2091]}, - {"ac-auditEntity", "ac-auditEntity", NID_ac_auditEntity, 8, &so[2099]}, + {"ac-auditIdentity", "X509v3 Audit Identity", NID_ac_auditIdentity, 8, &so[2099]}, {"ac-targeting", "ac-targeting", NID_ac_targeting, 8, &so[2107]}, {"aaControls", "aaControls", NID_aaControls, 8, &so[2115]}, {"sbgp-ipAddrBlock", "sbgp-ipAddrBlock", NID_sbgp_ipAddrBlock, 8, &so[2123]}, @@ -2367,9 +2600,248 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"rpkiNotify", "RPKI Notify", NID_rpkiNotify, 8, &so[8045]}, {"id-ct-geofeedCSVwithCRLF", "id-ct-geofeedCSVwithCRLF", NID_id_ct_geofeedCSVwithCRLF, 11, &so[8053]}, {"id-ct-signedChecklist", "id-ct-signedChecklist", NID_id_ct_signedChecklist, 11, &so[8064]}, + {"SM4-GCM", "sm4-gcm", NID_sm4_gcm, 8, &so[8075]}, + {"SM4-CCM", "sm4-ccm", NID_sm4_ccm, 8, &so[8083]}, + {"id-ct-ASPA", "id-ct-ASPA", NID_id_ct_ASPA, 11, &so[8091]}, + {"id-mod-cmp2000-02", "id-mod-cmp2000-02", NID_id_mod_cmp2000_02, 8, &so[8102]}, + {"id-mod-cmp2021-88", "id-mod-cmp2021-88", NID_id_mod_cmp2021_88, 8, &so[8110]}, + {"id-mod-cmp2021-02", "id-mod-cmp2021-02", NID_id_mod_cmp2021_02, 8, &so[8118]}, + {"id-it-rootCaCert", "id-it-rootCaCert", NID_id_it_rootCaCert, 8, &so[8126]}, + {"id-it-certProfile", "id-it-certProfile", NID_id_it_certProfile, 8, &so[8134]}, + {"id-it-crlStatusList", "id-it-crlStatusList", NID_id_it_crlStatusList, 8, &so[8142]}, + {"id-it-crls", "id-it-crls", NID_id_it_crls, 8, &so[8150]}, + {"id-regCtrl-altCertTemplate", "id-regCtrl-altCertTemplate", NID_id_regCtrl_altCertTemplate, 9, &so[8158]}, + {"id-regCtrl-algId", "id-regCtrl-algId", NID_id_regCtrl_algId, 9, &so[8167]}, + {"id-regCtrl-rsaKeyLen", "id-regCtrl-rsaKeyLen", NID_id_regCtrl_rsaKeyLen, 9, &so[8176]}, + {"id-aa-ets-attrCertificateRefs", "id-aa-ets-attrCertificateRefs", NID_id_aa_ets_attrCertificateRefs, 11, &so[8185]}, + {"id-aa-ets-attrRevocationRefs", "id-aa-ets-attrRevocationRefs", NID_id_aa_ets_attrRevocationRefs, 11, &so[8196]}, + {"id-aa-CMSAlgorithmProtection", "id-aa-CMSAlgorithmProtection", NID_id_aa_CMSAlgorithmProtection, 9, &so[8207]}, + {"itu-t-identified-organization", "itu-t-identified-organization", NID_itu_t_identified_organization, 1, &so[8216]}, + {"etsi", "etsi", NID_etsi, 2, &so[8217]}, + {"electronic-signature-standard", "electronic-signature-standard", NID_electronic_signature_standard, 4, &so[8219]}, + {"ess-attributes", "ess-attributes", NID_ess_attributes, 5, &so[8223]}, + {"id-aa-ets-mimeType", "id-aa-ets-mimeType", NID_id_aa_ets_mimeType, 6, &so[8228]}, + {"id-aa-ets-longTermValidation", "id-aa-ets-longTermValidation", NID_id_aa_ets_longTermValidation, 6, &so[8234]}, + {"id-aa-ets-SignaturePolicyDocument", "id-aa-ets-SignaturePolicyDocument", NID_id_aa_ets_SignaturePolicyDocument, 6, &so[8240]}, + {"id-aa-ets-archiveTimestampV3", "id-aa-ets-archiveTimestampV3", NID_id_aa_ets_archiveTimestampV3, 6, &so[8246]}, + {"id-aa-ATSHashIndex", "id-aa-ATSHashIndex", NID_id_aa_ATSHashIndex, 6, &so[8252]}, + {"cades", "cades", NID_cades, 5, &so[8258]}, + {"cades-attributes", "cades-attributes", NID_cades_attributes, 6, &so[8263]}, + {"id-aa-ets-signerAttrV2", "id-aa-ets-signerAttrV2", NID_id_aa_ets_signerAttrV2, 7, &so[8269]}, + {"id-aa-ets-sigPolicyStore", "id-aa-ets-sigPolicyStore", NID_id_aa_ets_sigPolicyStore, 7, &so[8276]}, + {"id-aa-ATSHashIndex-v2", "id-aa-ATSHashIndex-v2", NID_id_aa_ATSHashIndex_v2, 7, &so[8283]}, + {"id-aa-ATSHashIndex-v3", "id-aa-ATSHashIndex-v3", NID_id_aa_ATSHashIndex_v3, 7, &so[8290]}, + {"signedAssertion", "signedAssertion", NID_signedAssertion, 7, &so[8297]}, + {"id-aa-ets-archiveTimestampV2", "id-aa-ets-archiveTimestampV2", NID_id_aa_ets_archiveTimestampV2, 11, &so[8304]}, + {"hmacWithSM3", "hmacWithSM3", NID_hmacWithSM3, 10, &so[8315]}, + {"oracle-organization", "Oracle organization", NID_oracle, 7, &so[8325]}, + {"oracle-jdk-trustedkeyusage", "Trusted key usage (Oracle)", NID_oracle_jdk_trustedkeyusage, 12, &so[8332]}, + {"id-ct-signedTAL", "id-ct-signedTAL", NID_id_ct_signedTAL, 11, &so[8344]}, + {"brainpoolP256r1tls13", "brainpoolP256r1tls13", NID_brainpoolP256r1tls13}, + {"brainpoolP384r1tls13", "brainpoolP384r1tls13", NID_brainpoolP384r1tls13}, + {"brainpoolP512r1tls13", "brainpoolP512r1tls13", NID_brainpoolP512r1tls13}, + {"brotli", "Brotli compression", NID_brotli}, + {"zstd", "Zstandard compression", NID_zstd}, + {"SM4-XTS", "sm4-xts", NID_sm4_xts, 8, &so[8355]}, + {"ms-ntds-obj-sid", "Microsoft NTDS AD objectSid", NID_ms_ntds_obj_sid, 10, &so[8363]}, + {"ms-ntds-sec-ext", "Microsoft NTDS CA Extension", NID_ms_ntds_sec_ext, 9, &so[8373]}, + {"ms-cert-templ", "Microsoft certificate template", NID_ms_cert_templ, 9, &so[8382]}, + {"ms-app-policies", "Microsoft Application Policies Extension", NID_ms_app_policies, 9, &so[8391]}, + {"authorityAttributeIdentifier", "X509v3 Authority Attribute Identifier", NID_authority_attribute_identifier, 3, &so[8400]}, + {"roleSpecCertIdentifier", "X509v3 Role Specification Certificate Identifier", NID_role_spec_cert_identifier, 3, &so[8403]}, + {"basicAttConstraints", "X509v3 Basic Attribute Certificate Constraints", NID_basic_att_constraints, 3, &so[8406]}, + {"delegatedNameConstraints", "X509v3 Delegated Name Constraints", NID_delegated_name_constraints, 3, &so[8409]}, + {"timeSpecification", "X509v3 Time Specification", NID_time_specification, 3, &so[8412]}, + {"attributeDescriptor", "X509v3 Attribute Descriptor", NID_attribute_descriptor, 3, &so[8415]}, + {"userNotice", "X509v3 User Notice", NID_user_notice, 3, &so[8418]}, + {"sOAIdentifier", "X509v3 Source of Authority Identifier", NID_soa_identifier, 3, &so[8421]}, + {"acceptableCertPolicies", "X509v3 Acceptable Certification Policies", NID_acceptable_cert_policies, 3, &so[8424]}, + {"acceptablePrivPolicies", "X509v3 Acceptable Privilege Policies", NID_acceptable_privilege_policies, 3, &so[8427]}, + {"indirectIssuer", "X509v3 Indirect Issuer", NID_indirect_issuer, 3, &so[8430]}, + {"noAssertion", "X509v3 No Assertion", NID_no_assertion, 3, &so[8433]}, + {"aAissuingDistributionPoint", "X509v3 Attribute Authority Issuing Distribution Point", NID_id_aa_issuing_distribution_point, 3, &so[8436]}, + {"issuedOnBehalfOf", "X509v3 Issued On Behalf Of", NID_issued_on_behalf_of, 3, &so[8439]}, + {"singleUse", "X509v3 Single Use", NID_single_use, 3, &so[8442]}, + {"groupAC", "X509v3 Group Attribute Certificate", NID_group_ac, 3, &so[8445]}, + {"allowedAttributeAssignments", "X509v3 Allowed Attribute Assignments", NID_allowed_attribute_assignments, 3, &so[8448]}, + {"attributeMappings", "X509v3 Attribute Mappings", NID_attribute_mappings, 3, &so[8451]}, + {"holderNameConstraints", "X509v3 Holder Name Constraints", NID_holder_name_constraints, 3, &so[8454]}, + {"authorizationValidation", "X509v3 Authorization Validation", NID_authorization_validation, 3, &so[8457]}, + {"protRestrict", "X509v3 Protocol Restriction", NID_prot_restrict, 3, &so[8460]}, + {"subjectAltPublicKeyInfo", "X509v3 Subject Alternative Public Key Info", NID_subject_alt_public_key_info, 3, &so[8463]}, + {"altSignatureAlgorithm", "X509v3 Alternative Signature Algorithm", NID_alt_signature_algorithm, 3, &so[8466]}, + {"altSignatureValue", "X509v3 Alternative Signature Value", NID_alt_signature_value, 3, &so[8469]}, + {"associatedInformation", "X509v3 Associated Information", NID_associated_information, 3, &so[8472]}, + {"id-ct-rpkiSignedPrefixList", "id-ct-rpkiSignedPrefixList", NID_id_ct_rpkiSignedPrefixList, 11, &so[8475]}, + {"id-on-hardwareModuleName", "Hardware Module Name", NID_id_on_hardwareModuleName, 8, &so[8486]}, + {"id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)", NID_id_kp_wisun_fan_device, 9, &so[8494]}, + {"NULL", "NULL", NID_ac_auditEntity}, + {"tcg", "Trusted Computing Group", NID_tcg, 3, &so[8503]}, + {"tcg-tcpaSpecVersion", "tcg-tcpaSpecVersion", NID_tcg_tcpaSpecVersion, 4, &so[8506]}, + {"tcg-attribute", "Trusted Computing Group Attributes", NID_tcg_attribute, 4, &so[8510]}, + {"tcg-protocol", "Trusted Computing Group Protocols", NID_tcg_protocol, 4, &so[8514]}, + {"tcg-algorithm", "Trusted Computing Group Algorithms", NID_tcg_algorithm, 4, &so[8518]}, + {"tcg-platformClass", "Trusted Computing Group Platform Classes", NID_tcg_platformClass, 4, &so[8522]}, + {"tcg-ce", "Trusted Computing Group Certificate Extensions", NID_tcg_ce, 4, &so[8526]}, + {"tcg-kp", "Trusted Computing Group Key Purposes", NID_tcg_kp, 4, &so[8530]}, + {"tcg-ca", "Trusted Computing Group Certificate Policies", NID_tcg_ca, 4, &so[8534]}, + {"tcg-address", "Trusted Computing Group Address Formats", NID_tcg_address, 4, &so[8538]}, + {"tcg-registry", "Trusted Computing Group Registry", NID_tcg_registry, 4, &so[8542]}, + {"tcg-traits", "Trusted Computing Group Traits", NID_tcg_traits, 4, &so[8546]}, + {"tcg-common", "Trusted Computing Group Common", NID_tcg_common, 5, &so[8550]}, + {"tcg-at-platformManufacturerStr", "TCG Platform Manufacturer String", NID_tcg_at_platformManufacturerStr, 6, &so[8555]}, + {"tcg-at-platformManufacturerId", "TCG Platform Manufacturer ID", NID_tcg_at_platformManufacturerId, 6, &so[8561]}, + {"tcg-at-platformConfigUri", "TCG Platform Configuration URI", NID_tcg_at_platformConfigUri, 6, &so[8567]}, + {"tcg-at-platformModel", "TCG Platform Model", NID_tcg_at_platformModel, 6, &so[8573]}, + {"tcg-at-platformVersion", "TCG Platform Version", NID_tcg_at_platformVersion, 6, &so[8579]}, + {"tcg-at-platformSerial", "TCG Platform Serial Number", NID_tcg_at_platformSerial, 6, &so[8585]}, + {"tcg-at-platformConfiguration", "TCG Platform Configuration", NID_tcg_at_platformConfiguration, 6, &so[8591]}, + {"tcg-at-platformIdentifier", "TCG Platform Identifier", NID_tcg_at_platformIdentifier, 6, &so[8597]}, + {"tcg-at-tpmManufacturer", "TPM Manufacturer", NID_tcg_at_tpmManufacturer, 5, &so[8603]}, + {"tcg-at-tpmModel", "TPM Model", NID_tcg_at_tpmModel, 5, &so[8608]}, + {"tcg-at-tpmVersion", "TPM Version", NID_tcg_at_tpmVersion, 5, &so[8613]}, + {"tcg-at-securityQualities", "Security Qualities", NID_tcg_at_securityQualities, 5, &so[8618]}, + {"tcg-at-tpmProtectionProfile", "TPM Protection Profile", NID_tcg_at_tpmProtectionProfile, 5, &so[8623]}, + {"tcg-at-tpmSecurityTarget", "TPM Security Target", NID_tcg_at_tpmSecurityTarget, 5, &so[8628]}, + {"tcg-at-tbbProtectionProfile", "TBB Protection Profile", NID_tcg_at_tbbProtectionProfile, 5, &so[8633]}, + {"tcg-at-tbbSecurityTarget", "TBB Security Target", NID_tcg_at_tbbSecurityTarget, 5, &so[8638]}, + {"tcg-at-tpmIdLabel", "TPM ID Label", NID_tcg_at_tpmIdLabel, 5, &so[8643]}, + {"tcg-at-tpmSpecification", "TPM Specification", NID_tcg_at_tpmSpecification, 5, &so[8648]}, + {"tcg-at-tcgPlatformSpecification", "TPM Platform Specification", NID_tcg_at_tcgPlatformSpecification, 5, &so[8653]}, + {"tcg-at-tpmSecurityAssertions", "TPM Security Assertions", NID_tcg_at_tpmSecurityAssertions, 5, &so[8658]}, + {"tcg-at-tbbSecurityAssertions", "TBB Security Assertions", NID_tcg_at_tbbSecurityAssertions, 5, &so[8663]}, + {"tcg-at-tcgCredentialSpecification", "TCG Credential Specification", NID_tcg_at_tcgCredentialSpecification, 5, &so[8668]}, + {"tcg-at-tcgCredentialType", "TCG Credential Type", NID_tcg_at_tcgCredentialType, 5, &so[8673]}, + {"tcg-at-previousPlatformCertificates", "TCG Previous Platform Certificates", NID_tcg_at_previousPlatformCertificates, 5, &so[8678]}, + {"tcg-at-tbbSecurityAssertions-v3", "TCG TBB Security Assertions V3", NID_tcg_at_tbbSecurityAssertions_v3, 5, &so[8683]}, + {"tcg-at-cryptographicAnchors", "TCG Cryptographic Anchors", NID_tcg_at_cryptographicAnchors, 5, &so[8688]}, + {"tcg-at-platformConfiguration-v1", "Platform Configuration Version 1", NID_tcg_at_platformConfiguration_v1, 7, &so[8693]}, + {"tcg-at-platformConfiguration-v2", "Platform Configuration Version 2", NID_tcg_at_platformConfiguration_v2, 7, &so[8700]}, + {"tcg-at-platformConfiguration-v3", "Platform Configuration Version 3", NID_tcg_at_platformConfiguration_v3, 7, &so[8707]}, + {"tcg-at-platformConfigUri-v3", "Platform Configuration URI Version 3", NID_tcg_at_platformConfigUri_v3, 7, &so[8714]}, + {"tcg-algorithm-null", "TCG NULL Algorithm", NID_tcg_algorithm_null, 5, &so[8721]}, + {"tcg-kp-EKCertificate", "Endorsement Key Certificate", NID_tcg_kp_EKCertificate, 5, &so[8726]}, + {"tcg-kp-PlatformAttributeCertificate", "Platform Attribute Certificate", NID_tcg_kp_PlatformAttributeCertificate, 5, &so[8731]}, + {"tcg-kp-AIKCertificate", "Attestation Identity Key Certificate", NID_tcg_kp_AIKCertificate, 5, &so[8736]}, + {"tcg-kp-PlatformKeyCertificate", "Platform Key Certificate", NID_tcg_kp_PlatformKeyCertificate, 5, &so[8741]}, + {"tcg-kp-DeltaPlatformAttributeCertificate", "Delta Platform Attribute Certificate", NID_tcg_kp_DeltaPlatformAttributeCertificate, 5, &so[8746]}, + {"tcg-kp-DeltaPlatformKeyCertificate", "Delta Platform Key Certificate", NID_tcg_kp_DeltaPlatformKeyCertificate, 5, &so[8751]}, + {"tcg-kp-AdditionalPlatformAttributeCertificate", "Additional Platform Attribute Certificate", NID_tcg_kp_AdditionalPlatformAttributeCertificate, 5, &so[8756]}, + {"tcg-kp-AdditionalPlatformKeyCertificate", "Additional Platform Key Certificate", NID_tcg_kp_AdditionalPlatformKeyCertificate, 5, &so[8761]}, + {"tcg-ce-relevantCredentials", "Relevant Credentials", NID_tcg_ce_relevantCredentials, 5, &so[8766]}, + {"tcg-ce-relevantManifests", "Relevant Manifests", NID_tcg_ce_relevantManifests, 5, &so[8771]}, + {"tcg-ce-virtualPlatformAttestationService", "Virtual Platform Attestation Service", NID_tcg_ce_virtualPlatformAttestationService, 5, &so[8776]}, + {"tcg-ce-migrationControllerAttestationService", "Migration Controller Attestation Service", NID_tcg_ce_migrationControllerAttestationService, 5, &so[8781]}, + {"tcg-ce-migrationControllerRegistrationService", "Migration Controller Registration Service", NID_tcg_ce_migrationControllerRegistrationService, 5, &so[8786]}, + {"tcg-ce-virtualPlatformBackupService", "Virtual Platform Backup Service", NID_tcg_ce_virtualPlatformBackupService, 5, &so[8791]}, + {"tcg-prt-tpmIdProtocol", "TCG TPM Protocol", NID_tcg_prt_tpmIdProtocol, 5, &so[8796]}, + {"tcg-address-ethernetmac", "Ethernet MAC Address", NID_tcg_address_ethernetmac, 5, &so[8801]}, + {"tcg-address-wlanmac", "WLAN MAC Address", NID_tcg_address_wlanmac, 5, &so[8806]}, + {"tcg-address-bluetoothmac", "Bluetooth MAC Address", NID_tcg_address_bluetoothmac, 5, &so[8811]}, + {"tcg-registry-componentClass", "TCG Component Class", NID_tcg_registry_componentClass, 5, &so[8816]}, + {"tcg-registry-componentClass-tcg", "Trusted Computed Group Registry", NID_tcg_registry_componentClass_tcg, 6, &so[8821]}, + {"tcg-registry-componentClass-ietf", "Internet Engineering Task Force Registry", NID_tcg_registry_componentClass_ietf, 6, &so[8827]}, + {"tcg-registry-componentClass-dmtf", "Distributed Management Task Force Registry", NID_tcg_registry_componentClass_dmtf, 6, &so[8833]}, + {"tcg-registry-componentClass-pcie", "PCIE Component Class", NID_tcg_registry_componentClass_pcie, 6, &so[8839]}, + {"tcg-registry-componentClass-disk", "Disk Component Class", NID_tcg_registry_componentClass_disk, 6, &so[8845]}, + {"tcg-cap-verifiedPlatformCertificate", "TCG Verified Platform Certificate CA Policy", NID_tcg_cap_verifiedPlatformCertificate, 5, &so[8851]}, + {"tcg-tr-ID", "TCG Trait Identifiers", NID_tcg_tr_ID, 5, &so[8856]}, + {"tcg-tr-category", "TCG Trait Categories", NID_tcg_tr_category, 5, &so[8861]}, + {"tcg-tr-registry", "TCG Trait Registries", NID_tcg_tr_registry, 5, &so[8866]}, + {"tcg-tr-ID-Boolean", "Boolean Trait", NID_tcg_tr_ID_Boolean, 6, &so[8871]}, + {"tcg-tr-ID-CertificateIdentifier", "Certificate Identifier Trait", NID_tcg_tr_ID_CertificateIdentifier, 6, &so[8877]}, + {"tcg-tr-ID-CommonCriteria", "Common Criteria Trait", NID_tcg_tr_ID_CommonCriteria, 6, &so[8883]}, + {"tcg-tr-ID-componentClass", "Component Class Trait", NID_tcg_tr_ID_componentClass, 6, &so[8889]}, + {"tcg-tr-ID-componentIdentifierV11", "Component Identifier V1.1 Trait", NID_tcg_tr_ID_componentIdentifierV11, 6, &so[8895]}, + {"tcg-tr-ID-FIPSLevel", "FIPS Level Trait", NID_tcg_tr_ID_FIPSLevel, 6, &so[8901]}, + {"tcg-tr-ID-ISO9000Level", "ISO 9000 Level Trait", NID_tcg_tr_ID_ISO9000Level, 6, &so[8907]}, + {"tcg-tr-ID-networkMAC", "Network MAC Trait", NID_tcg_tr_ID_networkMAC, 6, &so[8913]}, + {"tcg-tr-ID-OID", "Object Identifier Trait", NID_tcg_tr_ID_OID, 6, &so[8919]}, + {"tcg-tr-ID-PEN", "Private Enterprise Number Trait", NID_tcg_tr_ID_PEN, 6, &so[8925]}, + {"tcg-tr-ID-platformFirmwareCapabilities", "Platform Firmware Capabilities Trait", NID_tcg_tr_ID_platformFirmwareCapabilities, 6, &so[8931]}, + {"tcg-tr-ID-platformFirmwareSignatureVerification", "Platform Firmware Signature Verification Trait", NID_tcg_tr_ID_platformFirmwareSignatureVerification, 6, &so[8937]}, + {"tcg-tr-ID-platformFirmwareUpdateCompliance", "Platform Firmware Update Compliance Trait", NID_tcg_tr_ID_platformFirmwareUpdateCompliance, 6, &so[8943]}, + {"tcg-tr-ID-platformHardwareCapabilities", "Platform Hardware Capabilities Trait", NID_tcg_tr_ID_platformHardwareCapabilities, 6, &so[8949]}, + {"tcg-tr-ID-RTM", "Root of Trust for Measurement Trait", NID_tcg_tr_ID_RTM, 6, &so[8955]}, + {"tcg-tr-ID-status", "Attribute Status Trait", NID_tcg_tr_ID_status, 6, &so[8961]}, + {"tcg-tr-ID-URI", "Uniform Resource Identifier Trait", NID_tcg_tr_ID_URI, 6, &so[8967]}, + {"tcg-tr-ID-UTF8String", "UTF8String Trait", NID_tcg_tr_ID_UTF8String, 6, &so[8973]}, + {"tcg-tr-ID-IA5String", "IA5String Trait", NID_tcg_tr_ID_IA5String, 6, &so[8979]}, + {"tcg-tr-ID-PEMCertString", "PEM-Encoded Certificate String Trait", NID_tcg_tr_ID_PEMCertString, 6, &so[8985]}, + {"tcg-tr-ID-PublicKey", "Public Key Trait", NID_tcg_tr_ID_PublicKey, 6, &so[8991]}, + {"tcg-tr-cat-platformManufacturer", "Platform Manufacturer Trait Category", NID_tcg_tr_cat_platformManufacturer, 6, &so[8997]}, + {"tcg-tr-cat-platformModel", "Platform Model Trait Category", NID_tcg_tr_cat_platformModel, 6, &so[9003]}, + {"tcg-tr-cat-platformVersion", "Platform Version Trait Category", NID_tcg_tr_cat_platformVersion, 6, &so[9009]}, + {"tcg-tr-cat-platformSerial", "Platform Serial Trait Category", NID_tcg_tr_cat_platformSerial, 6, &so[9015]}, + {"tcg-tr-cat-platformManufacturerIdentifier", "Platform Manufacturer Identifier Trait Category", NID_tcg_tr_cat_platformManufacturerIdentifier, 6, &so[9021]}, + {"tcg-tr-cat-platformOwnership", "Platform Ownership Trait Category", NID_tcg_tr_cat_platformOwnership, 6, &so[9027]}, + {"tcg-tr-cat-componentClass", "Component Class Trait Category", NID_tcg_tr_cat_componentClass, 6, &so[9033]}, + {"tcg-tr-cat-componentManufacturer", "Component Manufacturer Trait Category", NID_tcg_tr_cat_componentManufacturer, 6, &so[9039]}, + {"tcg-tr-cat-componentModel", "Component Model Trait Category", NID_tcg_tr_cat_componentModel, 6, &so[9045]}, + {"tcg-tr-cat-componentSerial", "Component Serial Trait Category", NID_tcg_tr_cat_componentSerial, 6, &so[9051]}, + {"tcg-tr-cat-componentStatus", "Component Status Trait Category", NID_tcg_tr_cat_componentStatus, 6, &so[9057]}, + {"tcg-tr-cat-componentLocation", "Component Location Trait Category", NID_tcg_tr_cat_componentLocation, 6, &so[9063]}, + {"tcg-tr-cat-componentRevision", "Component Revision Trait Category", NID_tcg_tr_cat_componentRevision, 6, &so[9069]}, + {"tcg-tr-cat-componentFieldReplaceable", "Component Field Replaceable Trait Category", NID_tcg_tr_cat_componentFieldReplaceable, 6, &so[9075]}, + {"tcg-tr-cat-EKCertificate", "EK Certificate Trait Category", NID_tcg_tr_cat_EKCertificate, 6, &so[9081]}, + {"tcg-tr-cat-IAKCertificate", "IAK Certificate Trait Category", NID_tcg_tr_cat_IAKCertificate, 6, &so[9087]}, + {"tcg-tr-cat-IDevIDCertificate", "IDevID Certificate Trait Category", NID_tcg_tr_cat_IDevIDCertificate, 6, &so[9093]}, + {"tcg-tr-cat-DICECertificate", "DICE Certificate Trait Category", NID_tcg_tr_cat_DICECertificate, 6, &so[9099]}, + {"tcg-tr-cat-SPDMCertificate", "SPDM Certificate Trait Category", NID_tcg_tr_cat_SPDMCertificate, 6, &so[9105]}, + {"tcg-tr-cat-PEMCertificate", "PEM Certificate Trait Category", NID_tcg_tr_cat_PEMCertificate, 6, &so[9111]}, + {"tcg-tr-cat-PlatformCertificate", "Platform Certificate Trait Category", NID_tcg_tr_cat_PlatformCertificate, 6, &so[9117]}, + {"tcg-tr-cat-DeltaPlatformCertificate", "Delta Platform Certificate Trait Category", NID_tcg_tr_cat_DeltaPlatformCertificate, 6, &so[9123]}, + {"tcg-tr-cat-RebasePlatformCertificate", "Rebase Platform Certificate Trait Category", NID_tcg_tr_cat_RebasePlatformCertificate, 6, &so[9129]}, + {"tcg-tr-cat-genericCertificate", "Generic Certificate Trait Category", NID_tcg_tr_cat_genericCertificate, 6, &so[9135]}, + {"tcg-tr-cat-CommonCriteria", "Common Criteria Trait Category", NID_tcg_tr_cat_CommonCriteria, 6, &so[9141]}, + {"tcg-tr-cat-componentIdentifierV11", "Component Identifier V1.1 Trait Category", NID_tcg_tr_cat_componentIdentifierV11, 6, &so[9147]}, + {"tcg-tr-cat-FIPSLevel", "FIPS Level Trait Category", NID_tcg_tr_cat_FIPSLevel, 6, &so[9153]}, + {"tcg-tr-cat-ISO9000", "ISO 9000 Trait Category", NID_tcg_tr_cat_ISO9000, 6, &so[9159]}, + {"tcg-tr-cat-networkMAC", "Network MAC Trait Category", NID_tcg_tr_cat_networkMAC, 6, &so[9165]}, + {"tcg-tr-cat-attestationProtocol", "Attestation Protocol Trait Category", NID_tcg_tr_cat_attestationProtocol, 6, &so[9171]}, + {"tcg-tr-cat-PEN", "Private Enterprise Number Trait Category", NID_tcg_tr_cat_PEN, 6, &so[9177]}, + {"tcg-tr-cat-platformFirmwareCapabilities", "Platform Firmware Capabilities Trait Category", NID_tcg_tr_cat_platformFirmwareCapabilities, 6, &so[9183]}, + {"tcg-tr-cat-platformHardwareCapabilities", "Platform Hardware Capabilities Trait Category", NID_tcg_tr_cat_platformHardwareCapabilities, 6, &so[9189]}, + {"tcg-tr-cat-platformFirmwareSignatureVerification", "Platform Firmware Signature Verification Trait Category", NID_tcg_tr_cat_platformFirmwareSignatureVerification, 6, &so[9195]}, + {"tcg-tr-cat-platformFirmwareUpdateCompliance", "Platform Firmware Update Compliance Trait Category", NID_tcg_tr_cat_platformFirmwareUpdateCompliance, 6, &so[9201]}, + {"tcg-tr-cat-RTM", "Root of Trust of Measurement Trait Category", NID_tcg_tr_cat_RTM, 6, &so[9207]}, + {"tcg-tr-cat-PublicKey", "Public Key Trait Category", NID_tcg_tr_cat_PublicKey, 6, &so[9213]}, + {"id-alg-ml-kem-512", "ML-KEM-512", NID_ML_KEM_512, 9, &so[9219]}, + {"id-alg-ml-kem-768", "ML-KEM-768", NID_ML_KEM_768, 9, &so[9228]}, + {"id-alg-ml-kem-1024", "ML-KEM-1024", NID_ML_KEM_1024, 9, &so[9237]}, + {"id-ml-dsa-44", "ML-DSA-44", NID_ML_DSA_44, 9, &so[9246]}, + {"id-ml-dsa-65", "ML-DSA-65", NID_ML_DSA_65, 9, &so[9255]}, + {"id-ml-dsa-87", "ML-DSA-87", NID_ML_DSA_87, 9, &so[9264]}, + {"id-slh-dsa-sha2-128s", "SLH-DSA-SHA2-128s", NID_SLH_DSA_SHA2_128s, 9, &so[9273]}, + {"id-slh-dsa-sha2-128f", "SLH-DSA-SHA2-128f", NID_SLH_DSA_SHA2_128f, 9, &so[9282]}, + {"id-slh-dsa-sha2-192s", "SLH-DSA-SHA2-192s", NID_SLH_DSA_SHA2_192s, 9, &so[9291]}, + {"id-slh-dsa-sha2-192f", "SLH-DSA-SHA2-192f", NID_SLH_DSA_SHA2_192f, 9, &so[9300]}, + {"id-slh-dsa-sha2-256s", "SLH-DSA-SHA2-256s", NID_SLH_DSA_SHA2_256s, 9, &so[9309]}, + {"id-slh-dsa-sha2-256f", "SLH-DSA-SHA2-256f", NID_SLH_DSA_SHA2_256f, 9, &so[9318]}, + {"id-slh-dsa-shake-128s", "SLH-DSA-SHAKE-128s", NID_SLH_DSA_SHAKE_128s, 9, &so[9327]}, + {"id-slh-dsa-shake-128f", "SLH-DSA-SHAKE-128f", NID_SLH_DSA_SHAKE_128f, 9, &so[9336]}, + {"id-slh-dsa-shake-192s", "SLH-DSA-SHAKE-192s", NID_SLH_DSA_SHAKE_192s, 9, &so[9345]}, + {"id-slh-dsa-shake-192f", "SLH-DSA-SHAKE-192f", NID_SLH_DSA_SHAKE_192f, 9, &so[9354]}, + {"id-slh-dsa-shake-256s", "SLH-DSA-SHAKE-256s", NID_SLH_DSA_SHAKE_256s, 9, &so[9363]}, + {"id-slh-dsa-shake-256f", "SLH-DSA-SHAKE-256f", NID_SLH_DSA_SHAKE_256f, 9, &so[9372]}, + {"id-hash-ml-dsa-44-with-sha512", "HASH-ML-DSA-44-WITH-SHA512", NID_HASH_ML_DSA_44_WITH_SHA512, 9, &so[9381]}, + {"id-hash-ml-dsa-65-with-sha512", "HASH-ML-DSA-65-WITH-SHA512", NID_HASH_ML_DSA_65_WITH_SHA512, 9, &so[9390]}, + {"id-hash-ml-dsa-87-with-sha512", "HASH-ML-DSA-87-WITH-SHA512", NID_HASH_ML_DSA_87_WITH_SHA512, 9, &so[9399]}, + {"id-hash-slh-dsa-sha2-128s-with-sha256", "SLH-DSA-SHA2-128s-WITH-SHA256", NID_SLH_DSA_SHA2_128s_WITH_SHA256, 9, &so[9408]}, + {"id-hash-slh-dsa-sha2-128f-with-sha256", "SLH-DSA-SHA2-128f-WITH-SHA256", NID_SLH_DSA_SHA2_128f_WITH_SHA256, 9, &so[9417]}, + {"id-hash-slh-dsa-sha2-192s-with-sha512", "SLH-DSA-SHA2-192s-WITH-SHA512", NID_SLH_DSA_SHA2_192s_WITH_SHA512, 9, &so[9426]}, + {"id-hash-slh-dsa-sha2-192f-with-sha512", "SLH-DSA-SHA2-192f-WITH-SHA512", NID_SLH_DSA_SHA2_192f_WITH_SHA512, 9, &so[9435]}, + {"id-hash-slh-dsa-sha2-256s-with-sha512", "SLH-DSA-SHA2-256s-WITH-SHA512", NID_SLH_DSA_SHA2_256s_WITH_SHA512, 9, &so[9444]}, + {"id-hash-slh-dsa-sha2-256f-with-sha512", "SLH-DSA-SHA2-256f-WITH-SHA512", NID_SLH_DSA_SHA2_256f_WITH_SHA512, 9, &so[9453]}, + {"id-hash-slh-dsa-shake-128s-with-shake128", "SLH-DSA-SHAKE-128s-WITH-SHAKE128", NID_SLH_DSA_SHAKE_128s_WITH_SHAKE128, 9, &so[9462]}, + {"id-hash-slh-dsa-shake-128f-with-shake128", "SLH-DSA-SHAKE-128f-WITH-SHAKE128", NID_SLH_DSA_SHAKE_128f_WITH_SHAKE128, 9, &so[9471]}, + {"id-hash-slh-dsa-shake-192s-with-shake256", "SLH-DSA-SHAKE-192s-WITH-SHAKE256", NID_SLH_DSA_SHAKE_192s_WITH_SHAKE256, 9, &so[9480]}, + {"id-hash-slh-dsa-shake-192f-with-shake256", "SLH-DSA-SHAKE-192f-WITH-SHAKE256", NID_SLH_DSA_SHAKE_192f_WITH_SHAKE256, 9, &so[9489]}, + {"id-hash-slh-dsa-shake-256s-with-shake256", "SLH-DSA-SHAKE-256s-WITH-SHAKE256", NID_SLH_DSA_SHAKE_256s_WITH_SHAKE256, 9, &so[9498]}, + {"id-hash-slh-dsa-shake-256f-with-shake256", "SLH-DSA-SHAKE-256f-WITH-SHAKE256", NID_SLH_DSA_SHAKE_256f_WITH_SHAKE256, 9, &so[9507]}, }; -#define NUM_SN 1239 +#define NUM_SN 1478 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -2564,6 +3036,7 @@ static const unsigned int sn_objs[NUM_SN] = { 388, /* "Mail" */ 393, /* "NULL" */ 404, /* "NULL" */ + 1323, /* "NULL" */ 57, /* "Netscape" */ 366, /* "Nonce" */ 17, /* "O" */ @@ -2648,12 +3121,15 @@ static const unsigned int sn_objs[NUM_SN] = { 1204, /* "SM2-SM3" */ 1143, /* "SM3" */ 1134, /* "SM4-CBC" */ + 1249, /* "SM4-CCM" */ 1137, /* "SM4-CFB" */ 1136, /* "SM4-CFB1" */ 1138, /* "SM4-CFB8" */ 1139, /* "SM4-CTR" */ 1133, /* "SM4-ECB" */ + 1248, /* "SM4-GCM" */ 1135, /* "SM4-OFB" */ + 1290, /* "SM4-XTS" */ 188, /* "SMIME" */ 167, /* "SMIME-CAPS" */ 100, /* "SN" */ @@ -2676,25 +3152,37 @@ static const unsigned int sn_objs[NUM_SN] = { 1206, /* "X963KDF" */ 185, /* "X9cm" */ 125, /* "ZLIB" */ + 1307, /* "aAissuingDistributionPoint" */ 478, /* "aRecord" */ 289, /* "aaControls" */ - 287, /* "ac-auditEntity" */ + 287, /* "ac-auditIdentity" */ 397, /* "ac-proxying" */ 288, /* "ac-targeting" */ + 1303, /* "acceptableCertPolicies" */ + 1304, /* "acceptablePrivPolicies" */ 368, /* "acceptableResponses" */ 446, /* "account" */ 363, /* "ad_timestamping" */ 376, /* "algorithm" */ + 1311, /* "allowedAttributeAssignments" */ + 1317, /* "altSignatureAlgorithm" */ + 1318, /* "altSignatureValue" */ 405, /* "ansi-X9-62" */ 910, /* "anyExtendedKeyUsage" */ 746, /* "anyPolicy" */ 370, /* "archiveCutoff" */ 484, /* "associatedDomain" */ + 1319, /* "associatedInformation" */ 485, /* "associatedName" */ + 1300, /* "attributeDescriptor" */ + 1312, /* "attributeMappings" */ 501, /* "audio" */ + 1295, /* "authorityAttributeIdentifier" */ 177, /* "authorityInfoAccess" */ 90, /* "authorityKeyIdentifier" */ 882, /* "authorityRevocationList" */ + 1314, /* "authorizationValidation" */ + 1297, /* "basicAttConstraints" */ 87, /* "basicConstraints" */ 365, /* "basicOCSPResponse" */ 285, /* "biometricInfo" */ @@ -2705,13 +3193,17 @@ static const unsigned int sn_objs[NUM_SN] = { 925, /* "brainpoolP224r1" */ 926, /* "brainpoolP224t1" */ 927, /* "brainpoolP256r1" */ + 1285, /* "brainpoolP256r1tls13" */ 928, /* "brainpoolP256t1" */ 929, /* "brainpoolP320r1" */ 930, /* "brainpoolP320t1" */ 931, /* "brainpoolP384r1" */ + 1286, /* "brainpoolP384r1tls13" */ 932, /* "brainpoolP384t1" */ 933, /* "brainpoolP512r1" */ + 1287, /* "brainpoolP512r1tls13" */ 934, /* "brainpoolP512t1" */ + 1288, /* "brotli" */ 494, /* "buildingName" */ 860, /* "businessCategory" */ 691, /* "c2onb191v4" */ @@ -2739,6 +3231,8 @@ static const unsigned int sn_objs[NUM_SN] = { 483, /* "cNAMERecord" */ 179, /* "caIssuers" */ 785, /* "caRepository" */ + 1273, /* "cades" */ + 1274, /* "cades-attributes" */ 1023, /* "capwapAC" */ 1024, /* "capwapWTP" */ 443, /* "caseIgnoreIA5StringSyntax" */ @@ -2780,6 +3274,7 @@ static const unsigned int sn_objs[NUM_SN] = { 495, /* "dSAQuality" */ 434, /* "data" */ 390, /* "dcobject" */ + 1298, /* "delegatedNameConstraints" */ 140, /* "deltaCRL" */ 891, /* "deltaRevocationList" */ 107, /* "description" */ @@ -2829,10 +3324,13 @@ static const unsigned int sn_objs[NUM_SN] = { 795, /* "ecdsa-with-SHA384" */ 796, /* "ecdsa-with-SHA512" */ 792, /* "ecdsa-with-Specified" */ + 1266, /* "electronic-signature-standard" */ 48, /* "emailAddress" */ 132, /* "emailProtection" */ 885, /* "enhancedSearchGuide" */ 389, /* "enterprises" */ + 1267, /* "ess-attributes" */ + 1265, /* "etsi" */ 384, /* "experimental" */ 172, /* "extReq" */ 56, /* "extendedCertificateAttributes" */ @@ -2864,6 +3362,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1010, /* "gost89-ecb" */ 812, /* "gost94" */ 850, /* "gost94cc" */ + 1310, /* "groupAC" */ 1156, /* "hmacWithDstu34311" */ 797, /* "hmacWithMD5" */ 163, /* "hmacWithSHA1" */ @@ -2873,10 +3372,12 @@ static const unsigned int sn_objs[NUM_SN] = { 801, /* "hmacWithSHA512" */ 1193, /* "hmacWithSHA512-224" */ 1194, /* "hmacWithSHA512-256" */ + 1281, /* "hmacWithSM3" */ 432, /* "holdInstructionCallIssuer" */ 430, /* "holdInstructionCode" */ 431, /* "holdInstructionNone" */ 433, /* "holdInstructionReject" */ + 1313, /* "holderNameConstraints" */ 486, /* "homePostalAddress" */ 473, /* "homeTelephoneNumber" */ 466, /* "host" */ @@ -2923,6 +3424,19 @@ static const unsigned int sn_objs[NUM_SN] = { 852, /* "id-GostR3411-94-with-GostR3410-94-cc" */ 810, /* "id-HMACGostR3411-94" */ 782, /* "id-PasswordBasedMAC" */ + 1272, /* "id-aa-ATSHashIndex" */ + 1277, /* "id-aa-ATSHashIndex-v2" */ + 1278, /* "id-aa-ATSHashIndex-v3" */ + 1263, /* "id-aa-CMSAlgorithmProtection" */ + 1270, /* "id-aa-ets-SignaturePolicyDocument" */ + 1280, /* "id-aa-ets-archiveTimestampV2" */ + 1271, /* "id-aa-ets-archiveTimestampV3" */ + 1261, /* "id-aa-ets-attrCertificateRefs" */ + 1262, /* "id-aa-ets-attrRevocationRefs" */ + 1269, /* "id-aa-ets-longTermValidation" */ + 1268, /* "id-aa-ets-mimeType" */ + 1276, /* "id-aa-ets-sigPolicyStore" */ + 1275, /* "id-aa-ets-signerAttrV2" */ 266, /* "id-aca" */ 355, /* "id-aca-accessIdentity" */ 354, /* "id-aca-authenticationInfo" */ @@ -2948,6 +3462,9 @@ static const unsigned int sn_objs[NUM_SN] = { 323, /* "id-alg-des40" */ 326, /* "id-alg-dh-pop" */ 325, /* "id-alg-dh-sig-hmac-sha1" */ + 1456, /* "id-alg-ml-kem-1024" */ + 1454, /* "id-alg-ml-kem-512" */ + 1455, /* "id-alg-ml-kem-768" */ 324, /* "id-alg-noSignature" */ 907, /* "id-camellia128-wrap" */ 908, /* "id-camellia192-wrap" */ @@ -2980,13 +3497,16 @@ static const unsigned int sn_objs[NUM_SN] = { 327, /* "id-cmc-statusInfo" */ 331, /* "id-cmc-transactionId" */ 1238, /* "id-cp" */ + 1250, /* "id-ct-ASPA" */ 787, /* "id-ct-asciiTextWithCRLF" */ 1246, /* "id-ct-geofeedCSVwithCRLF" */ 1237, /* "id-ct-resourceTaggedAttest" */ 1234, /* "id-ct-routeOriginAuthz" */ 1236, /* "id-ct-rpkiGhostbusters" */ 1235, /* "id-ct-rpkiManifest" */ + 1320, /* "id-ct-rpkiSignedPrefixList" */ 1247, /* "id-ct-signedChecklist" */ + 1284, /* "id-ct-signedTAL" */ 1060, /* "id-ct-xml" */ 1108, /* "id-dsa-with-sha3-224" */ 1109, /* "id-dsa-with-sha3-256" */ @@ -2999,6 +3519,21 @@ static const unsigned int sn_objs[NUM_SN] = { 1113, /* "id-ecdsa-with-sha3-256" */ 1114, /* "id-ecdsa-with-sha3-384" */ 1115, /* "id-ecdsa-with-sha3-512" */ + 1472, /* "id-hash-ml-dsa-44-with-sha512" */ + 1473, /* "id-hash-ml-dsa-65-with-sha512" */ + 1474, /* "id-hash-ml-dsa-87-with-sha512" */ + 1476, /* "id-hash-slh-dsa-sha2-128f-with-sha256" */ + 1475, /* "id-hash-slh-dsa-sha2-128s-with-sha256" */ + 1478, /* "id-hash-slh-dsa-sha2-192f-with-sha512" */ + 1477, /* "id-hash-slh-dsa-sha2-192s-with-sha512" */ + 1480, /* "id-hash-slh-dsa-sha2-256f-with-sha512" */ + 1479, /* "id-hash-slh-dsa-sha2-256s-with-sha512" */ + 1482, /* "id-hash-slh-dsa-shake-128f-with-shake128" */ + 1481, /* "id-hash-slh-dsa-shake-128s-with-shake128" */ + 1484, /* "id-hash-slh-dsa-shake-192f-with-shake256" */ + 1483, /* "id-hash-slh-dsa-shake-192s-with-shake256" */ + 1486, /* "id-hash-slh-dsa-shake-256f-with-shake256" */ + 1485, /* "id-hash-slh-dsa-shake-256s-with-shake256" */ 508, /* "id-hex-multipart-message" */ 507, /* "id-hex-partial-message" */ 1102, /* "id-hmacWithSHA3-224" */ @@ -3009,8 +3544,11 @@ static const unsigned int sn_objs[NUM_SN] = { 1223, /* "id-it-caCerts" */ 302, /* "id-it-caKeyUpdateInfo" */ 298, /* "id-it-caProtEncCert" */ + 1255, /* "id-it-certProfile" */ 1225, /* "id-it-certReqTemplate" */ 311, /* "id-it-confirmWaitTime" */ + 1256, /* "id-it-crlStatusList" */ + 1257, /* "id-it-crls" */ 303, /* "id-it-currentCRL" */ 300, /* "id-it-encKeyPairTypes" */ 310, /* "id-it-implicitConfirm" */ @@ -3019,6 +3557,7 @@ static const unsigned int sn_objs[NUM_SN] = { 312, /* "id-it-origPKIMessage" */ 301, /* "id-it-preferredSymmAlg" */ 309, /* "id-it-revPassphrase" */ + 1254, /* "id-it-rootCaCert" */ 1224, /* "id-it-rootCaKeyUpdate" */ 299, /* "id-it-signKeyPairTypes" */ 305, /* "id-it-subscriptionRequest" */ @@ -3028,10 +3567,17 @@ static const unsigned int sn_objs[NUM_SN] = { 128, /* "id-kp" */ 1221, /* "id-kp-BrandIndicatorforMessageIdentification" */ 1220, /* "id-kp-bgpsec-router" */ + 1322, /* "id-kp-wisun-fan-device" */ + 1457, /* "id-ml-dsa-44" */ + 1458, /* "id-ml-dsa-65" */ + 1459, /* "id-ml-dsa-87" */ 280, /* "id-mod-attribute-cert" */ 274, /* "id-mod-cmc" */ 277, /* "id-mod-cmp" */ 284, /* "id-mod-cmp2000" */ + 1251, /* "id-mod-cmp2000-02" */ + 1253, /* "id-mod-cmp2021-02" */ + 1252, /* "id-mod-cmp2021-88" */ 273, /* "id-mod-crmf" */ 283, /* "id-mod-dvcs" */ 275, /* "id-mod-kea-profile-88" */ @@ -3044,6 +3590,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1211, /* "id-on-NAIRealm" */ 1208, /* "id-on-SmtpUTF8Mailbox" */ 1210, /* "id-on-dnsSRV" */ + 1321, /* "id-on-hardwareModuleName" */ 858, /* "id-on-permanentIdentifier" */ 347, /* "id-on-personalData" */ 1209, /* "id-on-xmppAddr" */ @@ -3071,12 +3618,15 @@ static const unsigned int sn_objs[NUM_SN] = { 164, /* "id-qt-cps" */ 165, /* "id-qt-unotice" */ 313, /* "id-regCtrl" */ + 1259, /* "id-regCtrl-algId" */ + 1258, /* "id-regCtrl-altCertTemplate" */ 316, /* "id-regCtrl-authenticator" */ 319, /* "id-regCtrl-oldCertID" */ 318, /* "id-regCtrl-pkiArchiveOptions" */ 317, /* "id-regCtrl-pkiPublicationInfo" */ 320, /* "id-regCtrl-protocolEncrKey" */ 315, /* "id-regCtrl-regToken" */ + 1260, /* "id-regCtrl-rsaKeyLen" */ 314, /* "id-regInfo" */ 322, /* "id-regInfo-certReq" */ 321, /* "id-regInfo-utf8Pairs" */ @@ -3086,6 +3636,18 @@ static const unsigned int sn_objs[NUM_SN] = { 1119, /* "id-rsassa-pkcs1-v1_5-with-sha3-512" */ 973, /* "id-scrypt" */ 512, /* "id-set" */ + 1461, /* "id-slh-dsa-sha2-128f" */ + 1460, /* "id-slh-dsa-sha2-128s" */ + 1463, /* "id-slh-dsa-sha2-192f" */ + 1462, /* "id-slh-dsa-sha2-192s" */ + 1465, /* "id-slh-dsa-sha2-256f" */ + 1464, /* "id-slh-dsa-sha2-256s" */ + 1467, /* "id-slh-dsa-shake-128f" */ + 1466, /* "id-slh-dsa-shake-128s" */ + 1469, /* "id-slh-dsa-shake-192f" */ + 1468, /* "id-slh-dsa-shake-192s" */ + 1471, /* "id-slh-dsa-shake-256f" */ + 1470, /* "id-slh-dsa-shake-256s" */ 191, /* "id-smime-aa" */ 215, /* "id-smime-aa-contentHint" */ 218, /* "id-smime-aa-contentIdentifier" */ @@ -3196,6 +3758,7 @@ static const unsigned int sn_objs[NUM_SN] = { 676, /* "identified-organization" */ 1170, /* "ieee" */ 1171, /* "ieee-siswg" */ + 1305, /* "indirectIssuer" */ 461, /* "info" */ 748, /* "inhibitAnyPolicy" */ 101, /* "initials" */ @@ -3208,9 +3771,11 @@ static const unsigned int sn_objs[NUM_SN] = { 1022, /* "ipsecIKE" */ 295, /* "ipsecTunnel" */ 296, /* "ipsecUser" */ + 1308, /* "issuedOnBehalfOf" */ 86, /* "issuerAltName" */ 1008, /* "issuerSignTool" */ 770, /* "issuingDistributionPoint" */ + 1264, /* "itu-t-identified-organization" */ 492, /* "janetMailbox" */ 957, /* "jurisdictionC" */ 955, /* "jurisdictionL" */ @@ -3259,6 +3824,10 @@ static const unsigned int sn_objs[NUM_SN] = { 1215, /* "modp_4096" */ 1216, /* "modp_6144" */ 1217, /* "modp_8192" */ + 1294, /* "ms-app-policies" */ + 1293, /* "ms-cert-templ" */ + 1291, /* "ms-ntds-obj-sid" */ + 1292, /* "ms-ntds-sec-ext" */ 136, /* "msCTLSign" */ 135, /* "msCodeCom" */ 134, /* "msCodeInd" */ @@ -3271,6 +3840,7 @@ static const unsigned int sn_objs[NUM_SN] = { 481, /* "nSRecord" */ 173, /* "name" */ 666, /* "nameConstraints" */ + 1306, /* "noAssertion" */ 369, /* "noCheck" */ 403, /* "noRevAvail" */ 72, /* "nsBaseUrl" */ @@ -3286,6 +3856,8 @@ static const unsigned int sn_objs[NUM_SN] = { 139, /* "nsSGC" */ 77, /* "nsSslServerName" */ 681, /* "onBasis" */ + 1283, /* "oracle-jdk-trustedkeyusage" */ + 1282, /* "oracle-organization" */ 1089, /* "organizationIdentifier" */ 491, /* "organizationalStatus" */ 1141, /* "oscca" */ @@ -3342,6 +3914,7 @@ static const unsigned int sn_objs[NUM_SN] = { 415, /* "prime256v1" */ 385, /* "private" */ 84, /* "privateKeyUsagePeriod" */ + 1315, /* "protRestrict" */ 886, /* "protocolInformation" */ 663, /* "proxyCertInfo" */ 510, /* "pseudonym" */ @@ -3352,6 +3925,7 @@ static const unsigned int sn_objs[NUM_SN] = { 870, /* "registeredAddress" */ 400, /* "role" */ 877, /* "roleOccupant" */ + 1296, /* "roleSpecCertIdentifier" */ 448, /* "room" */ 463, /* "roomNumber" */ 1243, /* "rpkiManifest" */ @@ -3360,6 +3934,7 @@ static const unsigned int sn_objs[NUM_SN] = { 644, /* "rsaOAEPEncryptionSET" */ 377, /* "rsaSignature" */ 1, /* "rsadsi" */ + 1302, /* "sOAIdentifier" */ 482, /* "sOARecord" */ 155, /* "safeContentsBag" */ 291, /* "sbgp-autonomousSysNum" */ @@ -3544,14 +4119,17 @@ static const unsigned int sn_objs[NUM_SN] = { 604, /* "setext-pinAny" */ 603, /* "setext-pinSecure" */ 605, /* "setext-track2" */ + 1279, /* "signedAssertion" */ 1244, /* "signedObject" */ 52, /* "signingTime" */ 454, /* "simpleSecurityObject" */ 496, /* "singleLevelQuality" */ + 1309, /* "singleUse" */ 1142, /* "sm-scheme" */ 387, /* "snmpv2" */ 660, /* "street" */ 85, /* "subjectAltName" */ + 1316, /* "subjectAltPublicKeyInfo" */ 769, /* "subjectDirectoryAttributes" */ 398, /* "subjectInfoAccess" */ 82, /* "subjectKeyIdentifier" */ @@ -3561,11 +4139,142 @@ static const unsigned int sn_objs[NUM_SN] = { 890, /* "supportedAlgorithms" */ 874, /* "supportedApplicationContext" */ 402, /* "targetInformation" */ + 1324, /* "tcg" */ + 1333, /* "tcg-address" */ + 1385, /* "tcg-address-bluetoothmac" */ + 1383, /* "tcg-address-ethernetmac" */ + 1384, /* "tcg-address-wlanmac" */ + 1328, /* "tcg-algorithm" */ + 1367, /* "tcg-algorithm-null" */ + 1362, /* "tcg-at-cryptographicAnchors" */ + 1339, /* "tcg-at-platformConfigUri" */ + 1366, /* "tcg-at-platformConfigUri-v3" */ + 1343, /* "tcg-at-platformConfiguration" */ + 1363, /* "tcg-at-platformConfiguration-v1" */ + 1364, /* "tcg-at-platformConfiguration-v2" */ + 1365, /* "tcg-at-platformConfiguration-v3" */ + 1344, /* "tcg-at-platformIdentifier" */ + 1338, /* "tcg-at-platformManufacturerId" */ + 1337, /* "tcg-at-platformManufacturerStr" */ + 1340, /* "tcg-at-platformModel" */ + 1342, /* "tcg-at-platformSerial" */ + 1341, /* "tcg-at-platformVersion" */ + 1360, /* "tcg-at-previousPlatformCertificates" */ + 1348, /* "tcg-at-securityQualities" */ + 1351, /* "tcg-at-tbbProtectionProfile" */ + 1357, /* "tcg-at-tbbSecurityAssertions" */ + 1361, /* "tcg-at-tbbSecurityAssertions-v3" */ + 1352, /* "tcg-at-tbbSecurityTarget" */ + 1358, /* "tcg-at-tcgCredentialSpecification" */ + 1359, /* "tcg-at-tcgCredentialType" */ + 1355, /* "tcg-at-tcgPlatformSpecification" */ + 1353, /* "tcg-at-tpmIdLabel" */ + 1345, /* "tcg-at-tpmManufacturer" */ + 1346, /* "tcg-at-tpmModel" */ + 1349, /* "tcg-at-tpmProtectionProfile" */ + 1356, /* "tcg-at-tpmSecurityAssertions" */ + 1350, /* "tcg-at-tpmSecurityTarget" */ + 1354, /* "tcg-at-tpmSpecification" */ + 1347, /* "tcg-at-tpmVersion" */ + 1326, /* "tcg-attribute" */ + 1332, /* "tcg-ca" */ + 1392, /* "tcg-cap-verifiedPlatformCertificate" */ + 1330, /* "tcg-ce" */ + 1379, /* "tcg-ce-migrationControllerAttestationService" */ + 1380, /* "tcg-ce-migrationControllerRegistrationService" */ + 1376, /* "tcg-ce-relevantCredentials" */ + 1377, /* "tcg-ce-relevantManifests" */ + 1378, /* "tcg-ce-virtualPlatformAttestationService" */ + 1381, /* "tcg-ce-virtualPlatformBackupService" */ + 1336, /* "tcg-common" */ + 1331, /* "tcg-kp" */ + 1370, /* "tcg-kp-AIKCertificate" */ + 1374, /* "tcg-kp-AdditionalPlatformAttributeCertificate" */ + 1375, /* "tcg-kp-AdditionalPlatformKeyCertificate" */ + 1372, /* "tcg-kp-DeltaPlatformAttributeCertificate" */ + 1373, /* "tcg-kp-DeltaPlatformKeyCertificate" */ + 1368, /* "tcg-kp-EKCertificate" */ + 1369, /* "tcg-kp-PlatformAttributeCertificate" */ + 1371, /* "tcg-kp-PlatformKeyCertificate" */ + 1329, /* "tcg-platformClass" */ + 1327, /* "tcg-protocol" */ + 1382, /* "tcg-prt-tpmIdProtocol" */ + 1334, /* "tcg-registry" */ + 1386, /* "tcg-registry-componentClass" */ + 1391, /* "tcg-registry-componentClass-disk" */ + 1389, /* "tcg-registry-componentClass-dmtf" */ + 1388, /* "tcg-registry-componentClass-ietf" */ + 1390, /* "tcg-registry-componentClass-pcie" */ + 1387, /* "tcg-registry-componentClass-tcg" */ + 1325, /* "tcg-tcpaSpecVersion" */ + 1393, /* "tcg-tr-ID" */ + 1396, /* "tcg-tr-ID-Boolean" */ + 1397, /* "tcg-tr-ID-CertificateIdentifier" */ + 1398, /* "tcg-tr-ID-CommonCriteria" */ + 1401, /* "tcg-tr-ID-FIPSLevel" */ + 1414, /* "tcg-tr-ID-IA5String" */ + 1402, /* "tcg-tr-ID-ISO9000Level" */ + 1404, /* "tcg-tr-ID-OID" */ + 1415, /* "tcg-tr-ID-PEMCertString" */ + 1405, /* "tcg-tr-ID-PEN" */ + 1416, /* "tcg-tr-ID-PublicKey" */ + 1410, /* "tcg-tr-ID-RTM" */ + 1412, /* "tcg-tr-ID-URI" */ + 1413, /* "tcg-tr-ID-UTF8String" */ + 1399, /* "tcg-tr-ID-componentClass" */ + 1400, /* "tcg-tr-ID-componentIdentifierV11" */ + 1403, /* "tcg-tr-ID-networkMAC" */ + 1406, /* "tcg-tr-ID-platformFirmwareCapabilities" */ + 1407, /* "tcg-tr-ID-platformFirmwareSignatureVerification" */ + 1408, /* "tcg-tr-ID-platformFirmwareUpdateCompliance" */ + 1409, /* "tcg-tr-ID-platformHardwareCapabilities" */ + 1411, /* "tcg-tr-ID-status" */ + 1441, /* "tcg-tr-cat-CommonCriteria" */ + 1434, /* "tcg-tr-cat-DICECertificate" */ + 1438, /* "tcg-tr-cat-DeltaPlatformCertificate" */ + 1431, /* "tcg-tr-cat-EKCertificate" */ + 1443, /* "tcg-tr-cat-FIPSLevel" */ + 1432, /* "tcg-tr-cat-IAKCertificate" */ + 1433, /* "tcg-tr-cat-IDevIDCertificate" */ + 1444, /* "tcg-tr-cat-ISO9000" */ + 1436, /* "tcg-tr-cat-PEMCertificate" */ + 1447, /* "tcg-tr-cat-PEN" */ + 1437, /* "tcg-tr-cat-PlatformCertificate" */ + 1453, /* "tcg-tr-cat-PublicKey" */ + 1452, /* "tcg-tr-cat-RTM" */ + 1439, /* "tcg-tr-cat-RebasePlatformCertificate" */ + 1435, /* "tcg-tr-cat-SPDMCertificate" */ + 1446, /* "tcg-tr-cat-attestationProtocol" */ + 1423, /* "tcg-tr-cat-componentClass" */ + 1430, /* "tcg-tr-cat-componentFieldReplaceable" */ + 1442, /* "tcg-tr-cat-componentIdentifierV11" */ + 1428, /* "tcg-tr-cat-componentLocation" */ + 1424, /* "tcg-tr-cat-componentManufacturer" */ + 1425, /* "tcg-tr-cat-componentModel" */ + 1429, /* "tcg-tr-cat-componentRevision" */ + 1426, /* "tcg-tr-cat-componentSerial" */ + 1427, /* "tcg-tr-cat-componentStatus" */ + 1440, /* "tcg-tr-cat-genericCertificate" */ + 1445, /* "tcg-tr-cat-networkMAC" */ + 1448, /* "tcg-tr-cat-platformFirmwareCapabilities" */ + 1450, /* "tcg-tr-cat-platformFirmwareSignatureVerification" */ + 1451, /* "tcg-tr-cat-platformFirmwareUpdateCompliance" */ + 1449, /* "tcg-tr-cat-platformHardwareCapabilities" */ + 1417, /* "tcg-tr-cat-platformManufacturer" */ + 1421, /* "tcg-tr-cat-platformManufacturerIdentifier" */ + 1418, /* "tcg-tr-cat-platformModel" */ + 1422, /* "tcg-tr-cat-platformOwnership" */ + 1420, /* "tcg-tr-cat-platformSerial" */ + 1419, /* "tcg-tr-cat-platformVersion" */ + 1394, /* "tcg-tr-category" */ + 1395, /* "tcg-tr-registry" */ + 1335, /* "tcg-traits" */ 864, /* "telephoneNumber" */ 866, /* "teletexTerminalIdentifier" */ 865, /* "telexNumber" */ 459, /* "textEncodedORAddress" */ 293, /* "textNotice" */ + 1299, /* "timeSpecification" */ 133, /* "timeStamping" */ 106, /* "title" */ 1020, /* "tlsfeature" */ @@ -3589,6 +4298,7 @@ static const unsigned int sn_objs[NUM_SN] = { 49, /* "unstructuredName" */ 880, /* "userCertificate" */ 465, /* "userClass" */ + 1301, /* "userNotice" */ 879, /* "userPassword" */ 373, /* "valid" */ 678, /* "wap" */ @@ -3610,20 +4320,29 @@ static const unsigned int sn_objs[NUM_SN] = { 158, /* "x509Certificate" */ 160, /* "x509Crl" */ 1093, /* "x509ExtAdmission" */ + 1289, /* "zstd" */ }; -#define NUM_LN 1239 +#define NUM_LN 1478 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ 368, /* "Acceptable OCSP Responses" */ + 1374, /* "Additional Platform Attribute Certificate" */ + 1375, /* "Additional Platform Key Certificate" */ 910, /* "Any Extended Key Usage" */ 664, /* "Any language" */ + 1370, /* "Attestation Identity Key Certificate" */ + 1446, /* "Attestation Protocol Trait Category" */ + 1411, /* "Attribute Status Trait" */ 177, /* "Authority Information Access" */ 1220, /* "BGPsec Router" */ 365, /* "Basic OCSP Response" */ 285, /* "Biometric Info" */ + 1385, /* "Bluetooth MAC Address" */ + 1396, /* "Boolean Trait" */ 1221, /* "Brand Indicator for Message Identification" */ + 1288, /* "Brotli compression" */ 179, /* "CA Issuers" */ 785, /* "CA Repository" */ 1219, /* "CMC Archive Server" */ @@ -3633,6 +4352,7 @@ static const unsigned int ln_objs[NUM_LN] = { 952, /* "CT Precertificate Poison" */ 951, /* "CT Precertificate SCTs" */ 953, /* "CT Precertificate Signer" */ + 1397, /* "Certificate Identifier Trait" */ 1222, /* "Certificate Management Key Generation Authority" */ 1227, /* "Class of Signing Tool" */ 1233, /* "Class of Signing Tool KA1" */ @@ -3642,8 +4362,22 @@ static const unsigned int ln_objs[NUM_LN] = { 1229, /* "Class of Signing Tool KC2" */ 1230, /* "Class of Signing Tool KC3" */ 131, /* "Code Signing" */ + 1398, /* "Common Criteria Trait" */ + 1441, /* "Common Criteria Trait Category" */ + 1399, /* "Component Class Trait" */ + 1423, /* "Component Class Trait Category" */ + 1430, /* "Component Field Replaceable Trait Category" */ + 1400, /* "Component Identifier V1.1 Trait" */ + 1442, /* "Component Identifier V1.1 Trait Category" */ + 1428, /* "Component Location Trait Category" */ + 1424, /* "Component Manufacturer Trait Category" */ + 1425, /* "Component Model Trait Category" */ + 1429, /* "Component Revision Trait Category" */ + 1426, /* "Component Serial Trait Category" */ + 1427, /* "Component Status Trait Category" */ 1024, /* "Ctrl/Provision WAP Termination" */ 1023, /* "Ctrl/provision WAP Access" */ + 1434, /* "DICE Certificate Trait Category" */ 1159, /* "DSTU 4145-2002 big endian" */ 1158, /* "DSTU 4145-2002 little endian" */ 1152, /* "DSTU Gost 28147-2009" */ @@ -3661,16 +4395,26 @@ static const unsigned int ln_objs[NUM_LN] = { 1167, /* "DSTU curve 7" */ 1168, /* "DSTU curve 8" */ 1169, /* "DSTU curve 9" */ + 1372, /* "Delta Platform Attribute Certificate" */ + 1438, /* "Delta Platform Certificate Trait Category" */ + 1373, /* "Delta Platform Key Certificate" */ 783, /* "Diffie-Hellman based MAC" */ 382, /* "Directory" */ + 1391, /* "Disk Component Class" */ + 1389, /* "Distributed Management Task Force Registry" */ 392, /* "Domain" */ 132, /* "E-mail Protection" */ 1087, /* "ED25519" */ 1088, /* "ED448" */ + 1431, /* "EK Certificate Trait Category" */ + 1368, /* "Endorsement Key Certificate" */ 389, /* "Enterprises" */ + 1383, /* "Ethernet MAC Address" */ 384, /* "Experimental" */ 372, /* "Extended OCSP Status" */ 172, /* "Extension Request" */ + 1401, /* "FIPS Level Trait" */ + 1443, /* "FIPS Level Trait Category" */ 813, /* "GOST 28147-89" */ 849, /* "GOST 28147-89 Cryptocom ParamSet" */ 815, /* "GOST 28147-89 MAC" */ @@ -3702,20 +4446,30 @@ static const unsigned int ln_objs[NUM_LN] = { 808, /* "GOST R 34.11-94 with GOST R 34.10-94" */ 852, /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */ 854, /* "GOST R 3410-2001 Parameter Set Cryptocom" */ + 1440, /* "Generic Certificate Trait Category" */ + 1472, /* "HASH-ML-DSA-44-WITH-SHA512" */ + 1473, /* "HASH-ML-DSA-65-WITH-SHA512" */ + 1474, /* "HASH-ML-DSA-87-WITH-SHA512" */ 1156, /* "HMAC DSTU Gost 34311-95" */ 988, /* "HMAC GOST 34.11-2012 256 bit" */ 989, /* "HMAC GOST 34.11-2012 512 bit" */ 810, /* "HMAC GOST 34.11-94" */ + 1321, /* "Hardware Module Name" */ 432, /* "Hold Instruction Call Issuer" */ 430, /* "Hold Instruction Code" */ 431, /* "Hold Instruction None" */ 433, /* "Hold Instruction Reject" */ + 1414, /* "IA5String Trait" */ + 1432, /* "IAK Certificate Trait Category" */ 634, /* "ICC or token signature" */ + 1433, /* "IDevID Certificate Trait Category" */ 1171, /* "IEEE Security in Storage Working Group" */ 1004, /* "INN" */ 294, /* "IPSec End System" */ 295, /* "IPSec Tunnel" */ 296, /* "IPSec User" */ + 1402, /* "ISO 9000 Level Trait" */ + 1444, /* "ISO 9000 Trait Category" */ 1140, /* "ISO CN Member Body" */ 182, /* "ISO Member Body" */ 183, /* "ISO US Member Body" */ @@ -3723,23 +4477,37 @@ static const unsigned int ln_objs[NUM_LN] = { 667, /* "Independent" */ 665, /* "Inherit all" */ 647, /* "International Organizations" */ + 1388, /* "Internet Engineering Task Force Registry" */ 142, /* "Invalidity Date" */ 504, /* "MIME MHS" */ + 1457, /* "ML-DSA-44" */ + 1458, /* "ML-DSA-65" */ + 1459, /* "ML-DSA-87" */ + 1456, /* "ML-KEM-1024" */ + 1454, /* "ML-KEM-512" */ + 1455, /* "ML-KEM-768" */ 388, /* "Mail" */ 383, /* "Management" */ + 1294, /* "Microsoft Application Policies Extension" */ 417, /* "Microsoft CSP Name" */ 135, /* "Microsoft Commercial Code Signing" */ 138, /* "Microsoft Encrypted File System" */ 171, /* "Microsoft Extension Request" */ 134, /* "Microsoft Individual Code Signing" */ 856, /* "Microsoft Local Key set" */ + 1291, /* "Microsoft NTDS AD objectSid" */ + 1292, /* "Microsoft NTDS CA Extension" */ 137, /* "Microsoft Server Gated Crypto" */ 648, /* "Microsoft Smartcard Login" */ 136, /* "Microsoft Trust List Signing" */ 649, /* "Microsoft User Principal Name" */ + 1293, /* "Microsoft certificate template" */ + 1379, /* "Migration Controller Attestation Service" */ + 1380, /* "Migration Controller Registration Service" */ 1211, /* "NAIRealm" */ 393, /* "NULL" */ 404, /* "NULL" */ + 1323, /* "NULL" */ 72, /* "Netscape Base Url" */ 76, /* "Netscape CA Policy Url" */ 74, /* "Netscape CA Revocation Url" */ @@ -3753,6 +4521,8 @@ static const unsigned int ln_objs[NUM_LN] = { 73, /* "Netscape Revocation Url" */ 77, /* "Netscape SSL Server Name" */ 139, /* "Netscape Server Gated Crypto" */ + 1403, /* "Network MAC Trait" */ + 1445, /* "Network MAC Trait Category" */ 178, /* "OCSP" */ 370, /* "OCSP Archive Cutoff" */ 367, /* "OCSP CRL ID" */ @@ -3762,17 +4532,47 @@ static const unsigned int ln_objs[NUM_LN] = { 180, /* "OCSP Signing" */ 1005, /* "OGRN" */ 1226, /* "OGRNIP" */ + 1404, /* "Object Identifier Trait" */ + 1282, /* "Oracle organization" */ 161, /* "PBES2" */ 69, /* "PBKDF2" */ 162, /* "PBMAC1" */ + 1390, /* "PCIE Component Class" */ + 1436, /* "PEM Certificate Trait Category" */ + 1415, /* "PEM-Encoded Certificate String Trait" */ 1032, /* "PKINIT Client Auth" */ 127, /* "PKIX" */ 858, /* "Permanent Identifier" */ + 1369, /* "Platform Attribute Certificate" */ + 1437, /* "Platform Certificate Trait Category" */ + 1366, /* "Platform Configuration URI Version 3" */ + 1363, /* "Platform Configuration Version 1" */ + 1364, /* "Platform Configuration Version 2" */ + 1365, /* "Platform Configuration Version 3" */ + 1406, /* "Platform Firmware Capabilities Trait" */ + 1448, /* "Platform Firmware Capabilities Trait Category" */ + 1407, /* "Platform Firmware Signature Verification Trait" */ + 1450, /* "Platform Firmware Signature Verification Trait Category" */ + 1408, /* "Platform Firmware Update Compliance Trait" */ + 1451, /* "Platform Firmware Update Compliance Trait Category" */ + 1409, /* "Platform Hardware Capabilities Trait" */ + 1449, /* "Platform Hardware Capabilities Trait Category" */ + 1371, /* "Platform Key Certificate" */ + 1421, /* "Platform Manufacturer Identifier Trait Category" */ + 1417, /* "Platform Manufacturer Trait Category" */ + 1418, /* "Platform Model Trait Category" */ + 1422, /* "Platform Ownership Trait Category" */ + 1420, /* "Platform Serial Trait Category" */ + 1419, /* "Platform Version Trait Category" */ 164, /* "Policy Qualifier CPS" */ 165, /* "Policy Qualifier User Notice" */ 385, /* "Private" */ + 1405, /* "Private Enterprise Number Trait" */ + 1447, /* "Private Enterprise Number Trait Category" */ 1093, /* "Professional Information or basis for Admission" */ 663, /* "Proxy Certificate Information" */ + 1416, /* "Public Key Trait" */ + 1453, /* "Public Key Trait Category" */ 1243, /* "RPKI Manifest" */ 1245, /* "RPKI Notify" */ 1, /* "RSA Data Security, Inc." */ @@ -3781,16 +4581,47 @@ static const unsigned int ln_objs[NUM_LN] = { 1117, /* "RSA-SHA3-256" */ 1118, /* "RSA-SHA3-384" */ 1119, /* "RSA-SHA3-512" */ + 1439, /* "Rebase Platform Certificate Trait Category" */ + 1376, /* "Relevant Credentials" */ + 1377, /* "Relevant Manifests" */ + 1410, /* "Root of Trust for Measurement Trait" */ + 1452, /* "Root of Trust of Measurement Trait Category" */ 188, /* "S/MIME" */ 167, /* "S/MIME Capabilities" */ + 1461, /* "SLH-DSA-SHA2-128f" */ + 1476, /* "SLH-DSA-SHA2-128f-WITH-SHA256" */ + 1460, /* "SLH-DSA-SHA2-128s" */ + 1475, /* "SLH-DSA-SHA2-128s-WITH-SHA256" */ + 1463, /* "SLH-DSA-SHA2-192f" */ + 1478, /* "SLH-DSA-SHA2-192f-WITH-SHA512" */ + 1462, /* "SLH-DSA-SHA2-192s" */ + 1477, /* "SLH-DSA-SHA2-192s-WITH-SHA512" */ + 1465, /* "SLH-DSA-SHA2-256f" */ + 1480, /* "SLH-DSA-SHA2-256f-WITH-SHA512" */ + 1464, /* "SLH-DSA-SHA2-256s" */ + 1479, /* "SLH-DSA-SHA2-256s-WITH-SHA512" */ + 1467, /* "SLH-DSA-SHAKE-128f" */ + 1482, /* "SLH-DSA-SHAKE-128f-WITH-SHAKE128" */ + 1466, /* "SLH-DSA-SHAKE-128s" */ + 1481, /* "SLH-DSA-SHAKE-128s-WITH-SHAKE128" */ + 1469, /* "SLH-DSA-SHAKE-192f" */ + 1484, /* "SLH-DSA-SHAKE-192f-WITH-SHAKE256" */ + 1468, /* "SLH-DSA-SHAKE-192s" */ + 1483, /* "SLH-DSA-SHAKE-192s-WITH-SHAKE256" */ + 1471, /* "SLH-DSA-SHAKE-256f" */ + 1486, /* "SLH-DSA-SHAKE-256f-WITH-SHAKE256" */ + 1470, /* "SLH-DSA-SHAKE-256s" */ + 1485, /* "SLH-DSA-SHAKE-256s-WITH-SHAKE256" */ 1204, /* "SM2-with-SM3" */ 1006, /* "SNILS" */ 387, /* "SNMPv2" */ + 1435, /* "SPDM Certificate Trait Category" */ 1210, /* "SRVName" */ 1025, /* "SSH Client" */ 1026, /* "SSH Server" */ 512, /* "Secure Electronic Transactions" */ 386, /* "Security" */ + 1348, /* "Security Qualities" */ 394, /* "Selected Attribute Types" */ 1029, /* "Send Owner" */ 1030, /* "Send Proxied Owner" */ @@ -3803,45 +4634,123 @@ static const unsigned int ln_objs[NUM_LN] = { 1208, /* "Smtp UTF8 Mailbox" */ 143, /* "Strong Extranet ID" */ 398, /* "Subject Information Access" */ + 1351, /* "TBB Protection Profile" */ + 1357, /* "TBB Security Assertions" */ + 1352, /* "TBB Security Target" */ + 1386, /* "TCG Component Class" */ + 1358, /* "TCG Credential Specification" */ + 1359, /* "TCG Credential Type" */ + 1362, /* "TCG Cryptographic Anchors" */ + 1367, /* "TCG NULL Algorithm" */ + 1343, /* "TCG Platform Configuration" */ + 1339, /* "TCG Platform Configuration URI" */ + 1344, /* "TCG Platform Identifier" */ + 1338, /* "TCG Platform Manufacturer ID" */ + 1337, /* "TCG Platform Manufacturer String" */ + 1340, /* "TCG Platform Model" */ + 1342, /* "TCG Platform Serial Number" */ + 1341, /* "TCG Platform Version" */ + 1360, /* "TCG Previous Platform Certificates" */ + 1361, /* "TCG TBB Security Assertions V3" */ + 1382, /* "TCG TPM Protocol" */ + 1394, /* "TCG Trait Categories" */ + 1393, /* "TCG Trait Identifiers" */ + 1395, /* "TCG Trait Registries" */ + 1392, /* "TCG Verified Platform Certificate CA Policy" */ 1020, /* "TLS Feature" */ 130, /* "TLS Web Client Authentication" */ 129, /* "TLS Web Server Authentication" */ + 1353, /* "TPM ID Label" */ + 1345, /* "TPM Manufacturer" */ + 1346, /* "TPM Model" */ + 1355, /* "TPM Platform Specification" */ + 1349, /* "TPM Protection Profile" */ + 1356, /* "TPM Security Assertions" */ + 1350, /* "TPM Security Target" */ + 1354, /* "TPM Specification" */ + 1347, /* "TPM Version" */ 133, /* "Time Stamping" */ 375, /* "Trust Root" */ + 1387, /* "Trusted Computed Group Registry" */ + 1324, /* "Trusted Computing Group" */ + 1333, /* "Trusted Computing Group Address Formats" */ + 1328, /* "Trusted Computing Group Algorithms" */ + 1326, /* "Trusted Computing Group Attributes" */ + 1330, /* "Trusted Computing Group Certificate Extensions" */ + 1332, /* "Trusted Computing Group Certificate Policies" */ + 1336, /* "Trusted Computing Group Common" */ + 1331, /* "Trusted Computing Group Key Purposes" */ + 1329, /* "Trusted Computing Group Platform Classes" */ + 1327, /* "Trusted Computing Group Protocols" */ + 1334, /* "Trusted Computing Group Registry" */ + 1335, /* "Trusted Computing Group Traits" */ + 1283, /* "Trusted key usage (Oracle)" */ + 1413, /* "UTF8String Trait" */ + 1412, /* "Uniform Resource Identifier Trait" */ + 1378, /* "Virtual Platform Attestation Service" */ + 1381, /* "Virtual Platform Backup Service" */ + 1384, /* "WLAN MAC Address" */ + 1322, /* "Wi-SUN Alliance Field Area Network (FAN)" */ 1034, /* "X25519" */ 1035, /* "X448" */ 12, /* "X509" */ 402, /* "X509v3 AC Targeting" */ + 1303, /* "X509v3 Acceptable Certification Policies" */ + 1304, /* "X509v3 Acceptable Privilege Policies" */ + 1311, /* "X509v3 Allowed Attribute Assignments" */ + 1317, /* "X509v3 Alternative Signature Algorithm" */ + 1318, /* "X509v3 Alternative Signature Value" */ 746, /* "X509v3 Any Policy" */ + 1319, /* "X509v3 Associated Information" */ + 1307, /* "X509v3 Attribute Authority Issuing Distribution Point" */ + 1300, /* "X509v3 Attribute Descriptor" */ + 1312, /* "X509v3 Attribute Mappings" */ + 287, /* "X509v3 Audit Identity" */ + 1295, /* "X509v3 Authority Attribute Identifier" */ 90, /* "X509v3 Authority Key Identifier" */ + 1314, /* "X509v3 Authorization Validation" */ + 1297, /* "X509v3 Basic Attribute Certificate Constraints" */ 87, /* "X509v3 Basic Constraints" */ 103, /* "X509v3 CRL Distribution Points" */ 88, /* "X509v3 CRL Number" */ 141, /* "X509v3 CRL Reason Code" */ 771, /* "X509v3 Certificate Issuer" */ 89, /* "X509v3 Certificate Policies" */ + 1298, /* "X509v3 Delegated Name Constraints" */ 140, /* "X509v3 Delta CRL Indicator" */ 126, /* "X509v3 Extended Key Usage" */ 857, /* "X509v3 Freshest CRL" */ + 1310, /* "X509v3 Group Attribute Certificate" */ + 1313, /* "X509v3 Holder Name Constraints" */ + 1305, /* "X509v3 Indirect Issuer" */ 748, /* "X509v3 Inhibit Any Policy" */ + 1308, /* "X509v3 Issued On Behalf Of" */ 86, /* "X509v3 Issuer Alternative Name" */ 770, /* "X509v3 Issuing Distribution Point" */ 83, /* "X509v3 Key Usage" */ 666, /* "X509v3 Name Constraints" */ + 1306, /* "X509v3 No Assertion" */ 403, /* "X509v3 No Revocation Available" */ 401, /* "X509v3 Policy Constraints" */ 747, /* "X509v3 Policy Mappings" */ 84, /* "X509v3 Private Key Usage Period" */ + 1315, /* "X509v3 Protocol Restriction" */ + 1296, /* "X509v3 Role Specification Certificate Identifier" */ + 1309, /* "X509v3 Single Use" */ + 1302, /* "X509v3 Source of Authority Identifier" */ 85, /* "X509v3 Subject Alternative Name" */ + 1316, /* "X509v3 Subject Alternative Public Key Info" */ 769, /* "X509v3 Subject Directory Attributes" */ 82, /* "X509v3 Subject Key Identifier" */ + 1299, /* "X509v3 Time Specification" */ + 1301, /* "X509v3 User Notice" */ 920, /* "X9.42 DH" */ 184, /* "X9.57" */ 185, /* "X9.57 CM ?" */ 1209, /* "XmppAddr" */ + 1289, /* "Zstandard compression" */ 478, /* "aRecord" */ 289, /* "aaControls" */ - 287, /* "ac-auditEntity" */ 397, /* "ac-proxying" */ 288, /* "ac-targeting" */ 446, /* "account" */ @@ -3944,12 +4853,15 @@ static const unsigned int ln_objs[NUM_LN] = { 925, /* "brainpoolP224r1" */ 926, /* "brainpoolP224t1" */ 927, /* "brainpoolP256r1" */ + 1285, /* "brainpoolP256r1tls13" */ 928, /* "brainpoolP256t1" */ 929, /* "brainpoolP320r1" */ 930, /* "brainpoolP320t1" */ 931, /* "brainpoolP384r1" */ + 1286, /* "brainpoolP384r1tls13" */ 932, /* "brainpoolP384t1" */ 933, /* "brainpoolP512r1" */ + 1287, /* "brainpoolP512r1tls13" */ 934, /* "brainpoolP512t1" */ 494, /* "buildingName" */ 860, /* "businessCategory" */ @@ -3975,6 +4887,8 @@ static const unsigned int ln_objs[NUM_LN] = { 703, /* "c2tnb431r1" */ 881, /* "cACertificate" */ 483, /* "cNAMERecord" */ + 1273, /* "cades" */ + 1274, /* "cades-attributes" */ 751, /* "camellia-128-cbc" */ 962, /* "camellia-128-ccm" */ 757, /* "camellia-128-cfb" */ @@ -4113,9 +5027,12 @@ static const unsigned int ln_objs[NUM_LN] = { 1113, /* "ecdsa_with_SHA3-256" */ 1114, /* "ecdsa_with_SHA3-384" */ 1115, /* "ecdsa_with_SHA3-512" */ + 1266, /* "electronic-signature-standard" */ 48, /* "emailAddress" */ 632, /* "encrypted track 2" */ 885, /* "enhancedSearchGuide" */ + 1267, /* "ess-attributes" */ + 1265, /* "etsi" */ 56, /* "extendedCertificateAttributes" */ 867, /* "facsimileTelephoneNumber" */ 462, /* "favouriteDrink" */ @@ -4154,6 +5071,7 @@ static const unsigned int ln_objs[NUM_LN] = { 801, /* "hmacWithSHA512" */ 1193, /* "hmacWithSHA512-224" */ 1194, /* "hmacWithSHA512-256" */ + 1281, /* "hmacWithSM3" */ 486, /* "homePostalAddress" */ 473, /* "homeTelephoneNumber" */ 466, /* "host" */ @@ -4190,6 +5108,19 @@ static const unsigned int ln_objs[NUM_LN] = { 848, /* "id-GostR3410-94-bBis" */ 822, /* "id-GostR3411-94-CryptoProParamSet" */ 821, /* "id-GostR3411-94-TestParamSet" */ + 1272, /* "id-aa-ATSHashIndex" */ + 1277, /* "id-aa-ATSHashIndex-v2" */ + 1278, /* "id-aa-ATSHashIndex-v3" */ + 1263, /* "id-aa-CMSAlgorithmProtection" */ + 1270, /* "id-aa-ets-SignaturePolicyDocument" */ + 1280, /* "id-aa-ets-archiveTimestampV2" */ + 1271, /* "id-aa-ets-archiveTimestampV3" */ + 1261, /* "id-aa-ets-attrCertificateRefs" */ + 1262, /* "id-aa-ets-attrRevocationRefs" */ + 1269, /* "id-aa-ets-longTermValidation" */ + 1268, /* "id-aa-ets-mimeType" */ + 1276, /* "id-aa-ets-sigPolicyStore" */ + 1275, /* "id-aa-ets-signerAttrV2" */ 266, /* "id-aca" */ 355, /* "id-aca-accessIdentity" */ 354, /* "id-aca-authenticationInfo" */ @@ -4241,13 +5172,16 @@ static const unsigned int ln_objs[NUM_LN] = { 327, /* "id-cmc-statusInfo" */ 331, /* "id-cmc-transactionId" */ 1238, /* "id-cp" */ + 1250, /* "id-ct-ASPA" */ 787, /* "id-ct-asciiTextWithCRLF" */ 1246, /* "id-ct-geofeedCSVwithCRLF" */ 1237, /* "id-ct-resourceTaggedAttest" */ 1234, /* "id-ct-routeOriginAuthz" */ 1236, /* "id-ct-rpkiGhostbusters" */ 1235, /* "id-ct-rpkiManifest" */ + 1320, /* "id-ct-rpkiSignedPrefixList" */ 1247, /* "id-ct-signedChecklist" */ + 1284, /* "id-ct-signedTAL" */ 1060, /* "id-ct-xml" */ 408, /* "id-ecPublicKey" */ 508, /* "id-hex-multipart-message" */ @@ -4256,8 +5190,11 @@ static const unsigned int ln_objs[NUM_LN] = { 1223, /* "id-it-caCerts" */ 302, /* "id-it-caKeyUpdateInfo" */ 298, /* "id-it-caProtEncCert" */ + 1255, /* "id-it-certProfile" */ 1225, /* "id-it-certReqTemplate" */ 311, /* "id-it-confirmWaitTime" */ + 1256, /* "id-it-crlStatusList" */ + 1257, /* "id-it-crls" */ 303, /* "id-it-currentCRL" */ 300, /* "id-it-encKeyPairTypes" */ 310, /* "id-it-implicitConfirm" */ @@ -4266,6 +5203,7 @@ static const unsigned int ln_objs[NUM_LN] = { 312, /* "id-it-origPKIMessage" */ 301, /* "id-it-preferredSymmAlg" */ 309, /* "id-it-revPassphrase" */ + 1254, /* "id-it-rootCaCert" */ 1224, /* "id-it-rootCaKeyUpdate" */ 299, /* "id-it-signKeyPairTypes" */ 305, /* "id-it-subscriptionRequest" */ @@ -4277,6 +5215,9 @@ static const unsigned int ln_objs[NUM_LN] = { 274, /* "id-mod-cmc" */ 277, /* "id-mod-cmp" */ 284, /* "id-mod-cmp2000" */ + 1251, /* "id-mod-cmp2000-02" */ + 1253, /* "id-mod-cmp2021-02" */ + 1252, /* "id-mod-cmp2021-88" */ 273, /* "id-mod-crmf" */ 283, /* "id-mod-dvcs" */ 275, /* "id-mod-kea-profile-88" */ @@ -4306,12 +5247,15 @@ static const unsigned int ln_objs[NUM_LN] = { 359, /* "id-qcs-pkixQCSyntax-v1" */ 259, /* "id-qt" */ 313, /* "id-regCtrl" */ + 1259, /* "id-regCtrl-algId" */ + 1258, /* "id-regCtrl-altCertTemplate" */ 316, /* "id-regCtrl-authenticator" */ 319, /* "id-regCtrl-oldCertID" */ 318, /* "id-regCtrl-pkiArchiveOptions" */ 317, /* "id-regCtrl-pkiPublicationInfo" */ 320, /* "id-regCtrl-protocolEncrKey" */ 315, /* "id-regCtrl-regToken" */ + 1260, /* "id-regCtrl-rsaKeyLen" */ 314, /* "id-regInfo" */ 322, /* "id-regInfo-certReq" */ 321, /* "id-regInfo-utf8Pairs" */ @@ -4426,6 +5370,7 @@ static const unsigned int ln_objs[NUM_LN] = { 181, /* "iso" */ 623, /* "issuer capabilities" */ 645, /* "itu-t" */ + 1264, /* "itu-t-identified-organization" */ 492, /* "janetMailbox" */ 646, /* "joint-iso-itu-t" */ 957, /* "jurisdictionCountryName" */ @@ -4788,6 +5733,7 @@ static const unsigned int ln_objs[NUM_LN] = { 42, /* "shaWithRSAEncryption" */ 1100, /* "shake128" */ 1101, /* "shake256" */ + 1279, /* "signedAssertion" */ 52, /* "signingTime" */ 454, /* "simpleSecurityObject" */ 496, /* "singleLevelQuality" */ @@ -4797,12 +5743,15 @@ static const unsigned int ln_objs[NUM_LN] = { 1143, /* "sm3" */ 1144, /* "sm3WithRSAEncryption" */ 1134, /* "sm4-cbc" */ + 1249, /* "sm4-ccm" */ 1137, /* "sm4-cfb" */ 1136, /* "sm4-cfb1" */ 1138, /* "sm4-cfb8" */ 1139, /* "sm4-ctr" */ 1133, /* "sm4-ecb" */ + 1248, /* "sm4-gcm" */ 1135, /* "sm4-ofb" */ + 1290, /* "sm4-xts" */ 1203, /* "sshkdf" */ 1205, /* "sskdf" */ 16, /* "stateOrProvinceName" */ @@ -4812,6 +5761,7 @@ static const unsigned int ln_objs[NUM_LN] = { 890, /* "supportedAlgorithms" */ 874, /* "supportedApplicationContext" */ 100, /* "surname" */ + 1325, /* "tcg-tcpaSpecVersion" */ 864, /* "telephoneNumber" */ 866, /* "teletexTerminalIdentifier" */ 865, /* "telexNumber" */ @@ -4855,7 +5805,7 @@ static const unsigned int ln_objs[NUM_LN] = { 125, /* "zlib compression" */ }; -#define NUM_OBJ 1110 +#define NUM_OBJ 1344 static const unsigned int obj_objs[NUM_OBJ] = { 0, /* OBJ_undef 0 */ 181, /* OBJ_iso 1 */ @@ -4863,12 +5813,15 @@ static const unsigned int obj_objs[NUM_OBJ] = { 404, /* OBJ_ccitt OBJ_itu_t */ 645, /* OBJ_itu_t 0 */ 646, /* OBJ_joint_iso_itu_t 2 */ + 1323, /* OBJ_ac_auditEntity OBJ_ac_auditIdentity */ + 1264, /* OBJ_itu_t_identified_organization 0 4 */ 434, /* OBJ_data 0 9 */ 182, /* OBJ_member_body 1 2 */ 379, /* OBJ_org 1 3 */ 676, /* OBJ_identified_organization 1 3 */ 11, /* OBJ_X500 2 5 */ 647, /* OBJ_international_organizations 2 23 */ + 1265, /* OBJ_etsi 0 4 0 */ 380, /* OBJ_dod 1 3 6 */ 1170, /* OBJ_ieee 1 3 111 */ 12, /* OBJ_X509 2 5 4 */ @@ -4966,10 +5919,35 @@ static const unsigned int obj_objs[NUM_OBJ] = { 90, /* OBJ_authority_key_identifier 2 5 29 35 */ 401, /* OBJ_policy_constraints 2 5 29 36 */ 126, /* OBJ_ext_key_usage 2 5 29 37 */ + 1295, /* OBJ_authority_attribute_identifier 2 5 29 38 */ + 1296, /* OBJ_role_spec_cert_identifier 2 5 29 39 */ + 1297, /* OBJ_basic_att_constraints 2 5 29 41 */ + 1298, /* OBJ_delegated_name_constraints 2 5 29 42 */ + 1299, /* OBJ_time_specification 2 5 29 43 */ 857, /* OBJ_freshest_crl 2 5 29 46 */ + 1300, /* OBJ_attribute_descriptor 2 5 29 48 */ + 1301, /* OBJ_user_notice 2 5 29 49 */ + 1302, /* OBJ_soa_identifier 2 5 29 50 */ + 1303, /* OBJ_acceptable_cert_policies 2 5 29 52 */ 748, /* OBJ_inhibit_any_policy 2 5 29 54 */ 402, /* OBJ_target_information 2 5 29 55 */ 403, /* OBJ_no_rev_avail 2 5 29 56 */ + 1304, /* OBJ_acceptable_privilege_policies 2 5 29 57 */ + 1305, /* OBJ_indirect_issuer 2 5 29 61 */ + 1306, /* OBJ_no_assertion 2 5 29 62 */ + 1307, /* OBJ_id_aa_issuing_distribution_point 2 5 29 63 */ + 1308, /* OBJ_issued_on_behalf_of 2 5 29 64 */ + 1309, /* OBJ_single_use 2 5 29 65 */ + 1310, /* OBJ_group_ac 2 5 29 66 */ + 1311, /* OBJ_allowed_attribute_assignments 2 5 29 67 */ + 1312, /* OBJ_attribute_mappings 2 5 29 68 */ + 1313, /* OBJ_holder_name_constraints 2 5 29 69 */ + 1314, /* OBJ_authorization_validation 2 5 29 70 */ + 1315, /* OBJ_prot_restrict 2 5 29 71 */ + 1316, /* OBJ_subject_alt_public_key_info 2 5 29 72 */ + 1317, /* OBJ_alt_signature_algorithm 2 5 29 73 */ + 1318, /* OBJ_alt_signature_value 2 5 29 74 */ + 1319, /* OBJ_associated_information 2 5 29 75 */ 513, /* OBJ_set_ctype 2 23 42 0 */ 514, /* OBJ_set_msgExt 2 23 42 1 */ 515, /* OBJ_set_attr 2 23 42 3 */ @@ -4977,6 +5955,8 @@ static const unsigned int obj_objs[NUM_OBJ] = { 517, /* OBJ_set_certExt 2 23 42 7 */ 518, /* OBJ_set_brand 2 23 42 8 */ 679, /* OBJ_wap_wsg 2 23 43 1 */ + 1324, /* OBJ_tcg 2 23 133 */ + 1266, /* OBJ_electronic_signature_standard 0 4 0 1733 */ 382, /* OBJ_Directory 1 3 6 1 1 */ 383, /* OBJ_Management 1 3 6 1 2 */ 384, /* OBJ_Experimental 1 3 6 1 3 */ @@ -5102,6 +6082,19 @@ static const unsigned int obj_objs[NUM_OBJ] = { 637, /* OBJ_set_brand_Diners 2 23 42 8 30 */ 638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */ 639, /* OBJ_set_brand_JCB 2 23 42 8 35 */ + 1325, /* OBJ_tcg_tcpaSpecVersion 2 23 133 1 */ + 1326, /* OBJ_tcg_attribute 2 23 133 2 */ + 1327, /* OBJ_tcg_protocol 2 23 133 3 */ + 1328, /* OBJ_tcg_algorithm 2 23 133 4 */ + 1329, /* OBJ_tcg_platformClass 2 23 133 5 */ + 1330, /* OBJ_tcg_ce 2 23 133 6 */ + 1331, /* OBJ_tcg_kp 2 23 133 8 */ + 1332, /* OBJ_tcg_ca 2 23 133 11 */ + 1333, /* OBJ_tcg_address 2 23 133 17 */ + 1334, /* OBJ_tcg_registry 2 23 133 18 */ + 1335, /* OBJ_tcg_traits 2 23 133 19 */ + 1273, /* OBJ_cades 0 4 0 19122 */ + 1267, /* OBJ_ess_attributes 0 4 0 1733 2 */ 1195, /* OBJ_gmac 1 0 9797 3 4 */ 1141, /* OBJ_oscca 1 2 156 10197 */ 805, /* OBJ_cryptopro 1 2 643 2 2 */ @@ -5185,6 +6178,55 @@ static const unsigned int obj_objs[NUM_OBJ] = { 743, /* OBJ_wap_wsg_idm_ecid_wtls10 2 23 43 1 4 10 */ 744, /* OBJ_wap_wsg_idm_ecid_wtls11 2 23 43 1 4 11 */ 745, /* OBJ_wap_wsg_idm_ecid_wtls12 2 23 43 1 4 12 */ + 1345, /* OBJ_tcg_at_tpmManufacturer 2 23 133 2 1 */ + 1346, /* OBJ_tcg_at_tpmModel 2 23 133 2 2 */ + 1347, /* OBJ_tcg_at_tpmVersion 2 23 133 2 3 */ + 1348, /* OBJ_tcg_at_securityQualities 2 23 133 2 10 */ + 1349, /* OBJ_tcg_at_tpmProtectionProfile 2 23 133 2 11 */ + 1350, /* OBJ_tcg_at_tpmSecurityTarget 2 23 133 2 12 */ + 1351, /* OBJ_tcg_at_tbbProtectionProfile 2 23 133 2 13 */ + 1352, /* OBJ_tcg_at_tbbSecurityTarget 2 23 133 2 14 */ + 1353, /* OBJ_tcg_at_tpmIdLabel 2 23 133 2 15 */ + 1354, /* OBJ_tcg_at_tpmSpecification 2 23 133 2 16 */ + 1355, /* OBJ_tcg_at_tcgPlatformSpecification 2 23 133 2 17 */ + 1356, /* OBJ_tcg_at_tpmSecurityAssertions 2 23 133 2 18 */ + 1357, /* OBJ_tcg_at_tbbSecurityAssertions 2 23 133 2 19 */ + 1358, /* OBJ_tcg_at_tcgCredentialSpecification 2 23 133 2 23 */ + 1359, /* OBJ_tcg_at_tcgCredentialType 2 23 133 2 25 */ + 1360, /* OBJ_tcg_at_previousPlatformCertificates 2 23 133 2 26 */ + 1361, /* OBJ_tcg_at_tbbSecurityAssertions_v3 2 23 133 2 27 */ + 1362, /* OBJ_tcg_at_cryptographicAnchors 2 23 133 2 28 */ + 1382, /* OBJ_tcg_prt_tpmIdProtocol 2 23 133 3 1 */ + 1367, /* OBJ_tcg_algorithm_null 2 23 133 4 1 */ + 1336, /* OBJ_tcg_common 2 23 133 5 1 */ + 1376, /* OBJ_tcg_ce_relevantCredentials 2 23 133 6 2 */ + 1377, /* OBJ_tcg_ce_relevantManifests 2 23 133 6 3 */ + 1378, /* OBJ_tcg_ce_virtualPlatformAttestationService 2 23 133 6 4 */ + 1379, /* OBJ_tcg_ce_migrationControllerAttestationService 2 23 133 6 5 */ + 1380, /* OBJ_tcg_ce_migrationControllerRegistrationService 2 23 133 6 6 */ + 1381, /* OBJ_tcg_ce_virtualPlatformBackupService 2 23 133 6 7 */ + 1368, /* OBJ_tcg_kp_EKCertificate 2 23 133 8 1 */ + 1369, /* OBJ_tcg_kp_PlatformAttributeCertificate 2 23 133 8 2 */ + 1370, /* OBJ_tcg_kp_AIKCertificate 2 23 133 8 3 */ + 1371, /* OBJ_tcg_kp_PlatformKeyCertificate 2 23 133 8 4 */ + 1372, /* OBJ_tcg_kp_DeltaPlatformAttributeCertificate 2 23 133 8 5 */ + 1373, /* OBJ_tcg_kp_DeltaPlatformKeyCertificate 2 23 133 8 6 */ + 1374, /* OBJ_tcg_kp_AdditionalPlatformAttributeCertificate 2 23 133 8 7 */ + 1375, /* OBJ_tcg_kp_AdditionalPlatformKeyCertificate 2 23 133 8 8 */ + 1392, /* OBJ_tcg_cap_verifiedPlatformCertificate 2 23 133 11 4 */ + 1383, /* OBJ_tcg_address_ethernetmac 2 23 133 17 1 */ + 1384, /* OBJ_tcg_address_wlanmac 2 23 133 17 2 */ + 1385, /* OBJ_tcg_address_bluetoothmac 2 23 133 17 3 */ + 1386, /* OBJ_tcg_registry_componentClass 2 23 133 18 3 */ + 1393, /* OBJ_tcg_tr_ID 2 23 133 19 1 */ + 1394, /* OBJ_tcg_tr_category 2 23 133 19 2 */ + 1395, /* OBJ_tcg_tr_registry 2 23 133 19 3 */ + 1274, /* OBJ_cades_attributes 0 4 0 19122 1 */ + 1268, /* OBJ_id_aa_ets_mimeType 0 4 0 1733 2 1 */ + 1269, /* OBJ_id_aa_ets_longTermValidation 0 4 0 1733 2 2 */ + 1270, /* OBJ_id_aa_ets_SignaturePolicyDocument 0 4 0 1733 2 3 */ + 1271, /* OBJ_id_aa_ets_archiveTimestampV3 0 4 0 1733 2 4 */ + 1272, /* OBJ_id_aa_ATSHashIndex 0 4 0 1733 2 5 */ 804, /* OBJ_whirlpool 1 0 10118 3 0 55 */ 1142, /* OBJ_sm_scheme 1 2 156 10197 1 */ 773, /* OBJ_kisa 1 2 410 200004 */ @@ -5227,6 +6269,82 @@ static const unsigned int obj_objs[NUM_OBJ] = { 633, /* OBJ_setAttr_T2cleartxt 2 23 42 3 3 4 2 */ 634, /* OBJ_setAttr_TokICCsig 2 23 42 3 3 5 1 */ 635, /* OBJ_setAttr_SecDevSig 2 23 42 3 3 5 2 */ + 1337, /* OBJ_tcg_at_platformManufacturerStr 2 23 133 5 1 1 */ + 1338, /* OBJ_tcg_at_platformManufacturerId 2 23 133 5 1 2 */ + 1339, /* OBJ_tcg_at_platformConfigUri 2 23 133 5 1 3 */ + 1340, /* OBJ_tcg_at_platformModel 2 23 133 5 1 4 */ + 1341, /* OBJ_tcg_at_platformVersion 2 23 133 5 1 5 */ + 1342, /* OBJ_tcg_at_platformSerial 2 23 133 5 1 6 */ + 1343, /* OBJ_tcg_at_platformConfiguration 2 23 133 5 1 7 */ + 1344, /* OBJ_tcg_at_platformIdentifier 2 23 133 5 1 8 */ + 1387, /* OBJ_tcg_registry_componentClass_tcg 2 23 133 18 3 1 */ + 1388, /* OBJ_tcg_registry_componentClass_ietf 2 23 133 18 3 2 */ + 1389, /* OBJ_tcg_registry_componentClass_dmtf 2 23 133 18 3 3 */ + 1390, /* OBJ_tcg_registry_componentClass_pcie 2 23 133 18 3 4 */ + 1391, /* OBJ_tcg_registry_componentClass_disk 2 23 133 18 3 5 */ + 1396, /* OBJ_tcg_tr_ID_Boolean 2 23 133 19 1 1 */ + 1397, /* OBJ_tcg_tr_ID_CertificateIdentifier 2 23 133 19 1 2 */ + 1398, /* OBJ_tcg_tr_ID_CommonCriteria 2 23 133 19 1 3 */ + 1399, /* OBJ_tcg_tr_ID_componentClass 2 23 133 19 1 4 */ + 1400, /* OBJ_tcg_tr_ID_componentIdentifierV11 2 23 133 19 1 5 */ + 1401, /* OBJ_tcg_tr_ID_FIPSLevel 2 23 133 19 1 6 */ + 1402, /* OBJ_tcg_tr_ID_ISO9000Level 2 23 133 19 1 7 */ + 1403, /* OBJ_tcg_tr_ID_networkMAC 2 23 133 19 1 8 */ + 1404, /* OBJ_tcg_tr_ID_OID 2 23 133 19 1 9 */ + 1405, /* OBJ_tcg_tr_ID_PEN 2 23 133 19 1 10 */ + 1406, /* OBJ_tcg_tr_ID_platformFirmwareCapabilities 2 23 133 19 1 11 */ + 1407, /* OBJ_tcg_tr_ID_platformFirmwareSignatureVerification 2 23 133 19 1 12 */ + 1408, /* OBJ_tcg_tr_ID_platformFirmwareUpdateCompliance 2 23 133 19 1 13 */ + 1409, /* OBJ_tcg_tr_ID_platformHardwareCapabilities 2 23 133 19 1 14 */ + 1410, /* OBJ_tcg_tr_ID_RTM 2 23 133 19 1 15 */ + 1411, /* OBJ_tcg_tr_ID_status 2 23 133 19 1 16 */ + 1412, /* OBJ_tcg_tr_ID_URI 2 23 133 19 1 17 */ + 1413, /* OBJ_tcg_tr_ID_UTF8String 2 23 133 19 1 18 */ + 1414, /* OBJ_tcg_tr_ID_IA5String 2 23 133 19 1 19 */ + 1415, /* OBJ_tcg_tr_ID_PEMCertString 2 23 133 19 1 20 */ + 1416, /* OBJ_tcg_tr_ID_PublicKey 2 23 133 19 1 21 */ + 1417, /* OBJ_tcg_tr_cat_platformManufacturer 2 23 133 19 2 1 */ + 1418, /* OBJ_tcg_tr_cat_platformModel 2 23 133 19 2 2 */ + 1419, /* OBJ_tcg_tr_cat_platformVersion 2 23 133 19 2 3 */ + 1420, /* OBJ_tcg_tr_cat_platformSerial 2 23 133 19 2 4 */ + 1421, /* OBJ_tcg_tr_cat_platformManufacturerIdentifier 2 23 133 19 2 5 */ + 1422, /* OBJ_tcg_tr_cat_platformOwnership 2 23 133 19 2 6 */ + 1423, /* OBJ_tcg_tr_cat_componentClass 2 23 133 19 2 7 */ + 1424, /* OBJ_tcg_tr_cat_componentManufacturer 2 23 133 19 2 8 */ + 1425, /* OBJ_tcg_tr_cat_componentModel 2 23 133 19 2 9 */ + 1426, /* OBJ_tcg_tr_cat_componentSerial 2 23 133 19 2 10 */ + 1427, /* OBJ_tcg_tr_cat_componentStatus 2 23 133 19 2 11 */ + 1428, /* OBJ_tcg_tr_cat_componentLocation 2 23 133 19 2 12 */ + 1429, /* OBJ_tcg_tr_cat_componentRevision 2 23 133 19 2 13 */ + 1430, /* OBJ_tcg_tr_cat_componentFieldReplaceable 2 23 133 19 2 14 */ + 1431, /* OBJ_tcg_tr_cat_EKCertificate 2 23 133 19 2 15 */ + 1432, /* OBJ_tcg_tr_cat_IAKCertificate 2 23 133 19 2 16 */ + 1433, /* OBJ_tcg_tr_cat_IDevIDCertificate 2 23 133 19 2 17 */ + 1434, /* OBJ_tcg_tr_cat_DICECertificate 2 23 133 19 2 18 */ + 1435, /* OBJ_tcg_tr_cat_SPDMCertificate 2 23 133 19 2 19 */ + 1436, /* OBJ_tcg_tr_cat_PEMCertificate 2 23 133 19 2 20 */ + 1437, /* OBJ_tcg_tr_cat_PlatformCertificate 2 23 133 19 2 21 */ + 1438, /* OBJ_tcg_tr_cat_DeltaPlatformCertificate 2 23 133 19 2 22 */ + 1439, /* OBJ_tcg_tr_cat_RebasePlatformCertificate 2 23 133 19 2 23 */ + 1440, /* OBJ_tcg_tr_cat_genericCertificate 2 23 133 19 2 24 */ + 1441, /* OBJ_tcg_tr_cat_CommonCriteria 2 23 133 19 2 25 */ + 1442, /* OBJ_tcg_tr_cat_componentIdentifierV11 2 23 133 19 2 26 */ + 1443, /* OBJ_tcg_tr_cat_FIPSLevel 2 23 133 19 2 27 */ + 1444, /* OBJ_tcg_tr_cat_ISO9000 2 23 133 19 2 28 */ + 1445, /* OBJ_tcg_tr_cat_networkMAC 2 23 133 19 2 29 */ + 1446, /* OBJ_tcg_tr_cat_attestationProtocol 2 23 133 19 2 30 */ + 1447, /* OBJ_tcg_tr_cat_PEN 2 23 133 19 2 31 */ + 1448, /* OBJ_tcg_tr_cat_platformFirmwareCapabilities 2 23 133 19 2 32 */ + 1449, /* OBJ_tcg_tr_cat_platformHardwareCapabilities 2 23 133 19 2 33 */ + 1450, /* OBJ_tcg_tr_cat_platformFirmwareSignatureVerification 2 23 133 19 2 34 */ + 1451, /* OBJ_tcg_tr_cat_platformFirmwareUpdateCompliance 2 23 133 19 2 35 */ + 1452, /* OBJ_tcg_tr_cat_RTM 2 23 133 19 2 36 */ + 1453, /* OBJ_tcg_tr_cat_PublicKey 2 23 133 19 2 37 */ + 1275, /* OBJ_id_aa_ets_signerAttrV2 0 4 0 19122 1 1 */ + 1276, /* OBJ_id_aa_ets_sigPolicyStore 0 4 0 19122 1 3 */ + 1277, /* OBJ_id_aa_ATSHashIndex_v2 0 4 0 19122 1 4 */ + 1278, /* OBJ_id_aa_ATSHashIndex_v3 0 4 0 19122 1 5 */ + 1279, /* OBJ_signedAssertion 0 4 0 19122 1 6 */ 436, /* OBJ_ucl 0 9 2342 19200300 */ 820, /* OBJ_id_Gost28147_89_None_KeyMeshing 1 2 643 2 2 14 0 */ 819, /* OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1 2 643 2 2 14 1 */ @@ -5303,6 +6421,11 @@ static const unsigned int obj_objs[NUM_OBJ] = { 507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */ 508, /* OBJ_id_hex_multipart_message 1 3 6 1 7 1 1 2 */ 57, /* OBJ_netscape 2 16 840 1 113730 */ + 1282, /* OBJ_oracle 2 16 840 1 113894 */ + 1363, /* OBJ_tcg_at_platformConfiguration_v1 2 23 133 5 1 7 1 */ + 1364, /* OBJ_tcg_at_platformConfiguration_v2 2 23 133 5 1 7 2 */ + 1365, /* OBJ_tcg_at_platformConfiguration_v3 2 23 133 5 1 7 3 */ + 1366, /* OBJ_tcg_at_platformConfigUri_v3 2 23 133 5 1 7 4 */ 754, /* OBJ_camellia_128_ecb 0 3 4401 5 3 1 9 1 */ 766, /* OBJ_camellia_128_ofb128 0 3 4401 5 3 1 9 3 */ 757, /* OBJ_camellia_128_cfb128 0 3 4401 5 3 1 9 4 */ @@ -5332,6 +6455,9 @@ static const unsigned int obj_objs[NUM_OBJ] = { 1136, /* OBJ_sm4_cfb1 1 2 156 10197 1 104 5 */ 1138, /* OBJ_sm4_cfb8 1 2 156 10197 1 104 6 */ 1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */ + 1248, /* OBJ_sm4_gcm 1 2 156 10197 1 104 8 */ + 1249, /* OBJ_sm4_ccm 1 2 156 10197 1 104 9 */ + 1290, /* OBJ_sm4_xts 1 2 156 10197 1 104 10 */ 1172, /* OBJ_sm2 1 2 156 10197 1 301 */ 1143, /* OBJ_sm3 1 2 156 10197 1 401 */ 1204, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */ @@ -5433,10 +6559,13 @@ static const unsigned int obj_objs[NUM_OBJ] = { 282, /* OBJ_id_mod_ocsp 1 3 6 1 5 5 7 0 14 */ 283, /* OBJ_id_mod_dvcs 1 3 6 1 5 5 7 0 15 */ 284, /* OBJ_id_mod_cmp2000 1 3 6 1 5 5 7 0 16 */ + 1251, /* OBJ_id_mod_cmp2000_02 1 3 6 1 5 5 7 0 50 */ + 1252, /* OBJ_id_mod_cmp2021_88 1 3 6 1 5 5 7 0 99 */ + 1253, /* OBJ_id_mod_cmp2021_02 1 3 6 1 5 5 7 0 100 */ 177, /* OBJ_info_access 1 3 6 1 5 5 7 1 1 */ 285, /* OBJ_biometricInfo 1 3 6 1 5 5 7 1 2 */ 286, /* OBJ_qcStatements 1 3 6 1 5 5 7 1 3 */ - 287, /* OBJ_ac_auditEntity 1 3 6 1 5 5 7 1 4 */ + 287, /* OBJ_ac_auditIdentity 1 3 6 1 5 5 7 1 4 */ 288, /* OBJ_ac_targeting 1 3 6 1 5 5 7 1 5 */ 289, /* OBJ_aaControls 1 3 6 1 5 5 7 1 6 */ 290, /* OBJ_sbgp_ipAddrBlock 1 3 6 1 5 5 7 1 7 */ @@ -5495,6 +6624,10 @@ static const unsigned int obj_objs[NUM_OBJ] = { 1223, /* OBJ_id_it_caCerts 1 3 6 1 5 5 7 4 17 */ 1224, /* OBJ_id_it_rootCaKeyUpdate 1 3 6 1 5 5 7 4 18 */ 1225, /* OBJ_id_it_certReqTemplate 1 3 6 1 5 5 7 4 19 */ + 1254, /* OBJ_id_it_rootCaCert 1 3 6 1 5 5 7 4 20 */ + 1255, /* OBJ_id_it_certProfile 1 3 6 1 5 5 7 4 21 */ + 1256, /* OBJ_id_it_crlStatusList 1 3 6 1 5 5 7 4 22 */ + 1257, /* OBJ_id_it_crls 1 3 6 1 5 5 7 4 23 */ 313, /* OBJ_id_regCtrl 1 3 6 1 5 5 7 5 1 */ 314, /* OBJ_id_regInfo 1 3 6 1 5 5 7 5 2 */ 323, /* OBJ_id_alg_des40 1 3 6 1 5 5 7 6 1 */ @@ -5523,6 +6656,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 346, /* OBJ_id_cmc_confirmCertAcceptance 1 3 6 1 5 5 7 7 24 */ 347, /* OBJ_id_on_personalData 1 3 6 1 5 5 7 8 1 */ 858, /* OBJ_id_on_permanentIdentifier 1 3 6 1 5 5 7 8 3 */ + 1321, /* OBJ_id_on_hardwareModuleName 1 3 6 1 5 5 7 8 4 */ 1209, /* OBJ_XmppAddr 1 3 6 1 5 5 7 8 5 */ 1210, /* OBJ_SRVName 1 3 6 1 5 5 7 8 7 */ 1211, /* OBJ_NAIRealm 1 3 6 1 5 5 7 8 8 */ @@ -5651,11 +6785,16 @@ static const unsigned int obj_objs[NUM_OBJ] = { 188, /* OBJ_SMIME 1 2 840 113549 1 9 16 */ 156, /* OBJ_friendlyName 1 2 840 113549 1 9 20 */ 157, /* OBJ_localKeyID 1 2 840 113549 1 9 21 */ + 1263, /* OBJ_id_aa_CMSAlgorithmProtection 1 2 840 113549 1 9 52 */ 681, /* OBJ_X9_62_onBasis 1 2 840 10045 1 2 3 1 */ 682, /* OBJ_X9_62_tpBasis 1 2 840 10045 1 2 3 2 */ 683, /* OBJ_X9_62_ppBasis 1 2 840 10045 1 2 3 3 */ 417, /* OBJ_ms_csp_name 1 3 6 1 4 1 311 17 1 */ 856, /* OBJ_LocalKeySet 1 3 6 1 4 1 311 17 2 */ + 1293, /* OBJ_ms_cert_templ 1 3 6 1 4 1 311 21 7 */ + 1294, /* OBJ_ms_app_policies 1 3 6 1 4 1 311 21 10 */ + 1292, /* OBJ_ms_ntds_sec_ext 1 3 6 1 4 1 311 25 2 */ + 1322, /* OBJ_id_kp_wisun_fan_device 1 3 6 1 4 1 45605 1 */ 390, /* OBJ_dcObject 1 3 6 1 4 1 1466 344 */ 91, /* OBJ_bf_cbc 1 3 6 1 4 1 3029 1 2 */ 973, /* OBJ_id_scrypt 1 3 6 1 4 1 11591 4 11 */ @@ -5665,6 +6804,9 @@ static const unsigned int obj_objs[NUM_OBJ] = { 318, /* OBJ_id_regCtrl_pkiArchiveOptions 1 3 6 1 5 5 7 5 1 4 */ 319, /* OBJ_id_regCtrl_oldCertID 1 3 6 1 5 5 7 5 1 5 */ 320, /* OBJ_id_regCtrl_protocolEncrKey 1 3 6 1 5 5 7 5 1 6 */ + 1258, /* OBJ_id_regCtrl_altCertTemplate 1 3 6 1 5 5 7 5 1 7 */ + 1259, /* OBJ_id_regCtrl_algId 1 3 6 1 5 5 7 5 1 11 */ + 1260, /* OBJ_id_regCtrl_rsaKeyLen 1 3 6 1 5 5 7 5 1 12 */ 321, /* OBJ_id_regInfo_utf8Pairs 1 3 6 1 5 5 7 5 2 1 */ 322, /* OBJ_id_regInfo_certReq 1 3 6 1 5 5 7 5 2 2 */ 365, /* OBJ_id_pkix_OCSP_basic 1 3 6 1 5 5 7 48 1 1 */ @@ -5752,6 +6894,39 @@ static const unsigned int obj_objs[NUM_OBJ] = { 1117, /* OBJ_RSA_SHA3_256 2 16 840 1 101 3 4 3 14 */ 1118, /* OBJ_RSA_SHA3_384 2 16 840 1 101 3 4 3 15 */ 1119, /* OBJ_RSA_SHA3_512 2 16 840 1 101 3 4 3 16 */ + 1457, /* OBJ_ML_DSA_44 2 16 840 1 101 3 4 3 17 */ + 1458, /* OBJ_ML_DSA_65 2 16 840 1 101 3 4 3 18 */ + 1459, /* OBJ_ML_DSA_87 2 16 840 1 101 3 4 3 19 */ + 1460, /* OBJ_SLH_DSA_SHA2_128s 2 16 840 1 101 3 4 3 20 */ + 1461, /* OBJ_SLH_DSA_SHA2_128f 2 16 840 1 101 3 4 3 21 */ + 1462, /* OBJ_SLH_DSA_SHA2_192s 2 16 840 1 101 3 4 3 22 */ + 1463, /* OBJ_SLH_DSA_SHA2_192f 2 16 840 1 101 3 4 3 23 */ + 1464, /* OBJ_SLH_DSA_SHA2_256s 2 16 840 1 101 3 4 3 24 */ + 1465, /* OBJ_SLH_DSA_SHA2_256f 2 16 840 1 101 3 4 3 25 */ + 1466, /* OBJ_SLH_DSA_SHAKE_128s 2 16 840 1 101 3 4 3 26 */ + 1467, /* OBJ_SLH_DSA_SHAKE_128f 2 16 840 1 101 3 4 3 27 */ + 1468, /* OBJ_SLH_DSA_SHAKE_192s 2 16 840 1 101 3 4 3 28 */ + 1469, /* OBJ_SLH_DSA_SHAKE_192f 2 16 840 1 101 3 4 3 29 */ + 1470, /* OBJ_SLH_DSA_SHAKE_256s 2 16 840 1 101 3 4 3 30 */ + 1471, /* OBJ_SLH_DSA_SHAKE_256f 2 16 840 1 101 3 4 3 31 */ + 1472, /* OBJ_HASH_ML_DSA_44_WITH_SHA512 2 16 840 1 101 3 4 3 32 */ + 1473, /* OBJ_HASH_ML_DSA_65_WITH_SHA512 2 16 840 1 101 3 4 3 33 */ + 1474, /* OBJ_HASH_ML_DSA_87_WITH_SHA512 2 16 840 1 101 3 4 3 34 */ + 1475, /* OBJ_SLH_DSA_SHA2_128s_WITH_SHA256 2 16 840 1 101 3 4 3 35 */ + 1476, /* OBJ_SLH_DSA_SHA2_128f_WITH_SHA256 2 16 840 1 101 3 4 3 36 */ + 1477, /* OBJ_SLH_DSA_SHA2_192s_WITH_SHA512 2 16 840 1 101 3 4 3 37 */ + 1478, /* OBJ_SLH_DSA_SHA2_192f_WITH_SHA512 2 16 840 1 101 3 4 3 38 */ + 1479, /* OBJ_SLH_DSA_SHA2_256s_WITH_SHA512 2 16 840 1 101 3 4 3 39 */ + 1480, /* OBJ_SLH_DSA_SHA2_256f_WITH_SHA512 2 16 840 1 101 3 4 3 40 */ + 1481, /* OBJ_SLH_DSA_SHAKE_128s_WITH_SHAKE128 2 16 840 1 101 3 4 3 41 */ + 1482, /* OBJ_SLH_DSA_SHAKE_128f_WITH_SHAKE128 2 16 840 1 101 3 4 3 42 */ + 1483, /* OBJ_SLH_DSA_SHAKE_192s_WITH_SHAKE256 2 16 840 1 101 3 4 3 43 */ + 1484, /* OBJ_SLH_DSA_SHAKE_192f_WITH_SHAKE256 2 16 840 1 101 3 4 3 44 */ + 1485, /* OBJ_SLH_DSA_SHAKE_256s_WITH_SHAKE256 2 16 840 1 101 3 4 3 45 */ + 1486, /* OBJ_SLH_DSA_SHAKE_256f_WITH_SHAKE256 2 16 840 1 101 3 4 3 46 */ + 1454, /* OBJ_ML_KEM_512 2 16 840 1 101 3 4 4 1 */ + 1455, /* OBJ_ML_KEM_768 2 16 840 1 101 3 4 4 2 */ + 1456, /* OBJ_ML_KEM_1024 2 16 840 1 101 3 4 4 3 */ 71, /* OBJ_netscape_cert_type 2 16 840 1 113730 1 1 */ 72, /* OBJ_netscape_base_url 2 16 840 1 113730 1 2 */ 73, /* OBJ_netscape_revocation_url 2 16 840 1 113730 1 3 */ @@ -5826,6 +7001,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 455, /* OBJ_pilotOrganization 0 9 2342 19200300 100 4 20 */ 456, /* OBJ_pilotDSA 0 9 2342 19200300 100 4 21 */ 457, /* OBJ_qualityLabelledData 0 9 2342 19200300 100 4 22 */ + 1281, /* OBJ_hmacWithSM3 1 2 156 10197 1 401 3 1 */ 1152, /* OBJ_dstu28147 1 2 804 2 1 1 1 1 1 1 */ 1156, /* OBJ_hmacWithDstu34311 1 2 804 2 1 1 1 1 1 2 */ 1157, /* OBJ_dstu34311 1 2 804 2 1 1 1 1 2 1 */ @@ -5853,6 +7029,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 138, /* OBJ_ms_efs 1 3 6 1 4 1 311 10 3 4 */ 648, /* OBJ_ms_smartcard_login 1 3 6 1 4 1 311 20 2 2 */ 649, /* OBJ_ms_upn 1 3 6 1 4 1 311 20 2 3 */ + 1291, /* OBJ_ms_ntds_obj_sid 1 3 6 1 4 1 311 25 2 1 */ 1201, /* OBJ_blake2bmac 1 3 6 1 4 1 1722 12 2 1 */ 1202, /* OBJ_blake2smac 1 3 6 1 4 1 1722 12 2 2 */ 951, /* OBJ_ct_precert_scts 1 3 6 1 4 1 11129 2 4 2 */ @@ -5896,6 +7073,9 @@ static const unsigned int obj_objs[NUM_OBJ] = { 1237, /* OBJ_id_ct_resourceTaggedAttest 1 2 840 113549 1 9 16 1 36 */ 1246, /* OBJ_id_ct_geofeedCSVwithCRLF 1 2 840 113549 1 9 16 1 47 */ 1247, /* OBJ_id_ct_signedChecklist 1 2 840 113549 1 9 16 1 48 */ + 1250, /* OBJ_id_ct_ASPA 1 2 840 113549 1 9 16 1 49 */ + 1284, /* OBJ_id_ct_signedTAL 1 2 840 113549 1 9 16 1 50 */ + 1320, /* OBJ_id_ct_rpkiSignedPrefixList 1 2 840 113549 1 9 16 1 51 */ 212, /* OBJ_id_smime_aa_receiptRequest 1 2 840 113549 1 9 16 2 1 */ 213, /* OBJ_id_smime_aa_securityLabel 1 2 840 113549 1 9 16 2 2 */ 214, /* OBJ_id_smime_aa_mlExpandHistory 1 2 840 113549 1 9 16 2 3 */ @@ -5925,7 +7105,10 @@ static const unsigned int obj_objs[NUM_OBJ] = { 238, /* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */ 239, /* OBJ_id_smime_aa_signatureType 1 2 840 113549 1 9 16 2 28 */ 240, /* OBJ_id_smime_aa_dvcs_dvc 1 2 840 113549 1 9 16 2 29 */ + 1261, /* OBJ_id_aa_ets_attrCertificateRefs 1 2 840 113549 1 9 16 2 44 */ + 1262, /* OBJ_id_aa_ets_attrRevocationRefs 1 2 840 113549 1 9 16 2 45 */ 1086, /* OBJ_id_smime_aa_signingCertificateV2 1 2 840 113549 1 9 16 2 47 */ + 1280, /* OBJ_id_aa_ets_archiveTimestampV2 1 2 840 113549 1 9 16 2 48 */ 241, /* OBJ_id_smime_alg_ESDHwith3DES 1 2 840 113549 1 9 16 3 1 */ 242, /* OBJ_id_smime_alg_ESDHwithRC2 1 2 840 113549 1 9 16 3 2 */ 243, /* OBJ_id_smime_alg_3DESwrap 1 2 840 113549 1 9 16 3 3 */ @@ -5956,6 +7139,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 957, /* OBJ_jurisdictionCountryName 1 3 6 1 4 1 311 60 2 1 3 */ 1056, /* OBJ_blake2b512 1 3 6 1 4 1 1722 12 2 1 16 */ 1057, /* OBJ_blake2s256 1 3 6 1 4 1 1722 12 2 2 8 */ + 1283, /* OBJ_oracle_jdk_trustedkeyusage 2 16 840 1 113894 746875 1 1 */ 1159, /* OBJ_dstu4145be 1 2 804 2 1 1 1 1 3 1 1 1 1 */ 1160, /* OBJ_uacurve0 1 2 804 2 1 1 1 1 3 1 1 2 0 */ 1161, /* OBJ_uacurve1 1 2 804 2 1 1 1 1 3 1 1 2 1 */ diff --git a/crypto/objects/obj_dat.pl b/crypto/objects/obj_dat.pl index 60a5e5a6833e..510a906f57fd 100644 --- a/crypto/objects/obj_dat.pl +++ b/crypto/objects/obj_dat.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -134,7 +134,7 @@ for (my $i = 0; $i < $n; $i++) { my $r = &der_it($v); my $z = ""; my $length = 0; - # Format using fixed-with because we use strcmp later. + # Format using fixed-width because we use strcmp later. foreach (unpack("C*",$r)) { $z .= sprintf("0x%02X,", $_); $length++; diff --git a/crypto/objects/obj_lib.c b/crypto/objects/obj_lib.c index 72c0c2c81dd9..6cdc1d7e7465 100644 --- a/crypto/objects/obj_lib.c +++ b/crypto/objects/obj_lib.c @@ -50,7 +50,6 @@ ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) return r; err: ASN1_OBJECT_free(r); - ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); return NULL; } diff --git a/crypto/objects/obj_local.h b/crypto/objects/obj_local.h index 4436b799fd3b..73848a6fbfe1 100644 --- a/crypto/objects/obj_local.h +++ b/crypto/objects/obj_local.h @@ -9,6 +9,6 @@ typedef struct name_funcs_st NAME_FUNCS; DEFINE_STACK_OF(NAME_FUNCS) -DEFINE_LHASH_OF(OBJ_NAME); +DEFINE_LHASH_OF_EX(OBJ_NAME); typedef struct added_obj_st ADDED_OBJ; -DEFINE_LHASH_OF(ADDED_OBJ); +DEFINE_LHASH_OF_EX(ADDED_OBJ); diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index c626558ad5c1..80413e087a09 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -284,7 +284,7 @@ id_mod_dvcs 283 id_mod_cmp2000 284 biometricInfo 285 qcStatements 286 -ac_auditEntity 287 +ac_auditIdentity 287 ac_targeting 288 aaControls 289 sbgp_ipAddrBlock 290 @@ -1245,3 +1245,242 @@ signedObject 1244 rpkiNotify 1245 id_ct_geofeedCSVwithCRLF 1246 id_ct_signedChecklist 1247 +sm4_gcm 1248 +sm4_ccm 1249 +id_ct_ASPA 1250 +id_mod_cmp2000_02 1251 +id_mod_cmp2021_88 1252 +id_mod_cmp2021_02 1253 +id_it_rootCaCert 1254 +id_it_certProfile 1255 +id_it_crlStatusList 1256 +id_it_crls 1257 +id_regCtrl_altCertTemplate 1258 +id_regCtrl_algId 1259 +id_regCtrl_rsaKeyLen 1260 +id_aa_ets_attrCertificateRefs 1261 +id_aa_ets_attrRevocationRefs 1262 +id_aa_CMSAlgorithmProtection 1263 +itu_t_identified_organization 1264 +etsi 1265 +electronic_signature_standard 1266 +ess_attributes 1267 +id_aa_ets_mimeType 1268 +id_aa_ets_longTermValidation 1269 +id_aa_ets_SignaturePolicyDocument 1270 +id_aa_ets_archiveTimestampV3 1271 +id_aa_ATSHashIndex 1272 +cades 1273 +cades_attributes 1274 +id_aa_ets_signerAttrV2 1275 +id_aa_ets_sigPolicyStore 1276 +id_aa_ATSHashIndex_v2 1277 +id_aa_ATSHashIndex_v3 1278 +signedAssertion 1279 +id_aa_ets_archiveTimestampV2 1280 +hmacWithSM3 1281 +oracle 1282 +oracle_jdk_trustedkeyusage 1283 +id_ct_signedTAL 1284 +brainpoolP256r1tls13 1285 +brainpoolP384r1tls13 1286 +brainpoolP512r1tls13 1287 +brotli 1288 +zstd 1289 +sm4_xts 1290 +ms_ntds_obj_sid 1291 +ms_ntds_sec_ext 1292 +ms_cert_templ 1293 +ms_app_policies 1294 +authority_attribute_identifier 1295 +role_spec_cert_identifier 1296 +basic_att_constraints 1297 +delegated_name_constraints 1298 +time_specification 1299 +attribute_descriptor 1300 +user_notice 1301 +soa_identifier 1302 +acceptable_cert_policies 1303 +acceptable_privilege_policies 1304 +indirect_issuer 1305 +no_assertion 1306 +id_aa_issuing_distribution_point 1307 +issued_on_behalf_of 1308 +single_use 1309 +group_ac 1310 +allowed_attribute_assignments 1311 +attribute_mappings 1312 +holder_name_constraints 1313 +authorization_validation 1314 +prot_restrict 1315 +subject_alt_public_key_info 1316 +alt_signature_algorithm 1317 +alt_signature_value 1318 +associated_information 1319 +id_ct_rpkiSignedPrefixList 1320 +id_on_hardwareModuleName 1321 +id_kp_wisun_fan_device 1322 +ac_auditEntity 1323 +tcg 1324 +tcg_tcpaSpecVersion 1325 +tcg_attribute 1326 +tcg_protocol 1327 +tcg_algorithm 1328 +tcg_platformClass 1329 +tcg_ce 1330 +tcg_kp 1331 +tcg_ca 1332 +tcg_address 1333 +tcg_registry 1334 +tcg_traits 1335 +tcg_common 1336 +tcg_at_platformManufacturerStr 1337 +tcg_at_platformManufacturerId 1338 +tcg_at_platformConfigUri 1339 +tcg_at_platformModel 1340 +tcg_at_platformVersion 1341 +tcg_at_platformSerial 1342 +tcg_at_platformConfiguration 1343 +tcg_at_platformIdentifier 1344 +tcg_at_tpmManufacturer 1345 +tcg_at_tpmModel 1346 +tcg_at_tpmVersion 1347 +tcg_at_securityQualities 1348 +tcg_at_tpmProtectionProfile 1349 +tcg_at_tpmSecurityTarget 1350 +tcg_at_tbbProtectionProfile 1351 +tcg_at_tbbSecurityTarget 1352 +tcg_at_tpmIdLabel 1353 +tcg_at_tpmSpecification 1354 +tcg_at_tcgPlatformSpecification 1355 +tcg_at_tpmSecurityAssertions 1356 +tcg_at_tbbSecurityAssertions 1357 +tcg_at_tcgCredentialSpecification 1358 +tcg_at_tcgCredentialType 1359 +tcg_at_previousPlatformCertificates 1360 +tcg_at_tbbSecurityAssertions_v3 1361 +tcg_at_cryptographicAnchors 1362 +tcg_at_platformConfiguration_v1 1363 +tcg_at_platformConfiguration_v2 1364 +tcg_at_platformConfiguration_v3 1365 +tcg_at_platformConfigUri_v3 1366 +tcg_algorithm_null 1367 +tcg_kp_EKCertificate 1368 +tcg_kp_PlatformAttributeCertificate 1369 +tcg_kp_AIKCertificate 1370 +tcg_kp_PlatformKeyCertificate 1371 +tcg_kp_DeltaPlatformAttributeCertificate 1372 +tcg_kp_DeltaPlatformKeyCertificate 1373 +tcg_kp_AdditionalPlatformAttributeCertificate 1374 +tcg_kp_AdditionalPlatformKeyCertificate 1375 +tcg_ce_relevantCredentials 1376 +tcg_ce_relevantManifests 1377 +tcg_ce_virtualPlatformAttestationService 1378 +tcg_ce_migrationControllerAttestationService 1379 +tcg_ce_migrationControllerRegistrationService 1380 +tcg_ce_virtualPlatformBackupService 1381 +tcg_prt_tpmIdProtocol 1382 +tcg_address_ethernetmac 1383 +tcg_address_wlanmac 1384 +tcg_address_bluetoothmac 1385 +tcg_registry_componentClass 1386 +tcg_registry_componentClass_tcg 1387 +tcg_registry_componentClass_ietf 1388 +tcg_registry_componentClass_dmtf 1389 +tcg_registry_componentClass_pcie 1390 +tcg_registry_componentClass_disk 1391 +tcg_cap_verifiedPlatformCertificate 1392 +tcg_tr_ID 1393 +tcg_tr_category 1394 +tcg_tr_registry 1395 +tcg_tr_ID_Boolean 1396 +tcg_tr_ID_CertificateIdentifier 1397 +tcg_tr_ID_CommonCriteria 1398 +tcg_tr_ID_componentClass 1399 +tcg_tr_ID_componentIdentifierV11 1400 +tcg_tr_ID_FIPSLevel 1401 +tcg_tr_ID_ISO9000Level 1402 +tcg_tr_ID_networkMAC 1403 +tcg_tr_ID_OID 1404 +tcg_tr_ID_PEN 1405 +tcg_tr_ID_platformFirmwareCapabilities 1406 +tcg_tr_ID_platformFirmwareSignatureVerification 1407 +tcg_tr_ID_platformFirmwareUpdateCompliance 1408 +tcg_tr_ID_platformHardwareCapabilities 1409 +tcg_tr_ID_RTM 1410 +tcg_tr_ID_status 1411 +tcg_tr_ID_URI 1412 +tcg_tr_ID_UTF8String 1413 +tcg_tr_ID_IA5String 1414 +tcg_tr_ID_PEMCertString 1415 +tcg_tr_ID_PublicKey 1416 +tcg_tr_cat_platformManufacturer 1417 +tcg_tr_cat_platformModel 1418 +tcg_tr_cat_platformVersion 1419 +tcg_tr_cat_platformSerial 1420 +tcg_tr_cat_platformManufacturerIdentifier 1421 +tcg_tr_cat_platformOwnership 1422 +tcg_tr_cat_componentClass 1423 +tcg_tr_cat_componentManufacturer 1424 +tcg_tr_cat_componentModel 1425 +tcg_tr_cat_componentSerial 1426 +tcg_tr_cat_componentStatus 1427 +tcg_tr_cat_componentLocation 1428 +tcg_tr_cat_componentRevision 1429 +tcg_tr_cat_componentFieldReplaceable 1430 +tcg_tr_cat_EKCertificate 1431 +tcg_tr_cat_IAKCertificate 1432 +tcg_tr_cat_IDevIDCertificate 1433 +tcg_tr_cat_DICECertificate 1434 +tcg_tr_cat_SPDMCertificate 1435 +tcg_tr_cat_PEMCertificate 1436 +tcg_tr_cat_PlatformCertificate 1437 +tcg_tr_cat_DeltaPlatformCertificate 1438 +tcg_tr_cat_RebasePlatformCertificate 1439 +tcg_tr_cat_genericCertificate 1440 +tcg_tr_cat_CommonCriteria 1441 +tcg_tr_cat_componentIdentifierV11 1442 +tcg_tr_cat_FIPSLevel 1443 +tcg_tr_cat_ISO9000 1444 +tcg_tr_cat_networkMAC 1445 +tcg_tr_cat_attestationProtocol 1446 +tcg_tr_cat_PEN 1447 +tcg_tr_cat_platformFirmwareCapabilities 1448 +tcg_tr_cat_platformHardwareCapabilities 1449 +tcg_tr_cat_platformFirmwareSignatureVerification 1450 +tcg_tr_cat_platformFirmwareUpdateCompliance 1451 +tcg_tr_cat_RTM 1452 +tcg_tr_cat_PublicKey 1453 +ML_KEM_512 1454 +ML_KEM_768 1455 +ML_KEM_1024 1456 +ML_DSA_44 1457 +ML_DSA_65 1458 +ML_DSA_87 1459 +SLH_DSA_SHA2_128s 1460 +SLH_DSA_SHA2_128f 1461 +SLH_DSA_SHA2_192s 1462 +SLH_DSA_SHA2_192f 1463 +SLH_DSA_SHA2_256s 1464 +SLH_DSA_SHA2_256f 1465 +SLH_DSA_SHAKE_128s 1466 +SLH_DSA_SHAKE_128f 1467 +SLH_DSA_SHAKE_192s 1468 +SLH_DSA_SHAKE_192f 1469 +SLH_DSA_SHAKE_256s 1470 +SLH_DSA_SHAKE_256f 1471 +HASH_ML_DSA_44_WITH_SHA512 1472 +HASH_ML_DSA_65_WITH_SHA512 1473 +HASH_ML_DSA_87_WITH_SHA512 1474 +SLH_DSA_SHA2_128s_WITH_SHA256 1475 +SLH_DSA_SHA2_128f_WITH_SHA256 1476 +SLH_DSA_SHA2_192s_WITH_SHA512 1477 +SLH_DSA_SHA2_192f_WITH_SHA512 1478 +SLH_DSA_SHA2_256s_WITH_SHA512 1479 +SLH_DSA_SHA2_256f_WITH_SHA512 1480 +SLH_DSA_SHAKE_128s_WITH_SHAKE128 1481 +SLH_DSA_SHAKE_128f_WITH_SHAKE128 1482 +SLH_DSA_SHAKE_192s_WITH_SHAKE256 1483 +SLH_DSA_SHAKE_192f_WITH_SHAKE256 1484 +SLH_DSA_SHAKE_256s_WITH_SHAKE256 1485 +SLH_DSA_SHAKE_256f_WITH_SHAKE256 1486 diff --git a/crypto/objects/obj_xref.c b/crypto/objects/obj_xref.c index da1035112f4f..2eb757cb774c 100644 --- a/crypto/objects/obj_xref.c +++ b/crypto/objects/obj_xref.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,9 +10,11 @@ #include #include "obj_xref.h" #include "internal/nelem.h" +#include "internal/thread_once.h" #include static STACK_OF(nid_triple) *sig_app, *sigx_app; +static CRYPTO_RWLOCK *sig_lock; static int sig_cmp(const nid_triple *a, const nid_triple *b) { @@ -32,62 +34,112 @@ DECLARE_OBJ_BSEARCH_CMP_FN(const nid_triple *, const nid_triple *, sigx); static int sigx_cmp(const nid_triple *const *a, const nid_triple *const *b) { int ret; + ret = (*a)->hash_id - (*b)->hash_id; - if (ret) + /* The "b" side of the comparison carries the algorithms already + * registered. A NID_undef for 'hash_id' there means that the + * signature algorithm doesn't need a digest to operate OK. In + * such case, any hash_id/digest algorithm on the test side (a), + * incl. NID_undef, is acceptable. signature algorithm NID + * (pkey_id) must match in any case. + */ + if ((ret != 0) && ((*b)->hash_id != NID_undef)) return ret; return (*a)->pkey_id - (*b)->pkey_id; } IMPLEMENT_OBJ_BSEARCH_CMP_FN(const nid_triple *, const nid_triple *, sigx); -int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid) +static CRYPTO_ONCE sig_init = CRYPTO_ONCE_STATIC_INIT; + +DEFINE_RUN_ONCE_STATIC(o_sig_init) +{ + sig_lock = CRYPTO_THREAD_lock_new(); + return sig_lock != NULL; +} + +static ossl_inline int obj_sig_init(void) +{ + return RUN_ONCE(&sig_init, o_sig_init); +} + +static int ossl_obj_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid, + int lock) { nid_triple tmp; - const nid_triple *rv = NULL; - tmp.sign_id = signid; + const nid_triple *rv; + int idx; - if (sig_app != NULL) { - int idx = sk_nid_triple_find(sig_app, &tmp); - rv = sk_nid_triple_value(sig_app, idx); - } -#ifndef OBJ_XREF_TEST2 - if (rv == NULL) { - rv = OBJ_bsearch_sig(&tmp, sigoid_srt, OSSL_NELEM(sigoid_srt)); - } -#endif - if (rv == NULL) + if (signid == NID_undef) return 0; - if (pdig_nid) + + tmp.sign_id = signid; + rv = OBJ_bsearch_sig(&tmp, sigoid_srt, OSSL_NELEM(sigoid_srt)); + if (rv == NULL) { + if (!obj_sig_init()) + return 0; + if (lock && !CRYPTO_THREAD_read_lock(sig_lock)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return 0; + } + if (sig_app != NULL) { + idx = sk_nid_triple_find(sig_app, &tmp); + if (idx >= 0) + rv = sk_nid_triple_value(sig_app, idx); + } + if (lock) + CRYPTO_THREAD_unlock(sig_lock); + if (rv == NULL) + return 0; + } + + if (pdig_nid != NULL) *pdig_nid = rv->hash_id; - if (ppkey_nid) + if (ppkey_nid != NULL) *ppkey_nid = rv->pkey_id; return 1; } +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid) +{ + return ossl_obj_find_sigid_algs(signid, pdig_nid, ppkey_nid, 1); +} + int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid) { nid_triple tmp; const nid_triple *t = &tmp; - const nid_triple **rv = NULL; + const nid_triple **rv; + int idx; + + /* permitting searches for sig algs without digest: */ + if (pkey_nid == NID_undef) + return 0; tmp.hash_id = dig_nid; tmp.pkey_id = pkey_nid; - if (sigx_app) { - int idx = sk_nid_triple_find(sigx_app, &tmp); - if (idx >= 0) { - t = sk_nid_triple_value(sigx_app, idx); - rv = &t; - } - } -#ifndef OBJ_XREF_TEST2 + rv = OBJ_bsearch_sigx(&t, sigoid_srt_xref, OSSL_NELEM(sigoid_srt_xref)); if (rv == NULL) { - rv = OBJ_bsearch_sigx(&t, sigoid_srt_xref, OSSL_NELEM(sigoid_srt_xref)); + if (!obj_sig_init()) + return 0; + if (!CRYPTO_THREAD_read_lock(sig_lock)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK); + return 0; + } + if (sigx_app != NULL) { + idx = sk_nid_triple_find(sigx_app, &tmp); + if (idx >= 0) { + t = sk_nid_triple_value(sigx_app, idx); + rv = &t; + } + } + CRYPTO_THREAD_unlock(sig_lock); + if (rv == NULL) + return 0; } -#endif - if (rv == NULL) - return 0; - if (psignid) + + if (psignid != NULL) *psignid = (*rv)->sign_id; return 1; } @@ -95,34 +147,63 @@ int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid) int OBJ_add_sigid(int signid, int dig_id, int pkey_id) { nid_triple *ntr; - if (sig_app == NULL) - sig_app = sk_nid_triple_new(sig_sk_cmp); - if (sig_app == NULL) + int dnid = NID_undef, pnid = NID_undef, ret = 0; + + if (signid == NID_undef || pkey_id == NID_undef) return 0; - if (sigx_app == NULL) - sigx_app = sk_nid_triple_new(sigx_cmp); - if (sigx_app == NULL) + + if (!obj_sig_init()) return 0; - if ((ntr = OPENSSL_malloc(sizeof(*ntr))) == NULL) { - ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE); + + if ((ntr = OPENSSL_malloc(sizeof(*ntr))) == NULL) return 0; - } ntr->sign_id = signid; ntr->hash_id = dig_id; ntr->pkey_id = pkey_id; - if (!sk_nid_triple_push(sig_app, ntr)) { + if (!CRYPTO_THREAD_write_lock(sig_lock)) { + ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK); OPENSSL_free(ntr); return 0; } - if (!sk_nid_triple_push(sigx_app, ntr)) - return 0; + /* Check that the entry doesn't exist or exists as desired */ + if (ossl_obj_find_sigid_algs(signid, &dnid, &pnid, 0)) { + ret = dnid == dig_id && pnid == pkey_id; + goto err; + } + + if (sig_app == NULL) { + sig_app = sk_nid_triple_new(sig_sk_cmp); + if (sig_app == NULL) + goto err; + } + if (sigx_app == NULL) { + sigx_app = sk_nid_triple_new(sigx_cmp); + if (sigx_app == NULL) + goto err; + } + + /* + * Better might be to find where to insert the element and insert it there. + * This would avoid the sorting steps below. + */ + if (!sk_nid_triple_push(sig_app, ntr)) + goto err; + if (!sk_nid_triple_push(sigx_app, ntr)) { + ntr = NULL; /* This is referenced by sig_app still */ + goto err; + } sk_nid_triple_sort(sig_app); sk_nid_triple_sort(sigx_app); - return 1; + ntr = NULL; + ret = 1; + err: + OPENSSL_free(ntr); + CRYPTO_THREAD_unlock(sig_lock); + return ret; } static void sid_free(nid_triple *tt) @@ -133,7 +214,9 @@ static void sid_free(nid_triple *tt) void OBJ_sigid_free(void) { sk_nid_triple_pop_free(sig_app, sid_free); - sig_app = NULL; sk_nid_triple_free(sigx_app); + CRYPTO_THREAD_lock_free(sig_lock); + sig_app = NULL; sigx_app = NULL; + sig_lock = NULL; } diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h index 21a193ee98bc..fed298906e9a 100644 --- a/crypto/objects/obj_xref.h +++ b/crypto/objects/obj_xref.h @@ -2,7 +2,7 @@ * WARNING: do not edit! * Generated by objxref.pl * - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -75,11 +75,30 @@ static const nid_triple sigoid_srt[] = { NID_id_GostR3410_2012_512}, {NID_ED25519, NID_undef, NID_ED25519}, {NID_ED448, NID_undef, NID_ED448}, + {NID_ecdsa_with_SHA3_224, NID_sha3_224, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA3_256, NID_sha3_256, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA3_384, NID_sha3_384, NID_X9_62_id_ecPublicKey}, + {NID_ecdsa_with_SHA3_512, NID_sha3_512, NID_X9_62_id_ecPublicKey}, {NID_RSA_SHA3_224, NID_sha3_224, NID_rsaEncryption}, {NID_RSA_SHA3_256, NID_sha3_256, NID_rsaEncryption}, {NID_RSA_SHA3_384, NID_sha3_384, NID_rsaEncryption}, {NID_RSA_SHA3_512, NID_sha3_512, NID_rsaEncryption}, {NID_SM2_with_SM3, NID_sm3, NID_sm2}, + {NID_ML_DSA_44, NID_undef, NID_ML_DSA_44}, + {NID_ML_DSA_65, NID_undef, NID_ML_DSA_65}, + {NID_ML_DSA_87, NID_undef, NID_ML_DSA_87}, + {NID_SLH_DSA_SHA2_128s, NID_undef, NID_SLH_DSA_SHA2_128s}, + {NID_SLH_DSA_SHA2_128f, NID_undef, NID_SLH_DSA_SHA2_128f}, + {NID_SLH_DSA_SHA2_192s, NID_undef, NID_SLH_DSA_SHA2_192s}, + {NID_SLH_DSA_SHA2_192f, NID_undef, NID_SLH_DSA_SHA2_192f}, + {NID_SLH_DSA_SHA2_256s, NID_undef, NID_SLH_DSA_SHA2_256s}, + {NID_SLH_DSA_SHA2_256f, NID_undef, NID_SLH_DSA_SHA2_256f}, + {NID_SLH_DSA_SHAKE_128s, NID_undef, NID_SLH_DSA_SHAKE_128s}, + {NID_SLH_DSA_SHAKE_128f, NID_undef, NID_SLH_DSA_SHAKE_128f}, + {NID_SLH_DSA_SHAKE_192s, NID_undef, NID_SLH_DSA_SHAKE_192s}, + {NID_SLH_DSA_SHAKE_192f, NID_undef, NID_SLH_DSA_SHAKE_192f}, + {NID_SLH_DSA_SHAKE_256s, NID_undef, NID_SLH_DSA_SHAKE_256s}, + {NID_SLH_DSA_SHAKE_256f, NID_undef, NID_SLH_DSA_SHAKE_256f}, }; static const nid_triple *const sigoid_srt_xref[] = { @@ -122,9 +141,13 @@ static const nid_triple *const sigoid_srt_xref[] = { &sigoid_srt[28], &sigoid_srt[40], &sigoid_srt[41], - &sigoid_srt[44], - &sigoid_srt[45], - &sigoid_srt[46], - &sigoid_srt[47], &sigoid_srt[48], + &sigoid_srt[44], + &sigoid_srt[49], + &sigoid_srt[45], + &sigoid_srt[50], + &sigoid_srt[46], + &sigoid_srt[51], + &sigoid_srt[47], + &sigoid_srt[52], }; diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt index 2a61d4db5927..71bc12af7454 100644 --- a/crypto/objects/obj_xref.txt +++ b/crypto/objects/obj_xref.txt @@ -23,6 +23,21 @@ RSA_SHA3_512 sha3_512 rsaEncryption rsassaPss undef rsassaPss ED25519 undef ED25519 ED448 undef ED448 +ML_DSA_44 undef ML_DSA_44 +ML_DSA_65 undef ML_DSA_65 +ML_DSA_87 undef ML_DSA_87 +SLH_DSA_SHA2_128s undef SLH_DSA_SHA2_128s +SLH_DSA_SHA2_128f undef SLH_DSA_SHA2_128f +SLH_DSA_SHA2_192s undef SLH_DSA_SHA2_192s +SLH_DSA_SHA2_192f undef SLH_DSA_SHA2_192f +SLH_DSA_SHA2_256s undef SLH_DSA_SHA2_256s +SLH_DSA_SHA2_256f undef SLH_DSA_SHA2_256f +SLH_DSA_SHAKE_128s undef SLH_DSA_SHAKE_128s +SLH_DSA_SHAKE_128f undef SLH_DSA_SHAKE_128f +SLH_DSA_SHAKE_192s undef SLH_DSA_SHAKE_192s +SLH_DSA_SHAKE_192f undef SLH_DSA_SHAKE_192f +SLH_DSA_SHAKE_256s undef SLH_DSA_SHAKE_256s +SLH_DSA_SHAKE_256f undef SLH_DSA_SHAKE_256f # Alternative deprecated OIDs. By using the older "rsa" OID this # type will be recognized by not normally used. @@ -42,6 +57,10 @@ ecdsa_with_SHA384 sha384 X9_62_id_ecPublicKey ecdsa_with_SHA512 sha512 X9_62_id_ecPublicKey ecdsa_with_Recommended undef X9_62_id_ecPublicKey ecdsa_with_Specified undef X9_62_id_ecPublicKey +ecdsa_with_SHA3_224 sha3_224 X9_62_id_ecPublicKey +ecdsa_with_SHA3_256 sha3_256 X9_62_id_ecPublicKey +ecdsa_with_SHA3_384 sha3_384 X9_62_id_ecPublicKey +ecdsa_with_SHA3_512 sha3_512 X9_62_id_ecPublicKey dsa_with_SHA224 sha224 dsa dsa_with_SHA256 sha256 dsa diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 51dba7dcf397..06fe6f4bdadf 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -282,6 +282,9 @@ id-smime-ct 35 : id-ct-rpkiGhostbusters id-smime-ct 36 : id-ct-resourceTaggedAttest id-smime-ct 47 : id-ct-geofeedCSVwithCRLF id-smime-ct 48 : id-ct-signedChecklist +id-smime-ct 49 : id-ct-ASPA +id-smime-ct 50 : id-ct-signedTAL +id-smime-ct 51 : id-ct-rpkiSignedPrefixList # S/MIME Attributes id-smime-aa 1 : id-smime-aa-receiptRequest @@ -315,7 +318,10 @@ id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp id-smime-aa 28 : id-smime-aa-signatureType id-smime-aa 29 : id-smime-aa-dvcs-dvc +id-smime-aa 44 : id-aa-ets-attrCertificateRefs +id-smime-aa 45 : id-aa-ets-attrRevocationRefs id-smime-aa 47 : id-smime-aa-signingCertificateV2 +id-smime-aa 48 : id-aa-ets-archiveTimestampV2 # S/MIME Algorithm Identifiers # obsolete @@ -348,15 +354,18 @@ id-smime-cti 6 : id-smime-cti-ets-proofOfCreation pkcs9 20 : : friendlyName pkcs9 21 : : localKeyID +!Alias ms-corp 1 3 6 1 4 1 311 !Cname ms-csp-name -1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name -1 3 6 1 4 1 311 17 2 : LocalKeySet : Microsoft Local Key set +ms-corp 17 1 : CSPName : Microsoft CSP Name +ms-corp 17 2 : LocalKeySet : Microsoft Local Key set !Alias certTypes pkcs9 22 certTypes 1 : : x509Certificate certTypes 2 : : sdsiCertificate !Alias crlTypes pkcs9 23 crlTypes 1 : : x509Crl +pkcs9 52 : id-aa-CMSAlgorithmProtection + !Alias pkcs12 pkcs 12 !Alias pkcs12-pbeids pkcs12 1 @@ -396,6 +405,9 @@ sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption sm-scheme 501 : SM2-SM3 : SM2-with-SM3 +# From GM/T 0091-2020 +sm3 3 1 : : hmacWithSM3 + # From RFC4231 rsadsi 2 8 : : hmacWithSHA224 rsadsi 2 9 : : hmacWithSHA256 @@ -425,21 +437,26 @@ rsadsi 3 8 : RC5-CBC : rc5-cbc : RC5-OFB : rc5-ofb !Cname ms-ext-req -1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request +ms-corp 2 1 14 : msExtReq : Microsoft Extension Request !Cname ms-code-ind -1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing +ms-corp 2 1 21 : msCodeInd : Microsoft Individual Code Signing !Cname ms-code-com -1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing +ms-corp 2 1 22 : msCodeCom : Microsoft Commercial Code Signing !Cname ms-ctl-sign -1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing +ms-corp 10 3 1 : msCTLSign : Microsoft Trust List Signing !Cname ms-sgc -1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto +ms-corp 10 3 3 : msSGC : Microsoft Server Gated Crypto !Cname ms-efs -1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System +ms-corp 10 3 4 : msEFS : Microsoft Encrypted File System !Cname ms-smartcard-login -1 3 6 1 4 1 311 20 2 2 : msSmartcardLogin : Microsoft Smartcard Login +ms-corp 20 2 2 : msSmartcardLogin : Microsoft Smartcard Login !Cname ms-upn -1 3 6 1 4 1 311 20 2 3 : msUPN : Microsoft User Principal Name +ms-corp 20 2 3 : msUPN : Microsoft User Principal Name + +ms-corp 25 2 : ms-ntds-sec-ext : Microsoft NTDS CA Extension +ms-corp 25 2 1 : ms-ntds-obj-sid : Microsoft NTDS AD objectSid +ms-corp 21 7 : ms-cert-templ : Microsoft certificate template +ms-corp 21 10 : ms-app-policies : Microsoft Application Policies Extension 1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc : IDEA-ECB : idea-ecb @@ -493,13 +510,17 @@ id-pkix-mod 13 : id-mod-timestamp-protocol id-pkix-mod 14 : id-mod-ocsp id-pkix-mod 15 : id-mod-dvcs id-pkix-mod 16 : id-mod-cmp2000 +id-pkix-mod 50 : id-mod-cmp2000-02 +id-pkix-mod 99 : id-mod-cmp2021-88 +id-pkix-mod 100 : id-mod-cmp2021-02 # PKIX Private Extensions !Cname info-access id-pe 1 : authorityInfoAccess : Authority Information Access id-pe 2 : biometricInfo : Biometric Info id-pe 3 : qcStatements -id-pe 4 : ac-auditEntity +id-pe 4 : ac-auditIdentity : X509v3 Audit Identity +!Alias ac-auditEntity ac-auditIdentity id-pe 5 : ac-targeting id-pe 6 : aaControls id-pe 7 : sbgp-ipAddrBlock @@ -565,9 +586,9 @@ id-it 4 : id-it-preferredSymmAlg id-it 5 : id-it-caKeyUpdateInfo id-it 6 : id-it-currentCRL id-it 7 : id-it-unsupportedOIDs -# obsolete +# [Reserved and Obsolete]: id-it 8 : id-it-subscriptionRequest -# obsolete +# [Reserved and Obsolete]: id-it 9 : id-it-subscriptionResponse id-it 10 : id-it-keyPairParamReq id-it 11 : id-it-keyPairParamRep @@ -579,6 +600,10 @@ id-it 16 : id-it-suppLangTags id-it 17 : id-it-caCerts id-it 18 : id-it-rootCaKeyUpdate id-it 19 : id-it-certReqTemplate +id-it 20 : id-it-rootCaCert +id-it 21 : id-it-certProfile +id-it 22 : id-it-crlStatusList +id-it 23 : id-it-crls # CRMF registration id-pkip 1 : id-regCtrl @@ -591,6 +616,12 @@ id-regCtrl 3 : id-regCtrl-pkiPublicationInfo id-regCtrl 4 : id-regCtrl-pkiArchiveOptions id-regCtrl 5 : id-regCtrl-oldCertID id-regCtrl 6 : id-regCtrl-protocolEncrKey +id-regCtrl 7 : id-regCtrl-altCertTemplate +# id-regCtrl 8 : id-regCtrl-wtlsTemplate [Reserved and Obsolete] +# id-regCtrl 9 : id-regCtrl-regTokenUTF8 [Reserved and Obsolete] +# id-regCtrl 10 : id-regCtrl-authenticatorUTF8 [Reserved and Obsolete] +id-regCtrl 11 : id-regCtrl-algId +id-regCtrl 12 : id-regCtrl-rsaKeyLen # CRMF registration information id-regInfo 1 : id-regInfo-utf8Pairs @@ -627,6 +658,7 @@ id-cmc 24 : id-cmc-confirmCertAcceptance # other names id-on 1 : id-on-personalData id-on 3 : id-on-permanentIdentifier : Permanent Identifier +id-on 4 : id-on-hardwareModuleName : Hardware Module Name id-on 5 : id-on-xmppAddr : XmppAddr id-on 7 : id-on-dnsSRV : SRVName id-on 8 : id-on-NAIRealm : NAIRealm @@ -850,14 +882,64 @@ id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier id-ce 36 : policyConstraints : X509v3 Policy Constraints !Cname ext-key-usage id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage +!Cname authority-attribute-identifier +id-ce 38 : authorityAttributeIdentifier : X509v3 Authority Attribute Identifier +!Cname role-spec-cert-identifier +id-ce 39 : roleSpecCertIdentifier : X509v3 Role Specification Certificate Identifier +!Cname basic-att-constraints +id-ce 41 : basicAttConstraints : X509v3 Basic Attribute Certificate Constraints +!Cname delegated-name-constraints +id-ce 42 : delegatedNameConstraints : X509v3 Delegated Name Constraints +!Cname time-specification +id-ce 43 : timeSpecification : X509v3 Time Specification !Cname freshest-crl id-ce 46 : freshestCRL : X509v3 Freshest CRL +!Cname attribute-descriptor +id-ce 48 : attributeDescriptor : X509v3 Attribute Descriptor +!Cname user-notice +id-ce 49 : userNotice : X509v3 User Notice +!Cname soa-identifier +id-ce 50 : sOAIdentifier : X509v3 Source of Authority Identifier +!Cname acceptable-cert-policies +id-ce 52 : acceptableCertPolicies : X509v3 Acceptable Certification Policies !Cname inhibit-any-policy id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy !Cname target-information id-ce 55 : targetInformation : X509v3 AC Targeting !Cname no-rev-avail id-ce 56 : noRevAvail : X509v3 No Revocation Available +!Cname acceptable-privilege-policies +id-ce 57 : acceptablePrivPolicies : X509v3 Acceptable Privilege Policies +!Cname indirect-issuer +id-ce 61 : indirectIssuer : X509v3 Indirect Issuer +!Cname no-assertion +id-ce 62 : noAssertion : X509v3 No Assertion +!Cname id-aa-issuing-distribution-point +id-ce 63 : aAissuingDistributionPoint : X509v3 Attribute Authority Issuing Distribution Point +!Cname issued-on-behalf-of +id-ce 64 : issuedOnBehalfOf : X509v3 Issued On Behalf Of +!Cname single-use +id-ce 65 : singleUse : X509v3 Single Use +!Cname group-ac +id-ce 66 : groupAC : X509v3 Group Attribute Certificate +!Cname allowed-attribute-assignments +id-ce 67 : allowedAttributeAssignments : X509v3 Allowed Attribute Assignments +!Cname attribute-mappings +id-ce 68 : attributeMappings : X509v3 Attribute Mappings +!Cname holder-name-constraints +id-ce 69 : holderNameConstraints : X509v3 Holder Name Constraints +!Cname authorization-validation +id-ce 70 : authorizationValidation : X509v3 Authorization Validation +!Cname prot-restrict +id-ce 71 : protRestrict : X509v3 Protocol Restriction +!Cname subject-alt-public-key-info +id-ce 72 : subjectAltPublicKeyInfo : X509v3 Subject Alternative Public Key Info +!Cname alt-signature-algorithm +id-ce 73 : altSignatureAlgorithm : X509v3 Alternative Signature Algorithm +!Cname alt-signature-value +id-ce 74 : altSignatureValue : X509v3 Alternative Signature Value +!Cname associated-information +id-ce 75 : associatedInformation : X509v3 Associated Information # From RFC5280 ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage @@ -914,6 +996,9 @@ Private 1 : enterprises : Enterprises # RFC 2247 Enterprises 1466 344 : dcobject : dcObject +# Wi-SUN Assigned Value Registry +Enterprises 45605 1 : id-kp-wisun-fan-device : Wi-SUN Alliance Field Area Network (FAN) + # RFC 1495 Mail 1 : mime-mhs : MIME MHS mime-mhs 1 : mime-mhs-headings : mime-mhs-headings @@ -1036,6 +1121,36 @@ sigAlgs 13 : id-rsassa-pkcs1-v1_5-with-sha3-224 : RSA-SHA3-224 sigAlgs 14 : id-rsassa-pkcs1-v1_5-with-sha3-256 : RSA-SHA3-256 sigAlgs 15 : id-rsassa-pkcs1-v1_5-with-sha3-384 : RSA-SHA3-384 sigAlgs 16 : id-rsassa-pkcs1-v1_5-with-sha3-512 : RSA-SHA3-512 +sigAlgs 17 : id-ml-dsa-44 : ML-DSA-44 +sigAlgs 18 : id-ml-dsa-65 : ML-DSA-65 +sigAlgs 19 : id-ml-dsa-87 : ML-DSA-87 +sigAlgs 20 : id-slh-dsa-sha2-128s : SLH-DSA-SHA2-128s +sigAlgs 21 : id-slh-dsa-sha2-128f : SLH-DSA-SHA2-128f +sigAlgs 22 : id-slh-dsa-sha2-192s : SLH-DSA-SHA2-192s +sigAlgs 23 : id-slh-dsa-sha2-192f : SLH-DSA-SHA2-192f +sigAlgs 24 : id-slh-dsa-sha2-256s : SLH-DSA-SHA2-256s +sigAlgs 25 : id-slh-dsa-sha2-256f : SLH-DSA-SHA2-256f +sigAlgs 26 : id-slh-dsa-shake-128s : SLH-DSA-SHAKE-128s +sigAlgs 27 : id-slh-dsa-shake-128f : SLH-DSA-SHAKE-128f +sigAlgs 28 : id-slh-dsa-shake-192s : SLH-DSA-SHAKE-192s +sigAlgs 29 : id-slh-dsa-shake-192f : SLH-DSA-SHAKE-192f +sigAlgs 30 : id-slh-dsa-shake-256s : SLH-DSA-SHAKE-256s +sigAlgs 31 : id-slh-dsa-shake-256f : SLH-DSA-SHAKE-256f +sigAlgs 32 : id-hash-ml-dsa-44-with-sha512 : HASH-ML-DSA-44-WITH-SHA512 +sigAlgs 33 : id-hash-ml-dsa-65-with-sha512 : HASH-ML-DSA-65-WITH-SHA512 +sigAlgs 34 : id-hash-ml-dsa-87-with-sha512 : HASH-ML-DSA-87-WITH-SHA512 +sigAlgs 35 : id-hash-slh-dsa-sha2-128s-with-sha256 : SLH-DSA-SHA2-128s-WITH-SHA256 +sigAlgs 36 : id-hash-slh-dsa-sha2-128f-with-sha256 : SLH-DSA-SHA2-128f-WITH-SHA256 +sigAlgs 37 : id-hash-slh-dsa-sha2-192s-with-sha512 : SLH-DSA-SHA2-192s-WITH-SHA512 +sigAlgs 38 : id-hash-slh-dsa-sha2-192f-with-sha512 : SLH-DSA-SHA2-192f-WITH-SHA512 +sigAlgs 39 : id-hash-slh-dsa-sha2-256s-with-sha512 : SLH-DSA-SHA2-256s-WITH-SHA512 +sigAlgs 40 : id-hash-slh-dsa-sha2-256f-with-sha512 : SLH-DSA-SHA2-256f-WITH-SHA512 +sigAlgs 41 : id-hash-slh-dsa-shake-128s-with-shake128 : SLH-DSA-SHAKE-128s-WITH-SHAKE128 +sigAlgs 42 : id-hash-slh-dsa-shake-128f-with-shake128 : SLH-DSA-SHAKE-128f-WITH-SHAKE128 +sigAlgs 43 : id-hash-slh-dsa-shake-192s-with-shake256 : SLH-DSA-SHAKE-192s-WITH-SHAKE256 +sigAlgs 44 : id-hash-slh-dsa-shake-192f-with-shake256 : SLH-DSA-SHAKE-192f-WITH-SHAKE256 +sigAlgs 45 : id-hash-slh-dsa-shake-256s-with-shake256 : SLH-DSA-SHAKE-256s-WITH-SHAKE256 +sigAlgs 46 : id-hash-slh-dsa-shake-256f-with-shake256 : SLH-DSA-SHAKE-256f-WITH-SHAKE256 # Hold instruction CRL entry extension !Cname hold-instruction-code @@ -1050,6 +1165,27 @@ holdInstruction 3 : holdInstructionReject : Hold Instruction Reject # OID's from ITU-T. Most of this is defined in RFC 1274. A couple of # them are also mentioned in RFC 2247 +# OIDs specific to Electronic Signature Standard/CAdES are as specified in +# ETSI EN 319 122-1 V1.2.1 (2021-10): +# Electronic Signatures and Infrastructures (ESI); CAdES digital signatures; +# Part 1: Building blocks and CAdES baseline signatures +itu-t 4 : itu-t-identified-organization +itu-t-identified-organization 0: etsi +etsi 1733 : electronic-signature-standard +electronic-signature-standard 2: ess-attributes +ess-attributes 1 : id-aa-ets-mimeType +ess-attributes 2 : id-aa-ets-longTermValidation +ess-attributes 3 : id-aa-ets-SignaturePolicyDocument +ess-attributes 4 : id-aa-ets-archiveTimestampV3 +ess-attributes 5 : id-aa-ATSHashIndex +etsi 19122 : cades +cades 1 : cades-attributes +cades-attributes 1 : id-aa-ets-signerAttrV2 +cades-attributes 3 : id-aa-ets-sigPolicyStore +cades-attributes 4 : id-aa-ATSHashIndex-v2 +cades-attributes 5 : id-aa-ATSHashIndex-v3 +cades-attributes 6 : signedAssertion + itu-t 9 : data data 2342 : pss pss 19200300 : ucl @@ -1565,6 +1701,9 @@ sm-scheme 104 4 : SM4-CFB : sm4-cfb sm-scheme 104 5 : SM4-CFB1 : sm4-cfb1 sm-scheme 104 6 : SM4-CFB8 : sm4-cfb8 sm-scheme 104 7 : SM4-CTR : sm4-ctr +sm-scheme 104 8 : SM4-GCM : sm4-gcm +sm-scheme 104 9 : SM4-CCM : sm4-ccm +sm-scheme 104 10 : SM4-XTS : sm4-xts # There is no OID that just denotes "HMAC" oddly enough... @@ -1597,12 +1736,18 @@ ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH 1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1 1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1 1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1 +# Alternate NID to represent the TLSv1.3 brainpoolP256r1 group + : brainpoolP256r1tls13 1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1 1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1 1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1 1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1 +# Alternate NID to represent the TLSv1.3 brainpoolP384r1 group + : brainpoolP384r1tls13 1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1 1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1 +# Alternate NID to represent the TLSv1.3 brainpoolP512r1 group + : brainpoolP512r1tls13 1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1 # ECDH schemes from RFC5753 @@ -1633,9 +1778,9 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme # CABForum EV SSL Certificate Guidelines # (see https://cabforum.org/extended-validation/) # OIDs for Subject Jurisdiction of Incorporation or Registration -1 3 6 1 4 1 311 60 2 1 1 : jurisdictionL : jurisdictionLocalityName -1 3 6 1 4 1 311 60 2 1 2 : jurisdictionST : jurisdictionStateOrProvinceName -1 3 6 1 4 1 311 60 2 1 3 : jurisdictionC : jurisdictionCountryName +ms-corp 60 2 1 1 : jurisdictionL : jurisdictionLocalityName +ms-corp 60 2 1 2 : jurisdictionST : jurisdictionStateOrProvinceName +ms-corp 60 2 1 3 : jurisdictionC : jurisdictionCountryName # SCRYPT algorithm !Cname id-scrypt @@ -1744,3 +1889,164 @@ dstu4145le 2 9 : uacurve9 : DSTU curve 9 : AES-128-SIV : aes-128-siv : AES-192-SIV : aes-192-siv : AES-256-SIV : aes-256-siv + + +!Cname oracle +joint-iso-itu-t 16 840 1 113894 : oracle-organization : Oracle organization +# Jdk trustedKeyUsage attribute +oracle 746875 1 1 : oracle-jdk-trustedkeyusage : Trusted key usage (Oracle) + +# NID for compression + : brotli : Brotli compression + : zstd : Zstandard compression + +2 23 133 : tcg : Trusted Computing Group + +tcg 1 : tcg-tcpaSpecVersion +tcg 2 : tcg-attribute : Trusted Computing Group Attributes +tcg 3 : tcg-protocol : Trusted Computing Group Protocols +tcg 4 : tcg-algorithm : Trusted Computing Group Algorithms +tcg 5 : tcg-platformClass : Trusted Computing Group Platform Classes +tcg 6 : tcg-ce : Trusted Computing Group Certificate Extensions +tcg 8 : tcg-kp : Trusted Computing Group Key Purposes +tcg 11 : tcg-ca : Trusted Computing Group Certificate Policies +tcg 17 : tcg-address : Trusted Computing Group Address Formats +tcg 18 : tcg-registry : Trusted Computing Group Registry +tcg 19 : tcg-traits : Trusted Computing Group Traits + +tcg-platformClass 1 : tcg-common : Trusted Computing Group Common +tcg-common 1 : tcg-at-platformManufacturerStr : TCG Platform Manufacturer String +tcg-common 2 : tcg-at-platformManufacturerId : TCG Platform Manufacturer ID +tcg-common 3 : tcg-at-platformConfigUri : TCG Platform Configuration URI +tcg-common 4 : tcg-at-platformModel : TCG Platform Model +tcg-common 5 : tcg-at-platformVersion : TCG Platform Version +tcg-common 6 : tcg-at-platformSerial : TCG Platform Serial Number +tcg-common 7 : tcg-at-platformConfiguration : TCG Platform Configuration +tcg-common 8 : tcg-at-platformIdentifier : TCG Platform Identifier + +tcg-attribute 1 : tcg-at-tpmManufacturer : TPM Manufacturer +tcg-attribute 2 : tcg-at-tpmModel : TPM Model +tcg-attribute 3 : tcg-at-tpmVersion : TPM Version +tcg-attribute 10 : tcg-at-securityQualities : Security Qualities +tcg-attribute 11 : tcg-at-tpmProtectionProfile : TPM Protection Profile +tcg-attribute 12 : tcg-at-tpmSecurityTarget : TPM Security Target +tcg-attribute 13 : tcg-at-tbbProtectionProfile : TBB Protection Profile +tcg-attribute 14 : tcg-at-tbbSecurityTarget : TBB Security Target +tcg-attribute 15 : tcg-at-tpmIdLabel : TPM ID Label +tcg-attribute 16 : tcg-at-tpmSpecification : TPM Specification +tcg-attribute 17 : tcg-at-tcgPlatformSpecification : TPM Platform Specification +tcg-attribute 18 : tcg-at-tpmSecurityAssertions : TPM Security Assertions +tcg-attribute 19 : tcg-at-tbbSecurityAssertions : TBB Security Assertions +tcg-attribute 23 : tcg-at-tcgCredentialSpecification : TCG Credential Specification +tcg-attribute 25 : tcg-at-tcgCredentialType : TCG Credential Type +tcg-attribute 26 : tcg-at-previousPlatformCertificates : TCG Previous Platform Certificates +tcg-attribute 27 : tcg-at-tbbSecurityAssertions-v3 : TCG TBB Security Assertions V3 +tcg-attribute 28 : tcg-at-cryptographicAnchors : TCG Cryptographic Anchors + +tcg-at-platformConfiguration 1 : tcg-at-platformConfiguration-v1 : Platform Configuration Version 1 +tcg-at-platformConfiguration 2 : tcg-at-platformConfiguration-v2 : Platform Configuration Version 2 +tcg-at-platformConfiguration 3 : tcg-at-platformConfiguration-v3 : Platform Configuration Version 3 +tcg-at-platformConfiguration 4 : tcg-at-platformConfigUri-v3 : Platform Configuration URI Version 3 + +tcg-algorithm 1 : tcg-algorithm-null : TCG NULL Algorithm + +tcg-kp 1 : tcg-kp-EKCertificate : Endorsement Key Certificate +tcg-kp 2 : tcg-kp-PlatformAttributeCertificate : Platform Attribute Certificate +tcg-kp 3 : tcg-kp-AIKCertificate : Attestation Identity Key Certificate +tcg-kp 4 : tcg-kp-PlatformKeyCertificate : Platform Key Certificate +tcg-kp 5 : tcg-kp-DeltaPlatformAttributeCertificate : Delta Platform Attribute Certificate +tcg-kp 6 : tcg-kp-DeltaPlatformKeyCertificate : Delta Platform Key Certificate +tcg-kp 7 : tcg-kp-AdditionalPlatformAttributeCertificate : Additional Platform Attribute Certificate +tcg-kp 8 : tcg-kp-AdditionalPlatformKeyCertificate : Additional Platform Key Certificate + +tcg-ce 2 : tcg-ce-relevantCredentials : Relevant Credentials +tcg-ce 3 : tcg-ce-relevantManifests : Relevant Manifests +tcg-ce 4 : tcg-ce-virtualPlatformAttestationService : Virtual Platform Attestation Service +tcg-ce 5 : tcg-ce-migrationControllerAttestationService : Migration Controller Attestation Service +tcg-ce 6 : tcg-ce-migrationControllerRegistrationService : Migration Controller Registration Service +tcg-ce 7 : tcg-ce-virtualPlatformBackupService : Virtual Platform Backup Service + +tcg-protocol 1 : tcg-prt-tpmIdProtocol : TCG TPM Protocol + +tcg-address 1 : tcg-address-ethernetmac : Ethernet MAC Address +tcg-address 2 : tcg-address-wlanmac : WLAN MAC Address +tcg-address 3 : tcg-address-bluetoothmac : Bluetooth MAC Address + +tcg-registry 3 : tcg-registry-componentClass : TCG Component Class + +tcg-registry-componentClass 1 : tcg-registry-componentClass-tcg : Trusted Computed Group Registry +tcg-registry-componentClass 2 : tcg-registry-componentClass-ietf : Internet Engineering Task Force Registry +tcg-registry-componentClass 3 : tcg-registry-componentClass-dmtf : Distributed Management Task Force Registry +tcg-registry-componentClass 4 : tcg-registry-componentClass-pcie : PCIE Component Class +tcg-registry-componentClass 5 : tcg-registry-componentClass-disk : Disk Component Class + +tcg-ca 4 : tcg-cap-verifiedPlatformCertificate : TCG Verified Platform Certificate CA Policy + +tcg-traits 1 : tcg-tr-ID : TCG Trait Identifiers +tcg-traits 2 : tcg-tr-category : TCG Trait Categories +tcg-traits 3 : tcg-tr-registry : TCG Trait Registries + +tcg-tr-ID 1 : tcg-tr-ID-Boolean : Boolean Trait +tcg-tr-ID 2 : tcg-tr-ID-CertificateIdentifier : Certificate Identifier Trait +tcg-tr-ID 3 : tcg-tr-ID-CommonCriteria : Common Criteria Trait +tcg-tr-ID 4 : tcg-tr-ID-componentClass : Component Class Trait +tcg-tr-ID 5 : tcg-tr-ID-componentIdentifierV11 : Component Identifier V1.1 Trait +tcg-tr-ID 6 : tcg-tr-ID-FIPSLevel : FIPS Level Trait +tcg-tr-ID 7 : tcg-tr-ID-ISO9000Level : ISO 9000 Level Trait +tcg-tr-ID 8 : tcg-tr-ID-networkMAC : Network MAC Trait +tcg-tr-ID 9 : tcg-tr-ID-OID : Object Identifier Trait +tcg-tr-ID 10 : tcg-tr-ID-PEN : Private Enterprise Number Trait +tcg-tr-ID 11 : tcg-tr-ID-platformFirmwareCapabilities : Platform Firmware Capabilities Trait +tcg-tr-ID 12 : tcg-tr-ID-platformFirmwareSignatureVerification : Platform Firmware Signature Verification Trait +tcg-tr-ID 13 : tcg-tr-ID-platformFirmwareUpdateCompliance : Platform Firmware Update Compliance Trait +tcg-tr-ID 14 : tcg-tr-ID-platformHardwareCapabilities : Platform Hardware Capabilities Trait +tcg-tr-ID 15 : tcg-tr-ID-RTM : Root of Trust for Measurement Trait +tcg-tr-ID 16 : tcg-tr-ID-status : Attribute Status Trait +tcg-tr-ID 17 : tcg-tr-ID-URI : Uniform Resource Identifier Trait +tcg-tr-ID 18 : tcg-tr-ID-UTF8String : UTF8String Trait +tcg-tr-ID 19 : tcg-tr-ID-IA5String : IA5String Trait +tcg-tr-ID 20 : tcg-tr-ID-PEMCertString : PEM-Encoded Certificate String Trait +tcg-tr-ID 21 : tcg-tr-ID-PublicKey : Public Key Trait + +tcg-tr-category 1 : tcg-tr-cat-platformManufacturer : Platform Manufacturer Trait Category +tcg-tr-category 2 : tcg-tr-cat-platformModel : Platform Model Trait Category +tcg-tr-category 3 : tcg-tr-cat-platformVersion : Platform Version Trait Category +tcg-tr-category 4 : tcg-tr-cat-platformSerial : Platform Serial Trait Category +tcg-tr-category 5 : tcg-tr-cat-platformManufacturerIdentifier : Platform Manufacturer Identifier Trait Category +tcg-tr-category 6 : tcg-tr-cat-platformOwnership : Platform Ownership Trait Category +tcg-tr-category 7 : tcg-tr-cat-componentClass : Component Class Trait Category +tcg-tr-category 8 : tcg-tr-cat-componentManufacturer : Component Manufacturer Trait Category +tcg-tr-category 9 : tcg-tr-cat-componentModel : Component Model Trait Category +tcg-tr-category 10 : tcg-tr-cat-componentSerial : Component Serial Trait Category +tcg-tr-category 11 : tcg-tr-cat-componentStatus : Component Status Trait Category +tcg-tr-category 12 : tcg-tr-cat-componentLocation : Component Location Trait Category +tcg-tr-category 13 : tcg-tr-cat-componentRevision : Component Revision Trait Category +tcg-tr-category 14 : tcg-tr-cat-componentFieldReplaceable : Component Field Replaceable Trait Category +tcg-tr-category 15 : tcg-tr-cat-EKCertificate : EK Certificate Trait Category +tcg-tr-category 16 : tcg-tr-cat-IAKCertificate : IAK Certificate Trait Category +tcg-tr-category 17 : tcg-tr-cat-IDevIDCertificate : IDevID Certificate Trait Category +tcg-tr-category 18 : tcg-tr-cat-DICECertificate : DICE Certificate Trait Category +tcg-tr-category 19 : tcg-tr-cat-SPDMCertificate : SPDM Certificate Trait Category +tcg-tr-category 20 : tcg-tr-cat-PEMCertificate : PEM Certificate Trait Category +tcg-tr-category 21 : tcg-tr-cat-PlatformCertificate : Platform Certificate Trait Category +tcg-tr-category 22 : tcg-tr-cat-DeltaPlatformCertificate : Delta Platform Certificate Trait Category +tcg-tr-category 23 : tcg-tr-cat-RebasePlatformCertificate : Rebase Platform Certificate Trait Category +tcg-tr-category 24 : tcg-tr-cat-genericCertificate : Generic Certificate Trait Category +tcg-tr-category 25 : tcg-tr-cat-CommonCriteria : Common Criteria Trait Category +tcg-tr-category 26 : tcg-tr-cat-componentIdentifierV11 : Component Identifier V1.1 Trait Category +tcg-tr-category 27 : tcg-tr-cat-FIPSLevel : FIPS Level Trait Category +tcg-tr-category 28 : tcg-tr-cat-ISO9000 : ISO 9000 Trait Category +tcg-tr-category 29 : tcg-tr-cat-networkMAC : Network MAC Trait Category +tcg-tr-category 30 : tcg-tr-cat-attestationProtocol : Attestation Protocol Trait Category +tcg-tr-category 31 : tcg-tr-cat-PEN : Private Enterprise Number Trait Category +tcg-tr-category 32 : tcg-tr-cat-platformFirmwareCapabilities : Platform Firmware Capabilities Trait Category +tcg-tr-category 33 : tcg-tr-cat-platformHardwareCapabilities : Platform Hardware Capabilities Trait Category +tcg-tr-category 34 : tcg-tr-cat-platformFirmwareSignatureVerification : Platform Firmware Signature Verification Trait Category +tcg-tr-category 35 : tcg-tr-cat-platformFirmwareUpdateCompliance : Platform Firmware Update Compliance Trait Category +tcg-tr-category 36 : tcg-tr-cat-RTM : Root of Trust of Measurement Trait Category +tcg-tr-category 37 : tcg-tr-cat-PublicKey : Public Key Trait Category + +!Alias nistKems nistAlgorithms 4 +nistKems 1 : id-alg-ml-kem-512 : ML-KEM-512 +nistKems 2 : id-alg-ml-kem-768 : ML-KEM-768 +nistKems 3 : id-alg-ml-kem-1024 : ML-KEM-1024 diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c index 9707ccb94f4c..95f693ba0cd4 100644 --- a/crypto/ocsp/ocsp_ext.c +++ b/crypto/ocsp/ocsp_ext.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -400,7 +400,8 @@ X509_EXTENSION *OCSP_accept_responses_new(char **oids) goto err; while (oids && *oids) { if ((nid = OBJ_txt2nid(*oids)) != NID_undef && (o = OBJ_nid2obj(nid))) - sk_ASN1_OBJECT_push(sk, o); + if (!sk_ASN1_OBJECT_push(sk, o)) + goto err; oids++; } x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk); diff --git a/crypto/ocsp/ocsp_prn.c b/crypto/ocsp/ocsp_prn.c index 654ddbc7fff3..6fe65b6c0de3 100644 --- a/crypto/ocsp/ocsp_prn.c +++ b/crypto/ocsp/ocsp_prn.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2020 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 @@ -79,7 +79,9 @@ const char *OCSP_crl_reason_str(long s) {OCSP_REVOKED_STATUS_SUPERSEDED, "superseded"}, {OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation"}, {OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold"}, - {OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL"} + {OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL"}, + {OCSP_REVOKED_STATUS_PRIVILEGEWITHDRAWN, "privilegeWithdrawn"}, + {OCSP_REVOKED_STATUS_AACOMPROMISE, "aACompromise"} }; return table2string(s, reason_tbl); } diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index fa07539d7e86..b0c2d6fd12a7 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -1,5 +1,5 @@ /* - * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -36,7 +36,7 @@ static int ocsp_verify_signer(X509 *signer, int response, int ret = -1; if (ctx == NULL) { - ERR_raise(ERR_LIB_OCSP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OCSP, ERR_R_X509_LIB); goto end; } if (!X509_STORE_CTX_init(ctx, st, signer, untrusted)) { @@ -154,7 +154,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, } end: - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); sk_X509_free(untrusted); return ret; } @@ -328,7 +328,7 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, (void)ERR_pop_to_mark(); mdlen = EVP_MD_get_size(dgst); - if (mdlen < 0) { + if (mdlen <= 0) { ERR_raise(ERR_LIB_OCSP, OCSP_R_DIGEST_SIZE_ERR); goto end; } diff --git a/crypto/ocsp/v3_ocsp.c b/crypto/ocsp/v3_ocsp.c index 2250208a1577..4f54b7ceab95 100644 --- a/crypto/ocsp/v3_ocsp.c +++ b/crypto/ocsp/v3_ocsp.c @@ -203,7 +203,7 @@ static void *d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) err: if ((pos == NULL) || (*pos != os)) ASN1_OCTET_STRING_free(os); - ERR_raise(ERR_LIB_OCSP, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OCSP, ERR_R_ASN1_LIB); return NULL; } diff --git a/crypto/packet.c b/crypto/packet.c index 927bb3f80f6c..6a43b35655fb 100644 --- a/crypto/packet.c +++ b/crypto/packet.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,9 @@ #include "internal/cryptlib.h" #include "internal/packet.h" +#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE +# include "internal/packet_quic.h" +#endif #include #define DEFAULT_BUF_SIZE 256 @@ -104,10 +107,8 @@ static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes) pkt->curr = 0; pkt->written = 0; - if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((pkt->subs = OPENSSL_zalloc(sizeof(*pkt->subs))) == NULL) return 0; - } if (lenbytes == 0) return 1; @@ -225,6 +226,20 @@ static int put_value(unsigned char *data, uint64_t value, size_t len) return 1; } +#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE +static int put_quic_value(unsigned char *data, size_t value, size_t len) +{ + if (data == NULL) + return 1; + + /* Value too large for field. */ + if (ossl_quic_vlint_encode_len(value) > len) + return 0; + + ossl_quic_vlint_encode_n(data, value, len); + return 1; +} +#endif /* * Internal helper function used by WPACKET_close(), WPACKET_finish() and @@ -261,10 +276,20 @@ static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose) if (sub->lenbytes > 0) { unsigned char *buf = GETBUF(pkt); - if (buf != NULL - && !put_value(&buf[sub->packet_len], packlen, - sub->lenbytes)) - return 0; + if (buf != NULL) { +#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE + if ((sub->flags & WPACKET_FLAGS_QUIC_VLINT) == 0) { + if (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes)) + return 0; + } else { + if (!put_quic_value(&buf[sub->packet_len], packlen, sub->lenbytes)) + return 0; + } +#else + if (!put_value(&buf[sub->packet_len], packlen, sub->lenbytes)) + return 0; +#endif + } } else if (pkt->endfirst && sub->parent != NULL && (packlen != 0 || (sub->flags @@ -351,10 +376,8 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes) if (lenbytes > 0 && pkt->endfirst) return 0; - if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((sub = OPENSSL_zalloc(sizeof(*sub))) == NULL) return 0; - } sub->parent = pkt->subs; pkt->subs = sub; @@ -510,3 +533,58 @@ void WPACKET_cleanup(WPACKET *pkt) } pkt->subs = NULL; } + +#if !defined OPENSSL_NO_QUIC && !defined FIPS_MODULE + +int WPACKET_start_quic_sub_packet_bound(WPACKET *pkt, size_t max_len) +{ + size_t enclen = ossl_quic_vlint_encode_len(max_len); + + if (enclen == 0) + return 0; + + if (WPACKET_start_sub_packet_len__(pkt, enclen) == 0) + return 0; + + pkt->subs->flags |= WPACKET_FLAGS_QUIC_VLINT; + return 1; +} + +int WPACKET_start_quic_sub_packet(WPACKET *pkt) +{ + /* + * Assume no (sub)packet will exceed 4GiB, thus the 8-byte encoding need not + * be used. + */ + return WPACKET_start_quic_sub_packet_bound(pkt, OSSL_QUIC_VLINT_4B_MIN); +} + +int WPACKET_quic_sub_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) +{ + if (!WPACKET_start_quic_sub_packet_bound(pkt, len) + || !WPACKET_allocate_bytes(pkt, len, allocbytes) + || !WPACKET_close(pkt)) + return 0; + + return 1; +} + +/* + * Write a QUIC variable-length integer to the packet. + */ +int WPACKET_quic_write_vlint(WPACKET *pkt, uint64_t v) +{ + unsigned char *b = NULL; + size_t enclen = ossl_quic_vlint_encode_len(v); + + if (enclen == 0) + return 0; + + if (WPACKET_allocate_bytes(pkt, enclen, &b) == 0) + return 0; + + ossl_quic_vlint_encode(b, v); + return 1; +} + +#endif diff --git a/crypto/param_build.c b/crypto/param_build.c index 56537e676b77..3294045156fa 100644 --- a/crypto/param_build.c +++ b/crypto/param_build.c @@ -32,7 +32,7 @@ typedef struct { union { /* * These fields are never directly addressed, but their sizes are - * imporant so that all native types can be copied here without overrun. + * important so that all native types can be copied here without overrun. */ ossl_intmax_t i; ossl_uintmax_t u; @@ -49,15 +49,13 @@ struct ossl_param_bld_st { }; static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, - int size, size_t alloc, int type, + size_t size, size_t alloc, int type, int secure) { OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd)); - if (pd == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (pd == NULL) return NULL; - } pd->key = key; pd->type = type; pd->size = size; @@ -78,8 +76,10 @@ static int param_push_num(OSSL_PARAM_BLD *bld, const char *key, { OSSL_PARAM_BLD_DEF *pd = param_push(bld, key, size, size, type, 0); - if (pd == NULL) + if (pd == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return 0; + } if (size > sizeof(pd->num)) { ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_BYTES); return 0; @@ -190,23 +190,20 @@ int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD *bld, const char *key, return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL); } -int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, - const BIGNUM *bn) -{ - return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, - bn == NULL ? 0 : BN_num_bytes(bn)); -} - -int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, - const BIGNUM *bn, size_t sz) +static int push_BN(OSSL_PARAM_BLD *bld, const char *key, + const BIGNUM *bn, size_t sz, int type) { int n, secure = 0; OSSL_PARAM_BLD_DEF *pd; + if (!ossl_assert(type == OSSL_PARAM_UNSIGNED_INTEGER + || type == OSSL_PARAM_INTEGER)) + return 0; + if (bn != NULL) { - if (BN_is_negative(bn)) { + if (type == OSSL_PARAM_UNSIGNED_INTEGER && BN_is_negative(bn)) { ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_UNSUPPORTED, - "Negative big numbers are unsupported for OSSL_PARAM"); + "Negative big numbers are unsupported for OSSL_PARAM_UNSIGNED_INTEGER"); return 0; } @@ -226,13 +223,32 @@ int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, if (sz == 0) sz++; } - pd = param_push(bld, key, sz, sz, OSSL_PARAM_UNSIGNED_INTEGER, secure); + pd = param_push(bld, key, sz, sz, type, secure); if (pd == NULL) return 0; pd->bn = bn; return 1; } +int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, + const BIGNUM *bn) +{ + if (bn != NULL && BN_is_negative(bn)) + return push_BN(bld, key, bn, BN_num_bytes(bn) + 1, + OSSL_PARAM_INTEGER); + return push_BN(bld, key, bn, bn == NULL ? 0 : BN_num_bytes(bn), + OSSL_PARAM_UNSIGNED_INTEGER); +} + +int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, + const BIGNUM *bn, size_t sz) +{ + if (bn != NULL && BN_is_negative(bn)) + return push_BN(bld, key, bn, BN_num_bytes(bn), + OSSL_PARAM_INTEGER); + return push_BN(bld, key, bn, sz, OSSL_PARAM_UNSIGNED_INTEGER); +} + int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, const char *buf, size_t bsize) { @@ -241,10 +257,6 @@ int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, if (bsize == 0) bsize = strlen(buf); - if (bsize > INT_MAX) { - ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); - return 0; - } secure = CRYPTO_secure_allocated(buf); pd = param_push(bld, key, bsize, bsize + 1, OSSL_PARAM_UTF8_STRING, secure); if (pd == NULL) @@ -260,10 +272,6 @@ int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, if (bsize == 0) bsize = strlen(buf); - if (bsize > INT_MAX) { - ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); - return 0; - } pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_UTF8_PTR, 0); if (pd == NULL) return 0; @@ -277,10 +285,6 @@ int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, OSSL_PARAM_BLD_DEF *pd; int secure; - if (bsize > INT_MAX) { - ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); - return 0; - } secure = CRYPTO_secure_allocated(buf); pd = param_push(bld, key, bsize, bsize, OSSL_PARAM_OCTET_STRING, secure); if (pd == NULL) @@ -294,10 +298,6 @@ int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, { OSSL_PARAM_BLD_DEF *pd; - if (bsize > INT_MAX) { - ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_STRING_TOO_LONG); - return 0; - } pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_OCTET_PTR, 0); if (pd == NULL) return 0; @@ -330,7 +330,10 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param, param[i].data = p; if (pd->bn != NULL) { /* BIGNUM */ - BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size); + if (pd->type == OSSL_PARAM_UNSIGNED_INTEGER) + BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size); + else + BN_signed_bn2native(pd->bn, (unsigned char *)p, pd->size); } else if (pd->type == OSSL_PARAM_OCTET_PTR || pd->type == OSSL_PARAM_UTF8_PTR) { /* PTR */ @@ -373,7 +376,6 @@ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld) } params = OPENSSL_malloc(total); if (params == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); OPENSSL_secure_free(s); return NULL; } diff --git a/crypto/param_build_set.c b/crypto/param_build_set.c index 5de06cc7ed68..f205d101936a 100644 --- a/crypto/param_build_set.c +++ b/crypto/param_build_set.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -73,8 +73,10 @@ int ossl_param_build_set_bn_pad(OSSL_PARAM_BLD *bld, OSSL_PARAM *p, return OSSL_PARAM_BLD_push_BN_pad(bld, key, bn, sz); p = OSSL_PARAM_locate(p, key); if (p != NULL) { - if (sz > p->data_size) + if (sz > p->data_size) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER); return 0; + } p->data_size = sz; return OSSL_PARAM_set_BN(p, bn); } diff --git a/crypto/params.c b/crypto/params.c index 4d85b5943c71..6f88a8539308 100644 --- a/crypto/params.c +++ b/crypto/params.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -10,9 +10,33 @@ #include #include +#include #include "internal/thread_once.h" #include "internal/numbers.h" #include "internal/endian.h" +#include "internal/params.h" +#include "internal/packet.h" + +/* Shortcuts for raising errors that are widely used */ +#define err_unsigned_negative \ + ERR_raise(ERR_LIB_CRYPTO, \ + CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED) +#define err_out_of_range \ + ERR_raise(ERR_LIB_CRYPTO, \ + CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION) +#define err_inexact \ + ERR_raise(ERR_LIB_CRYPTO, \ + CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY) +#define err_not_integer \ + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_NOT_INTEGER_TYPE) +#define err_too_small \ + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER) +#define err_bad_type \ + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE) +#define err_null_argument \ + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER) +#define err_unsupported_real \ + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT) #ifndef OPENSSL_SYS_UEFI /* @@ -109,8 +133,10 @@ static int copy_integer(unsigned char *dest, size_t dest_len, * Shortening a signed value must retain the correct sign. * Avoiding this kind of thing: -253 = 0xff03 -> 0x03 = 3 */ - || (signed_int && ((pad ^ src[n]) & 0x80) != 0)) + || (signed_int && ((pad ^ src[n]) & 0x80) != 0)) { + err_out_of_range; return 0; + } memcpy(dest, src + n, dest_len); } } else /* IS_LITTLE_ENDIAN */ { @@ -125,8 +151,10 @@ static int copy_integer(unsigned char *dest, size_t dest_len, * Shortening a signed value must retain the correct sign. * Avoiding this kind of thing: 130 = 0x0082 -> 0x82 = -126 */ - || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0)) + || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0)) { + err_out_of_range; return 0; + } memcpy(dest, src, dest_len); } } @@ -152,8 +180,10 @@ static int signed_from_unsigned(void *dest, size_t dest_len, static int unsigned_from_signed(void *dest, size_t dest_len, const void *src, size_t src_len) { - if (is_negative(src, src_len)) + if (is_negative(src, src_len)) { + err_unsigned_negative; return 0; + } return copy_integer(dest, dest_len, src, src_len, 0, 0); } @@ -167,10 +197,15 @@ static int unsigned_from_unsigned(void *dest, size_t dest_len, /* General purpose get integer parameter call that handles odd sizes */ static int general_get_int(const OSSL_PARAM *p, void *val, size_t val_size) { + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_INTEGER) return signed_from_signed(val, val_size, p->data, p->data_size); if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) return signed_from_unsigned(val, val_size, p->data, p->data_size); + err_not_integer; return 0; } @@ -179,13 +214,16 @@ static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size) { int r = 0; - p->return_size = val_size; /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = val_size; /* Expected size */ return 1; + } if (p->data_type == OSSL_PARAM_INTEGER) r = signed_from_signed(p->data, p->data_size, val, val_size); else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) r = unsigned_from_signed(p->data, p->data_size, val, val_size); + else + err_not_integer; p->return_size = r ? p->data_size : val_size; return r; } @@ -193,10 +231,16 @@ static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size) /* General purpose get unsigned integer parameter call that handles odd sizes */ static int general_get_uint(const OSSL_PARAM *p, void *val, size_t val_size) { + + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_INTEGER) return unsigned_from_signed(val, val_size, p->data, p->data_size); if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) return unsigned_from_unsigned(val, val_size, p->data, p->data_size); + err_not_integer; return 0; } @@ -205,13 +249,16 @@ static int general_set_uint(OSSL_PARAM *p, void *val, size_t val_size) { int r = 0; - p->return_size = val_size; /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = val_size; /* Expected size */ return 1; + } if (p->data_type == OSSL_PARAM_INTEGER) r = signed_from_unsigned(p->data, p->data_size, val, val_size); else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) r = unsigned_from_unsigned(p->data, p->data_size, val, val_size); + else + err_not_integer; p->return_size = r ? p->data_size : val_size; return r; } @@ -344,8 +391,15 @@ OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf) int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) { - if (val == NULL || p == NULL ) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT @@ -361,6 +415,7 @@ int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) *val = (int32_t)i64; return 1; } + err_out_of_range; return 0; } #endif @@ -378,6 +433,7 @@ int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) *val = (int32_t)u32; return 1; } + err_out_of_range; return 0; case sizeof(uint64_t): u64 = *(const uint64_t *)p->data; @@ -385,6 +441,7 @@ int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) *val = (int32_t)u64; return 1; } + err_out_of_range; return 0; } #endif @@ -401,17 +458,23 @@ int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val) *val = (int32_t)d; return 1; } - break; + err_out_of_range; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; if (p->data_type == OSSL_PARAM_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT @@ -447,16 +510,30 @@ int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val) return general_set_int(p, &val, sizeof(val)); } else if (p->data_type == OSSL_PARAM_REAL) { #ifndef OPENSSL_SYS_UEFI + uint32_t u32; + unsigned int shift; + p->return_size = sizeof(double); if (p->data == NULL) return 1; switch (p->data_size) { case sizeof(double): + shift = real_shift(); + if (shift < 8 * sizeof(val) - 1) { + u32 = val < 0 ? -val : val; + if ((u32 >> shift) != 0) { + err_inexact; + return 0; + } + } *(double *)p->data = (double)val; return 1; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } @@ -468,8 +545,15 @@ OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf) int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) { - if (val == NULL || p == NULL) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT @@ -485,6 +569,7 @@ int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) *val = (uint32_t)u64; return 1; } + err_out_of_range; return 0; } #endif @@ -501,6 +586,7 @@ int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) *val = i32; return 1; } + err_unsigned_negative; return 0; case sizeof(int64_t): i64 = *(const int64_t *)p->data; @@ -508,6 +594,10 @@ int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) *val = (uint32_t)i64; return 1; } + if (i64 < 0) + err_unsigned_negative; + else + err_out_of_range; return 0; } #endif @@ -523,17 +613,23 @@ int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val) *val = (uint32_t)d; return 1; } - break; + err_inexact; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { @@ -563,6 +659,7 @@ int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val) *(int32_t *)p->data = (int32_t)val; return 1; } + err_out_of_range; return 0; case sizeof(int64_t): p->return_size = sizeof(int64_t); @@ -573,16 +670,28 @@ int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val) return general_set_uint(p, &val, sizeof(val)); } else if (p->data_type == OSSL_PARAM_REAL) { #ifndef OPENSSL_SYS_UEFI - p->return_size = sizeof(double); - if (p->data == NULL) - return 1; - switch (p->data_size) { - case sizeof(double): - *(double *)p->data = (double)val; + unsigned int shift; + + if (p->data == NULL) { + p->return_size = sizeof(double); return 1; } + switch (p->data_size) { + case sizeof(double): + shift = real_shift(); + if (shift < 8 * sizeof(val) && (val >> shift) != 0) { + err_inexact; + return 0; + } + *(double *)p->data = (double)val; + p->return_size = sizeof(double); + return 1; + } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } @@ -594,8 +703,15 @@ OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf) int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val) { - if (val == NULL || p == NULL ) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT @@ -623,6 +739,7 @@ int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val) *val = (int64_t)u64; return 1; } + err_out_of_range; return 0; } #endif @@ -645,23 +762,30 @@ int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val) *val = (int64_t)d; return 1; } - break; + err_inexact; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; if (p->data_type == OSSL_PARAM_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT - p->return_size = sizeof(int64_t); /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(int64_t); /* Expected size */ return 1; + } switch (p->data_size) { case sizeof(int32_t): if (val >= INT32_MIN && val <= INT32_MAX) { @@ -669,8 +793,10 @@ int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) *(int32_t *)p->data = (int32_t)val; return 1; } + err_out_of_range; return 0; case sizeof(int64_t): + p->return_size = sizeof(int64_t); *(int64_t *)p->data = val; return 1; } @@ -678,9 +804,10 @@ int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) return general_set_int(p, &val, sizeof(val)); } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) { #ifndef OPENSSL_SMALL_FOOTPRINT - p->return_size = sizeof(uint64_t); /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(uint64_t); /* Expected size */ return 1; + } switch (p->data_size) { case sizeof(uint32_t): if (val <= UINT32_MAX) { @@ -688,8 +815,10 @@ int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) *(uint32_t *)p->data = (uint32_t)val; return 1; } + err_out_of_range; return 0; case sizeof(uint64_t): + p->return_size = sizeof(uint64_t); *(uint64_t *)p->data = (uint64_t)val; return 1; } @@ -699,20 +828,26 @@ int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val) #ifndef OPENSSL_SYS_UEFI uint64_t u64; - p->return_size = sizeof(double); - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(double); return 1; + } switch (p->data_size) { case sizeof(double): u64 = val < 0 ? -val : val; if ((u64 >> real_shift()) == 0) { + p->return_size = sizeof(double); *(double *)p->data = (double)val; return 1; } - break; + err_inexact; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } @@ -723,8 +858,15 @@ OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf) int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) { - if (val == NULL || p == NULL) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + + if (p->data == NULL) { + err_null_argument; + return 0; + } if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT @@ -750,6 +892,7 @@ int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) *val = (uint64_t)i32; return 1; } + err_unsigned_negative; return 0; case sizeof(int64_t): i64 = *(const int64_t *)p->data; @@ -757,6 +900,7 @@ int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) *val = (uint64_t)i64; return 1; } + err_unsigned_negative; return 0; } #endif @@ -779,24 +923,31 @@ int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val) *val = (uint64_t)d; return 1; } - break; + err_inexact; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT - p->return_size = sizeof(uint64_t); /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(uint64_t); /* Expected size */ return 1; + } switch (p->data_size) { case sizeof(uint32_t): if (val <= UINT32_MAX) { @@ -804,8 +955,10 @@ int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val) *(uint32_t *)p->data = (uint32_t)val; return 1; } + err_out_of_range; return 0; case sizeof(uint64_t): + p->return_size = sizeof(uint64_t); *(uint64_t *)p->data = val; return 1; } @@ -813,9 +966,10 @@ int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val) return general_set_uint(p, &val, sizeof(val)); } else if (p->data_type == OSSL_PARAM_INTEGER) { #ifndef OPENSSL_SMALL_FOOTPRINT - p->return_size = sizeof(int64_t); /* Expected size */ - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(int64_t); /* Expected size */ return 1; + } switch (p->data_size) { case sizeof(int32_t): if (val <= INT32_MAX) { @@ -823,29 +977,36 @@ int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val) *(int32_t *)p->data = (int32_t)val; return 1; } + err_out_of_range; return 0; case sizeof(int64_t): if (val <= INT64_MAX) { + p->return_size = sizeof(int64_t); *(int64_t *)p->data = (int64_t)val; return 1; } + err_out_of_range; return 0; } #endif return general_set_uint(p, &val, sizeof(val)); } else if (p->data_type == OSSL_PARAM_REAL) { #ifndef OPENSSL_SYS_UEFI - p->return_size = sizeof(double); switch (p->data_size) { case sizeof(double): if ((val >> real_shift()) == 0) { + p->return_size = sizeof(double); *(double *)p->data = (double)val; return 1; } - break; + err_inexact; + return 0; } + err_unsupported_real; + return 0; #endif } + err_bad_type; return 0; } @@ -920,47 +1081,88 @@ OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf) int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val) { - BIGNUM *b; + BIGNUM *b = NULL; - if (val == NULL - || p == NULL - || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) + if (val == NULL || p == NULL || p->data == NULL) { + err_null_argument; return 0; - - b = BN_native2bn(p->data, (int)p->data_size, *val); - if (b != NULL) { - *val = b; - return 1; } - return 0; + + switch (p->data_type) { + case OSSL_PARAM_UNSIGNED_INTEGER: + b = BN_native2bn(p->data, (int)p->data_size, *val); + break; + case OSSL_PARAM_INTEGER: + b = BN_signed_native2bn(p->data, (int)p->data_size, *val); + break; + default: + err_bad_type; + break; + } + + if (b == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_BN_LIB); + return 0; + } + + *val = b; + return 1; } int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val) { size_t bytes; - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; - if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER) + if (val == NULL) { + err_null_argument; return 0; - - /* For the moment, only positive values are permitted */ - if (BN_is_negative(val)) + } + if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && BN_is_negative(val)) { + err_bad_type; return 0; + } bytes = (size_t)BN_num_bytes(val); + /* We add 1 byte for signed numbers, to make space for a sign extension */ + if (p->data_type == OSSL_PARAM_INTEGER) + bytes++; /* We make sure that at least one byte is used, so zero is properly set */ if (bytes == 0) bytes++; - p->return_size = bytes; - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = bytes; return 1; - if (p->data_size >= bytes) { - p->return_size = p->data_size; - return BN_bn2nativepad(val, p->data, p->data_size) >= 0; } + if (p->data_size >= bytes) { + + switch (p->data_type) { + case OSSL_PARAM_UNSIGNED_INTEGER: + if (BN_bn2nativepad(val, p->data, p->data_size) < 0) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW); + return 0; + } + break; + case OSSL_PARAM_INTEGER: + if (BN_signed_bn2native(val, p->data, p->data_size) < 0) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW); + return 0; + } + break; + default: + err_bad_type; + return 0; + } + p->return_size = p->data_size; + return 1; + } + p->return_size = bytes; + err_too_small; return 0; } @@ -977,8 +1179,10 @@ int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) int64_t i64; uint64_t u64; - if (val == NULL || p == NULL) + if (val == NULL || p == NULL || p->data == NULL) { + err_null_argument; return 0; + } if (p->data_type == OSSL_PARAM_REAL) { switch (p->data_size) { @@ -986,6 +1190,8 @@ int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) *val = *(const double *)p->data; return 1; } + err_unsupported_real; + return 0; } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { switch (p->data_size) { case sizeof(uint32_t): @@ -997,7 +1203,8 @@ int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) *val = (double)u64; return 1; } - break; + err_inexact; + return 0; } } else if (p->data_type == OSSL_PARAM_INTEGER) { switch (p->data_size) { @@ -1011,80 +1218,105 @@ int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val) *val = 0.0 + i64; return 1; } - break; + err_inexact; + return 0; } } + err_bad_type; return 0; } int OSSL_PARAM_set_double(OSSL_PARAM *p, double val) { - if (p == NULL) +# define D_POW_31 ((double) (((uint32_t) 1) << 31)) + const double d_pow_31 = D_POW_31; + const double d_pow_32 = 2.0 * D_POW_31; + const double d_pow_63 = 2.0 * D_POW_31 * D_POW_31; + const double d_pow_64 = 4.0 * D_POW_31 * D_POW_31; + + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; if (p->data_type == OSSL_PARAM_REAL) { - p->return_size = sizeof(double); - if (p->data == NULL) + if (p->data == NULL) { + p->return_size = sizeof(double); return 1; + } switch (p->data_size) { case sizeof(double): + p->return_size = sizeof(double); *(double *)p->data = val; return 1; } - } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER - && val == (uint64_t)val) { - p->return_size = sizeof(double); - if (p->data == NULL) + err_unsupported_real; + return 0; + } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) { + if (p->data == NULL) { + /* + * Unclear how this is usable, the parameter's type is integral. + * Its size should be the size of some integral type. + */ + p->return_size = sizeof(double); return 1; + } + if (val != (uint64_t)val) { + err_inexact; + return 0; + } switch (p->data_size) { case sizeof(uint32_t): - if (val >= 0 && val <= UINT32_MAX) { + if (val >= 0 && val < d_pow_32) { p->return_size = sizeof(uint32_t); *(uint32_t *)p->data = (uint32_t)val; return 1; } - break; + err_out_of_range; + return 0; case sizeof(uint64_t): - if (val >= 0 - /* - * By subtracting 65535 (2^16-1) we cancel the low order - * 15 bits of UINT64_MAX to avoid using imprecise floating - * point values. - */ - && val < (double)(UINT64_MAX - 65535) + 65536.0) { + if (val >= 0 && val < d_pow_64) { p->return_size = sizeof(uint64_t); *(uint64_t *)p->data = (uint64_t)val; return 1; } - break; } - } else if (p->data_type == OSSL_PARAM_INTEGER && val == (int64_t)val) { - p->return_size = sizeof(double); - if (p->data == NULL) + err_out_of_range; + return 0; + } + } else if (p->data_type == OSSL_PARAM_INTEGER) { + if (p->data == NULL) { + /* + * Unclear how this is usable, the parameter's type is integral. + * Its size should be the size of some integral type. + */ + p->return_size = sizeof(double); return 1; + } + if (val != (int64_t)val) { + err_inexact; + return 0; + } switch (p->data_size) { case sizeof(int32_t): - if (val >= INT32_MIN && val <= INT32_MAX) { + if (val >= -d_pow_31 && val < d_pow_31) { p->return_size = sizeof(int32_t); *(int32_t *)p->data = (int32_t)val; return 1; } - break; + err_out_of_range; + return 0; case sizeof(int64_t): - if (val >= INT64_MIN - /* - * By subtracting 65535 (2^16-1) we cancel the low order - * 15 bits of INT64_MAX to avoid using imprecise floating - * point values. - */ - && val < (double)(INT64_MAX - 65535) + 65536.0) { + if (val >= -d_pow_63 && val < d_pow_63) { p->return_size = sizeof(int64_t); *(int64_t *)p->data = (int64_t)val; return 1; } - break; + err_out_of_range; + return 0; } } + err_bad_type; return 0; } @@ -1100,8 +1332,14 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, { size_t sz, alloc_sz; - if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type) + if ((val == NULL && used_len == NULL) || p == NULL) { + err_null_argument; return 0; + } + if (p->data_type != type) { + err_bad_type; + return 0; + } sz = p->data_size; /* @@ -1113,8 +1351,10 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, if (used_len != NULL) *used_len = sz; - if (p->data == NULL) + if (p->data == NULL) { + err_null_argument; return 0; + } if (val == NULL) return 1; @@ -1128,8 +1368,10 @@ static int get_string_internal(const OSSL_PARAM *p, void **val, *max_len = alloc_sz; } - if (*max_len < sz) + if (*max_len < sz) { + err_too_small; return 0; + } memcpy(*val, p->data, sz); return 1; } @@ -1156,8 +1398,10 @@ int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len) return 0; if (data_length >= max_len) data_length = OPENSSL_strnlen(p->data, data_length); - if (data_length >= max_len) + if (data_length >= max_len) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL); return 0; /* No space for a terminating NUL byte */ + } (*val)[data_length] = '\0'; return ret; @@ -1173,11 +1417,17 @@ int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len, static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len, unsigned int type) { + if (p->data_type != type) { + err_bad_type; + return 0; + } p->return_size = len; if (p->data == NULL) return 1; - if (p->data_type != type || p->data_size < len) + if (p->data_size < len) { + err_too_small; return 0; + } memcpy(p->data, val, len); /* If possible within the size of p->data, add a NUL terminator byte */ @@ -1188,24 +1438,22 @@ static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len, int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val) { - if (p == NULL) + if (p == NULL || val == NULL) { + err_null_argument; return 0; - + } p->return_size = 0; - if (val == NULL) - return 0; return set_string_internal(p, val, strlen(val), OSSL_PARAM_UTF8_STRING); } int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val, size_t len) { - if (p == NULL) + if (p == NULL || val == NULL) { + err_null_argument; return 0; - + } p->return_size = 0; - if (val == NULL) - return 0; return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING); } @@ -1226,8 +1474,14 @@ OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf, static int get_ptr_internal(const OSSL_PARAM *p, const void **val, size_t *used_len, unsigned int type) { - if (val == NULL || p == NULL || p->data_type != type) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + if (p->data_type != type) { + err_bad_type; + return 0; + } if (used_len != NULL) *used_len = p->data_size; *val = *(const void **)p->data; @@ -1248,9 +1502,11 @@ int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val, static int set_ptr_internal(OSSL_PARAM *p, const void *val, unsigned int type, size_t len) { - p->return_size = len; - if (p->data_type != type) + if (p->data_type != type) { + err_bad_type; return 0; + } + p->return_size = len; if (p->data != NULL) *(const void **)p->data = val; return 1; @@ -1258,8 +1514,10 @@ static int set_ptr_internal(OSSL_PARAM *p, const void *val, int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR, val == NULL ? 0 : strlen(val)); @@ -1268,8 +1526,10 @@ int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val) int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val, size_t used_len) { - if (p == NULL) + if (p == NULL) { + err_null_argument; return 0; + } p->return_size = 0; return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len); } @@ -1286,6 +1546,111 @@ OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf, return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize); } +/* + * Extract the parameter into an allocated buffer. + * Any existing allocation in *out is cleared and freed. + * + * Returns 1 on success, 0 on failure and -1 if there are no matching params. + * + * *out and *out_len are guaranteed to be untouched if this function + * doesn't return success. + */ +int ossl_param_get1_octet_string(const OSSL_PARAM *params, const char *name, + unsigned char **out, size_t *out_len) +{ + const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name); + void *buf = NULL; + size_t len = 0; + + if (p == NULL) + return -1; + + if (p->data != NULL + && p->data_size > 0 + && !OSSL_PARAM_get_octet_string(p, &buf, 0, &len)) + return 0; + + OPENSSL_clear_free(*out, *out_len); + *out = buf; + *out_len = len; + return 1; +} + +static int setbuf_fromparams(const OSSL_PARAM *p, const char *name, + 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, name)) { + 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; +} + +int ossl_param_get1_concat_octet_string(const OSSL_PARAM *params, const char *name, + unsigned char **out, + size_t *out_len, size_t maxsize) +{ + const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name); + unsigned char *res; + size_t sz = 0; + + if (p == NULL) + return -1; + + /* Calculate the total size */ + if (!setbuf_fromparams(p, name, NULL, &sz)) + return 0; + + /* Check that it's not oversized */ + if (maxsize > 0 && sz > maxsize) + return 0; + + /* Special case zero length */ + if (sz == 0) { + if ((res = OPENSSL_zalloc(1)) == NULL) + return 0; + goto fin; + } + + /* Allocate the buffer */ + res = OPENSSL_malloc(sz); + if (res == NULL) + return 0; + + /* Concat one or more OSSL_KDF_PARAM_INFO fields */ + if (!setbuf_fromparams(p, name, res, &sz)) { + OPENSSL_clear_free(res, sz); + return 0; + } + + fin: + OPENSSL_clear_free(*out, *out_len); + *out = res; + *out_len = sz; + return 1; +} + OSSL_PARAM OSSL_PARAM_construct_end(void) { OSSL_PARAM end = OSSL_PARAM_END; @@ -1296,8 +1661,14 @@ OSSL_PARAM OSSL_PARAM_construct_end(void) static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val, size_t *used_len, unsigned int type) { - if (val == NULL || p == NULL || p->data_type != type) + if (val == NULL || p == NULL) { + err_null_argument; return 0; + } + if (p->data_type != type) { + err_bad_type; + return 0; + } if (used_len != NULL) *used_len = p->data_size; *val = p->data; @@ -1306,14 +1677,25 @@ static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val, int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val) { - return OSSL_PARAM_get_utf8_ptr(p, val) - || get_string_ptr_internal(p, (const void **)val, NULL, - OSSL_PARAM_UTF8_STRING); + int rv; + + ERR_set_mark(); + rv = OSSL_PARAM_get_utf8_ptr(p, val); + ERR_pop_to_mark(); + + return rv || get_string_ptr_internal(p, (const void **)val, NULL, + OSSL_PARAM_UTF8_STRING); } int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val, size_t *used_len) { - return OSSL_PARAM_get_octet_ptr(p, val, used_len) - || get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING); + int rv; + + ERR_set_mark(); + rv = OSSL_PARAM_get_octet_ptr(p, val, used_len); + ERR_pop_to_mark(); + + return rv || get_string_ptr_internal(p, val, used_len, + OSSL_PARAM_OCTET_STRING); } diff --git a/crypto/params_dup.c b/crypto/params_dup.c index bc1546fc53cb..769629bbf324 100644 --- a/crypto/params_dup.c +++ b/crypto/params_dup.c @@ -37,11 +37,8 @@ static int ossl_param_buf_alloc(OSSL_PARAM_BUF *out, size_t extra_blocks, size_t sz = OSSL_PARAM_ALIGN_SIZE * (extra_blocks + out->blocks); out->alloc = is_secure ? OPENSSL_secure_zalloc(sz) : OPENSSL_zalloc(sz); - if (out->alloc == NULL) { - ERR_raise(ERR_LIB_CRYPTO, is_secure ? CRYPTO_R_SECURE_MALLOC_FAILURE - : ERR_R_MALLOC_FAILURE); + if (out->alloc == NULL) return 0; - } out->alloc_sz = sz; out->cur = out->alloc + extra_blocks; return 1; @@ -105,8 +102,10 @@ OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *src) OSSL_PARAM *last, *dst; int param_count = 1; /* Include terminator in the count */ - if (src == NULL) + if (src == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } memset(buf, 0, sizeof(buf)); @@ -154,8 +153,10 @@ OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2) size_t list1_sz = 0, list2_sz = 0; int diff; - if (p1 == NULL && p2 == NULL) + if (p1 == NULL && p2 == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } /* Copy p1 to list1 */ if (p1 != NULL) { @@ -170,8 +171,10 @@ OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2) list2[list2_sz++] = p; } list2[list2_sz] = NULL; - if (list1_sz == 0 && list2_sz == 0) + if (list1_sz == 0 && list2_sz == 0) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_NO_PARAMS_TO_MERGE); return NULL; + } /* Sort the 2 lists */ qsort(list1, list1_sz, sizeof(OSSL_PARAM *), compare_params); @@ -179,10 +182,8 @@ OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2) /* Allocate enough space to store the merged parameters */ params = OPENSSL_zalloc((list1_sz + list2_sz + 1) * sizeof(*p1)); - if (params == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (params == NULL) return NULL; - } dst = params; p1cur = list1; p2cur = list2; diff --git a/crypto/params_from_text.c b/crypto/params_from_text.c index a323bf2616ad..7532d4d43923 100644 --- a/crypto/params_from_text.c +++ b/crypto/params_from_text.c @@ -8,10 +8,11 @@ * https://www.openssl.org/source/license.html */ -#include +#include "internal/common.h" /* for HAS_PREFIX */ #include #include #include +#include /* * When processing text to params, we're trying to be smart with numbers. @@ -35,10 +36,7 @@ static int prepare_from_text(const OSSL_PARAM *paramdefs, const char *key, * ishex is used to translate legacy style string controls in hex format * to octet string parameters. */ - *ishex = strncmp(key, "hex", 3) == 0; - - if (*ishex) - key += 3; + *ishex = CHECK_AND_SKIP_PREFIX(key, "hex"); p = *paramdef = OSSL_PARAM_locate_const(paramdefs, key); if (found != NULL) @@ -200,6 +198,111 @@ static int construct_from_text(OSSL_PARAM *to, const OSSL_PARAM *paramdef, return 1; } +/** + * OSSL_PARAM_print_to_bio - Print OSSL_PARAM array to a bio + * + * @p: Array of OSSL_PARAM structures containing keys and values. + * @bio: Pointer to bio where the formatted output will be written. + * @print_values: If non-zero, prints both keys and values. If zero, only keys + * are printed. + * + * This function iterates through the given array of OSSL_PARAM structures, + * printing each key to an in-memory buffer, and optionally printing its + * value based on the provided data type. Supported types include integers, + * strings, octet strings, and real numbers. + * + * Return: 1 on success, 0 on failure. + */ +int OSSL_PARAM_print_to_bio(const OSSL_PARAM *p, BIO *bio, int print_values) +{ + int64_t i; + uint64_t u; + BIGNUM *bn; +#ifndef OPENSSL_SYS_UEFI + double d; +#endif + int ok = -1; + int dok; + + /* + * Iterate through each key in the array printing its key and value + */ + for (; p->key != NULL; p++) { + ok = -1; + ok = BIO_printf(bio, "%s: ", p->key); + + if (ok == -1) + goto end; + + /* + * if printing of values was not requested, just move on + * to the next param, after adding a newline to the buffer + */ + if (print_values == 0) { + BIO_printf(bio, "\n"); + continue; + } + + switch (p->data_type) { + case OSSL_PARAM_UNSIGNED_INTEGER: + if (p->data_size > sizeof(int64_t)) { + if (OSSL_PARAM_get_BN(p, &bn)) + ok = BN_print(bio, bn); + else + ok = BIO_printf(bio, "error getting value\n"); + } else { + if (OSSL_PARAM_get_uint64(p, &u)) + ok = BIO_printf(bio, "%llu\n", (unsigned long long int)u); + else + ok = BIO_printf(bio, "error getting value\n"); + } + break; + case OSSL_PARAM_INTEGER: + if (p->data_size > sizeof(int64_t)) { + if (OSSL_PARAM_get_BN(p, &bn)) + ok = BN_print(bio, bn); + else + ok = BIO_printf(bio, "error getting value\n"); + } else { + if (OSSL_PARAM_get_int64(p, &i)) + ok = BIO_printf(bio, "%lld\n", (long long int)i); + else + ok = BIO_printf(bio, "error getting value\n"); + } + break; + case OSSL_PARAM_UTF8_PTR: + ok = BIO_dump(bio, p->data, p->data_size); + break; + case OSSL_PARAM_UTF8_STRING: + ok = BIO_dump(bio, (char *)p->data, p->data_size); + break; + case OSSL_PARAM_OCTET_PTR: + case OSSL_PARAM_OCTET_STRING: + ok = BIO_dump(bio, (char *)p->data, p->data_size); + break; + case OSSL_PARAM_REAL: + dok = 0; +#ifndef OPENSSL_SYS_UEFI + dok = OSSL_PARAM_get_double(p, &d); +#endif + if (dok == 1) + ok = BIO_printf(bio, "%f\n", d); + else + ok = BIO_printf(bio, "error getting value\n"); + break; + default: + ok = BIO_printf(bio, "unknown type (%u) of %zu bytes\n", + p->data_type, p->data_size); + break; + } + if (ok == -1) + goto end; + } + +end: + return ok == -1 ? 0 : 1; +} + int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to, const OSSL_PARAM *paramdefs, const char *key, const char *value, @@ -219,10 +322,8 @@ int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to, ¶mdef, &ishex, &buf_n, &tmpbn, found)) goto err; - if ((buf = OPENSSL_zalloc(buf_n > 0 ? buf_n : 1)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_zalloc(buf_n > 0 ? buf_n : 1)) == NULL) goto err; - } ok = construct_from_text(to, paramdef, value, value_n, ishex, buf, buf_n, tmpbn); diff --git a/crypto/passphrase.c b/crypto/passphrase.c index fcc40f6dab53..563c5acd1e54 100644 --- a/crypto/passphrase.c +++ b/crypto/passphrase.c @@ -43,10 +43,8 @@ int ossl_pw_set_passphrase(struct ossl_passphrase_data_st *data, data->_.expl_passphrase.passphrase_copy = passphrase_len != 0 ? OPENSSL_memdup(passphrase, passphrase_len) : OPENSSL_malloc(1); - if (data->_.expl_passphrase.passphrase_copy == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (data->_.expl_passphrase.passphrase_copy == NULL) return 0; - } data->_.expl_passphrase.passphrase_len = passphrase_len; return 1; } @@ -130,7 +128,7 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len, } if ((ui = UI_new()) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB); return 0; } @@ -143,16 +141,14 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len, /* Get an application constructed prompt */ prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); if (prompt == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB); goto end; } /* Get a buffer for verification prompt */ ipass = OPENSSL_zalloc(pass_size + 1); - if (ipass == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (ipass == NULL) goto end; - } prompt_idx = UI_add_input_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD, @@ -165,10 +161,8 @@ static int do_ui_passphrase(char *pass, size_t pass_size, size_t *pass_len, if (verify) { /* Get a buffer for verification prompt */ vpass = OPENSSL_zalloc(pass_size + 1); - if (vpass == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (vpass == NULL) goto end; - } verify_idx = UI_add_verify_string(ui, prompt, UI_INPUT_FLAG_DEFAULT_PWD, vpass, 0, pass_size, @@ -269,7 +263,7 @@ int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len, ui_data = data->_.pem_password.password_cbarg; if (ui_method == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_UI_LIB); return 0; } } else if (data->type == is_ui_method) { @@ -299,7 +293,6 @@ int ossl_pw_get_passphrase(char *pass, size_t pass_size, size_t *pass_len, if (new_cache == NULL) { OPENSSL_cleanse(pass, *pass_len); - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return 0; } data->cached_passphrase = new_cache; diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c index 5fa9fc09bec7..e5e5facfb468 100644 --- a/crypto/pem/pem_err.c +++ b/crypto/pem/pem_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -59,6 +59,8 @@ static const ERR_STRING_DATA PEM_str_reasons[] = { "unsupported key components"}, {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"}, + {ERR_PACK(ERR_LIB_PEM, 0, PEM_R_UNSUPPORTED_PVK_KEY_TYPE), + "unsupported pvk key type"}, {0, NULL} }; diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c index 061c9b9f68c8..f8dc4416e216 100644 --- a/crypto/pem/pem_info.c +++ b/crypto/pem/pem_info.c @@ -67,7 +67,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_ex(BIO *bp, STACK_OF(X509_INFO) *sk, if (sk == NULL) { if ((ret = sk_X509_INFO_new_null()) == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PEM, ERR_R_CRYPTO_LIB); goto err; } } else diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c index 6cd998f21669..4f0a0049a484 100644 --- a/crypto/pem/pem_lib.c +++ b/crypto/pem/pem_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -218,18 +218,25 @@ static int check_pem(const char *nm, const char *name) return 0; } -static void pem_free(void *p, unsigned int flags, size_t num) +#define PEM_FREE(p, flags, num) \ + pem_free((p), (flags), (num), OPENSSL_FILE, OPENSSL_LINE) +static void pem_free(void *p, unsigned int flags, size_t num, + const char *file, int line) { if (flags & PEM_FLAG_SECURE) - OPENSSL_secure_clear_free(p, num); + CRYPTO_secure_clear_free(p, num, file, line); else - OPENSSL_free(p); + CRYPTO_free(p, file, line); } -static void *pem_malloc(int num, unsigned int flags) +#define PEM_MALLOC(num, flags) \ + pem_malloc((num), (flags), OPENSSL_FILE, OPENSSL_LINE) +static void *pem_malloc(int num, unsigned int flags, + const char *file, int line) { - return (flags & PEM_FLAG_SECURE) ? OPENSSL_secure_malloc(num) - : OPENSSL_malloc(num); + return (flags & PEM_FLAG_SECURE) ? CRYPTO_secure_malloc(num, file, line) + : CRYPTO_malloc(num, file, line); + } static int pem_bytes_read_bio_flags(unsigned char **pdata, long *plen, @@ -244,9 +251,9 @@ static int pem_bytes_read_bio_flags(unsigned char **pdata, long *plen, int ret = 0; do { - pem_free(nm, flags, 0); - pem_free(header, flags, 0); - pem_free(data, flags, len); + PEM_FREE(nm, flags, 0); + PEM_FREE(header, flags, 0); + PEM_FREE(data, flags, len); if (!PEM_read_bio_ex(bp, &nm, &header, &data, &len, flags)) { if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) ERR_add_error_data(2, "Expecting: ", name); @@ -268,10 +275,10 @@ static int pem_bytes_read_bio_flags(unsigned char **pdata, long *plen, err: if (!ret || pnm == NULL) - pem_free(nm, flags, 0); - pem_free(header, flags, 0); + PEM_FREE(nm, flags, 0); + PEM_FREE(header, flags, 0); if (!ret) - pem_free(data, flags, len); + PEM_FREE(data, flags, len); return ret; } @@ -309,10 +316,11 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, } #endif -int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, - const void *x, const EVP_CIPHER *enc, - const unsigned char *kstr, int klen, - pem_password_cb *callback, void *u) +static int +PEM_ASN1_write_bio_internal( + i2d_of_void *i2d, OSSL_i2d_of_void_ctx *i2d_ctx, void *vctx, + const char *name, BIO *bp, const void *x, const EVP_CIPHER *enc, + const unsigned char *kstr, int klen, pem_password_cb *callback, void *u) { EVP_CIPHER_CTX *ctx = NULL; int dsize = 0, i = 0, j = 0, ret = 0; @@ -337,20 +345,23 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, } } - if ((dsize = i2d(x, NULL)) <= 0) { + if (i2d == NULL && i2d_ctx == NULL) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INVALID_NULL_ARGUMENT); + dsize = 0; + goto err; + } + dsize = i2d != NULL ? i2d(x, NULL) : i2d_ctx(x, NULL, vctx); + if (dsize <= 0) { ERR_raise(ERR_LIB_PEM, ERR_R_ASN1_LIB); dsize = 0; goto err; } - /* dsize + 8 bytes are needed */ - /* actually it needs the cipher block size extra... */ - data = OPENSSL_malloc((unsigned int)dsize + 20); - if (data == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + /* Allocate enough space for one extra cipher block */ + data = OPENSSL_malloc((unsigned int)dsize + EVP_MAX_BLOCK_LENGTH); + if (data == NULL) goto err; - } p = data; - i = i2d(x, &p); + i = i2d != NULL ? i2d(x, &p) : i2d_ctx(x, &p, vctx); if (enc != NULL) { if (kstr == NULL) { @@ -411,6 +422,24 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, return ret; } +int +PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, const void *x, + const EVP_CIPHER *enc, const unsigned char *kstr, int klen, + pem_password_cb *callback, void *u) +{ + return PEM_ASN1_write_bio_internal(i2d, NULL, NULL, name, bp, x, enc, + kstr, klen, callback, u); +} + +int PEM_ASN1_write_bio_ctx(OSSL_i2d_of_void_ctx *i2d, void *vctx, + const char *name, BIO *bp, const void *x, + const EVP_CIPHER *enc, const unsigned char *kstr, + int klen, pem_password_cb *callback, void *u) +{ + return PEM_ASN1_write_bio_internal(NULL, i2d, vctx, name, bp, x, enc, + kstr, klen, callback, u); +} + int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, pem_password_cb *callback, void *u) { @@ -484,11 +513,11 @@ int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, * presumably we also parse rfc822-style headers for S/MIME, so a common * abstraction might well be more generally useful. */ +#define PROC_TYPE "Proc-Type:" +#define ENCRYPTED "ENCRYPTED" +#define DEK_INFO "DEK-Info:" int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) { - static const char ProcType[] = "Proc-Type:"; - static const char ENCRYPTED[] = "ENCRYPTED"; - static const char DEKInfo[] = "DEK-Info:"; const EVP_CIPHER *enc = NULL; int ivlen; char *dekinfostart, c; @@ -498,11 +527,10 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) if ((header == NULL) || (*header == '\0') || (*header == '\n')) return 1; - if (strncmp(header, ProcType, sizeof(ProcType)-1) != 0) { + if (!CHECK_AND_SKIP_PREFIX(header, PROC_TYPE)) { ERR_raise(ERR_LIB_PEM, PEM_R_NOT_PROC_TYPE); return 0; } - header += sizeof(ProcType)-1; header += strspn(header, " \t"); if (*header++ != '4' || *header++ != ',') @@ -510,12 +538,11 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) header += strspn(header, " \t"); /* We expect "ENCRYPTED" followed by optional white-space + line break */ - if (strncmp(header, ENCRYPTED, sizeof(ENCRYPTED)-1) != 0 || - strspn(header+sizeof(ENCRYPTED)-1, " \t\r\n") == 0) { + if (!CHECK_AND_SKIP_PREFIX(header, ENCRYPTED) || + strspn(header, " \t\r\n") == 0) { ERR_raise(ERR_LIB_PEM, PEM_R_NOT_ENCRYPTED); return 0; } - header += sizeof(ENCRYPTED)-1; header += strspn(header, " \t\r"); if (*header++ != '\n') { ERR_raise(ERR_LIB_PEM, PEM_R_SHORT_HEADER); @@ -526,11 +553,10 @@ int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) * https://tools.ietf.org/html/rfc1421#section-4.6.1.3 * We expect "DEK-Info: algo[,hex-parameters]" */ - if (strncmp(header, DEKInfo, sizeof(DEKInfo)-1) != 0) { + if (!CHECK_AND_SKIP_PREFIX(header, DEK_INFO)) { ERR_raise(ERR_LIB_PEM, PEM_R_NOT_DEK_INFO); return 0; } - header += sizeof(DEKInfo)-1; header += strspn(header, " \t"); /* @@ -611,11 +637,11 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header, int nlen, n, i, j, outl; unsigned char *buf = NULL; EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new(); - int reason = ERR_R_BUF_LIB; + int reason = 0; int retval = 0; if (ctx == NULL) { - reason = ERR_R_MALLOC_FAILURE; + reason = ERR_R_EVP_LIB; goto err; } @@ -624,43 +650,53 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header, if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || (BIO_write(bp, name, nlen) != nlen) || - (BIO_write(bp, "-----\n", 6) != 6)) + (BIO_write(bp, "-----\n", 6) != 6)) { + reason = ERR_R_BIO_LIB; goto err; + } i = header != NULL ? strlen(header) : 0; if (i > 0) { - if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) + if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) { + reason = ERR_R_BIO_LIB; goto err; + } } buf = OPENSSL_malloc(PEM_BUFSIZE * 8); - if (buf == NULL) { - reason = ERR_R_MALLOC_FAILURE; + if (buf == NULL) goto err; - } i = j = 0; while (len > 0) { n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); - if (!EVP_EncodeUpdate(ctx, buf, &outl, &(data[j]), n)) + if (!EVP_EncodeUpdate(ctx, buf, &outl, &(data[j]), n)) { + reason = ERR_R_EVP_LIB; goto err; - if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) + } + if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) { + reason = ERR_R_BIO_LIB; goto err; + } i += outl; len -= n; j += n; } EVP_EncodeFinal(ctx, buf, &outl); - if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) + if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) { + reason = ERR_R_BIO_LIB; goto err; + } if ((BIO_write(bp, "-----END ", 9) != 9) || (BIO_write(bp, name, nlen) != nlen) || - (BIO_write(bp, "-----\n", 6) != 6)) + (BIO_write(bp, "-----\n", 6) != 6)) { + reason = ERR_R_BIO_LIB; goto err; + } retval = i + outl; err: - if (retval == 0) + if (retval == 0 && reason != 0) ERR_raise(ERR_LIB_PEM, reason); EVP_ENCODE_CTX_free(ctx); OPENSSL_clear_free(buf, PEM_BUFSIZE * 8); @@ -733,12 +769,12 @@ static int sanitize_line(char *linebuf, int len, unsigned int flags, int first_c #define LINESIZE 255 /* Note trailing spaces for begin and end. */ -static const char beginstr[] = "-----BEGIN "; -static const char endstr[] = "-----END "; -static const char tailstr[] = "-----\n"; -#define BEGINLEN ((int)(sizeof(beginstr) - 1)) -#define ENDLEN ((int)(sizeof(endstr) - 1)) -#define TAILLEN ((int)(sizeof(tailstr) - 1)) +#define BEGINSTR "-----BEGIN " +#define ENDSTR "-----END " +#define TAILSTR "-----\n" +#define BEGINLEN ((int)(sizeof(BEGINSTR) - 1)) +#define ENDLEN ((int)(sizeof(ENDSTR) - 1)) +#define TAILLEN ((int)(sizeof(TAILSTR) - 1)) static int get_name(BIO *bp, char **name, unsigned int flags) { char *linebuf; @@ -750,11 +786,9 @@ static int get_name(BIO *bp, char **name, unsigned int flags) * Need to hold trailing NUL (accounted for by BIO_gets() and the newline * that will be added by sanitize_line() (the extra '1'). */ - linebuf = pem_malloc(LINESIZE + 1, flags); - if (linebuf == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + linebuf = PEM_MALLOC(LINESIZE + 1, flags); + if (linebuf == NULL) return 0; - } do { len = BIO_gets(bp, linebuf, LINESIZE); @@ -769,21 +803,19 @@ static int get_name(BIO *bp, char **name, unsigned int flags) first_call = 0; /* Allow leading empty or non-matching lines. */ - } while (strncmp(linebuf, beginstr, BEGINLEN) != 0 + } while (!HAS_PREFIX(linebuf, BEGINSTR) || len < TAILLEN - || strncmp(linebuf + len - TAILLEN, tailstr, TAILLEN) != 0); + || !HAS_PREFIX(linebuf + len - TAILLEN, TAILSTR)); linebuf[len - TAILLEN] = '\0'; len = len - BEGINLEN - TAILLEN + 1; - *name = pem_malloc(len, flags); - if (*name == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + *name = PEM_MALLOC(len, flags); + if (*name == NULL) goto err; - } memcpy(*name, linebuf + BEGINLEN, len); ret = 1; err: - pem_free(linebuf, flags, LINESIZE + 1); + PEM_FREE(linebuf, flags, LINESIZE + 1); return ret; } @@ -818,11 +850,9 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, /* Need to hold trailing NUL (accounted for by BIO_gets() and the newline * that will be added by sanitize_line() (the extra '1'). */ - linebuf = pem_malloc(LINESIZE + 1, flags); - if (linebuf == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + linebuf = PEM_MALLOC(LINESIZE + 1, flags); + if (linebuf == NULL) return 0; - } while(1) { flags_mask = ~0u; @@ -844,7 +874,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, if (memchr(linebuf, ':', len) != NULL) got_header = IN_HEADER; } - if (!strncmp(linebuf, endstr, ENDLEN) || got_header == IN_HEADER) + if (HAS_PREFIX(linebuf, ENDSTR) || got_header == IN_HEADER) flags_mask &= ~PEM_FLAG_ONLY_B64; len = sanitize_line(linebuf, len, flags & flags_mask, 0); @@ -867,11 +897,11 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, } /* Check for end of stream (which means there is no header). */ - if (strncmp(linebuf, endstr, ENDLEN) == 0) { - p = linebuf + ENDLEN; + p = linebuf; + if (CHECK_AND_SKIP_PREFIX(p, ENDSTR)) { namelen = strlen(name); if (strncmp(p, name, namelen) != 0 || - strncmp(p + namelen, tailstr, TAILLEN) != 0) { + !HAS_PREFIX(p + namelen, TAILSTR)) { ERR_raise(ERR_LIB_PEM, PEM_R_BAD_END_LINE); goto err; } @@ -905,7 +935,7 @@ static int get_header_and_data(BIO *bp, BIO **header, BIO **data, char *name, ret = 1; err: - pem_free(linebuf, flags, LINESIZE + 1); + PEM_FREE(linebuf, flags, LINESIZE + 1); return ret; } @@ -923,7 +953,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, BIO *headerB = NULL, *dataB = NULL; char *name = NULL; int len, taillen, headerlen, ret = 0; - BUF_MEM * buf_mem; + BUF_MEM *buf_mem; *len_out = 0; *name_out = *header = NULL; @@ -938,7 +968,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, headerB = BIO_new(bmeth); dataB = BIO_new(bmeth); if (headerB == NULL || dataB == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PEM, ERR_R_BIO_LIB); goto end; } @@ -956,7 +986,7 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, ctx = EVP_ENCODE_CTX_new(); if (ctx == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PEM, ERR_R_EVP_LIB); goto end; } @@ -972,8 +1002,8 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, buf_mem->length = len; headerlen = BIO_get_mem_data(headerB, NULL); - *header = pem_malloc(headerlen + 1, flags); - *data = pem_malloc(len, flags); + *header = PEM_MALLOC(headerlen + 1, flags); + *data = PEM_MALLOC(len, flags); if (*header == NULL || *data == NULL) goto out_free; if (headerlen != 0 && BIO_read(headerB, *header, headerlen) != headerlen) @@ -988,13 +1018,13 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, goto end; out_free: - pem_free(*header, flags, 0); + PEM_FREE(*header, flags, 0); *header = NULL; - pem_free(*data, flags, 0); + PEM_FREE(*data, flags, 0); *data = NULL; end: EVP_ENCODE_CTX_free(ctx); - pem_free(name, flags, 0); + PEM_FREE(name, flags, 0); BIO_free(headerB); BIO_free(dataB); return ret; diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c index 4deee46ce550..b640d3a7ae27 100644 --- a/crypto/pem/pem_pkey.c +++ b/crypto/pem/pem_pkey.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -334,7 +334,7 @@ PEM_write_cb_fnsig(PrivateKey, EVP_PKEY, BIO, write_bio) /* * Note: there is no way to tell a provided pkey encoder to use "traditional" - * encoding. Therefore, if the pkey is provided, we try to take a copy + * encoding. Therefore, if the pkey is provided, we try to take a copy */ int PEM_write_bio_PrivateKey_traditional(BIO *bp, const EVP_PKEY *x, const EVP_CIPHER *enc, diff --git a/crypto/pem/pem_sign.c b/crypto/pem/pem_sign.c index 6ad8e4303721..f6b0ff4ddadb 100644 --- a/crypto/pem/pem_sign.c +++ b/crypto/pem/pem_sign.c @@ -33,10 +33,8 @@ int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int m_len; m = OPENSSL_malloc(EVP_PKEY_get_size(pkey)); - if (m == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + if (m == NULL) goto err; - } if (EVP_SignFinal(ctx, m, &m_len, pkey) <= 0) goto err; diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c index 21b16f5928c1..3d234a507b74 100644 --- a/crypto/pem/pvkfmt.c +++ b/crypto/pem/pvkfmt.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "internal/cryptlib.h" #include "crypto/pem.h" #include "crypto/evp.h" @@ -88,6 +90,7 @@ static EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type) case EVP_PKEY_RSA: if (EVP_PKEY_set1_RSA(pkey, key)) break; + ERR_raise(ERR_LIB_PEM, ERR_R_EVP_LIB); EVP_PKEY_free(pkey); pkey = NULL; break; @@ -95,11 +98,14 @@ static EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type) case EVP_PKEY_DSA: if (EVP_PKEY_set1_DSA(pkey, key)) break; + ERR_raise(ERR_LIB_PEM, ERR_R_EVP_LIB); EVP_PKEY_free(pkey); pkey = NULL; break; #endif } + } else { + ERR_raise(ERR_LIB_PEM, ERR_R_EVP_LIB); } switch (evp_type) { @@ -113,8 +119,6 @@ static EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type) #endif } - if (pkey == NULL) - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); return pkey; } @@ -146,7 +150,7 @@ static EVP_PKEY *evp_pkey_new0_key(void *key, int evp_type) * Read the MSBLOB header and get relevant data from it. * * |pisdss| and |pispub| have a double role, as they can be used for - * discovery as well as to check the the blob meets expectations. + * discovery as well as to check the blob meets expectations. * |*pisdss| is the indicator for whether the key is a DSA key or not. * |*pispub| is the indicator for whether the key is public or not. * In both cases, the following input values apply: @@ -341,10 +345,8 @@ EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub) return NULL; } buf = OPENSSL_malloc(length); - if (buf == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + if (buf == NULL) goto err; - } p = buf; if (BIO_read(in, buf, length) != (int)length) { ERR_raise(ERR_LIB_PEM, PEM_R_KEYBLOB_TOO_SHORT); @@ -382,22 +384,22 @@ DSA *ossl_b2i_DSA_after_header(const unsigned char **in, unsigned int bitlen, dsa = DSA_new(); if (dsa == NULL) - goto memerr; + goto dsaerr; if (!read_lebn(&p, nbyte, &pbn)) - goto memerr; + goto bnerr; if (!read_lebn(&p, 20, &qbn)) - goto memerr; + goto bnerr; if (!read_lebn(&p, nbyte, &gbn)) - goto memerr; + goto bnerr; if (ispub) { if (!read_lebn(&p, nbyte, &pub_key)) - goto memerr; + goto bnerr; } else { if (!read_lebn(&p, 20, &priv_key)) - goto memerr; + goto bnerr; /* Set constant time flag before public key calculation */ BN_set_flags(priv_key, BN_FLG_CONSTTIME); @@ -405,28 +407,33 @@ DSA *ossl_b2i_DSA_after_header(const unsigned char **in, unsigned int bitlen, /* Calculate public key */ pub_key = BN_new(); if (pub_key == NULL) - goto memerr; + goto bnerr; if ((ctx = BN_CTX_new()) == NULL) - goto memerr; + goto bnerr; if (!BN_mod_exp(pub_key, gbn, priv_key, pbn, ctx)) - goto memerr; + goto bnerr; BN_CTX_free(ctx); ctx = NULL; } if (!DSA_set0_pqg(dsa, pbn, qbn, gbn)) - goto memerr; + goto dsaerr; pbn = qbn = gbn = NULL; if (!DSA_set0_key(dsa, pub_key, priv_key)) - goto memerr; + goto dsaerr; pub_key = priv_key = NULL; *in = p; return dsa; - memerr: - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + dsaerr: + ERR_raise(ERR_LIB_PEM, ERR_R_DSA_LIB); + goto err; + bnerr: + ERR_raise(ERR_LIB_PEM, ERR_R_BN_LIB); + + err: DSA_free(dsa); BN_free(pbn); BN_free(qbn); @@ -450,42 +457,48 @@ RSA *ossl_b2i_RSA_after_header(const unsigned char **in, unsigned int bitlen, rsa = RSA_new(); if (rsa == NULL) - goto memerr; + goto rsaerr; e = BN_new(); if (e == NULL) - goto memerr; + goto bnerr; if (!BN_set_word(e, read_ledword(&pin))) - goto memerr; + goto bnerr; if (!read_lebn(&pin, nbyte, &n)) - goto memerr; + goto bnerr; if (!ispub) { if (!read_lebn(&pin, hnbyte, &p)) - goto memerr; + goto bnerr; if (!read_lebn(&pin, hnbyte, &q)) - goto memerr; + goto bnerr; if (!read_lebn(&pin, hnbyte, &dmp1)) - goto memerr; + goto bnerr; if (!read_lebn(&pin, hnbyte, &dmq1)) - goto memerr; + goto bnerr; if (!read_lebn(&pin, hnbyte, &iqmp)) - goto memerr; + goto bnerr; if (!read_lebn(&pin, nbyte, &d)) - goto memerr; + goto bnerr; if (!RSA_set0_factors(rsa, p, q)) - goto memerr; + goto rsaerr; p = q = NULL; if (!RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp)) - goto memerr; + goto rsaerr; dmp1 = dmq1 = iqmp = NULL; } if (!RSA_set0_key(rsa, n, e, d)) - goto memerr; + goto rsaerr; n = e = d = NULL; *in = pin; return rsa; - memerr: - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + + rsaerr: + ERR_raise(ERR_LIB_PEM, ERR_R_RSA_LIB); + goto err; + bnerr: + ERR_raise(ERR_LIB_PEM, ERR_R_BN_LIB); + + err: BN_free(e); BN_free(n); BN_free(p); @@ -577,7 +590,6 @@ static int do_i2b(unsigned char **out, const EVP_PKEY *pk, int ispub) p = *out; else { if ((p = OPENSSL_malloc(outlen)) == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); outlen = -1; goto end; } @@ -746,7 +758,7 @@ int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk) } int ossl_do_PVK_header(const unsigned char **in, unsigned int length, - int skip_magic, + int skip_magic, int *isdss, unsigned int *psaltlen, unsigned int *pkeylen) { const unsigned char *p = *in; @@ -770,9 +782,26 @@ int ossl_do_PVK_header(const unsigned char **in, unsigned int length, } /* Skip reserved */ p += 4; - /* - * keytype = - */ read_ledword(&p); + /* Check the key type */ + switch (read_ledword(&p)) { + case MS_KEYTYPE_KEYX: + if (*isdss == 1) { + ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_RSA_KEY_BLOB); + return 0; + } + *isdss = 0; + break; + case MS_KEYTYPE_SIGN: + if (*isdss == 0) { + ERR_raise(ERR_LIB_PEM, PEM_R_EXPECTING_DSS_KEY_BLOB); + return 0; + } + *isdss = 1; + break; + default: + ERR_raise(ERR_LIB_PEM, PEM_R_UNSUPPORTED_PVK_KEY_TYPE); + return 0; + } is_encrypted = read_ledword(&p); *psaltlen = read_ledword(&p); *pkeylen = read_ledword(&p); @@ -790,29 +819,34 @@ int ossl_do_PVK_header(const unsigned char **in, unsigned int length, } #ifndef OPENSSL_NO_RC4 -static int derive_pvk_key(unsigned char *key, +static int derive_pvk_key(unsigned char *key, size_t keylen, const unsigned char *salt, unsigned int saltlen, const unsigned char *pass, int passlen, OSSL_LIB_CTX *libctx, const char *propq) { - EVP_MD_CTX *mctx = EVP_MD_CTX_new(); - int rv = 0; - EVP_MD *sha1 = NULL; + EVP_KDF *kdf; + EVP_KDF_CTX *ctx; + OSSL_PARAM params[5], *p = params; + int rv; - if ((sha1 = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL) - goto err; + if ((kdf = EVP_KDF_fetch(libctx, "PVKKDF", propq)) == NULL) + return 0; + ctx = EVP_KDF_CTX_new(kdf); + EVP_KDF_free(kdf); + if (ctx == NULL) + return 0; - if (mctx == NULL - || !EVP_DigestInit_ex(mctx, sha1, NULL) - || !EVP_DigestUpdate(mctx, salt, saltlen) - || !EVP_DigestUpdate(mctx, pass, passlen) - || !EVP_DigestFinal_ex(mctx, key, NULL)) - goto err; + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, + (void *)salt, saltlen); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, + (void *)pass, passlen); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, SN_sha1, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_PROPERTIES, + (char *)propq, 0); + *p = OSSL_PARAM_construct_end(); - rv = 1; -err: - EVP_MD_CTX_free(mctx); - EVP_MD_free(sha1); + rv = EVP_KDF_derive(ctx, key, keylen, params); + EVP_KDF_CTX_free(ctx); return rv; } #endif @@ -833,7 +867,7 @@ static void *do_PVK_body_key(const unsigned char **in, EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new(); if (cctx == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PEM, ERR_R_EVP_LIB); goto err; } @@ -853,11 +887,9 @@ static void *do_PVK_body_key(const unsigned char **in, goto err; } enctmp = OPENSSL_malloc(keylen + 8); - if (enctmp == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + if (enctmp == NULL) goto err; - } - if (!derive_pvk_key(keybuf, p, saltlen, + if (!derive_pvk_key(keybuf, sizeof(keybuf), p, saltlen, (unsigned char *)psbuf, inlen, libctx, propq)) goto err; p += saltlen; @@ -930,14 +962,12 @@ static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u, } p = pvk_hdr; - if (!ossl_do_PVK_header(&p, 24, 0, &saltlen, &keylen)) + if (!ossl_do_PVK_header(&p, 24, 0, isdss, &saltlen, &keylen)) return 0; buflen = (int)keylen + saltlen; buf = OPENSSL_malloc(buflen); - if (buf == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + if (buf == NULL) return 0; - } p = buf; if (BIO_read(in, buf, buflen) != buflen) { ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT); @@ -1020,10 +1050,8 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, p = *out; } else { start = p = OPENSSL_malloc(outlen); - if (p == NULL) { - ERR_raise(ERR_LIB_PEM, ERR_R_MALLOC_FAILURE); + if (p == NULL) return -1; - } } cctx = EVP_CIPHER_CTX_new(); @@ -1063,7 +1091,7 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel, ERR_raise(ERR_LIB_PEM, PEM_R_BAD_PASSWORD_READ); goto error; } - if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN, + if (!derive_pvk_key(keybuf, sizeof(keybuf), salt, PVK_SALTLEN, (unsigned char *)psbuf, inlen, libctx, propq)) goto error; if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL) diff --git a/crypto/perlasm/arm-xlate.pl b/crypto/perlasm/arm-xlate.pl index 38d570c79017..b94d1c762ddb 100755 --- a/crypto/perlasm/arm-xlate.pl +++ b/crypto/perlasm/arm-xlate.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -22,6 +22,7 @@ my $dotinlocallabels=($flavour=~/linux/)?1:0; ################################################################ my $arch = sub { if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } + elsif ($flavour =~ /win64/) { ".arch\t".join(',',@_); } else { ""; } }; my $fpu = sub { @@ -32,11 +33,21 @@ my $rodata = sub { SWITCH: for ($flavour) { /linux/ && return ".section\t.rodata"; /ios/ && return ".section\t__TEXT,__const"; + /win64/ && return ".section\t.rodata"; + last; + } +}; +my $previous = sub { + SWITCH: for ($flavour) { + /linux/ && return ".previous"; + /ios/ && return ".previous"; + /win64/ && return ".text"; last; } }; my $hidden = sub { if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } + elsif ($flavour =~ /win64/) { ""; } else { ".hidden\t".join(',',@_); } }; my $comm = sub { @@ -85,6 +96,15 @@ my $type = sub { "#endif"; } } + elsif ($flavour =~ /win64/) { if (join(',',@_) =~ /(\w+),%function/) { + # See https://sourceware.org/binutils/docs/as/Pseudo-Ops.html + # Per https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table, + # the type for functions is 0x20, or 32. + ".def $1\n". + " .type 32\n". + ".endef"; + } + } else { ""; } }; my $size = sub { @@ -105,9 +125,26 @@ my $asciz = sub { my $adrp = sub { my ($args,$comment) = split(m|\s*//|,shift); - "\tadrp\t$args\@PAGE"; -} if ($flavour =~ /ios64/); - + if ($flavour =~ /ios64/) { + "\tadrp\t$args\@PAGE"; + } elsif ($flavour =~ /linux/) { + # + # there seem to be two forms of 'addrp' instruction + # to calculate offset: + # addrp x3,x3,:lo12:Lrcon + # and alternate form: + # addrp x3,x3,:#lo12:Lrcon + # the '#' is mandatory for some compilers + # so make sure our asm always uses '#' here. + # + $args =~ s/(\w+)#?:lo2:(\.?\w+)/$1#:lo2:$2/; + if ($flavour =~ /linux32/) { + "\tadr\t$args"; + } else { + "\tadrp\t$args"; + } + } +} if (($flavour =~ /ios64/) || ($flavour =~ /linux/)); sub range { my ($r,$sfx,$start,$end) = @_; @@ -139,7 +176,12 @@ sub expand_line { $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; if ($flavour =~ /ios64/) { - $line =~ s/#:lo12:(\w+)/$1\@PAGEOFF/; + $line =~ s/#?:lo12:(\w+)/$1\@PAGEOFF/; + } elsif($flavour =~ /linux/) { + # + # make '#' mandatory for :lo12: (similar to adrp above) + # + $line =~ s/#?:lo12:(\.?\w+)/\#:lo12:$1/; } return $line; @@ -186,6 +228,16 @@ while(my $line=<>) { } } + # ldr REG, #VALUE psuedo-instruction - avoid clang issue with Neon registers + # + if ($line =~ /^\s*ldr\s+([qd]\d\d?)\s*,\s*=(\w+)/i) { + # Immediate load via literal pool into qN or DN - clang max is 2^32-1 + my ($reg, $value) = ($1, $2); + # If $value is hex, 0x + 8 hex chars = 10 chars total will be okay + # If $value is decimal, 2^32 - 1 = 4294967295 will be okay (also 10 chars) + die("$line: immediate load via literal pool into $reg: value too large for clang - redo manually") if length($value) > 10; + } + print $line if ($line); print "\n"; } diff --git a/crypto/perlasm/ppc-xlate.pl b/crypto/perlasm/ppc-xlate.pl index 2ee444045ff9..249435f56a0c 100755 --- a/crypto/perlasm/ppc-xlate.pl +++ b/crypto/perlasm/ppc-xlate.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -293,6 +293,14 @@ my $vpermdi = sub { # xxpermdi $dm = oct($dm) if ($dm =~ /^0/); " .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|($dm<<8)|(10<<3)|7; }; +my $vxxlor = sub { # xxlor + my ($f, $vrt, $vra, $vrb) = @_; + " .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|(146<<3)|6; +}; +my $vxxlorc = sub { # xxlor + my ($f, $vrt, $vra, $vrb) = @_; + " .long ".sprintf "0x%X",(60<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|(146<<3)|1; +}; # PowerISA 2.07 stuff sub vcrypto_op { @@ -377,6 +385,15 @@ my $addex = sub { }; my $vmsumudm = sub { vfour_vsr(@_, 35); }; +# PowerISA 3.1 stuff +my $brd = sub { + my ($f, $ra, $rs) = @_; + " .long ".sprintf "0x%X",(31<<26)|($rs<<21)|($ra<<16)|(187<<1); +}; +my $vsrq = sub { vcrypto_op(@_, 517); }; + + + while($line=<>) { $line =~ s|[#!;].*$||; # get rid of asm-style comments... diff --git a/crypto/perlasm/sparcv9_modes.pl b/crypto/perlasm/sparcv9_modes.pl index 76a2727aba62..3f24511c1a6b 100644 --- a/crypto/perlasm/sparcv9_modes.pl +++ b/crypto/perlasm/sparcv9_modes.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2012-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -46,8 +46,8 @@ $::code.=<<___; .align 32 ${alg}${bits}_t4_cbc_encrypt: save %sp, -$::frame, %sp - cmp $len, 0 - be,pn $::size_t_cc, .L${bits}_cbc_enc_abort + cmp $len, 15 + bleu,pn $::size_t_cc, .L${bits}_cbc_enc_abort srln $len, 0, $len ! needed on v8+, "nop" on v9 sub $inp, $out, $blk_init ! $inp!=$out ___ @@ -264,8 +264,8 @@ $::code.=<<___; .align 32 ${alg}${bits}_t4_cbc_decrypt: save %sp, -$::frame, %sp - cmp $len, 0 - be,pn $::size_t_cc, .L${bits}_cbc_dec_abort + cmp $len, 15 + bleu,pn $::size_t_cc, .L${bits}_cbc_dec_abort srln $len, 0, $len ! needed on v8+, "nop" on v9 sub $inp, $out, $blk_init ! $inp!=$out ___ diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl index b2bf96cef01e..2cd9a219c239 100755 --- a/crypto/perlasm/x86_64-xlate.pl +++ b/crypto/perlasm/x86_64-xlate.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -156,6 +156,65 @@ _____ } my $current_segment; +# +# I could not find equivalent of .previous directive for MASM (Microsoft +# assembler ML). Using of .previous got introduced to .pl files with +# placing of various constants into .rodata sections (segments). +# Each .rodata section is terminated by .previous directive which +# restores the preceding section to .rodata: +# +# .text +# ; this is is the text section/segment +# .rodata +# ; constant definitions go here +# .previous +# ; the .text section which precedes .rodata got restored here +# +# The equivalent form for masm reads as follows: +# +# .text$ SEGMENT ALIGN(256) 'CODE' +# ; this is is the text section/segment +# .text$ ENDS +# .rdata SEGMENT READONLY ALIGN(64) +# ; constant definitions go here +# .rdata$ ENDS +# .text$ SEGMENT ALIGN(256) 'CODE' +# ; text section follows +# .text$ ENDS +# +# The .previous directive typically terminates .roadata segments/sections which +# hold definitions of constants. In order to place constants into .rdata +# segments when using masm we need to introduce a segment_stack array so we can +# emit proper ENDS directive whenever we see .previous. +# +# The code is tailored to work current set of .pl/asm files. There are some +# inconsistencies. For example .text section is the first section in all those +# files except ecp_nistz256. So we need to take that into account. +# +# ; stack is empty +# .text +# ; push '.text ' section twice, the stack looks as +# ; follows: +# ; ('.text', '.text') +# .rodata +# ; pop() so we can generate proper 'ENDS' for masm. +# ; stack looks like: +# ; ('.text') +# ; push '.rodata', so we can create corresponding ENDS for masm. +# ; stack looks like: +# ; ('.rodata', '.text') +# .previous +# ; pop() '.rodata' from stack, so we create '.rodata ENDS' +# ; in masm flavour. For nasm flavour we just pop() because +# ; nasm does not use .rodata ENDS to close the current section +# ; the stack content is like this: +# ; ('.text', '.text') +# ; pop() again to find a previous section we need to restore. +# ; Depending on flavour we either generate .section .text +# ; or .text SEGMENT. The stack looks like: +# ; ('.text') +# +my @segment_stack = (); my $current_function; my %globals; @@ -816,7 +875,7 @@ my %globals; } last; }; - /\.rva|\.long|\.quad/ + /\.rva|\.long|\.quad|\.byte/ && do { $$line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei; $$line =~ s/\.L/$decor/g; last; @@ -844,19 +903,63 @@ my %globals; } elsif (!$elf && $dir =~ /\.align/) { $self->{value} = ".p2align\t" . (log($$line)/log(2)); } elsif ($dir eq ".section") { - $current_segment=$$line; + # + # get rid off align option, it's not supported/tolerated + # by gcc. openssl project introduced the option as an aid + # to deal with nasm/masm assembly. + # + $self->{value} =~ s/(.+)\s+align\s*=.*$/$1/; + $current_segment = pop(@segment_stack); + if (not $current_segment) { + # if no previous section is defined, then assume .text + # so code does not land in .data section by accident. + # this deals with inconsistency of perl-assembly files. + push(@segment_stack, ".text"); + } + # + # $$line may still contains align= option. We do care + # about section type here. + # + $current_segment = $$line; + $current_segment =~ s/([^\s]+).*$/$1/; + push(@segment_stack, $current_segment); + if (!$elf && $current_segment eq ".rodata") { + if ($flavour eq "macosx") { $self->{value} = ".section\t__DATA,__const"; } + elsif ($flavour eq "mingw64") { $self->{value} = ".section\t.rodata"; } + } if (!$elf && $current_segment eq ".init") { if ($flavour eq "macosx") { $self->{value} = ".mod_init_func"; } elsif ($flavour eq "mingw64") { $self->{value} = ".section\t.ctors"; } } } elsif ($dir =~ /\.(text|data)/) { + $current_segment = pop(@segment_stack); + if (not $current_segment) { + # if no previous section is defined, then assume .text + # so code does not land in .data section by accident. + # this deals with inconsistency of perl-assembly files. + push(@segment_stack, ".text"); + } $current_segment=".$1"; + push(@segment_stack, $current_segment); } elsif ($dir =~ /\.hidden/) { if ($flavour eq "macosx") { $self->{value} = ".private_extern\t$prefix$$line"; } elsif ($flavour eq "mingw64") { $self->{value} = ""; } } elsif ($dir =~ /\.comm/) { $self->{value} = "$dir\t$prefix$$line"; $self->{value} =~ s|,([0-9]+),([0-9]+)$|",$1,".log($2)/log(2)|e if ($flavour eq "macosx"); + } elsif ($dir =~ /\.previous/) { + pop(@segment_stack); #pop ourselves + # just peek at the top of the stack here + $current_segment = @segment_stack[0]; + if (not $current_segment) { + # if no previous segment was defined assume .text so + # the code does not accidentally land in .data section. + $current_segment = ".text"; + push(@segment_stack, $current_segment); + } + if ($flavour eq "mingw64" || $flavour eq "macosx") { + $self->{value} = $current_segment; + } } $$line = ""; return $self; @@ -866,10 +969,21 @@ my %globals; SWITCH: for ($dir) { /\.text/ && do { my $v=undef; if ($nasm) { + $current_segment = pop(@segment_stack); + if (not $current_segment) { + push(@segment_stack, ".text"); + } $v="section .text code align=64\n"; + $current_segment = ".text"; + push(@segment_stack, $current_segment); } else { + $current_segment = pop(@segment_stack); + if (not $current_segment) { + push(@segment_stack, ".text\$"); + } $v="$current_segment\tENDS\n" if ($current_segment); $current_segment = ".text\$"; + push(@segment_stack, $current_segment); $v.="$current_segment\tSEGMENT "; $v.=$masm>=$masmref ? "ALIGN(256)" : "PAGE"; $v.=" 'CODE'"; @@ -881,36 +995,76 @@ my %globals; if ($nasm) { $v="section .data data align=8\n"; } else { + $current_segment = pop(@segment_stack); $v="$current_segment\tENDS\n" if ($current_segment); $current_segment = "_DATA"; + push(@segment_stack, $current_segment); $v.="$current_segment\tSEGMENT"; } $self->{value} = $v; last; }; /\.section/ && do { my $v=undef; - $$line =~ s/([^,]*).*/$1/; + my $align=undef; + # + # $$line may currently contain something like this + # .rodata align = 64 + # align part is optional + # + $align = $$line; + $align =~ s/(.*)(align\s*=\s*\d+$)/$2/; + $$line =~ s/(.*)(\s+align\s*=\s*\d+$)/$1/; + $$line =~ s/,.*//; $$line = ".CRT\$XCU" if ($$line eq ".init"); + $$line = ".rdata" if ($$line eq ".rodata"); if ($nasm) { + $current_segment = pop(@segment_stack); + if (not $current_segment) { + # + # This is a hack which deals with ecp_nistz256-x86_64.pl, + # The precomputed curve is stored in the first section + # in .asm file. Pushing extra .text section here + # allows our poor man's solution to stick to assumption + # .text section is always the first. + # + push(@segment_stack, ".text"); + } $v="section $$line"; - if ($$line=~/\.([px])data/) { - $v.=" rdata align="; - $v.=$1 eq "p"? 4 : 8; + if ($$line=~/\.([prx])data/) { + if ($align =~ /align\s*=\s*(\d+)/) { + $v.= " rdata align=$1" ; + } else { + $v.=" rdata align="; + $v.=$1 eq "p"? 4 : 8; + } } elsif ($$line=~/\.CRT\$/i) { $v.=" rdata align=8"; } } else { + $current_segment = pop(@segment_stack); + if (not $current_segment) { + # + # same hack for masm to keep ecp_nistz256-x86_64.pl + # happy. + # + push(@segment_stack, ".text\$"); + } $v="$current_segment\tENDS\n" if ($current_segment); $v.="$$line\tSEGMENT"; - if ($$line=~/\.([px])data/) { + if ($$line=~/\.([prx])data/) { $v.=" READONLY"; - $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref); + if ($align =~ /align\s*=\s*(\d+)$/) { + $v.=" ALIGN($1)" if ($masm>=$masmref); + } else { + $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref); + } } elsif ($$line=~/\.CRT\$/i) { $v.=" READONLY "; $v.=$masm>=$masmref ? "ALIGN(8)" : "DWORD"; } } $current_segment = $$line; + push(@segment_stack, $$line); $self->{value} = $v; last; }; @@ -973,14 +1127,44 @@ my %globals; if ($nasm) { $v.="common $prefix@str[0] @str[1]"; } else { + $current_segment = pop(@segment_stack);; $v="$current_segment\tENDS\n" if ($current_segment); $current_segment = "_DATA"; + push(@segment_stack, $current_segment); $v.="$current_segment\tSEGMENT\n"; $v.="COMM @str[0]:DWORD:".@str[1]/4; } $self->{value} = $v; last; }; + /^.previous/ && do { + my $v=undef; + if ($nasm) { + pop(@segment_stack); # pop ourselves, we don't need to emit END directive + # pop section so we can emit proper .section name. + $current_segment = pop(@segment_stack); + $v="section $current_segment"; + # Hack again: + # push section/segment to stack. The .previous is currently paired + # with .rodata only. We have to keep extra '.text' on stack for + # situation where there is for example .pdata section 'terminated' + # by new '.text' section. + # + push(@segment_stack, $current_segment); + } else { + $current_segment = pop(@segment_stack); + $v="$current_segment\tENDS\n" if ($current_segment); + $current_segment = pop(@segment_stack); + if ($current_segment =~ /\.text\$/) { + $v.="$current_segment\tSEGMENT "; + $v.=$masm>=$masmref ? "ALIGN(256)" : "PAGE"; + $v.=" 'CODE'"; + push(@segment_stack, $current_segment); + } + } + $self->{value} = $v; + last; + }; } $$line = ""; } diff --git a/crypto/perlasm/x86asm.pl b/crypto/perlasm/x86asm.pl index 8dcde9eacaa3..2ec16c5571d8 100644 --- a/crypto/perlasm/x86asm.pl +++ b/crypto/perlasm/x86asm.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy diff --git a/crypto/perlasm/x86gas.pl b/crypto/perlasm/x86gas.pl index 1b2b27c02286..f3c01ea89b4b 100644 --- a/crypto/perlasm/x86gas.pl +++ b/crypto/perlasm/x86gas.pl @@ -167,7 +167,8 @@ sub ::file_end } } if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) { - my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,16"; + # OPENSSL_ia32cap_P size should match with internal/cryptlib.h OPENSSL_IA32CAP_P_MAX_INDEXES + my $tmp=".comm\t${nmdecor}OPENSSL_ia32cap_P,40"; if ($::macosx) { push (@out,"$tmp,2\n"); } elsif ($::elf) { push (@out,"$tmp,4\n"); } else { push (@out,"$tmp\n"); } diff --git a/crypto/perlasm/x86masm.pl b/crypto/perlasm/x86masm.pl index 2dcd3f79f6ed..ccdba757dc28 100644 --- a/crypto/perlasm/x86masm.pl +++ b/crypto/perlasm/x86masm.pl @@ -139,9 +139,10 @@ ___ push(@out,"$segment ENDS\n"); if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) + # OPENSSL_ia32cap_P size should match with internal/cryptlib.h OPENSSL_IA32CAP_P_MAX_INDEXES { my $comm=<<___; .bss SEGMENT 'BSS' -COMM ${nmdecor}OPENSSL_ia32cap_P:DWORD:4 +COMM ${nmdecor}OPENSSL_ia32cap_P:DWORD:10 .bss ENDS ___ # comment out OPENSSL_ia32cap_P declarations diff --git a/crypto/perlasm/x86nasm.pl b/crypto/perlasm/x86nasm.pl index 7017b88e80a3..a8cdd2d0bbe5 100644 --- a/crypto/perlasm/x86nasm.pl +++ b/crypto/perlasm/x86nasm.pl @@ -124,9 +124,10 @@ sub ::function_end_B sub ::file_end { if (grep {/\b${nmdecor}OPENSSL_ia32cap_P\b/i} @out) + # OPENSSL_ia32cap_P size should match with internal/cryptlib.h OPENSSL_IA32CAP_P_MAX_INDEXES { my $comm=<<___; ${drdecor}segment .bss -${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 16 +${drdecor}common ${nmdecor}OPENSSL_ia32cap_P 40 ___ # comment out OPENSSL_ia32cap_P declarations grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out; diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 66dcf92ca11e..b2635ff1f64c 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -24,16 +24,16 @@ PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, PKCS12_SAFEBAG *safebag; if ((bag = PKCS12_BAGS_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } bag->type = OBJ_nid2obj(nid1); if (!ASN1_item_pack(obj, it, &bag->value.octet)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } if ((safebag = PKCS12_SAFEBAG_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } safebag->value.bag = bag; @@ -51,12 +51,12 @@ PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk) PKCS7 *p7; if ((p7 = PKCS7_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } p7->type = OBJ_nid2obj(NID_pkcs7_data); if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } @@ -84,7 +84,9 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) return NULL; } - return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS)); + return ASN1_item_unpack_ex(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), + ossl_pkcs7_ctx_get0_libctx(&p7->ctx), + ossl_pkcs7_ctx_get0_propq(&p7->ctx)); } /* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ @@ -100,7 +102,7 @@ PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen, EVP_CIPHER *pbe_ciph_fetch = NULL; if ((p7 = PKCS7_new_ex(ctx, propq)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } if (!PKCS7_set_type(p7, NID_pkcs7_encrypted)) { @@ -121,7 +123,7 @@ PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen, } if (pbe == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } X509_ALGOR_free(p7->d.encrypted->enc_data->algorithm); @@ -193,6 +195,7 @@ int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes) STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) { STACK_OF(PKCS7) *p7s; + PKCS7_CTX *p7ctx; PKCS7 *p7; int i; @@ -206,8 +209,11 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) return NULL; } - p7s = ASN1_item_unpack(p12->authsafes->d.data, - ASN1_ITEM_rptr(PKCS12_AUTHSAFES)); + p7ctx = &p12->authsafes->ctx; + p7s = ASN1_item_unpack_ex(p12->authsafes->d.data, + ASN1_ITEM_rptr(PKCS12_AUTHSAFES), + ossl_pkcs7_ctx_get0_libctx(p7ctx), + ossl_pkcs7_ctx_get0_propq(p7ctx)); if (p7s != NULL) { for (i = 0; i < sk_PKCS7_num(p7s); i++) { p7 = sk_PKCS7_value(p7s, i); diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c index aabbd38eefbe..e4247b27fc3a 100644 --- a/crypto/pkcs12/p12_asn.c +++ b/crypto/pkcs12/p12_asn.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2018 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 @@ -12,6 +12,7 @@ #include #include #include "p12_local.h" +#include "crypto/pkcs7.h" /* PKCS#12 ASN1 module */ @@ -21,7 +22,21 @@ ASN1_SEQUENCE(PKCS12) = { ASN1_OPT(PKCS12, mac, PKCS12_MAC_DATA) } ASN1_SEQUENCE_END(PKCS12) -IMPLEMENT_ASN1_FUNCTIONS(PKCS12) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(PKCS12, PKCS12, PKCS12) + +PKCS12 *PKCS12_new(void) +{ + return (PKCS12 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS12)); +} + +void PKCS12_free(PKCS12 *p12) +{ + if (p12 != NULL && p12->authsafes != NULL) { + OPENSSL_free(p12->authsafes->ctx.propq); + p12->authsafes->ctx.propq = NULL; + } + ASN1_item_free((ASN1_VALUE *)p12, ASN1_ITEM_rptr(PKCS12)); +} ASN1_SEQUENCE(PKCS12_MAC_DATA) = { ASN1_SIMPLE(PKCS12_MAC_DATA, dinfo, X509_SIG), diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c index da228336eb60..ea0d027c10fc 100644 --- a/crypto/pkcs12/p12_attr.c +++ b/crypto/pkcs12/p12_attr.c @@ -95,11 +95,11 @@ int PKCS12_add1_attr_by_txt(PKCS12_SAFEBAG *bag, const char *attrname, int type, ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid) { - X509_ATTRIBUTE *attrib; - int i; - i = X509at_get_attr_by_NID(attrs, attr_nid, -1); - attrib = X509at_get_attr(attrs, i); - return X509_ATTRIBUTE_get0_type(attrib, 0); + int i = X509at_get_attr_by_NID(attrs, attr_nid, -1); + + if (i < 0) + return NULL; + return X509_ATTRIBUTE_get0_type(X509at_get_attr(attrs, i), 0); } char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag) @@ -119,3 +119,11 @@ PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag) { return bag->attrib; } + +void PKCS12_SAFEBAG_set0_attrs(PKCS12_SAFEBAG *bag, STACK_OF(X509_ATTRIBUTE) *attrs) +{ + if (bag->attrib != attrs) + sk_X509_ATTRIBUTE_free(bag->attrib); + + bag->attrib = attrs; +} diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c index 3c7d5ff97c52..60cc49820f9a 100644 --- a/crypto/pkcs12/p12_crt.c +++ b/crypto/pkcs12/p12_crt.c @@ -14,6 +14,8 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag); +static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag); static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert, const char *name, @@ -23,27 +25,24 @@ static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) { - int idx; - X509_ATTRIBUTE *attr; - idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1); + int idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1); + if (idx < 0) return 1; - attr = EVP_PKEY_get_attr(pkey, idx); - if (!X509at_add1_attr(&bag->attrib, attr)) - return 0; - return 1; + return X509at_add1_attr(&bag->attrib, EVP_PKEY_get_attr(pkey, idx)) != NULL; } -PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, - X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, - int iter, int mac_iter, int keytype, - OSSL_LIB_CTX *ctx, const char *propq) +PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq, + PKCS12_create_cb *cb, void *cbarg) { PKCS12 *p12 = NULL; STACK_OF(PKCS7) *safes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; PKCS12_SAFEBAG *bag = NULL; - int i; + int i, cbret; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; int namelen = -1; @@ -83,12 +82,30 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, } bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen); + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } /* Add all other certificates */ for (i = 0; i < sk_X509_num(ca); i++) { - if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i))) + if ((bag = PKCS12_add_cert(&bags, sk_X509_value(ca, i))) == NULL) goto err; + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass, @@ -114,6 +131,15 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, goto err; if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) goto err; + if (cb != NULL) { + cbret = cb(bag, cbarg); + if (cbret == -1) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CALLBACK_FAILED); + goto err; + } else if (cbret == 0) { + pkcs12_remove_bag(&bags, bag); + } + } } if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL)) @@ -145,6 +171,16 @@ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, } +PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, + STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq) +{ + return PKCS12_create_ex2(pass, name, pkey, cert, ca, nid_key, nid_cert, + iter, mac_iter, keytype, ctx, propq, + NULL, NULL); +} + PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype) @@ -246,7 +282,7 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, NULL, NULL); } -PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags, +PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags, int nid_type, const unsigned char *value, int len) { PKCS12_SAFEBAG *bag = NULL; @@ -312,6 +348,22 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL); } + +static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + PKCS12_SAFEBAG *bag) +{ + PKCS12_SAFEBAG *tmp; + + if (pbags == NULL || bag == NULL) + return 1; + + if ((tmp = sk_PKCS12_SAFEBAG_delete_ptr(*pbags, bag)) == NULL) + return 0; + + PKCS12_SAFEBAG_free(tmp); + return 1; +} + static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag) { diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c index a5adafa954a3..3fa9c9c8ccec 100644 --- a/crypto/pkcs12/p12_decr.c +++ b/crypto/pkcs12/p12_decr.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -26,9 +26,10 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, int outlen, i; EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); int max_out_len, mac_len = 0; + int block_size; if (ctx == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_EVP_LIB); goto err; } @@ -43,7 +44,14 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, * It's appended to encrypted text on encrypting * MAC should be processed on decrypting separately from plain text */ - max_out_len = inlen + EVP_CIPHER_CTX_get_block_size(ctx); + block_size = EVP_CIPHER_CTX_get_block_size(ctx); + + if (block_size == 0) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + max_out_len = inlen + block_size; if ((EVP_CIPHER_get_flags(EVP_CIPHER_CTX_get0_cipher(ctx)) & EVP_CIPH_FLAG_CIPHER_WITH_MAC) != 0) { if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD, 0, &mac_len) < 0) { @@ -67,10 +75,8 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, } } - if ((out = OPENSSL_malloc(max_out_len)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((out = OPENSSL_malloc(max_out_len)) == NULL) goto err; - } if (!EVP_CipherUpdate(ctx, out, &i, in, inlen)) { OPENSSL_free(out); @@ -180,7 +186,7 @@ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor, int inlen; if ((oct = ASN1_OCTET_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } inlen = ASN1_item_i2d(obj, &in, it); diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c index 45aa2f9154b9..537a1e3168ce 100644 --- a/crypto/pkcs12/p12_init.c +++ b/crypto/pkcs12/p12_init.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -20,7 +20,7 @@ PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq) PKCS12 *pkcs12; if ((pkcs12 = PKCS12_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } if (!ASN1_INTEGER_set(pkcs12->version, 3)) @@ -29,14 +29,14 @@ PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq) ossl_pkcs7_set0_libctx(pkcs12->authsafes, ctx); if (!ossl_pkcs7_set1_propq(pkcs12->authsafes, propq)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_PKCS7_LIB); goto err; } switch (mode) { case NID_pkcs7_data: if ((pkcs12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } break; @@ -56,3 +56,9 @@ PKCS12 *PKCS12_init(int mode) return PKCS12_init_ex(mode, NULL, NULL); } +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12) +{ + if (p12 == NULL || p12->authsafes == NULL) + return NULL; + return &p12->authsafes->ctx; +} diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c index 41a2d7293e91..b5102110cd74 100644 --- a/crypto/pkcs12/p12_key.c +++ b/crypto/pkcs12/p12_key.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -29,7 +29,7 @@ int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt, unipass = NULL; uniplen = 0; } else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_PKCS12_LIB); return 0; } ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter, @@ -43,7 +43,7 @@ int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, unsigned char *out, const EVP_MD *md_type) { return PKCS12_key_gen_asc_ex(pass, passlen, salt, saltlen, id, iter, n, - out, md_type, NULL, NULL); + out, md_type, NULL, NULL); } int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt, @@ -59,7 +59,7 @@ int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt, unipass = NULL; uniplen = 0; } else if (!OPENSSL_utf82uni(pass, passlen, &unipass, &uniplen)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_PKCS12_LIB); return 0; } ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter, diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c index 229b34cf6429..0901dc94085f 100644 --- a/crypto/pkcs12/p12_kiss.c +++ b/crypto/pkcs12/p12_kiss.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -18,10 +18,12 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); /* * Parse and decrypt a PKCS#12 structure returning user key, user cert and @@ -49,33 +51,34 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, } /* Check the mac */ - - /* - * If password is zero length or NULL then try verifying both cases to - * determine which password is correct. The reason for this is that under - * PKCS#12 password based encryption no password and a zero length - * password are two different things... - */ - - if (pass == NULL || *pass == '\0') { - if (!PKCS12_mac_present(p12) - || PKCS12_verify_mac(p12, NULL, 0)) - pass = NULL; - else if (PKCS12_verify_mac(p12, "", 0)) - pass = ""; - else { + if (PKCS12_mac_present(p12)) { + /* + * If password is zero length or NULL then try verifying both cases to + * determine which password is correct. The reason for this is that under + * PKCS#12 password based encryption no password and a zero length + * password are two different things... + */ + if (pass == NULL || *pass == '\0') { + if (PKCS12_verify_mac(p12, NULL, 0)) + pass = NULL; + else if (PKCS12_verify_mac(p12, "", 0)) + pass = ""; + else { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); + goto err; + } + } else if (!PKCS12_verify_mac(p12, pass, -1)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); goto err; } - } else if (!PKCS12_verify_mac(p12, pass, -1)) { - ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); - goto err; + } else if (pass == NULL || *pass == '\0') { + pass = NULL; } /* If needed, allocate stack for other certificates */ if ((cert != NULL || ca != NULL) && (ocerts = sk_X509_new_null()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_CRYPTO_LIB); goto err; } @@ -125,7 +128,7 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, *cert = NULL; } X509_free(x); - sk_X509_pop_free(ocerts, X509_free); + OSSL_STACK_OF_X509_free(ocerts); return 0; } @@ -156,7 +159,8 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { + if (!parse_bags(bags, pass, passlen, pkey, ocerts, + p7->ctx.libctx, p7->ctx.propq)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; @@ -169,12 +173,14 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, /* pkey and/or ocerts may be NULL */ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), - pass, passlen, pkey, ocerts)) + pass, passlen, pkey, ocerts, + libctx, propq)) return 0; } return 1; @@ -182,7 +188,8 @@ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, /* pkey and/or ocerts may be NULL */ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { PKCS8_PRIV_KEY_INFO *p8; X509 *x509; @@ -200,7 +207,8 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_keyBag: if (pkey == NULL || *pkey != NULL) return 1; - *pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag)); + *pkey = EVP_PKCS82PKEY_ex(PKCS12_SAFEBAG_get0_p8inf(bag), + libctx, propq); if (*pkey == NULL) return 0; break; @@ -208,9 +216,10 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_pkcs8ShroudedKeyBag: if (pkey == NULL || *pkey != NULL) return 1; - if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + if ((p8 = PKCS12_decrypt_skey_ex(bag, pass, passlen, + libctx, propq)) == NULL) return 0; - *pkey = EVP_PKCS82PKEY(p8); + *pkey = EVP_PKCS82PKEY_ex(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); if (!(*pkey)) return 0; @@ -220,7 +229,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, if (ocerts == NULL || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1; - if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) + if ((x509 = PKCS12_SAFEBAG_get1_cert_ex(bag, libctx, propq)) == NULL) return 0; if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) { X509_free(x509); @@ -250,7 +259,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_safeContentsBag: return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, pkey, - ocerts); + ocerts, libctx, propq); default: return 1; diff --git a/crypto/pkcs12/p12_local.h b/crypto/pkcs12/p12_local.h index acaa27b193fa..7f02874a9762 100644 --- a/crypto/pkcs12/p12_local.h +++ b/crypto/pkcs12/p12_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 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 @@ -41,3 +41,5 @@ struct pkcs12_bag_st { ASN1_TYPE *other; /* Secret or other bag */ } value; }; + +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12); diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c index f8a6d33ddfae..b43c82f0ed29 100644 --- a/crypto/pkcs12/p12_mutl.c +++ b/crypto/pkcs12/p12_mutl.c @@ -15,12 +15,19 @@ #include #include "internal/cryptlib.h" +#include "crypto/evp.h" #include #include #include #include #include "p12_local.h" +static int pkcs12_pbmac1_pbkdf2_key_gen(const char *pass, int passlen, + unsigned char *salt, int saltlen, + int id, int iter, int keylen, + unsigned char *out, + const EVP_MD *md_type); + int PKCS12_mac_present(const PKCS12 *p12) { return p12->mac ? 1 : 0; @@ -72,9 +79,83 @@ static int pkcs12_gen_gost_mac_key(const char *pass, int passlen, return 1; } -/* Generate a MAC */ +PBKDF2PARAM *PBMAC1_get1_pbkdf2_param(const X509_ALGOR *macalg) +{ + PBMAC1PARAM *param = NULL; + PBKDF2PARAM *pbkdf2_param = NULL; + const ASN1_OBJECT *kdf_oid; + + param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), macalg->parameter); + if (param == NULL) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + + X509_ALGOR_get0(&kdf_oid, NULL, NULL, param->keyDerivationFunc); + if (OBJ_obj2nid(kdf_oid) != NID_id_pbkdf2) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_PASSED_INVALID_ARGUMENT); + PBMAC1PARAM_free(param); + return NULL; + } + + pbkdf2_param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), + param->keyDerivationFunc->parameter); + PBMAC1PARAM_free(param); + + return pbkdf2_param; +} + +static int PBMAC1_PBKDF2_HMAC(OSSL_LIB_CTX *ctx, const char *propq, + const char *pass, int passlen, + const X509_ALGOR *macalg, unsigned char *key) +{ + PBKDF2PARAM *pbkdf2_param = NULL; + const ASN1_OBJECT *kdf_hmac_oid; + int kdf_hmac_nid; + int ret = -1; + int keylen = 0; + EVP_MD *kdf_md = NULL; + const ASN1_OCTET_STRING *pbkdf2_salt = NULL; + + pbkdf2_param = PBMAC1_get1_pbkdf2_param(macalg); + if (pbkdf2_param == NULL) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED); + goto err; + } + keylen = ASN1_INTEGER_get(pbkdf2_param->keylength); + pbkdf2_salt = pbkdf2_param->salt->value.octet_string; + + if (pbkdf2_param->prf == NULL) { + kdf_hmac_nid = NID_hmacWithSHA1; + } else { + X509_ALGOR_get0(&kdf_hmac_oid, NULL, NULL, pbkdf2_param->prf); + kdf_hmac_nid = OBJ_obj2nid(kdf_hmac_oid); + } + + kdf_md = EVP_MD_fetch(ctx, OBJ_nid2sn(ossl_hmac2mdnid(kdf_hmac_nid)), propq); + if (kdf_md == NULL) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_FETCH_FAILED); + goto err; + } + + if (PKCS5_PBKDF2_HMAC(pass, passlen, pbkdf2_salt->data, pbkdf2_salt->length, + ASN1_INTEGER_get(pbkdf2_param->iter), kdf_md, keylen, key) <= 0) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_INTERNAL_ERROR); + goto err; + } + ret = keylen; + + err: + EVP_MD_free(kdf_md); + PBKDF2PARAM_free(pbkdf2_param); + + return ret; +} + +/* Generate a MAC, also used for verification */ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *mac, unsigned int *maclen, + int pbmac1_md_nid, int pbmac1_kdf_nid, int (*pkcs12_key_gen)(const char *pass, int passlen, unsigned char *salt, int slen, int id, int iter, int n, @@ -88,8 +169,8 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char key[EVP_MAX_MD_SIZE], *salt; int saltlen, iter; char md_name[80]; - int md_size = 0; - int md_nid; + int keylen = 0; + int md_nid = NID_undef; const X509_ALGOR *macalg; const ASN1_OBJECT *macoid; @@ -111,9 +192,13 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, iter = ASN1_INTEGER_get(p12->mac->iter); X509_SIG_get0(p12->mac->dinfo, &macalg, NULL); X509_ALGOR_get0(&macoid, NULL, NULL, macalg); - if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0) - return 0; - + if (OBJ_obj2nid(macoid) == NID_pbmac1) { + if (OBJ_obj2txt(md_name, sizeof(md_name), OBJ_nid2obj(pbmac1_md_nid), 0) < 0) + return 0; + } else { + if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0) + return 0; + } (void)ERR_set_mark(); md = md_fetch = EVP_MD_fetch(p12->authsafes->ctx.libctx, md_name, p12->authsafes->ctx.propq); @@ -127,40 +212,65 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen, } (void)ERR_pop_to_mark(); - md_size = EVP_MD_get_size(md); + keylen = EVP_MD_get_size(md); md_nid = EVP_MD_get_type(md); - if (md_size < 0) + if (keylen <= 0) goto err; - if ((md_nid == NID_id_GostR3411_94 - || md_nid == NID_id_GostR3411_2012_256 - || md_nid == NID_id_GostR3411_2012_512) - && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) { - md_size = TK26_MAC_KEY_LEN; + + /* For PBMAC1 we use a special keygen callback if not provided (e.g. on verification) */ + if (pbmac1_md_nid != NID_undef && pkcs12_key_gen == NULL) { + keylen = PBMAC1_PBKDF2_HMAC(p12->authsafes->ctx.libctx, p12->authsafes->ctx.propq, + pass, passlen, macalg, key); + if (keylen < 0) + goto err; + } else if ((md_nid == NID_id_GostR3411_94 + || md_nid == NID_id_GostR3411_2012_256 + || md_nid == NID_id_GostR3411_2012_512) + && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) { + keylen = TK26_MAC_KEY_LEN; if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter, - md_size, key, md)) { + keylen, key, md)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR); goto err; } } else { + EVP_MD *hmac_md = (EVP_MD *)md; + int fetched = 0; + + if (pbmac1_kdf_nid != NID_undef) { + char hmac_md_name[128]; + + if (OBJ_obj2txt(hmac_md_name, sizeof(hmac_md_name), OBJ_nid2obj(pbmac1_kdf_nid), 0) < 0) + goto err; + hmac_md = EVP_MD_fetch(NULL, hmac_md_name, NULL); + if (hmac_md == NULL) + goto err; + fetched = 1; + } if (pkcs12_key_gen != NULL) { - if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID, - iter, md_size, key, md)) { + int res = (*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID, + iter, keylen, key, hmac_md); + + if (fetched) + EVP_MD_free(hmac_md); + if (res != 1) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR); goto err; } } else { + if (fetched) + EVP_MD_free(hmac_md); /* Default to UTF-8 password */ if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_MAC_ID, - iter, md_size, key, md, - p12->authsafes->ctx.libctx, - p12->authsafes->ctx.propq)) { + iter, keylen, key, md, + p12->authsafes->ctx.libctx, p12->authsafes->ctx.propq)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR); goto err; } } } if ((hmac = HMAC_CTX_new()) == NULL - || !HMAC_Init_ex(hmac, key, md_size, md, NULL) + || !HMAC_Init_ex(hmac, key, keylen, md, NULL) || !HMAC_Update(hmac, p12->authsafes->d.data->data, p12->authsafes->d.data->length) || !HMAC_Final(hmac, mac, maclen)) { @@ -178,7 +288,7 @@ err: int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *mac, unsigned int *maclen) { - return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NULL); + return pkcs12_gen_mac(p12, pass, passlen, mac, maclen, NID_undef, NID_undef, NULL); } /* Verify the mac */ @@ -187,14 +297,40 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; const ASN1_OCTET_STRING *macoct; + const X509_ALGOR *macalg; + const ASN1_OBJECT *macoid; if (p12->mac == NULL) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT); return 0; } - if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) { - ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR); - return 0; + + X509_SIG_get0(p12->mac->dinfo, &macalg, NULL); + X509_ALGOR_get0(&macoid, NULL, NULL, macalg); + if (OBJ_obj2nid(macoid) == NID_pbmac1) { + PBMAC1PARAM *param = NULL; + const ASN1_OBJECT *hmac_oid; + int md_nid = NID_undef; + + param = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), macalg->parameter); + if (param == NULL) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_UNSUPPORTED); + return 0; + } + X509_ALGOR_get0(&hmac_oid, NULL, NULL, param->messageAuthScheme); + md_nid = ossl_hmac2mdnid(OBJ_obj2nid(hmac_oid)); + + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, md_nid, NID_undef, NULL)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR); + PBMAC1PARAM_free(param); + return 0; + } + PBMAC1PARAM_free(param); + } else { + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NID_undef, NID_undef, NULL)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR); + return 0; + } } X509_SIG_get0(p12->mac->dinfo, NULL, &macoct); if ((maclen != (unsigned int)ASN1_STRING_length(macoct)) @@ -205,7 +341,6 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) } /* Set a mac */ - int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, const EVP_MD *md_type) @@ -226,7 +361,7 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, /* * Note that output mac is forced to UTF-8... */ - if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) { + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NID_undef, NID_undef, NULL)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR); return 0; } @@ -238,9 +373,18 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, return 1; } -/* Set up a mac structure */ -int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, - const EVP_MD *md_type) +static int pkcs12_pbmac1_pbkdf2_key_gen(const char *pass, int passlen, + unsigned char *salt, int saltlen, + int id, int iter, int keylen, + unsigned char *out, + const EVP_MD *md_type) +{ + return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, + md_type, keylen, out); +} + +static int pkcs12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, + int nid) { X509_ALGOR *macalg; @@ -251,11 +395,11 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, return PKCS12_ERROR; if (iter > 1) { if ((p12->mac->iter = ASN1_INTEGER_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return 0; } if (!ASN1_INTEGER_set(p12->mac->iter, iter)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return 0; } } @@ -263,10 +407,8 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, saltlen = PKCS12_SALT_LEN; else if (saltlen < 0) return 0; - if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((p12->mac->salt->data = OPENSSL_malloc(saltlen)) == NULL) return 0; - } p12->mac->salt->length = saltlen; if (salt == NULL) { if (RAND_bytes_ex(p12->authsafes->ctx.libctx, p12->mac->salt->data, @@ -276,11 +418,112 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, memcpy(p12->mac->salt->data, salt, saltlen); } X509_SIG_getm(p12->mac->dinfo, &macalg, NULL); - if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(EVP_MD_get_type(md_type)), - V_ASN1_NULL, NULL)) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if (!X509_ALGOR_set0(macalg, OBJ_nid2obj(nid), V_ASN1_NULL, NULL)) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return 0; } return 1; } + +/* Set up a mac structure */ +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, + const EVP_MD *md_type) +{ + return pkcs12_setup_mac(p12, iter, salt, saltlen, EVP_MD_get_type(md_type)); +} + +int PKCS12_set_pbmac1_pbkdf2(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type, const char *prf_md_name) +{ + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned int maclen; + ASN1_OCTET_STRING *macoct; + X509_ALGOR *alg = NULL; + int ret = 0; + int prf_md_nid = NID_undef, prf_nid = NID_undef, hmac_nid; + unsigned char *known_salt = NULL; + int keylen = 0; + PBMAC1PARAM *param = NULL; + X509_ALGOR *hmac_alg = NULL, *macalg = NULL; + + if (md_type == NULL) + /* No need to do a fetch as the md_type is used only to get a NID */ + md_type = EVP_sha256(); + + if (prf_md_name == NULL) + prf_md_nid = EVP_MD_get_type(md_type); + else + prf_md_nid = OBJ_txt2nid(prf_md_name); + + if (iter == 0) + iter = PKCS12_DEFAULT_ITER; + + keylen = EVP_MD_get_size(md_type); + + prf_nid = ossl_md2hmacnid(prf_md_nid); + hmac_nid = ossl_md2hmacnid(EVP_MD_get_type(md_type)); + + if (prf_nid == NID_undef || hmac_nid == NID_undef) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM); + goto err; + } + + if (salt == NULL) { + known_salt = OPENSSL_malloc(saltlen); + if (known_salt == NULL) + goto err; + + if (RAND_bytes_ex(NULL, known_salt, saltlen, 0) <= 0) { + ERR_raise(ERR_LIB_PKCS12, ERR_R_RAND_LIB); + goto err; + } + } + + param = PBMAC1PARAM_new(); + hmac_alg = X509_ALGOR_new(); + alg = PKCS5_pbkdf2_set(iter, salt ? salt : known_salt, saltlen, prf_nid, keylen); + if (param == NULL || hmac_alg == NULL || alg == NULL) + goto err; + + if (pkcs12_setup_mac(p12, iter, salt ? salt : known_salt, saltlen, + NID_pbmac1) == PKCS12_ERROR) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR); + goto err; + } + + if (!X509_ALGOR_set0(hmac_alg, OBJ_nid2obj(hmac_nid), V_ASN1_NULL, NULL)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_SETUP_ERROR); + goto err; + } + + X509_ALGOR_free(param->keyDerivationFunc); + X509_ALGOR_free(param->messageAuthScheme); + param->keyDerivationFunc = alg; + param->messageAuthScheme = hmac_alg; + + X509_SIG_getm(p12->mac->dinfo, &macalg, &macoct); + if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBMAC1PARAM), param, &macalg->parameter)) + goto err; + + /* + * Note that output mac is forced to UTF-8... + */ + if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, + EVP_MD_get_type(md_type), prf_md_nid, + pkcs12_pbmac1_pbkdf2_key_gen)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR); + goto err; + } + if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_STRING_SET_ERROR); + goto err; + } + ret = 1; + + err: + PBMAC1PARAM_free(param); + OPENSSL_free(known_salt); + return ret; +} diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c index dfcfcf6ae677..37abb3821d4b 100644 --- a/crypto/pkcs12/p12_npas.c +++ b/crypto/pkcs12/p12_npas.c @@ -19,11 +19,13 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, - const char *newpass); + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq); static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, - const char *newpass); + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq); static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, - int *psaltlen); + int *psaltlen, int *cipherid); /* * Change the password on a PKCS#12 structure. @@ -39,12 +41,12 @@ int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass) } /* Check the mac */ - - if (!PKCS12_verify_mac(p12, oldpass, -1)) { - ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); - return 0; + if (p12->mac != NULL) { + if (!PKCS12_verify_mac(p12, oldpass, -1)) { + ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); + return 0; + } } - if (!newpass_p12(p12, oldpass, newpass)) { ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR); return 0; @@ -59,7 +61,7 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) { STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; - int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; + int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0, cipherid = NID_undef; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; @@ -72,6 +74,7 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) goto err; for (i = 0; i < sk_PKCS7_num(asafes); i++) { p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); @@ -79,21 +82,23 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); if (p7->d.encrypted == NULL || !alg_get(p7->d.encrypted->enc_data->algorithm, - &pbe_nid, &pbe_iter, &pbe_saltlen)) + &pbe_nid, &pbe_iter, &pbe_saltlen, &cipherid)) goto err; } else { continue; } if (bags == NULL) goto err; - if (!newpass_bags(bags, oldpass, newpass)) + if (!newpass_bags(bags, oldpass, newpass, + p7->ctx.libctx, p7->ctx.propq)) goto err; /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else - p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, - pbe_saltlen, pbe_iter, bags); + p7new = PKCS12_pack_p7encdata_ex(pbe_nid, newpass, -1, NULL, + pbe_saltlen, pbe_iter, bags, + p7->ctx.libctx, p7->ctx.propq); if (p7new == NULL || !sk_PKCS7_push(newsafes, p7new)) goto err; sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); @@ -108,11 +113,13 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) if (!PKCS12_pack_authsafes(p12, newsafes)) goto err; - if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) - goto err; - X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); - if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) - goto err; + if (p12->mac != NULL) { + if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) + goto err; + X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); + if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) + goto err; + } rv = 1; @@ -131,11 +138,13 @@ err: } static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, - const char *newpass) + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { - if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass)) + if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass, + libctx, propq)) return 0; } return 1; @@ -144,26 +153,37 @@ static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, /* Change password of safebag: only needs handle shrouded keybags */ static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, - const char *newpass) + const char *newpass, + OSSL_LIB_CTX *libctx, const char *propq) { + EVP_CIPHER *cipher = NULL; PKCS8_PRIV_KEY_INFO *p8; X509_SIG *p8new; - int p8_nid, p8_saltlen, p8_iter; + int p8_nid, p8_saltlen, p8_iter, cipherid = 0; const X509_ALGOR *shalg; if (PKCS12_SAFEBAG_get_nid(bag) != NID_pkcs8ShroudedKeyBag) return 1; - if ((p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)) == NULL) + if ((p8 = PKCS8_decrypt_ex(bag->value.shkeybag, oldpass, -1, + libctx, propq)) == NULL) return 0; X509_SIG_get0(bag->value.shkeybag, &shalg, NULL); - if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen)) { + if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen, &cipherid)) { PKCS8_PRIV_KEY_INFO_free(p8); return 0; } - p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, - p8_iter, p8); + if (cipherid != NID_undef) { + cipher = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(cipherid), propq); + if (cipher == NULL) { + PKCS8_PRIV_KEY_INFO_free(p8); + return 0; + } + } + p8new = PKCS8_encrypt_ex(p8_nid, cipher, newpass, -1, NULL, p8_saltlen, + p8_iter, p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); + EVP_CIPHER_free(cipher); if (p8new == NULL) return 0; X509_SIG_free(bag->value.shkeybag); @@ -172,16 +192,68 @@ static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, } static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, - int *psaltlen) + int *psaltlen, int *cipherid) { - PBEPARAM *pbe; + int ret = 0, pbenid, aparamtype; + int encnid, prfnid; + const ASN1_OBJECT *aoid; + const void *aparam; + PBEPARAM *pbe = NULL; + PBE2PARAM *pbe2 = NULL; + PBKDF2PARAM *kdf = NULL; - pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); - if (pbe == NULL) - return 0; - *pnid = OBJ_obj2nid(alg->algorithm); - *piter = ASN1_INTEGER_get(pbe->iter); - *psaltlen = pbe->salt->length; - PBEPARAM_free(pbe); - return 1; + X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg); + pbenid = OBJ_obj2nid(aoid); + + switch (pbenid) { + case NID_pbes2: + if (aparamtype == V_ASN1_SEQUENCE) + pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM)); + if (pbe2 == NULL) + goto done; + + X509_ALGOR_get0(NULL, &aparamtype, &aparam, pbe2->keyfunc); + X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption); + encnid = OBJ_obj2nid(aoid); + + if (aparamtype == V_ASN1_SEQUENCE) + kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM)); + if (kdf == NULL) + goto done; + + /* Only OCTET_STRING is supported */ + if (kdf->salt->type != V_ASN1_OCTET_STRING) + goto done; + + if (kdf->prf == NULL) { + prfnid = NID_hmacWithSHA1; + } else { + X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf); + prfnid = OBJ_obj2nid(aoid); + } + *psaltlen = kdf->salt->value.octet_string->length; + *piter = ASN1_INTEGER_get(kdf->iter); + *pnid = prfnid; + *cipherid = encnid; + break; + default: + pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); + if (pbe == NULL) + goto done; + *pnid = OBJ_obj2nid(alg->algorithm); + *piter = ASN1_INTEGER_get(pbe->iter); + *psaltlen = pbe->salt->length; + *cipherid = NID_undef; + ret = 1; + break; + } + ret = 1; +done: + if (kdf != NULL) + PBKDF2PARAM_free(kdf); + if (pbe2 != NULL) + PBE2PARAM_free(pbe2); + if (pbe != NULL) + PBEPARAM_free(pbe); + return ret; } diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c index 9c2753401786..1230c8c88cda 100644 --- a/crypto/pkcs12/p12_p8e.c +++ b/crypto/pkcs12/p12_p8e.c @@ -84,7 +84,6 @@ X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen, p8 = OPENSSL_zalloc(sizeof(*p8)); if (p8 == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); ASN1_OCTET_STRING_free(enckey); return NULL; } diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c index 7574c54120c7..04ef0b74edef 100644 --- a/crypto/pkcs12/p12_sbag.c +++ b/crypto/pkcs12/p12_sbag.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include #include "p12_local.h" +#include "crypto/x509.h" #ifndef OPENSSL_NO_DEPRECATED_1_1_0 ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid) @@ -101,6 +102,42 @@ X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag) ASN1_ITEM_rptr(X509_CRL)); } +X509 *PKCS12_SAFEBAG_get1_cert_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509 *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509), libctx, propq); + if (!ossl_x509_set0_libctx(ret, libctx, propq)) { + X509_free(ret); + return NULL; + } + return ret; +} + +X509_CRL *PKCS12_SAFEBAG_get1_crl_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509_CRL *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_crlBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509_CRL), libctx, propq); + if (!ossl_x509_crl_set0_libctx(ret, libctx, propq)) { + X509_CRL_free(ret); + return NULL; + } + return ret; +} + PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509) { return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509), @@ -119,18 +156,18 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned PKCS12_SAFEBAG *safebag; if ((bag = PKCS12_BAGS_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } bag->type = OBJ_nid2obj(type); - switch(vtype) { + switch (vtype) { case V_ASN1_OCTET_STRING: { ASN1_OCTET_STRING *strtmp = ASN1_OCTET_STRING_new(); if (strtmp == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } /* Pack data into an octet string */ @@ -142,7 +179,7 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned bag->value.other = ASN1_TYPE_new(); if (bag->value.other == NULL) { ASN1_OCTET_STRING_free(strtmp); - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } ASN1_TYPE_set(bag->value.other, vtype, strtmp); @@ -155,13 +192,13 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_secret(int type, int vtype, const unsigned } if ((safebag = PKCS12_SAFEBAG_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); goto err; } safebag->value.bag = bag; safebag->type = OBJ_nid2obj(NID_secretBag); return safebag; - + err: PKCS12_BAGS_free(bag); return NULL; @@ -174,7 +211,7 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8) PKCS12_SAFEBAG *bag = PKCS12_SAFEBAG_new(); if (bag == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } bag->type = OBJ_nid2obj(NID_keyBag); @@ -190,7 +227,7 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8) /* Set up the safe bag */ if (bag == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB); return NULL; } bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag); diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c index 3afc8b2f13c9..a96623f19fba 100644 --- a/crypto/pkcs12/p12_utl.c +++ b/crypto/pkcs12/p12_utl.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 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 @@ -10,6 +10,8 @@ #include #include "internal/cryptlib.h" #include +#include "p12_local.h" +#include "crypto/pkcs7/pk7_local.h" /* Cheap and nasty Unicode stuff */ @@ -24,10 +26,8 @@ unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, if (asclen < 0) return NULL; ulen = asclen * 2 + 2; - if ((unitmp = OPENSSL_malloc(ulen)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((unitmp = OPENSSL_malloc(ulen)) == NULL) return NULL; - } for (i = 0; i < ulen - 2; i += 2) { unitmp[i] = 0; unitmp[i + 1] = asc[i >> 1]; @@ -57,10 +57,8 @@ char *OPENSSL_uni2asc(const unsigned char *uni, int unilen) if (!unilen || uni[unilen - 1]) asclen++; uni++; - if ((asctmp = OPENSSL_malloc(asclen)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((asctmp = OPENSSL_malloc(asclen)) == NULL) return NULL; - } for (i = 0; i < unilen; i += 2) asctmp[i >> 1] = uni[i]; asctmp[asclen - 1] = 0; @@ -119,10 +117,8 @@ unsigned char *OPENSSL_utf82uni(const char *asc, int asclen, ulen += 2; /* for trailing UTF16 zero */ - if ((ret = OPENSSL_malloc(ulen)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((ret = OPENSSL_malloc(ulen)) == NULL) return NULL; - } /* re-run the loop writing down UTF-16 characters in big-endian order */ for (unitmp = ret, i = 0; i < asclen; i += j) { j = UTF8_getc((const unsigned char *)asc+i, asclen-i, &utf32chr); @@ -204,10 +200,8 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen) if (!unilen || (uni[unilen-2]||uni[unilen - 1])) asclen++; - if ((asctmp = OPENSSL_malloc(asclen)) == NULL) { - ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE); + if ((asctmp = OPENSSL_malloc(asclen)) == NULL) return NULL; - } /* re-run the loop emitting UTF-8 string */ for (asclen = 0, i = 0; i < unilen; ) { @@ -238,12 +232,34 @@ int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS12), bp, p12, libctx, propq); } #ifndef OPENSSL_NO_STDIO PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS12), fp, p12, libctx, propq); } #endif diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c index 6e3ec78cd6ea..e9bcaf4b6e5a 100644 --- a/crypto/pkcs12/pk12err.c +++ b/crypto/pkcs12/pk12err.c @@ -1,6 +1,6 @@ /* * 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 @@ -15,8 +15,9 @@ #ifndef OPENSSL_NO_ERR static const ERR_STRING_DATA PKCS12_str_reasons[] = { + {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CALLBACK_FAILED), "callback failed"}, {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CANT_PACK_STRUCTURE), - "cant pack structure"}, + "can't pack structure"}, {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_CONTENT_TYPE_NOT_DATA), "content type not data"}, {ERR_PACK(ERR_LIB_PKCS12, 0, PKCS12_R_DECODE_ERROR), "decode error"}, diff --git a/crypto/pkcs7/bio_pk7.c b/crypto/pkcs7/bio_pk7.c index 414f0da1c615..36f4d6196a80 100644 --- a/crypto/pkcs7/bio_pk7.c +++ b/crypto/pkcs7/bio_pk7.c @@ -11,11 +11,6 @@ #include #include -#if !defined(OPENSSL_SYS_VXWORKS) -# include -#endif -#include - /* Streaming encode support for PKCS#7 */ BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7) diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c index 1cd867721ee1..3abcc3dc8831 100644 --- a/crypto/pkcs7/pk7_asn1.c +++ b/crypto/pkcs7/pk7_asn1.c @@ -41,7 +41,7 @@ static int pk7_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, case ASN1_OP_STREAM_PRE: if (PKCS7_stream(&sarg->boundary, *pp7) <= 0) return 0; - /* fall thru */ + /* fall through */ case ASN1_OP_DETACHED_PRE: sarg->ndef_bio = PKCS7_dataInit(*pp7, sarg->out); if (!sarg->ndef_bio) @@ -104,7 +104,6 @@ PKCS7 *PKCS7_new_ex(OSSL_LIB_CTX *libctx, const char *propq) if (pkcs7->ctx.propq == NULL) { PKCS7_free(pkcs7); pkcs7 = NULL; - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); } } } diff --git a/crypto/pkcs7/pk7_attr.c b/crypto/pkcs7/pk7_attr.c index 80b128c30455..df83574eaa76 100644 --- a/crypto/pkcs7/pk7_attr.c +++ b/crypto/pkcs7/pk7_attr.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,11 +23,15 @@ int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, ASN1_STRING *seq; if ((seq = ASN1_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); return 0; } seq->length = ASN1_item_i2d((ASN1_VALUE *)cap, &seq->data, ASN1_ITEM_rptr(X509_ALGORS)); + if (seq->length <= 0 || seq->data == NULL) { + ASN1_STRING_free(seq); + return 1; + } if (!PKCS7_add_signed_attribute(si, NID_SMIMECapabilities, V_ASN1_SEQUENCE, seq)) { ASN1_STRING_free(seq); @@ -57,19 +61,22 @@ int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) X509_ALGOR *alg; if ((alg = X509_ALGOR_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); return 0; } ASN1_OBJECT_free(alg->algorithm); alg->algorithm = OBJ_nid2obj(nid); if (arg > 0) { if ((alg->parameter = ASN1_TYPE_new()) == NULL) { + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); goto err; } if ((nbit = ASN1_INTEGER_new()) == NULL) { + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); goto err; } if (!ASN1_INTEGER_set(nbit, arg)) { + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); goto err; } alg->parameter->value.integer = nbit; @@ -77,11 +84,11 @@ int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg) nbit = NULL; } if (!sk_X509_ALGOR_push(sk, alg)) { + ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB); goto err; } return 1; err: - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); ASN1_INTEGER_free(nbit); X509_ALGOR_free(alg); return 0; @@ -102,7 +109,7 @@ int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t) ASN1_TIME *tmp = NULL; if (t == NULL && (tmp = t = X509_gmtime_adj(NULL, 0)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); return 0; } if (!PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index e9de097da186..9fa215a62846 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -15,6 +15,7 @@ #include #include "internal/cryptlib.h" #include "internal/sizes.h" +#include "crypto/evp.h" #include "pk7_local.h" static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, @@ -54,6 +55,43 @@ ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) return NULL; } +static ASN1_OCTET_STRING *pkcs7_get1_data(PKCS7 *p7) +{ + ASN1_OCTET_STRING *os = PKCS7_get_octet_string(p7); + + if (os != NULL) { + /* Edge case for MIME content, see RFC 5652 section-5.2.1 */ + ASN1_OCTET_STRING *osdup = ASN1_OCTET_STRING_dup(os); + + if (osdup != NULL && (os->flags & ASN1_STRING_FLAG_NDEF)) + /* ASN1_STRING_FLAG_NDEF flag is currently used by openssl-smime */ + ASN1_STRING_set0(osdup, NULL, 0); + return osdup; + } + + /* General case for PKCS#7 content, see RFC 2315 section-7 */ + if (PKCS7_type_is_other(p7) && (p7->d.other != NULL) + && (p7->d.other->type == V_ASN1_SEQUENCE) + && (p7->d.other->value.sequence != NULL) + && (p7->d.other->value.sequence->length > 0)) { + const unsigned char *data = p7->d.other->value.sequence->data; + long len; + int inf, tag, class; + + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + return NULL; + inf = ASN1_get_object(&data, &len, &tag, &class, + p7->d.other->value.sequence->length); + if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE + || !ASN1_OCTET_STRING_set(os, data, len)) { + ASN1_OCTET_STRING_free(os); + os = NULL; + } + } + return os; +} + static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg, const PKCS7_CTX *ctx) { @@ -131,11 +169,8 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, goto err; ek = OPENSSL_malloc(eklen); - - if (ek == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + if (ek == NULL) goto err; - } if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) goto err; @@ -170,25 +205,17 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, if (EVP_PKEY_decrypt_init(pctx) <= 0) goto err; - if (EVP_PKEY_decrypt(pctx, NULL, &eklen, - ri->enc_key->data, ri->enc_key->length) <= 0) - goto err; + if (EVP_PKEY_is_a(pkey, "RSA")) + /* upper layer pkcs7 code incorrectly assumes that a successful RSA + * decryption means that the key matches ciphertext (which never + * was the case, implicit rejection or not), so to make it work + * disable implicit rejection for RSA keys */ + EVP_PKEY_CTX_ctrl_str(pctx, "rsa_pkcs1_implicit_rejection", "0"); - ek = OPENSSL_malloc(eklen); - - if (ek == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ret = evp_pkey_decrypt_alloc(pctx, &ek, &eklen, fixlen, + ri->enc_key->data, ri->enc_key->length); + if (ret <= 0) goto err; - } - - if (EVP_PKEY_decrypt(pctx, ek, &eklen, - ri->enc_key->data, ri->enc_key->length) <= 0 - || eklen == 0 - || (fixlen != 0 && eklen != fixlen)) { - ret = 0; - ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); - goto err; - } ret = 1; @@ -250,7 +277,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) switch (i) { case NID_pkcs7_signed: md_sk = p7->d.sign->md_algs; - os = PKCS7_get_octet_string(p7->d.sign->contents); + os = pkcs7_get1_data(p7->d.sign->contents); break; case NID_pkcs7_signedAndEnveloped: rsk = p7->d.signed_and_enveloped->recipientinfo; @@ -273,7 +300,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) break; case NID_pkcs7_digest: xa = p7->d.digest->md; - os = PKCS7_get_octet_string(p7->d.digest->contents); + os = pkcs7_get1_data(p7->d.digest->contents); break; case NID_pkcs7_data: break; @@ -356,8 +383,19 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) if (bio == NULL) { if (PKCS7_is_detached(p7)) { bio = BIO_new(BIO_s_null()); - } else if (os && os->length > 0) { - bio = BIO_new_mem_buf(os->data, os->length); + } else if (os != NULL && os->length > 0) { + /* + * bio needs a copy of os->data instead of a pointer because + * the data will be used after os has been freed + */ + bio = BIO_new(BIO_s_mem()); + if (bio != NULL) { + BIO_set_mem_eof_return(bio, 0); + if (BIO_write(bio, os->data, os->length) != os->length) { + BIO_free_all(bio); + bio = NULL; + } + } } else { bio = BIO_new(BIO_s_mem()); if (bio == NULL) @@ -371,9 +409,12 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) BIO_push(out, bio); else out = bio; + + ASN1_OCTET_STRING_free(os); return out; err: + ASN1_OCTET_STRING_free(os); EVP_CIPHER_free(fetched_cipher); BIO_free_all(out); BIO_free_all(btmp); @@ -702,7 +743,7 @@ static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) /* Add signing time if not already present */ if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { if (!PKCS7_add0_attrib_signing_time(si, NULL)) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); return 0; } } @@ -713,7 +754,7 @@ static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) return 0; } if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); return 0; } @@ -750,7 +791,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) ctx_tmp = EVP_MD_CTX_new(); if (ctx_tmp == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); return 0; } @@ -768,7 +809,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) if (os == NULL) { os = ASN1_OCTET_STRING_new(); if (os == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); goto err; } p7->d.signed_and_enveloped->enc_data->enc_data = os; @@ -780,7 +821,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) if (os == NULL) { os = ASN1_OCTET_STRING_new(); if (os == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); goto err; } p7->d.enveloped->enc_data->enc_data = os; @@ -844,10 +885,9 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) goto err; } else { unsigned char *abuf = NULL; - unsigned int abuflen; - abuflen = EVP_PKEY_get_size(si->pkey); - abuf = OPENSSL_malloc(abuflen); - if (abuf == NULL) + unsigned int abuflen = EVP_PKEY_get_size(si->pkey); + + if (abuflen == 0 || (abuf = OPENSSL_malloc(abuflen)) == NULL) goto err; if (!EVP_SignFinal_ex(ctx_tmp, abuf, &abuflen, si->pkey, @@ -919,7 +959,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) mctx = EVP_MD_CTX_new(); if (mctx == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); goto err; } @@ -931,7 +971,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); - if (!abuf) + if (alen < 0 || abuf == NULL) goto err; if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0) goto err; @@ -957,13 +997,15 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) return 0; } +/* This partly overlaps with PKCS7_verify(). It does not support flags. */ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si) { PKCS7_ISSUER_AND_SERIAL *ias; int ret = 0, i; - STACK_OF(X509) *cert; - X509 *x509; + STACK_OF(X509) *untrusted; + STACK_OF(X509_CRL) *crls; + X509 *signer; if (p7 == NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); @@ -976,26 +1018,30 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, } if (PKCS7_type_is_signed(p7)) { - cert = p7->d.sign->cert; + untrusted = p7->d.sign->cert; + crls = p7->d.sign->crl; } else if (PKCS7_type_is_signedAndEnveloped(p7)) { - cert = p7->d.signed_and_enveloped->cert; + untrusted = p7->d.signed_and_enveloped->cert; + crls = p7->d.signed_and_enveloped->crl; } else { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } + X509_STORE_CTX_set0_crls(ctx, crls); + /* XXXXXXXXXXXXXXXXXXXXXXX */ ias = si->issuer_and_serial; - x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial); + signer = X509_find_by_issuer_and_serial(untrusted, ias->issuer, ias->serial); - /* were we able to find the cert in passed to us */ - if (x509 == NULL) { + /* Were we able to find the signer certificate in passed to us? */ + if (signer == NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_UNABLE_TO_FIND_CERTIFICATE); goto err; } /* Lets verify */ - if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) { + if (!X509_STORE_CTX_init(ctx, cert_store, signer, untrusted)) { ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); goto err; } @@ -1006,13 +1052,13 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, goto err; } - return PKCS7_signatureVerify(bio, p7, si, x509); + return PKCS7_signatureVerify(bio, p7, si, signer); err: return ret; } int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, - X509 *x509) + X509 *signer) { ASN1_OCTET_STRING *os; EVP_MD_CTX *mdc_tmp, *mdc; @@ -1030,7 +1076,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, mdc_tmp = EVP_MD_CTX_new(); if (mdc_tmp == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB); goto err; } @@ -1108,7 +1154,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); - if (alen <= 0) { + if (alen <= 0 || abuf == NULL) { ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); ret = -1; goto err; @@ -1118,7 +1164,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, } os = si->enc_digest; - pkey = X509_get0_pubkey(x509); + pkey = X509_get0_pubkey(signer); if (pkey == NULL) { ret = -1; goto err; @@ -1170,11 +1216,11 @@ ASN1_TYPE *PKCS7_get_attribute(const PKCS7_SIGNER_INFO *si, int nid) static ASN1_TYPE *get_attribute(const STACK_OF(X509_ATTRIBUTE) *sk, int nid) { - int idx; - X509_ATTRIBUTE *xa; - idx = X509at_get_attr_by_NID(sk, nid, -1); - xa = X509at_get_attr(sk, idx); - return X509_ATTRIBUTE_get0_type(xa, 0); + int idx = X509at_get_attr_by_NID(sk, nid, -1); + + if (idx < 0) + return NULL; + return X509_ATTRIBUTE_get0_type(X509at_get_attr(sk, idx), 0); } ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) @@ -1188,38 +1234,20 @@ ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk) int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) { - int i; - sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free); - p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk); + p7si->auth_attr = sk_X509_ATTRIBUTE_deep_copy(sk, X509_ATTRIBUTE_dup, X509_ATTRIBUTE_free); if (p7si->auth_attr == NULL) return 0; - for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { - if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i, - X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value - (sk, i)))) - == NULL) - return 0; - } return 1; } int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk) { - int i; - sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free); - p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk); + p7si->unauth_attr = sk_X509_ATTRIBUTE_deep_copy(sk, X509_ATTRIBUTE_dup, X509_ATTRIBUTE_free); if (p7si->unauth_attr == NULL) return 0; - for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { - if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i, - X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value - (sk, i)))) - == NULL) - return 0; - } return 1; } diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index bdd620526969..ab0ae39ab253 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -229,7 +229,7 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) if ((alg = X509_ALGOR_new()) == NULL || (alg->parameter = ASN1_TYPE_new()) == NULL) { X509_ALGOR_free(alg); - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); return 0; } /* @@ -295,11 +295,12 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) if (*sk == NULL) *sk = sk_X509_CRL_new_null(); if (*sk == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB); return 0; } - X509_CRL_up_ref(crl); + if (!X509_CRL_up_ref(crl)) + return 0; if (!sk_X509_CRL_push(*sk, crl)) { X509_CRL_free(crl); return 0; @@ -310,7 +311,7 @@ int PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl) static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify) { - if (verify == 0) { + if (!verify) { int snid, hnid; X509_ALGOR *alg1, *alg2; EVP_PKEY *pkey = si->pkey; @@ -323,19 +324,20 @@ static int pkcs7_ecdsa_or_dsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, 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 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, NULL); } return 1; } static int pkcs7_rsa_sign_verify_setup(PKCS7_SIGNER_INFO *si, int verify) { - if (verify == 0) { + if (!verify) { X509_ALGOR *alg = NULL; PKCS7_SIGNER_INFO_get0_algs(si, NULL, NULL, &alg); if (alg != NULL) - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); + return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, NULL); } return 1; } @@ -347,10 +349,10 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, /* We now need to add another PKCS7_SIGNER_INFO entry */ if (!ASN1_INTEGER_set(p7i->version, 1)) - goto err; + return 0; if (!X509_NAME_set(&p7i->issuer_and_serial->issuer, X509_get_issuer_name(x509))) - goto err; + return 0; /* * because ASN1_INTEGER_set is used to set a 'long' we will do things the @@ -359,16 +361,19 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, ASN1_INTEGER_free(p7i->issuer_and_serial->serial); if (!(p7i->issuer_and_serial->serial = ASN1_INTEGER_dup(X509_get0_serialNumber(x509)))) - goto err; + return 0; /* lets keep the pkey around for a while */ - EVP_PKEY_up_ref(pkey); + if (!EVP_PKEY_up_ref(pkey)) + return 0; + p7i->pkey = pkey; /* Set the algorithms */ - X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_get_type(dgst)), - V_ASN1_NULL, NULL); + if (!X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_get_type(dgst)), + V_ASN1_NULL, NULL)) + return 0; if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "DSA")) return pkcs7_ecdsa_or_dsa_sign_verify_setup(p7i, 0); @@ -385,7 +390,6 @@ int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, } } ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE); - err: return 0; } @@ -417,7 +421,7 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, return NULL; } -static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7) +STACK_OF(X509) *pkcs7_get0_certificates(const PKCS7 *p7) { if (p7->d.ptr == NULL) return NULL; @@ -458,7 +462,7 @@ void ossl_pkcs7_resolve_libctx(PKCS7 *p7) rinfos = pkcs7_get_recipient_info(p7); sinfos = PKCS7_get_signer_info(p7); - certs = pkcs7_get_signer_certs(p7); + certs = pkcs7_get0_certificates(p7); for (i = 0; i < sk_X509_num(certs); i++) ossl_x509_set0_libctx(sk_X509_value(certs, i), libctx, propq); @@ -495,10 +499,8 @@ int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq) } if (propq != NULL) { p7->ctx.propq = OPENSSL_strdup(propq); - if (p7->ctx.propq == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + if (p7->ctx.propq == NULL) return 0; - } } return 1; } @@ -526,7 +528,7 @@ int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) { if (PKCS7_type_is_digest(p7)) { if ((p7->d.digest->md->parameter = ASN1_TYPE_new()) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_ASN1_LIB); return 0; } p7->d.digest->md->parameter->type = V_ASN1_NULL; @@ -611,10 +613,11 @@ static int pkcs7_rsa_encrypt_decrypt_setup(PKCS7_RECIP_INFO *ri, int decrypt) { X509_ALGOR *alg = NULL; - if (decrypt == 0) { + if (!decrypt) { PKCS7_RECIP_INFO_get0_alg(ri, &alg); if (alg != NULL) - X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0); + return X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), + V_ASN1_NULL, NULL); } return 1; } @@ -663,7 +666,9 @@ int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509) goto err; } finished: - X509_up_ref(x509); + if (!X509_up_ref(x509)) + goto err; + p7i->cert = x509; return 1; diff --git a/crypto/pkcs7/pk7_local.h b/crypto/pkcs7/pk7_local.h index 8deb342b7913..79f909f3dd86 100644 --- a/crypto/pkcs7/pk7_local.h +++ b/crypto/pkcs7/pk7_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,7 @@ #include "crypto/pkcs7.h" +STACK_OF(X509) *pkcs7_get0_certificates(const PKCS7 *p7); const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7); OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx); const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx); diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index 4593da8f5b41..3f9ba3b7d6df 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,6 +11,7 @@ #include #include "internal/cryptlib.h" +#include "crypto/x509.h" #include #include #include "pk7_local.h" @@ -28,7 +29,7 @@ PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, int i; if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); return NULL; } @@ -77,7 +78,7 @@ int PKCS7_final(PKCS7 *p7, BIO *data, int flags) int ret = 0; if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); return 0; } @@ -144,7 +145,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, /* Add SMIMECapabilities */ if (!(flags & PKCS7_NOSMIMECAP)) { if ((smcap = sk_X509_ALGOR_new_null()) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB); goto err; } if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1) @@ -210,10 +211,13 @@ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) return 0; } +/* This strongly overlaps with CMS_verify(), partly with PKCS7_dataVerify() */ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags) { STACK_OF(X509) *signers; + STACK_OF(X509) *included_certs; + STACK_OF(X509) *untrusted = NULL; X509 *signer; STACK_OF(PKCS7_SIGNER_INFO) *sinfos; PKCS7_SIGNER_INFO *si; @@ -221,7 +225,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, char *buf = NULL; int i, j = 0, k, ret = 0; BIO *p7bio = NULL; - BIO *tmpin = NULL, *tmpout = NULL; + BIO *tmpout = NULL; const PKCS7_CTX *p7_ctx; if (p7 == NULL) { @@ -235,7 +239,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, } /* Check for no data and no content: no data to verify signature */ - if (PKCS7_get_detached(p7) && !indata) { + if (PKCS7_get_detached(p7) && indata == NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); return 0; } @@ -248,7 +252,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, * tools like osslsigncode need it. In Authenticode the verification * process is different, but the existing PKCs7 verification works. */ - if (!PKCS7_get_detached(p7) && indata) { + if (!PKCS7_get_detached(p7) && indata != NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT); return 0; } @@ -271,27 +275,29 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, ossl_pkcs7_ctx_get0_propq(p7_ctx)); if (cert_ctx == NULL) goto err; - if (!(flags & PKCS7_NOVERIFY)) + if ((flags & PKCS7_NOVERIFY) == 0) { + if (!ossl_x509_add_certs_new(&untrusted, certs, X509_ADD_FLAG_NO_DUP)) + goto err; + included_certs = pkcs7_get0_certificates(p7); + if ((flags & PKCS7_NOCHAIN) == 0 + && !ossl_x509_add_certs_new(&untrusted, included_certs, + X509_ADD_FLAG_NO_DUP)) + goto err; + for (k = 0; k < sk_X509_num(signers); k++) { signer = sk_X509_value(signers, k); - if (!(flags & PKCS7_NOCHAIN)) { - if (!X509_STORE_CTX_init(cert_ctx, store, signer, - p7->d.sign->cert)) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); - goto err; - } - if (!X509_STORE_CTX_set_default(cert_ctx, "smime_sign")) - goto err; - } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) { + if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) { ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); goto err; } + if ((flags & PKCS7_NOCHAIN) == 0 + && !X509_STORE_CTX_set_default(cert_ctx, "smime_sign")) + goto err; if (!(flags & PKCS7_NOCRL)) X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl); i = X509_verify_cert(cert_ctx); - if (i <= 0) - j = X509_STORE_CTX_get_error(cert_ctx); if (i <= 0) { + j = X509_STORE_CTX_get_error(cert_ctx); ERR_raise_data(ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR, "Verify error: %s", X509_verify_cert_error_string(j)); @@ -299,32 +305,14 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, } /* Check for revocation status here */ } + } - /* - * 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 (indata && (BIO_method_type(indata) == BIO_TYPE_MEM)) { - char *ptr; - long len; - len = BIO_get_mem_data(indata, &ptr); - tmpin = (len == 0) ? indata : BIO_new_mem_buf(ptr, len); - if (tmpin == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); - goto err; - } - } else - tmpin = indata; - - if ((p7bio = PKCS7_dataInit(p7, tmpin)) == NULL) + if ((p7bio = PKCS7_dataInit(p7, indata)) == NULL) goto err; if (flags & PKCS7_TEXT) { if ((tmpout = BIO_new(BIO_s_mem())) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); goto err; } BIO_set_mem_eof_return(tmpout, 0); @@ -332,10 +320,8 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, tmpout = out; /* We now have to 'read' from p7bio to calculate digests etc. */ - if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) goto err; - } for (;;) { i = BIO_read(p7bio, buf, BUFFERSIZE); if (i <= 0) @@ -370,19 +356,18 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, err: X509_STORE_CTX_free(cert_ctx); OPENSSL_free(buf); - if (tmpin == indata) { - if (indata) - BIO_pop(p7bio); - } + if (indata != NULL) + BIO_pop(p7bio); BIO_free_all(p7bio); sk_X509_free(signers); + sk_X509_free(untrusted); return ret; } STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) { - STACK_OF(X509) *signers; + STACK_OF(X509) *signers, *included_certs; STACK_OF(PKCS7_SIGNER_INFO) *sinfos; PKCS7_SIGNER_INFO *si; PKCS7_ISSUER_AND_SERIAL *ias; @@ -398,6 +383,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); return NULL; } + included_certs = pkcs7_get0_certificates(p7); /* Collect all the signers together */ @@ -409,7 +395,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, } if ((signers = sk_X509_new_null()) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB); return NULL; } @@ -418,15 +404,12 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, ias = si->issuer_and_serial; signer = NULL; /* If any certificates passed they take priority */ - if (certs) - signer = X509_find_by_issuer_and_serial(certs, + signer = X509_find_by_issuer_and_serial(certs, + ias->issuer, ias->serial); + if (signer == NULL && (flags & PKCS7_NOINTERN) == 0) + signer = X509_find_by_issuer_and_serial(included_certs, ias->issuer, ias->serial); - if (!signer && !(flags & PKCS7_NOINTERN) - && p7->d.sign->cert) - signer = - X509_find_by_issuer_and_serial(p7->d.sign->cert, - ias->issuer, ias->serial); - if (!signer) { + if (signer == NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND); sk_X509_free(signers); return 0; @@ -452,7 +435,7 @@ PKCS7 *PKCS7_encrypt_ex(STACK_OF(X509) *certs, BIO *in, X509 *x509; if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB); return NULL; } @@ -503,7 +486,8 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) return 0; } - if (!PKCS7_type_is_enveloped(p7)) { + if (!PKCS7_type_is_enveloped(p7) + && !PKCS7_type_is_signedAndEnveloped(p7)) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE); return 0; } @@ -523,12 +507,12 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) BIO *tmpbuf, *bread; /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */ if ((tmpbuf = BIO_new(BIO_f_buffer())) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); BIO_free_all(tmpmem); return 0; } if ((bread = BIO_push(tmpbuf, tmpmem)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB); BIO_free_all(tmpbuf); BIO_free_all(tmpmem); return 0; @@ -541,10 +525,8 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) BIO_free_all(bread); return ret; } - if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) { - ERR_raise(ERR_LIB_PKCS7, ERR_R_MALLOC_FAILURE); + if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) goto err; - } for (;;) { i = BIO_read(tmpmem, buf, BUFFERSIZE); if (i <= 0) { diff --git a/crypto/poly1305/asm/poly1305-armv4.pl b/crypto/poly1305/asm/poly1305-armv4.pl index 041bfd46e699..673ea62ec388 100755 --- a/crypto/poly1305/asm/poly1305-armv4.pl +++ b/crypto/poly1305/asm/poly1305-armv4.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2020 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 @@ -1239,7 +1239,8 @@ $code.=<<___; .asciz "Poly1305 for ARMv4/NEON, CRYPTOGAMS by " .align 2 #if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/poly1305/asm/poly1305-armv8.pl b/crypto/poly1305/asm/poly1305-armv8.pl index dc39f4053fe6..df722dc26da8 100755 --- a/crypto/poly1305/asm/poly1305-armv8.pl +++ b/crypto/poly1305/asm/poly1305-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -72,6 +72,7 @@ $code.=<<___; .type poly1305_init,%function .align 5 poly1305_init: + AARCH64_VALID_CALL_TARGET cmp $inp,xzr stp xzr,xzr,[$ctx] // zero hash value stp xzr,xzr,[$ctx,#16] // [along with is_base2_26] @@ -96,10 +97,14 @@ poly1305_init: tst w17,#ARMV7_NEON - adr $d0,.Lpoly1305_blocks - adr $r0,.Lpoly1305_blocks_neon - adr $d1,.Lpoly1305_emit - adr $r1,.Lpoly1305_emit_neon + adrp $d0,poly1305_blocks + add $d0,$d0,#:lo12:.Lpoly1305_blocks + adrp $r0,poly1305_blocks_neon + add $r0,$r0,#:lo12:.Lpoly1305_blocks_neon + adrp $d1,poly1305_emit + add $d1,$d1,#:lo12:.Lpoly1305_emit + adrp $r1,poly1305_emit_neon + add $r1,$r1,#:lo12:.Lpoly1305_emit_neon csel $d0,$d0,$r0,eq csel $d1,$d1,$r1,eq @@ -119,6 +124,9 @@ poly1305_init: .align 5 poly1305_blocks: .Lpoly1305_blocks: + // The symbol .Lpoly1305_blocks is not a .globl symbol + // but a pointer to it is returned by poly1305_init + AARCH64_VALID_CALL_TARGET ands $len,$len,#-16 b.eq .Lno_data @@ -184,6 +192,9 @@ poly1305_blocks: .align 5 poly1305_emit: .Lpoly1305_emit: + // The symbol .poly1305_emit is not a .globl symbol + // but a pointer to it is returned by poly1305_init + AARCH64_VALID_CALL_TARGET ldp $h0,$h1,[$ctx] // load hash base 2^64 ldr $h2,[$ctx,#16] ldp $t0,$t1,[$nonce] // load nonce @@ -291,13 +302,16 @@ poly1305_splat: .align 5 poly1305_blocks_neon: .Lpoly1305_blocks_neon: + // The symbol .Lpoly1305_blocks_neon is not a .globl symbol + // but a pointer to it is returned by poly1305_init + AARCH64_VALID_CALL_TARGET ldr $is_base2_26,[$ctx,#24] cmp $len,#128 b.hs .Lblocks_neon cbz $is_base2_26,.Lpoly1305_blocks .Lblocks_neon: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-80]! add x29,sp,#0 @@ -432,7 +446,8 @@ poly1305_blocks_neon: ldr x30,[sp,#8] add $in2,$inp,#32 - adr $zeros,.Lzeros + adrp $zeros,.Lzeros + add $zeros,$zeros,:lo12:.Lzeros subs $len,$len,#64 csel $in2,$zeros,$in2,lo @@ -444,7 +459,8 @@ poly1305_blocks_neon: .align 4 .Leven_neon: add $in2,$inp,#32 - adr $zeros,.Lzeros + adrp $zeros,.Lzeros + add $zeros,$zeros,:lo12:.Lzeros subs $len,$len,#64 csel $in2,$zeros,$in2,lo @@ -867,7 +883,7 @@ poly1305_blocks_neon: .Lno_data_neon: ldr x29,[sp],#80 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size poly1305_blocks_neon,.-poly1305_blocks_neon @@ -875,6 +891,9 @@ poly1305_blocks_neon: .align 5 poly1305_emit_neon: .Lpoly1305_emit_neon: + // The symbol .Lpoly1305_emit_neon is not a .globl symbol + // but a pointer to it is returned by poly1305_init + AARCH64_VALID_CALL_TARGET ldr $is_base2_26,[$ctx,#24] cbz $is_base2_26,poly1305_emit @@ -924,6 +943,8 @@ poly1305_emit_neon: ret .size poly1305_emit_neon,.-poly1305_emit_neon +.rodata + .align 5 .Lzeros: .long 0,0,0,0,0,0,0,0 diff --git a/crypto/poly1305/asm/poly1305-x86_64.pl b/crypto/poly1305/asm/poly1305-x86_64.pl index 4cddca1c514c..305099ca0308 100755 --- a/crypto/poly1305/asm/poly1305-x86_64.pl +++ b/crypto/poly1305/asm/poly1305-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -229,6 +229,7 @@ $code.=<<___; .align 32 poly1305_blocks: .cfi_startproc + endbranch .Lblocks: shr \$4,$len jz .Lno_data # too short @@ -303,6 +304,7 @@ $code.=<<___; .align 32 poly1305_emit: .cfi_startproc + endbranch .Lemit: mov 0($ctx),%r8 # load hash value mov 8($ctx),%r9 @@ -524,6 +526,7 @@ __poly1305_init_avx: .align 32 poly1305_blocks_avx: .cfi_startproc + endbranch mov 20($ctx),%r8d # is_base2_26 cmp \$128,$len jae .Lblocks_avx @@ -1384,6 +1387,7 @@ $code.=<<___; .align 32 poly1305_emit_avx: .cfi_startproc + endbranch cmpl \$0,20($ctx) # is_base2_26? je .Lemit @@ -1448,6 +1452,7 @@ $code.=<<___; .align 32 poly1305_blocks_avx2: .cfi_startproc + endbranch mov 20($ctx),%r8d # is_base2_26 cmp \$128,$len jae .Lblocks_avx2 @@ -2144,6 +2149,7 @@ $code.=<<___; .align 32 poly1305_blocks_avx512: .cfi_startproc + endbranch .Lblocks_avx512: mov \$15,%eax kmovw %eax,%k2 @@ -3778,6 +3784,7 @@ poly1305_emit_base2_44: ___ } } } $code.=<<___; +.section .rodata align=64 .align 64 .Lconst: .Lmask24: @@ -3809,6 +3816,7 @@ $code.=<<___; .Lx_mask42: .quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff .quad 0x3ffffffffff,0x3ffffffffff,0x3ffffffffff,0x3ffffffffff +.previous ___ } $code.=<<___; diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c index b3bf2b117bbf..693decd4ee8e 100644 --- a/crypto/poly1305/poly1305.c +++ b/crypto/poly1305/poly1305.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -168,7 +168,7 @@ poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit) h1 = (u64)(d1 = (u128)h1 + (d0 >> 64) + U8TOU64(inp + 8)); /* * padbit can be zero only when original len was - * POLY1306_BLOCK_SIZE, but we don't check + * POLY1305_BLOCK_SIZE, but we don't check */ h2 += (u64)(d1 >> 64) + padbit; diff --git a/crypto/poly1305/poly1305_ieee754.c b/crypto/poly1305/poly1305_ieee754.c index 110feb4d5720..57a08aa248bb 100644 --- a/crypto/poly1305/poly1305_ieee754.c +++ b/crypto/poly1305/poly1305_ieee754.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,7 +10,7 @@ /* * This module is meant to be used as template for non-x87 floating- * point assembly modules. The template itself is x86_64-specific - * though, as it was debugged on x86_64. So that implementor would + * though, as it was debugged on x86_64. So that implementer would * have to recognize platform-specific parts, UxTOy and inline asm, * and act accordingly. * @@ -69,7 +69,7 @@ typedef union { double d; u64 u; } elem64; #if defined(__x86_64__) || (defined(__PPC__) && defined(__LITTLE_ENDIAN__)) # define U8TOU32(p) (*(const u32 *)(p)) # define U32TO8(p,v) (*(u32 *)(p) = (v)) -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) # define U8TOU32(p) ({u32 ret; asm ("lwbrx %0,0,%1":"=r"(ret):"b"(p)); ret; }) # define U32TO8(p,v) asm ("stwbrx %0,0,%1"::"r"(v),"b"(p):"memory") #elif defined(__s390x__) @@ -95,7 +95,7 @@ typedef struct { /* "round toward zero (truncate), mask all exceptions" */ #if defined(__x86_64__) static const u32 mxcsr = 0x7f80; -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) static const u64 one = 1; #elif defined(__s390x__) static const u32 fpc = 1; @@ -134,7 +134,7 @@ int poly1305_init(void *ctx, const unsigned char key[16]) asm volatile ("stmxcsr %0":"=m"(mxcsr_orig)); asm volatile ("ldmxcsr %0"::"m"(mxcsr)); -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) double fpscr_orig, fpscr = *(double *)&one; asm volatile ("mffs %0":"=f"(fpscr_orig)); @@ -207,7 +207,7 @@ int poly1305_init(void *ctx, const unsigned char key[16]) */ #if defined(__x86_64__) asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig)); -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig)); #elif defined(__s390x__) asm volatile ("lfpc %0"::"m"(fpc_orig)); @@ -256,7 +256,7 @@ void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, asm volatile ("stmxcsr %0":"=m"(mxcsr_orig)); asm volatile ("ldmxcsr %0"::"m"(mxcsr)); -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) double fpscr_orig, fpscr = *(double *)&one; asm volatile ("mffs %0":"=f"(fpscr_orig)); @@ -416,7 +416,7 @@ void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, */ #if defined(__x86_64__) asm volatile ("ldmxcsr %0"::"m"(mxcsr_orig)); -#elif defined(__PPC__) +#elif defined(__PPC__) || defined(__POWERPC__) asm volatile ("mtfsf 255,%0"::"f"(fpscr_orig)); #elif defined(__s390x__) asm volatile ("lfpc %0"::"m"(fpc_orig)); diff --git a/crypto/ppccap.c b/crypto/ppccap.c index 8bcfed25e057..08794a3ba62e 100644 --- a/crypto/ppccap.c +++ b/crypto/ppccap.c @@ -1,5 +1,5 @@ /* - * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2009-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -45,6 +45,7 @@ void OPENSSL_ppc64_probe(void); void OPENSSL_altivec_probe(void); void OPENSSL_crypto207_probe(void); void OPENSSL_madd300_probe(void); +void OPENSSL_brd31_probe(void); long OPENSSL_rdtsc_mftb(void); long OPENSSL_rdtsc_mfspr268(void); @@ -98,9 +99,10 @@ size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) # endif #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) # include -# if __FreeBSD_version >= 1200000 +# if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ + (defined(__OpenBSD__) && OpenBSD >= 202409) # include # define OSSL_IMPLEMENT_GETAUXVAL @@ -117,16 +119,21 @@ static unsigned long getauxval(unsigned long key) #endif /* I wish was universally available */ -#define HWCAP 16 /* AT_HWCAP */ +#ifndef AT_HWCAP +# define AT_HWCAP 16 /* AT_HWCAP */ +#endif #define HWCAP_PPC64 (1U << 30) #define HWCAP_ALTIVEC (1U << 28) #define HWCAP_FPU (1U << 27) #define HWCAP_POWER6_EXT (1U << 9) #define HWCAP_VSX (1U << 7) -#define HWCAP2 26 /* AT_HWCAP2 */ +#ifndef AT_HWCAP2 +# define AT_HWCAP2 26 /* AT_HWCAP2 */ +#endif #define HWCAP_VEC_CRYPTO (1U << 25) #define HWCAP_ARCH_3_00 (1U << 23) +#define HWCAP_ARCH_3_1 (1U << 18) # if defined(__GNUC__) && __GNUC__>=2 __attribute__ ((constructor)) @@ -187,6 +194,9 @@ void OPENSSL_cpuid_setup(void) if (__power_set(0xffffffffU<<17)) /* POWER9 and later */ OPENSSL_ppccap_P |= PPC_MADD300; + if (__power_set(0xffffffffU<<18)) /* POWER10 and later */ + OPENSSL_ppccap_P |= PPC_BRD31; + return; # endif #endif @@ -215,8 +225,8 @@ void OPENSSL_cpuid_setup(void) #ifdef OSSL_IMPLEMENT_GETAUXVAL { - unsigned long hwcap = getauxval(HWCAP); - unsigned long hwcap2 = getauxval(HWCAP2); + unsigned long hwcap = getauxval(AT_HWCAP); + unsigned long hwcap2 = getauxval(AT_HWCAP2); if (hwcap & HWCAP_FPU) { OPENSSL_ppccap_P |= PPC_FPU; @@ -242,6 +252,10 @@ void OPENSSL_cpuid_setup(void) if (hwcap2 & HWCAP_ARCH_3_00) { OPENSSL_ppccap_P |= PPC_MADD300; } + + if (hwcap2 & HWCAP_ARCH_3_1) { + OPENSSL_ppccap_P |= PPC_BRD31; + } } #endif @@ -263,7 +277,7 @@ void OPENSSL_cpuid_setup(void) sigaction(SIGILL, &ill_act, &ill_oact); #ifndef OSSL_IMPLEMENT_GETAUXVAL - if (sigsetjmp(ill_jmp,1) == 0) { + if (sigsetjmp(ill_jmp, 1) == 0) { OPENSSL_fpu_probe(); OPENSSL_ppccap_P |= PPC_FPU; diff --git a/crypto/ppccpuid.pl b/crypto/ppccpuid.pl index c6555df5d8e3..2814e72f509b 100755 --- a/crypto/ppccpuid.pl +++ b/crypto/ppccpuid.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2007-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -81,6 +81,17 @@ $code=<<___; .long 0 .byte 0,12,0x14,0,0,0,0,0 +.globl .OPENSSL_brd31_probe +.align 4 +.OPENSSL_brd31_probe: + xor r0,r0,r0 + brd r3,r0 + blr + .long 0 + .byte 0,12,0x14,0,0,0,0,0 +.size .OPENSSL_brd31_probe,.-.OPENSSL_brd31_probe + + .globl .OPENSSL_wipe_cpu .align 4 .OPENSSL_wipe_cpu: diff --git a/crypto/property/defn_cache.c b/crypto/property/defn_cache.c index b43f2d247ef6..eb68a55aa79e 100644 --- a/crypto/property/defn_cache.c +++ b/crypto/property/defn_cache.c @@ -15,6 +15,7 @@ #include "internal/property.h" #include "internal/core.h" #include "property_local.h" +#include "crypto/context.h" /* * Implement a property definition cache. @@ -28,7 +29,7 @@ typedef struct { char body[1]; } PROPERTY_DEFN_ELEM; -DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM); +DEFINE_LHASH_OF_EX(PROPERTY_DEFN_ELEM); static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a) { @@ -47,7 +48,7 @@ static void property_defn_free(PROPERTY_DEFN_ELEM *elem) OPENSSL_free(elem); } -static void property_defns_free(void *vproperty_defns) +void ossl_property_defns_free(void *vproperty_defns) { LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns; @@ -58,25 +59,18 @@ static void property_defns_free(void *vproperty_defns) } } -static void *property_defns_new(OSSL_LIB_CTX *ctx) { +void *ossl_property_defns_new(OSSL_LIB_CTX *ctx) { return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp); } -static const OSSL_LIB_CTX_METHOD property_defns_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - property_defns_new, - property_defns_free, -}; - OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop) { PROPERTY_DEFN_ELEM elem, *r; LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; property_defns = ossl_lib_ctx_get_data(ctx, - OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, - &property_defns_method); - if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx)) + OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); + if (!ossl_assert(property_defns != NULL) || !ossl_lib_ctx_read_lock(ctx)) return NULL; elem.prop = prop; @@ -101,8 +95,7 @@ int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop, int res = 1; property_defns = ossl_lib_ctx_get_data(ctx, - OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, - &property_defns_method); + OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); if (property_defns == NULL) return 0; diff --git a/crypto/property/property.c b/crypto/property/property.c index 75615d39af36..2c35222f76f8 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -19,10 +19,12 @@ #include "crypto/ctype.h" #include #include +#include #include "internal/thread_once.h" #include "crypto/lhash.h" #include "crypto/sparse_array.h" #include "property_local.h" +#include "crypto/context.h" /* * The number of elements in the query cache before we initiate a flush. @@ -52,7 +54,7 @@ typedef struct { char body[1]; } QUERY; -DEFINE_LHASH_OF(QUERY); +DEFINE_LHASH_OF_EX(QUERY); typedef struct { int nid; @@ -109,7 +111,7 @@ static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store, 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) +void ossl_ctx_global_properties_free(void *vglobp) { OSSL_GLOBAL_PROPERTIES *globp = vglobp; @@ -119,17 +121,11 @@ static void ossl_ctx_global_properties_free(void *vglobp) } } -static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx) +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, ossl_unused int loadconfig) { @@ -139,8 +135,7 @@ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx, 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); + globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); return globp != NULL ? &globp->list : NULL; } @@ -149,8 +144,7 @@ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx, 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); + = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); return globp != NULL && globp->no_mirrored ? 1 : 0; } @@ -158,8 +152,7 @@ int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx) 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); + = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES); if (globp != NULL) globp->no_mirrored = 1; @@ -296,6 +289,31 @@ static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg) return ossl_sa_ALGORITHM_set(store->algs, alg->nid, alg); } +/** + * @brief Adds a method to the specified method store. + * + * This function adds a new method to the provided method store, associating it + * with a specified id, properties, and provider. The method is stored with + * reference count and destruction callbacks. + * + * @param store Pointer to the OSSL_METHOD_STORE where the method will be added. + * Must be non-null. + * @param prov Pointer to the OSSL_PROVIDER for the provider of the method. + * Must be non-null. + * @param nid (identifier) associated with the method, must be > 0 + * @param properties String containing properties of the method. + * @param method Pointer to the method to be added. + * @param method_up_ref Function pointer for incrementing the method ref count. + * @param method_destruct Function pointer for destroying the method. + * + * @return 1 if the method is successfully added, 0 on failure. + * + * If tracing is enabled, a message is printed indicating that the method is + * being added to the method store. + * + * NOTE: The nid parameter here is _not_ a nid in the sense of the NID_* macros. + * It is an internal unique identifier. + */ 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 *), @@ -308,6 +326,7 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, if (nid <= 0 || method == NULL || store == NULL) return 0; + if (properties == NULL) properties = ""; @@ -332,7 +351,25 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, OPENSSL_free(impl); return 0; } + + /* + * Flush the alg cache of any implementation that already exists + * for this id. + * This is done to ensure that on the next lookup we go through the + * provider comparison in ossl_method_store_fetch. If we don't do this + * then this new method won't be given a chance to get selected. + * NOTE: This doesn't actually remove the method from the backing store + * It just ensures that we query the backing store when (re)-adding a + * method to the algorithm cache, in case the one selected by the next + * query selects a different implementation + */ ossl_method_cache_flush(store, nid); + + /* + * Parse the properties associated with this method, and convert it to a + * property list stored against the implementation for later comparison + * during fetch operations + */ if ((impl->properties = ossl_prop_defn_get(store->ctx, properties)) == NULL) { impl->properties = ossl_parse_property(store->ctx, properties); if (impl->properties == NULL) @@ -344,6 +381,10 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, } } + /* + * Check if we have an algorithm cache already for this nid. If so use + * it, otherwise, create it, and insert it into the store + */ alg = ossl_method_store_retrieve(store, nid); if (alg == NULL) { if ((alg = OPENSSL_zalloc(sizeof(*alg))) == NULL @@ -353,6 +394,7 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, alg->nid = nid; if (!ossl_method_store_insert(store, alg)) goto err; + OSSL_TRACE2(QUERY, "Inserted an alg with nid %d into the store %p\n", nid, (void *)store); } /* Push onto stack if there isn't one there already */ @@ -363,9 +405,20 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, && tmpimpl->properties == impl->properties) break; } + if (i == sk_IMPLEMENTATION_num(alg->impls) - && sk_IMPLEMENTATION_push(alg->impls, impl)) + && sk_IMPLEMENTATION_push(alg->impls, impl)) { ret = 1; +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(QUERY) { + BIO_printf(trc_out, "Adding to method store " + "nid: %d\nproperties: %s\nprovider: %s\n", + nid, properties, + ossl_provider_name(prov) == NULL ? "none" : + ossl_provider_name(prov)); + } OSSL_TRACE_END(QUERY); +#endif + } ossl_property_unlock(store); if (ret == 0) impl_free(impl); @@ -420,6 +473,21 @@ struct alg_cleanup_by_provider_data_st { const OSSL_PROVIDER *prov; }; +/** + * @brief Cleans up implementations of an algorithm associated with a provider. + * + * This function removes all implementations of a specified algorithm that are + * associated with a given provider. The function walks through the stack of + * implementations backwards to handle deletions without affecting indexing. + * + * @param idx Index of the algorithm (unused in this function). + * @param alg Pointer to the ALGORITHM structure containing the implementations. + * @param arg Pointer to the data containing the provider information. + * + * If tracing is enabled, messages are printed indicating the removal of each + * implementation and its properties. If any implementation is removed, the + * associated cache is flushed. + */ static void alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg) { @@ -434,9 +502,24 @@ alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg) IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i); if (impl->provider == data->prov) { - impl_free(impl); +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(QUERY) { + char buf[512]; + size_t size; + + size = ossl_property_list_to_string(NULL, impl->properties, buf, + sizeof(buf)); + BIO_printf(trc_out, "Removing implementation from " + "query cache\nproperties %s\nprovider %s\n", + size == 0 ? "none" : buf, + ossl_provider_name(impl->provider) == NULL ? "none" : + ossl_provider_name(impl->provider)); + } OSSL_TRACE_END(QUERY); +#endif + (void)sk_IMPLEMENTATION_delete(alg->impls, i); count++; + impl_free(impl); } } @@ -512,6 +595,29 @@ void ossl_method_store_do_all(OSSL_METHOD_STORE *store, } } +/** + * @brief Fetches a method from the method store matching the given properties. + * + * This function searches the method store for an implementation of a specified + * method, identified by its id (nid), and matching the given property query. If + * successful, it returns the method and its associated provider. + * + * @param store Pointer to the OSSL_METHOD_STORE from which to fetch the method. + * Must be non-null. + * @param nid (identifier) of the method to be fetched. Must be > 0 + * @param prop_query String containing the property query to match against. + * @param prov_rw Pointer to the OSSL_PROVIDER to restrict the search to, or + * to receive the matched provider. + * @param method Pointer to receive the fetched method. Must be non-null. + * + * @return 1 if the method is successfully fetched, 0 on failure. + * + * If tracing is enabled, a message is printed indicating the property query and + * the resolved provider. + * + * NOTE: The nid parameter here is _not_ a NID in the sense of the NID_* macros. + * It is a unique internal identifier value. + */ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, const char *prop_query, const OSSL_PROVIDER **prov_rw, void **method) @@ -536,14 +642,27 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, /* This only needs to be a read lock, because the query won't create anything */ if (!ossl_property_read_lock(store)) return 0; + + OSSL_TRACE2(QUERY, "Retrieving by nid %d from store %p\n", nid, (void *)store); alg = ossl_method_store_retrieve(store, nid); if (alg == NULL) { ossl_property_unlock(store); + OSSL_TRACE2(QUERY, "Failed to retrieve by nid %d from store %p\n", nid, (void *)store); return 0; } + OSSL_TRACE2(QUERY, "Retrieved by nid %d from store %p\n", nid, (void *)store); + /* + * If a property query string is provided, convert it to an + * OSSL_PROPERTY_LIST structure + */ if (prop_query != NULL) p2 = pq = ossl_parse_query(store->ctx, prop_query, 0); + + /* + * If the library context has default properties specified + * then merge those with the properties passed to this function + */ plp = ossl_ctx_global_properties(store->ctx, 0); if (plp != NULL && *plp != NULL) { if (pq == NULL) { @@ -557,6 +676,13 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, } } + /* + * Search for a provider that provides this implementation. + * If the requested provider is NULL, then any provider will do, + * otherwise we should try to find the one that matches the requested + * provider. Note that providers are given implicit preference via the + * ordering of the implementation stack + */ if (pq == NULL) { for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) { if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL @@ -568,6 +694,12 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, } goto fin; } + + /* + * If there are optional properties specified + * then run the search again, and select the provider that matches the + * most options + */ 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 @@ -590,6 +722,21 @@ fin: } else { ret = 0; } + +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(QUERY) { + char buf[512]; + int size; + + size = ossl_property_list_to_string(NULL, pq, buf, 512); + BIO_printf(trc_out, "method store query with properties %s " + "resolves to provider %s\n", + size == 0 ? "none" : buf, + best_impl == NULL ? "none" : + ossl_provider_name(best_impl->provider)); + } OSSL_TRACE_END(QUERY); +#endif + ossl_property_unlock(store); ossl_property_free(p2); return ret; @@ -691,7 +838,7 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store) store->cache_nelem = state.nelem; /* Without a timer, update the global seed */ if (state.using_global_seed) - tsan_store(&global_seed, state.seed); + tsan_add(&global_seed, state.seed); } int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c index 45c798f1b50b..3a67754224f0 100644 --- a/crypto/property/property_parse.c +++ b/crypto/property/property_parse.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -18,7 +18,7 @@ #include "crypto/ctype.h" #include "internal/nelem.h" #include "property_local.h" -#include "e_os.h" +#include "internal/e_os.h" DEFINE_STACK_OF(OSSL_PROPERTY_DEFINITION) @@ -567,8 +567,7 @@ OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a, r->has_optional |= copy->optional; } r->num_properties = n; - if (n != t) - r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0])); + return r; } diff --git a/crypto/property/property_string.c b/crypto/property/property_string.c index ef87a6a78235..e06f47a6b798 100644 --- a/crypto/property/property_string.c +++ b/crypto/property/property_string.c @@ -13,6 +13,7 @@ #include #include "crypto/lhash.h" #include "property_local.h" +#include "crypto/context.h" /* * Property strings are a consolidation of all strings seen by the property @@ -31,7 +32,7 @@ typedef struct { char body[1]; } PROPERTY_STRING; -DEFINE_LHASH_OF(PROPERTY_STRING); +DEFINE_LHASH_OF_EX(PROPERTY_STRING); typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE; typedef struct { @@ -40,6 +41,10 @@ typedef struct { PROP_TABLE *prop_values; OSSL_PROPERTY_IDX prop_name_idx; OSSL_PROPERTY_IDX prop_value_idx; +#ifndef OPENSSL_SMALL_FOOTPRINT + STACK_OF(OPENSSL_CSTRING) *prop_namelist; + STACK_OF(OPENSSL_CSTRING) *prop_valuelist; +#endif } PROPERTY_STRING_DATA; static unsigned long property_hash(const PROPERTY_STRING *a) @@ -68,7 +73,7 @@ static void property_table_free(PROP_TABLE **pt) } } -static void property_string_data_free(void *vpropdata) +void ossl_property_string_data_free(void *vpropdata) { PROPERTY_STRING_DATA *propdata = vpropdata; @@ -78,44 +83,44 @@ static void property_string_data_free(void *vpropdata) CRYPTO_THREAD_lock_free(propdata->lock); property_table_free(&propdata->prop_names); property_table_free(&propdata->prop_values); +#ifndef OPENSSL_SMALL_FOOTPRINT + sk_OPENSSL_CSTRING_free(propdata->prop_namelist); + sk_OPENSSL_CSTRING_free(propdata->prop_valuelist); + propdata->prop_namelist = propdata->prop_valuelist = NULL; +#endif propdata->prop_name_idx = propdata->prop_value_idx = 0; OPENSSL_free(propdata); } -static void *property_string_data_new(OSSL_LIB_CTX *ctx) { +void *ossl_property_string_data_new(OSSL_LIB_CTX *ctx) { PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata)); if (propdata == NULL) return NULL; propdata->lock = CRYPTO_THREAD_lock_new(); - if (propdata->lock == NULL) - goto err; - propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash, &property_cmp); - if (propdata->prop_names == NULL) - goto err; - propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash, &property_cmp); - if (propdata->prop_values == NULL) - goto err; - +#ifndef OPENSSL_SMALL_FOOTPRINT + propdata->prop_namelist = sk_OPENSSL_CSTRING_new_null(); + propdata->prop_valuelist = sk_OPENSSL_CSTRING_new_null(); +#endif + if (propdata->lock == NULL +#ifndef OPENSSL_SMALL_FOOTPRINT + || propdata->prop_namelist == NULL + || propdata->prop_valuelist == NULL +#endif + || propdata->prop_names == NULL + || propdata->prop_values == NULL) { + ossl_property_string_data_free(propdata); + return NULL; + } return propdata; - -err: - property_string_data_free(propdata); - return NULL; } -static const OSSL_LIB_CTX_METHOD property_string_data_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - property_string_data_new, - property_string_data_free, -}; - static PROPERTY_STRING *new_property_string(const char *s, OSSL_PROPERTY_IDX *pidx) { @@ -134,40 +139,66 @@ static PROPERTY_STRING *new_property_string(const char *s, return ps; } -static OSSL_PROPERTY_IDX ossl_property_string(CRYPTO_RWLOCK *lock, - PROP_TABLE *t, - OSSL_PROPERTY_IDX *pidx, - const char *s) +static OSSL_PROPERTY_IDX ossl_property_string(OSSL_LIB_CTX *ctx, int name, + int create, const char *s) { PROPERTY_STRING p, *ps, *ps_new; + PROP_TABLE *t; + OSSL_PROPERTY_IDX *pidx; + PROPERTY_STRING_DATA *propdata + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX); + if (propdata == NULL) + return 0; + + t = name ? propdata->prop_names : propdata->prop_values; p.s = s; - if (!CRYPTO_THREAD_read_lock(lock)) { + if (!CRYPTO_THREAD_read_lock(propdata->lock)) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK); return 0; } ps = lh_PROPERTY_STRING_retrieve(t, &p); - if (ps == NULL && pidx != NULL) { - CRYPTO_THREAD_unlock(lock); - if (!CRYPTO_THREAD_write_lock(lock)) { + if (ps == NULL && create) { + CRYPTO_THREAD_unlock(propdata->lock); + if (!CRYPTO_THREAD_write_lock(propdata->lock)) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_WRITE_LOCK); return 0; } + pidx = name ? &propdata->prop_name_idx : &propdata->prop_value_idx; ps = lh_PROPERTY_STRING_retrieve(t, &p); if (ps == NULL && (ps_new = new_property_string(s, pidx)) != NULL) { +#ifndef OPENSSL_SMALL_FOOTPRINT + STACK_OF(OPENSSL_CSTRING) *slist; + + slist = name ? propdata->prop_namelist : propdata->prop_valuelist; + if (sk_OPENSSL_CSTRING_push(slist, ps_new->s) <= 0) { + property_free(ps_new); + CRYPTO_THREAD_unlock(propdata->lock); + return 0; + } +#endif lh_PROPERTY_STRING_insert(t, ps_new); if (lh_PROPERTY_STRING_error(t)) { + /*- + * Undo the previous push which means also decrementing the + * index and freeing the allocated storage. + */ +#ifndef OPENSSL_SMALL_FOOTPRINT + sk_OPENSSL_CSTRING_pop(slist); +#endif property_free(ps_new); - CRYPTO_THREAD_unlock(lock); + --*pidx; + CRYPTO_THREAD_unlock(propdata->lock); return 0; } ps = ps_new; } } - CRYPTO_THREAD_unlock(lock); + CRYPTO_THREAD_unlock(propdata->lock); return ps != NULL ? ps->idx : 0; } +#ifdef OPENSSL_SMALL_FOOTPRINT struct find_str_st { const char *str; OSSL_PROPERTY_IDX idx; @@ -180,45 +211,47 @@ static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr) if (prop->idx == findstr->idx) findstr->str = prop->s; } +#endif static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) { - struct find_str_st findstr; + const char *r; PROPERTY_STRING_DATA *propdata - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, - &property_string_data_method); + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX); if (propdata == NULL) return NULL; - findstr.str = NULL; - findstr.idx = idx; - if (!CRYPTO_THREAD_read_lock(propdata->lock)) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK); return NULL; } - lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names - : propdata->prop_values, - find_str_fn, &findstr); +#ifdef OPENSSL_SMALL_FOOTPRINT + { + struct find_str_st findstr; + + findstr.str = NULL; + findstr.idx = idx; + + lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names + : propdata->prop_values, + find_str_fn, &findstr); + r = findstr.str; + } +#else + r = sk_OPENSSL_CSTRING_value(name ? propdata->prop_namelist + : propdata->prop_valuelist, idx - 1); +#endif CRYPTO_THREAD_unlock(propdata->lock); - return findstr.str; + return r; } OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s, int create) { - PROPERTY_STRING_DATA *propdata - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, - &property_string_data_method); - - if (propdata == NULL) - return 0; - return ossl_property_string(propdata->lock, propdata->prop_names, - create ? &propdata->prop_name_idx : NULL, - s); + return ossl_property_string(ctx, 1, create, s); } const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) @@ -229,15 +262,7 @@ const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s, int create) { - PROPERTY_STRING_DATA *propdata - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, - &property_string_data_method); - - if (propdata == NULL) - return 0; - return ossl_property_string(propdata->lock, propdata->prop_values, - create ? &propdata->prop_value_idx : NULL, - s); + return ossl_property_string(ctx, 0, create, s); } const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) diff --git a/crypto/provider.c b/crypto/provider.c index 114b42692940..c122cb4d0be2 100644 --- a/crypto/provider.c +++ b/crypto/provider.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,15 +15,15 @@ #include "internal/provider.h" #include "provider_local.h" -OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name, - int retain_fallbacks) +OSSL_PROVIDER *OSSL_PROVIDER_try_load_ex(OSSL_LIB_CTX *libctx, const char *name, + OSSL_PARAM *params, int retain_fallbacks) { OSSL_PROVIDER *prov = NULL, *actual; int isnew = 0; /* Find it or create it */ if ((prov = ossl_provider_find(libctx, name, 0)) == NULL) { - if ((prov = ossl_provider_new(libctx, name, NULL, 0)) == NULL) + if ((prov = ossl_provider_new(libctx, name, NULL, params, 0)) == NULL) return NULL; isnew = 1; } @@ -49,14 +49,25 @@ OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name, return actual; } -OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name) +OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name, + int retain_fallbacks) +{ + return OSSL_PROVIDER_try_load_ex(libctx, name, NULL, retain_fallbacks); +} + +OSSL_PROVIDER *OSSL_PROVIDER_load_ex(OSSL_LIB_CTX *libctx, const char *name, OSSL_PARAM *params) { /* Any attempt to load a provider disables auto-loading of defaults */ if (ossl_provider_disable_fallback_loading(libctx)) - return OSSL_PROVIDER_try_load(libctx, name, 0); + return OSSL_PROVIDER_try_load_ex(libctx, name, params, 0); return NULL; } +OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name) +{ + return OSSL_PROVIDER_load_ex(libctx, name, NULL); +} + int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov) { if (!ossl_provider_deactivate(prov, 1)) @@ -91,7 +102,7 @@ void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov, void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov) { - return ossl_provider_prov_ctx(prov); + return ossl_provider_ctx(prov); } const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov) @@ -123,10 +134,8 @@ int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, } memset(&entry, 0, sizeof(entry)); entry.name = OPENSSL_strdup(name); - if (entry.name == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (entry.name == NULL) return 0; - } entry.init = init_fn; if (!ossl_provider_info_add_to_store(libctx, &entry)) { ossl_provider_info_clear(&entry); diff --git a/crypto/provider_child.c b/crypto/provider_child.c index 861bcb035baa..52e9cb405f28 100644 --- a/crypto/provider_child.c +++ b/crypto/provider_child.c @@ -16,6 +16,7 @@ #include "internal/provider.h" #include "internal/cryptlib.h" #include "crypto/evp.h" +#include "crypto/context.h" DEFINE_STACK_OF(OSSL_PROVIDER) @@ -33,12 +34,12 @@ struct child_prov_globals { OSSL_FUNC_provider_free_fn *c_prov_free; }; -static void *child_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx) +void *ossl_child_prov_ctx_new(OSSL_LIB_CTX *libctx) { return OPENSSL_zalloc(sizeof(struct child_prov_globals)); } -static void child_prov_ossl_ctx_free(void *vgbl) +void ossl_child_prov_ctx_free(void *vgbl) { struct child_prov_globals *gbl = vgbl; @@ -46,12 +47,6 @@ static void child_prov_ossl_ctx_free(void *vgbl) OPENSSL_free(gbl); } -static const OSSL_LIB_CTX_METHOD child_prov_ossl_ctx_method = { - OSSL_LIB_CTX_METHOD_LOW_PRIORITY, - child_prov_ossl_ctx_new, - child_prov_ossl_ctx_free, -}; - static OSSL_provider_init_fn ossl_child_provider_init; static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle, @@ -84,8 +79,7 @@ static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle, */ ctx = (OSSL_LIB_CTX *)c_get_libctx(handle); - gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; @@ -103,8 +97,7 @@ static int provider_create_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata) OSSL_PROVIDER *cprov; int ret = 0; - gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; @@ -139,7 +132,7 @@ static int provider_create_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata) * init children */ if ((cprov = ossl_provider_new(ctx, provname, ossl_child_provider_init, - 1)) == NULL) + NULL, 1)) == NULL) goto err; if (!ossl_provider_activate(cprov, 0, 0)) { @@ -168,8 +161,7 @@ static int provider_remove_child_cb(const OSSL_CORE_HANDLE *prov, void *cbdata) const char *provname; OSSL_PROVIDER *cprov; - gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; @@ -205,8 +197,7 @@ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx, if (ctx == NULL) return 0; - gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; @@ -273,8 +264,7 @@ int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx, void ossl_provider_deinit_child(OSSL_LIB_CTX *ctx) { struct child_prov_globals *gbl - = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return; @@ -299,8 +289,7 @@ int ossl_provider_up_ref_parent(OSSL_PROVIDER *prov, int activate) const OSSL_CORE_HANDLE *parent_handle; gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov), - OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; @@ -316,8 +305,7 @@ int ossl_provider_free_parent(OSSL_PROVIDER *prov, int deactivate) const OSSL_CORE_HANDLE *parent_handle; gbl = ossl_lib_ctx_get_data(ossl_provider_libctx(prov), - OSSL_LIB_CTX_CHILD_PROVIDER_INDEX, - &child_prov_ossl_ctx_method); + OSSL_LIB_CTX_CHILD_PROVIDER_INDEX); if (gbl == NULL) return 0; diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index 9333b8777f2b..5ec50f97e4a5 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,6 +16,7 @@ #include "internal/provider.h" #include "internal/cryptlib.h" #include "provider_local.h" +#include "crypto/context.h" DEFINE_STACK_OF(OSSL_PROVIDER) @@ -26,7 +27,7 @@ typedef struct { STACK_OF(OSSL_PROVIDER) *activated_providers; } PROVIDER_CONF_GLOBAL; -static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx) +void *ossl_prov_conf_ctx_new(OSSL_LIB_CTX *libctx) { PROVIDER_CONF_GLOBAL *pcgbl = OPENSSL_zalloc(sizeof(*pcgbl)); @@ -42,7 +43,7 @@ static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx) return pcgbl; } -static void prov_conf_ossl_ctx_free(void *vpcgbl) +void ossl_prov_conf_ctx_free(void *vpcgbl) { PROVIDER_CONF_GLOBAL *pcgbl = vpcgbl; @@ -54,13 +55,6 @@ static void prov_conf_ossl_ctx_free(void *vpcgbl) OPENSSL_free(pcgbl); } -static const OSSL_LIB_CTX_METHOD provider_conf_ossl_ctx_method = { - /* Must be freed before the provider store is freed */ - OSSL_LIB_CTX_METHOD_PRIORITY_2, - prov_conf_ossl_ctx_new, - prov_conf_ossl_ctx_free, -}; - static const char *skip_dot(const char *name) { const char *p = strchr(name, '.'); @@ -142,7 +136,7 @@ static int provider_conf_params_internal(OSSL_PROVIDER *prov, } else { OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value); if (prov != NULL) - ok = ossl_provider_add_parameter(prov, name, value); + ok = OSSL_PROVIDER_add_conf_parameter(prov, name, value); else ok = ossl_provider_info_add_parameter(provinfo, name, value); } @@ -197,15 +191,131 @@ static int prov_already_activated(const char *name, return 0; } +/* + * Attempt to activate a provider + * Returns: + * 1 on successful activation + * 0 on failed activation for non-fatal error + * < 0 on failed activation for fatal errors + */ +static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, + const char *value, const char *path, + int soft, const CONF *cnf) +{ + PROVIDER_CONF_GLOBAL *pcgbl + = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX); + OSSL_PROVIDER *prov = NULL, *actual = NULL; + int ok = 0; + + if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + return -1; + } + if (!prov_already_activated(name, pcgbl->activated_providers)) { + /* + * There is an attempt to activate a provider, so we should disable + * loading of fallbacks. Otherwise a misconfiguration could mean the + * intended provider does not get loaded. Subsequent fetches could + * then fallback to the default provider - which may be the wrong + * thing. + */ + if (!ossl_provider_disable_fallback_loading(libctx)) { + CRYPTO_THREAD_unlock(pcgbl->lock); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + return -1; + } + prov = ossl_provider_find(libctx, name, 1); + if (prov == NULL) + prov = ossl_provider_new(libctx, name, NULL, NULL, 1); + if (prov == NULL) { + CRYPTO_THREAD_unlock(pcgbl->lock); + if (soft) + ERR_clear_error(); + return (soft == 0) ? -1 : 0; + } + + if (path != NULL) + ossl_provider_set_module_path(prov, path); + + ok = provider_conf_params(prov, NULL, NULL, value, cnf); + + if (ok == 1) { + if (!ossl_provider_activate(prov, 1, 0)) { + ok = 0; + } else if (!ossl_provider_add_to_store(prov, &actual, 0)) { + ossl_provider_deactivate(prov, 1); + ok = 0; + } else if (actual != prov + && !ossl_provider_activate(actual, 1, 0)) { + ossl_provider_free(actual); + ok = 0; + } else { + if (pcgbl->activated_providers == NULL) + pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); + if (pcgbl->activated_providers == NULL + || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers, + actual)) { + ossl_provider_deactivate(actual, 1); + ossl_provider_free(actual); + ok = 0; + } else { + ok = 1; + } + } + } + + if (ok <= 0) + ossl_provider_free(prov); + } + CRYPTO_THREAD_unlock(pcgbl->lock); + + return ok; +} + +static int provider_conf_parse_bool_setting(const char *confname, + const char *confvalue, int *val) +{ + + if (confvalue == NULL) { + ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR, + "directive %s set to unrecognized value", + confname); + return 0; + } + if ((strcmp(confvalue, "1") == 0) + || (strcmp(confvalue, "yes") == 0) + || (strcmp(confvalue, "YES") == 0) + || (strcmp(confvalue, "true") == 0) + || (strcmp(confvalue, "TRUE") == 0) + || (strcmp(confvalue, "on") == 0) + || (strcmp(confvalue, "ON") == 0)) { + *val = 1; + } else if ((strcmp(confvalue, "0") == 0) + || (strcmp(confvalue, "no") == 0) + || (strcmp(confvalue, "NO") == 0) + || (strcmp(confvalue, "false") == 0) + || (strcmp(confvalue, "FALSE") == 0) + || (strcmp(confvalue, "off") == 0) + || (strcmp(confvalue, "OFF") == 0)) { + *val = 0; + } else { + ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR, + "directive %s set to unrecognized value", + confname); + return 0; + } + + return 1; +} + static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, const char *value, const CONF *cnf) { int i; STACK_OF(CONF_VALUE) *ecmds; int soft = 0; - OSSL_PROVIDER *prov = NULL, *actual = NULL; const char *path = NULL; - long activate = 0; + int activate = 0; int ok = 0; int added = 0; @@ -232,82 +342,24 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, /* First handle some special pseudo confs */ /* Override provider name to use */ - if (strcmp(confname, "identity") == 0) + if (strcmp(confname, "identity") == 0) { name = confvalue; - else if (strcmp(confname, "soft_load") == 0) - soft = 1; + } else if (strcmp(confname, "soft_load") == 0) { + if (!provider_conf_parse_bool_setting(confname, + confvalue, &soft)) + return 0; /* Load a dynamic PROVIDER */ - else if (strcmp(confname, "module") == 0) + } else if (strcmp(confname, "module") == 0) { path = confvalue; - else if (strcmp(confname, "activate") == 0) - activate = 1; + } else if (strcmp(confname, "activate") == 0) { + if (!provider_conf_parse_bool_setting(confname, + confvalue, &activate)) + return 0; + } } if (activate) { - PROVIDER_CONF_GLOBAL *pcgbl - = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_CONF_INDEX, - &provider_conf_ossl_ctx_method); - - if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); - return 0; - } - if (!prov_already_activated(name, pcgbl->activated_providers)) { - /* - * There is an attempt to activate a provider, so we should disable - * loading of fallbacks. Otherwise a misconfiguration could mean the - * intended provider does not get loaded. Subsequent fetches could - * then fallback to the default provider - which may be the wrong - * thing. - */ - if (!ossl_provider_disable_fallback_loading(libctx)) { - CRYPTO_THREAD_unlock(pcgbl->lock); - ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); - return 0; - } - prov = ossl_provider_find(libctx, name, 1); - if (prov == NULL) - prov = ossl_provider_new(libctx, name, NULL, 1); - if (prov == NULL) { - CRYPTO_THREAD_unlock(pcgbl->lock); - if (soft) - ERR_clear_error(); - return 0; - } - - if (path != NULL) - ossl_provider_set_module_path(prov, path); - - ok = provider_conf_params(prov, NULL, NULL, value, cnf); - - if (ok > 0) { - if (!ossl_provider_activate(prov, 1, 0)) { - ok = 0; - } else if (!ossl_provider_add_to_store(prov, &actual, 0)) { - ossl_provider_deactivate(prov, 1); - ok = 0; - } else if (actual != prov - && !ossl_provider_activate(actual, 1, 0)) { - ossl_provider_free(actual); - ok = 0; - } else { - if (pcgbl->activated_providers == NULL) - pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); - if (pcgbl->activated_providers == NULL - || !sk_OSSL_PROVIDER_push(pcgbl->activated_providers, - actual)) { - ossl_provider_deactivate(actual, 1); - ossl_provider_free(actual); - ok = 0; - } else { - ok = 1; - } - } - } - if (ok <= 0) - ossl_provider_free(prov); - } - CRYPTO_THREAD_unlock(pcgbl->lock); + ok = provider_conf_activate(libctx, name, value, path, soft, cnf); } else { OSSL_PROVIDER_INFO entry; @@ -315,17 +367,13 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, ok = 1; if (name != NULL) { entry.name = OPENSSL_strdup(name); - if (entry.name == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (entry.name == NULL) ok = 0; - } } if (ok && path != NULL) { entry.path = OPENSSL_strdup(path); - if (entry.path == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (entry.path == NULL) ok = 0; - } } if (ok) ok = provider_conf_params(NULL, &entry, NULL, value, cnf); diff --git a/crypto/provider_core.c b/crypto/provider_core.c index cb4233eb52fd..490991b5e58b 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -29,8 +29,10 @@ #include "internal/bio.h" #include "internal/core.h" #include "provider_local.h" +#include "crypto/context.h" #ifndef FIPS_MODULE # include +# include #endif /* @@ -72,11 +74,10 @@ * The locks available are: * * The provider flag_lock: Used to control updates to the various provider - * "flags" (flag_initialized, flag_activated, flag_fallback) and associated - * "counts" (activatecnt). + * "flags" (flag_initialized and flag_activated). * - * The provider refcnt_lock: Only ever used to control updates to the provider - * refcnt value. + * The provider activatecnt_lock: Used to control updates to the provider + * activatecnt value. * * The provider optbits_lock: Used to control access to the provider's * operation_bits and operation_bits_sz fields. @@ -99,12 +100,12 @@ * introducing the possibility of deadlock. The following rules MUST be adhered * to in order to avoid that: * - Holding multiple locks at the same time is only allowed for the - * provider store lock, the provider flag_lock and the provider refcnt_lock. + * provider store lock, the provider activatecnt_lock and the provider flag_lock. * - When holding multiple locks they must be acquired in the following order of * precedence: * 1) provider store lock * 2) provider flag_lock - * 3) provider refcnt_lock + * 3) provider activatecnt_lock * - When releasing locks they must be released in the reverse order to which * they were acquired * - No locks may be held when making an upcall. NOTE: Some common functions @@ -142,14 +143,13 @@ struct ossl_provider_st { /* Flag bits */ unsigned int flag_initialized:1; unsigned int flag_activated:1; - unsigned int flag_fallback:1; /* Can be used as fallback */ /* Getting and setting the flags require synchronization */ CRYPTO_RWLOCK *flag_lock; /* OpenSSL library side data */ CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *refcnt_lock; /* For the ref counter */ + CRYPTO_RWLOCK *activatecnt_lock; /* For the activatecnt counter */ int activatecnt; char *name; char *path; @@ -175,6 +175,7 @@ struct ossl_provider_st { OSSL_FUNC_provider_get_params_fn *get_params; OSSL_FUNC_provider_get_capabilities_fn *get_capabilities; OSSL_FUNC_provider_self_test_fn *self_test; + OSSL_FUNC_provider_random_bytes_fn *random_bytes; OSSL_FUNC_provider_query_operation_fn *query_operation; OSSL_FUNC_provider_unquery_operation_fn *unquery_operation; @@ -283,7 +284,7 @@ void ossl_provider_info_clear(OSSL_PROVIDER_INFO *info) sk_INFOPAIR_pop_free(info->parameters, infopair_free); } -static void provider_store_free(void *vstore) +void ossl_provider_store_free(void *vstore) { struct provider_store_st *store = vstore; size_t i; @@ -305,7 +306,7 @@ static void provider_store_free(void *vstore) OPENSSL_free(store); } -static void *provider_store_new(OSSL_LIB_CTX *ctx) +void *ossl_provider_store_new(OSSL_LIB_CTX *ctx) { struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store)); @@ -316,7 +317,7 @@ static void *provider_store_new(OSSL_LIB_CTX *ctx) || (store->child_cbs = sk_OSSL_PROVIDER_CHILD_CB_new_null()) == NULL #endif || (store->lock = CRYPTO_THREAD_lock_new()) == NULL) { - provider_store_free(store); + ossl_provider_store_free(store); return NULL; } store->libctx = ctx; @@ -325,19 +326,11 @@ static void *provider_store_new(OSSL_LIB_CTX *ctx) return store; } -static const OSSL_LIB_CTX_METHOD provider_store_method = { - /* Needs to be freed before the child provider data is freed */ - OSSL_LIB_CTX_METHOD_PRIORITY_1, - provider_store_new, - provider_store_free, -}; - static struct provider_store_st *get_provider_store(OSSL_LIB_CTX *libctx) { struct provider_store_st *store = NULL; - store = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_STORE_INDEX, - &provider_store_method); + store = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_PROVIDER_STORE_INDEX); if (store == NULL) ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); return store; @@ -380,10 +373,8 @@ int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx, if (store->provinfosz == 0) { store->provinfo = OPENSSL_zalloc(sizeof(*store->provinfo) * BUILTINS_BLOCK_SIZE); - if (store->provinfo == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (store->provinfo == NULL) goto err; - } store->provinfosz = BUILTINS_BLOCK_SIZE; } else if (store->numprovinfo == store->provinfosz) { OSSL_PROVIDER_INFO *tmpbuiltins; @@ -391,10 +382,8 @@ int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx, tmpbuiltins = OPENSSL_realloc(store->provinfo, sizeof(*store->provinfo) * newsz); - if (tmpbuiltins == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (tmpbuiltins == NULL) goto err; - } store->provinfo = tmpbuiltins; store->provinfosz = newsz; } @@ -429,12 +418,9 @@ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name, #endif tmpl.name = (char *)name; - /* - * A "find" operation can sort the stack, and therefore a write lock is - * required. - */ if (!CRYPTO_THREAD_write_lock(store->lock)) return NULL; + sk_OSSL_PROVIDER_sort(store->providers); if ((i = sk_OSSL_PROVIDER_find(store->providers, &tmpl)) != -1) prov = sk_OSSL_PROVIDER_value(store->providers, i); CRYPTO_THREAD_unlock(store->lock); @@ -456,26 +442,29 @@ static OSSL_PROVIDER *provider_new(const char *name, { OSSL_PROVIDER *prov = NULL; - if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL -#ifndef HAVE_ATOMICS - || (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL -#endif - ) { + if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL) + return NULL; + if (!CRYPTO_NEW_REF(&prov->refcnt, 1)) { OPENSSL_free(prov); - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + return NULL; + } + if ((prov->activatecnt_lock = CRYPTO_THREAD_lock_new()) == NULL) { + ossl_provider_free(prov); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); return NULL; } - prov->refcnt = 1; /* 1 One reference to be returned */ - if ((prov->opbits_lock = CRYPTO_THREAD_lock_new()) == NULL || (prov->flag_lock = CRYPTO_THREAD_lock_new()) == NULL - || (prov->name = OPENSSL_strdup(name)) == NULL || (prov->parameters = sk_INFOPAIR_deep_copy(parameters, infopair_copy, infopair_free)) == NULL) { ossl_provider_free(prov); - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); + return NULL; + } + if ((prov->name = OPENSSL_strdup(name)) == NULL) { + ossl_provider_free(prov); return NULL; } @@ -488,7 +477,7 @@ int ossl_provider_up_ref(OSSL_PROVIDER *prov) { int ref = 0; - if (CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock) <= 0) + if (CRYPTO_UP_REF(&prov->refcnt, &ref) <= 0) return 0; #ifndef FIPS_MODULE @@ -529,7 +518,7 @@ static int provider_free_intern(OSSL_PROVIDER *prov, int deactivate) */ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, OSSL_provider_init_fn *init_function, - int noconfig) + OSSL_PARAM *params, int noconfig) { struct provider_store_st *store = NULL; OSSL_PROVIDER_INFO template; @@ -542,33 +531,73 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, if (init_function == NULL) { const OSSL_PROVIDER_INFO *p; size_t i; + int chosen = 0; /* Check if this is a predefined builtin provider */ for (p = ossl_predefined_providers; p->name != NULL; p++) { - if (strcmp(p->name, name) == 0) { + if (strcmp(p->name, name) != 0) + continue; + /* These compile-time templates always have NULL parameters */ + template = *p; + chosen = 1; + break; + } + if (!CRYPTO_THREAD_read_lock(store->lock)) + return NULL; + for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) { + if (strcmp(p->name, name) != 0) + continue; + /* For built-in providers, copy just implicit parameters. */ + if (!chosen) template = *p; + /* + * Explicit parameters override config-file defaults. If an empty + * parameter set is desired, a non-NULL empty set must be provided. + */ + if (params != NULL || p->parameters == NULL) { + template.parameters = NULL; break; } - } - if (p->name == NULL) { - /* Check if this is a user added builtin provider */ - if (!CRYPTO_THREAD_read_lock(store->lock)) + /* Always copy to avoid sharing/mutation. */ + template.parameters = sk_INFOPAIR_deep_copy(p->parameters, + infopair_copy, + infopair_free); + if (template.parameters == NULL) return NULL; - for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) { - if (strcmp(p->name, name) == 0) { - template = *p; - break; - } - } - CRYPTO_THREAD_unlock(store->lock); + break; } + CRYPTO_THREAD_unlock(store->lock); } else { template.init = init_function; } + if (params != NULL) { + int i; + + /* Don't leak if already non-NULL */ + if (template.parameters == NULL) + template.parameters = sk_INFOPAIR_new_null(); + if (template.parameters == NULL) + return NULL; + + for (i = 0; params[i].key != NULL; i++) { + if (params[i].data_type != OSSL_PARAM_UTF8_STRING) + continue; + if (ossl_provider_info_add_parameter(&template, params[i].key, + (char *)params[i].data) <= 0) { + sk_INFOPAIR_pop_free(template.parameters, infopair_free); + return NULL; + } + } + } + /* provider_new() generates an error, so no need here */ prov = provider_new(name, template.init, template.parameters); + /* If we copied the parameters, free them */ + if (template.parameters != NULL) + sk_INFOPAIR_pop_free(template.parameters, infopair_free); + if (prov == NULL) return NULL; @@ -654,7 +683,7 @@ int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov, if (actualprov != NULL) { if (!ossl_provider_up_ref(actualtmp)) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); actualtmp = NULL; return 0; } @@ -675,6 +704,15 @@ int ossl_provider_add_to_store(OSSL_PROVIDER *prov, OSSL_PROVIDER **actualprov, ossl_provider_deactivate(prov, 0); ossl_provider_free(prov); } +#ifndef FIPS_MODULE + else { + /* + * This can be done outside the lock. We tolerate other threads getting + * the wrong result briefly when creating OSSL_DECODER_CTXs. + */ + ossl_decoder_cache_flush(prov->libctx); + } +#endif return 1; @@ -688,7 +726,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov) if (prov != NULL) { int ref = 0; - CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock); + CRYPTO_DOWN_REF(&prov->refcnt, &ref); /* * When the refcount drops to zero, we clean up the provider. @@ -730,9 +768,8 @@ void ossl_provider_free(OSSL_PROVIDER *prov) sk_INFOPAIR_pop_free(prov->parameters, infopair_free); CRYPTO_THREAD_lock_free(prov->opbits_lock); CRYPTO_THREAD_lock_free(prov->flag_lock); -#ifndef HAVE_ATOMICS - CRYPTO_THREAD_lock_free(prov->refcnt_lock); -#endif + CRYPTO_THREAD_lock_free(prov->activatecnt_lock); + CRYPTO_FREE_REF(&prov->refcnt); OPENSSL_free(prov); } #ifndef FIPS_MODULE @@ -752,7 +789,6 @@ int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path) return 1; if ((prov->path = OPENSSL_strdup(module_path)) != NULL) return 1; - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return 0; } @@ -761,29 +797,84 @@ static int infopair_add(STACK_OF(INFOPAIR) **infopairsk, const char *name, { INFOPAIR *pair = NULL; - if ((pair = OPENSSL_zalloc(sizeof(*pair))) != NULL - && (*infopairsk != NULL - || (*infopairsk = sk_INFOPAIR_new_null()) != NULL) - && (pair->name = OPENSSL_strdup(name)) != NULL - && (pair->value = OPENSSL_strdup(value)) != NULL - && sk_INFOPAIR_push(*infopairsk, pair) > 0) - return 1; + if ((pair = OPENSSL_zalloc(sizeof(*pair))) == NULL + || (pair->name = OPENSSL_strdup(name)) == NULL + || (pair->value = OPENSSL_strdup(value)) == NULL) + goto err; + if ((*infopairsk == NULL + && (*infopairsk = sk_INFOPAIR_new_null()) == NULL) + || sk_INFOPAIR_push(*infopairsk, pair) <= 0) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); + goto err; + } + + return 1; + + err: if (pair != NULL) { OPENSSL_free(pair->name); OPENSSL_free(pair->value); OPENSSL_free(pair); } - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return 0; } -int ossl_provider_add_parameter(OSSL_PROVIDER *prov, - const char *name, const char *value) +int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov, + const char *name, const char *value) { return infopair_add(&prov->parameters, name, value); } +int OSSL_PROVIDER_get_conf_parameters(const OSSL_PROVIDER *prov, + OSSL_PARAM params[]) +{ + int i; + + if (prov->parameters == NULL) + return 1; + + for (i = 0; i < sk_INFOPAIR_num(prov->parameters); i++) { + INFOPAIR *pair = sk_INFOPAIR_value(prov->parameters, i); + OSSL_PARAM *p = OSSL_PARAM_locate(params, pair->name); + + if (p != NULL + && !OSSL_PARAM_set_utf8_ptr(p, pair->value)) + return 0; + } + return 1; +} + +int OSSL_PROVIDER_conf_get_bool(const OSSL_PROVIDER *prov, + const char *name, int defval) +{ + char *val = NULL; + OSSL_PARAM param[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + param[0].key = (char *)name; + param[0].data_type = OSSL_PARAM_UTF8_PTR; + param[0].data = (void *) &val; + param[0].data_size = sizeof(val); + param[0].return_size = OSSL_PARAM_UNMODIFIED; + + /* Errors are ignored, returning the default value */ + if (OSSL_PROVIDER_get_conf_parameters(prov, param) + && OSSL_PARAM_modified(param) + && val != NULL) { + if ((strcmp(val, "1") == 0) + || (OPENSSL_strcasecmp(val, "yes") == 0) + || (OPENSSL_strcasecmp(val, "true") == 0) + || (OPENSSL_strcasecmp(val, "on") == 0)) + return 1; + else if ((strcmp(val, "0") == 0) + || (OPENSSL_strcasecmp(val, "no") == 0) + || (OPENSSL_strcasecmp(val, "false") == 0) + || (OPENSSL_strcasecmp(val, "off") == 0)) + return 0; + } + return defval; +} + int ossl_provider_info_add_parameter(OSSL_PROVIDER_INFO *provinfo, const char *name, const char *value) @@ -813,10 +904,8 @@ int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, if (path != NULL) { p = OPENSSL_strdup(path); - if (p == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (p == NULL) return 0; - } } if ((store = get_provider_store(libctx)) != NULL && CRYPTO_THREAD_write_lock(store->default_path_lock)) { @@ -829,6 +918,19 @@ int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, return 0; } +const char *OSSL_PROVIDER_get0_default_search_path(OSSL_LIB_CTX *libctx) +{ + struct provider_store_st *store; + char *path = NULL; + + if ((store = get_provider_store(libctx)) != NULL + && CRYPTO_THREAD_read_lock(store->default_path_lock)) { + path = store->default_path; + CRYPTO_THREAD_unlock(store->default_path_lock); + } + return path; +} + /* * Internal version that doesn't affect the store flags, and thereby avoid * locking. Direct callers must remember to set the store flags when @@ -878,10 +980,8 @@ static int provider_init(OSSL_PROVIDER *prov) if (store->default_path != NULL) { allocated_load_dir = OPENSSL_strdup(store->default_path); CRYPTO_THREAD_unlock(store->default_path_lock); - if (allocated_load_dir == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (allocated_load_dir == NULL) goto end; - } load_dir = allocated_load_dir; } else { CRYPTO_THREAD_unlock(store->default_path_lock); @@ -890,7 +990,7 @@ static int provider_init(OSSL_PROVIDER *prov) if (load_dir == NULL) { load_dir = ossl_safe_getenv("OPENSSL_MODULES"); if (load_dir == NULL) - load_dir = MODULESDIR; + load_dir = ossl_get_modulesdir(); } DSO_ctrl(prov->module, DSO_CTRL_SET_FLAGS, @@ -933,6 +1033,12 @@ static int provider_init(OSSL_PROVIDER *prov) prov->name); goto end; } +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + BIO_printf(trc_out, + "(provider %s) initalizing\n", prov->name); + } OSSL_TRACE_END(PROVIDER); +#endif if (!prov->init_function((OSSL_CORE_HANDLE *)prov, core_dispatch, &provider_dispatch, &tmp_provctx)) { @@ -962,6 +1068,10 @@ static int provider_init(OSSL_PROVIDER *prov) prov->self_test = OSSL_FUNC_provider_self_test(provider_dispatch); break; + case OSSL_FUNC_PROVIDER_RANDOM_BYTES: + prov->random_bytes = + OSSL_FUNC_provider_random_bytes(provider_dispatch); + break; case OSSL_FUNC_PROVIDER_GET_CAPABILITIES: prov->get_capabilities = OSSL_FUNC_provider_get_capabilities(provider_dispatch); @@ -1059,6 +1169,12 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls, if (!ossl_assert(prov != NULL)) return -1; +#ifndef FIPS_MODULE + if (prov->random_bytes != NULL + && !ossl_rand_check_random_provider_on_unload(prov->libctx, prov)) + return -1; +#endif + /* * No need to lock if we've got no store because we've not been shared with * other threads. @@ -1074,8 +1190,16 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls, return -1; } + if (!CRYPTO_atomic_add(&prov->activatecnt, -1, &count, prov->activatecnt_lock)) { + if (lock) { + CRYPTO_THREAD_unlock(prov->flag_lock); + CRYPTO_THREAD_unlock(store->lock); + } + return -1; + } + #ifndef FIPS_MODULE - if (prov->activatecnt >= 2 && prov->ischild && upcalls) { + if (count >= 1 && prov->ischild && upcalls) { /* * We have had a direct activation in this child libctx so we need to * now down the ref count in the parent provider. We do the actual down @@ -1086,7 +1210,7 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls, } #endif - if ((count = --prov->activatecnt) < 1) + if (count < 1) prov->flag_activated = 0; #ifndef FIPS_MODULE else @@ -1107,6 +1231,14 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls, if (lock) { CRYPTO_THREAD_unlock(prov->flag_lock); CRYPTO_THREAD_unlock(store->lock); + /* + * This can be done outside the lock. We tolerate other threads getting + * the wrong result briefly when creating OSSL_DECODER_CTXs. + */ +#ifndef FIPS_MODULE + if (count < 1) + ossl_decoder_cache_flush(prov->libctx); +#endif } #ifndef FIPS_MODULE if (freeparent) @@ -1139,6 +1271,10 @@ static int provider_activate(OSSL_PROVIDER *prov, int lock, int upcalls) } #ifndef FIPS_MODULE + if (prov->random_bytes != NULL + && !ossl_rand_check_random_provider_on_load(prov->libctx, prov)) + return -1; + if (prov->ischild && upcalls && !ossl_provider_up_ref_parent(prov, 1)) return -1; #endif @@ -1159,16 +1295,24 @@ static int provider_activate(OSSL_PROVIDER *prov, int lock, int upcalls) #endif return -1; } + if (CRYPTO_atomic_add(&prov->activatecnt, 1, &count, prov->activatecnt_lock)) { + prov->flag_activated = 1; - count = ++prov->activatecnt; - prov->flag_activated = 1; - - if (prov->activatecnt == 1 && store != NULL) { - ret = create_provider_children(prov); + if (count == 1 && store != NULL) { + ret = create_provider_children(prov); + } } if (lock) { CRYPTO_THREAD_unlock(prov->flag_lock); CRYPTO_THREAD_unlock(store->lock); + /* + * This can be done outside the lock. We tolerate other threads getting + * the wrong result briefly when creating OSSL_DECODER_CTXs. + */ +#ifndef FIPS_MODULE + if (count == 1) + ossl_decoder_cache_flush(prov->libctx); +#endif } if (!ret) @@ -1314,14 +1458,25 @@ static int provider_activate_fallbacks(struct provider_store_st *store) for (p = ossl_predefined_providers; p->name != NULL; p++) { OSSL_PROVIDER *prov = NULL; + OSSL_PROVIDER_INFO *info = store->provinfo; + STACK_OF(INFOPAIR) *params = NULL; + size_t i; if (!p->is_fallback) continue; + + for (i = 0; i < store->numprovinfo; info++, i++) { + if (strcmp(info->name, p->name) != 0) + continue; + params = info->parameters; + break; + } + /* * We use the internal constructor directly here, * otherwise we get a call loop */ - prov = provider_new(p->name, p->init, NULL); + prov = provider_new(p->name, p->init, params); if (prov == NULL) goto err; prov->libctx = store->libctx; @@ -1398,7 +1553,7 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx, for (curr = max - 1; curr >= 0; curr--) { OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(provs, curr); - if (!CRYPTO_THREAD_write_lock(prov->flag_lock)) + if (!CRYPTO_THREAD_read_lock(prov->flag_lock)) goto err_unlock; if (prov->flag_activated) { /* @@ -1406,20 +1561,19 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx, * to avoid upping the ref count on the parent provider, which we * must not do while holding locks. */ - if (CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock) <= 0) { + if (CRYPTO_UP_REF(&prov->refcnt, &ref) <= 0) { CRYPTO_THREAD_unlock(prov->flag_lock); goto err_unlock; } /* * It's already activated, but we up the activated count to ensure * it remains activated until after we've called the user callback. - * We do this with no locking (because we already hold the locks) - * and no upcalls (which must not be called when locks are held). In - * theory this could mean the parent provider goes inactive, whilst - * still activated in the child for a short period. That's ok. + * In theory this could mean the parent provider goes inactive, + * whilst still activated in the child for a short period. That's ok. */ - if (provider_activate(prov, 0, 0) < 0) { - CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock); + if (!CRYPTO_atomic_add(&prov->activatecnt, 1, &ref, + prov->activatecnt_lock)) { + CRYPTO_DOWN_REF(&prov->refcnt, &ref); CRYPTO_THREAD_unlock(prov->flag_lock); goto err_unlock; } @@ -1458,13 +1612,32 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx, for (curr++; curr < max; curr++) { OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(provs, curr); - provider_deactivate(prov, 0, 1); + if (!CRYPTO_atomic_add(&prov->activatecnt, -1, &ref, + prov->activatecnt_lock)) { + ret = 0; + continue; + } + if (ref < 1) { + /* + * Looks like we need to deactivate properly. We could just have + * done this originally, but it involves taking a write lock so + * we avoid it. We up the count again and do a full deactivation + */ + if (CRYPTO_atomic_add(&prov->activatecnt, 1, &ref, + prov->activatecnt_lock)) + provider_deactivate(prov, 0, 1); + else + ret = 0; + } /* * As above where we did the up-ref, we don't call ossl_provider_free * to avoid making upcalls. There should always be at least one ref * to the provider in the store, so this should never drop to 0. */ - CRYPTO_DOWN_REF(&prov->refcnt, &ref, prov->refcnt_lock); + if (!CRYPTO_DOWN_REF(&prov->refcnt, &ref)) { + ret = 0; + continue; + } /* * Not much we can do if this assert ever fails. So we don't use * ossl_assert here. @@ -1495,16 +1668,6 @@ int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name) return available; } -/* Setters of Provider Object data */ -int ossl_provider_set_fallback(OSSL_PROVIDER *prov) -{ - if (prov == NULL) - return 0; - - prov->flag_fallback = 1; - return 1; -} - /* Getters of Provider Object data */ const char *ossl_provider_name(const OSSL_PROVIDER *prov) { @@ -1535,14 +1698,6 @@ const char *ossl_provider_module_path(const OSSL_PROVIDER *prov) #endif } -void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov) -{ - if (prov != NULL) - return prov->provctx; - - return NULL; -} - const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov) { if (prov != NULL) @@ -1556,59 +1711,256 @@ OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov) return prov != NULL ? prov->libctx : NULL; } -/* Wrappers around calls to the provider */ +/** + * @brief Tears down the given provider. + * + * This function calls the `teardown` callback of the given provider to release + * any resources associated with it. The teardown is skipped if the callback is + * not defined or, in non-FIPS builds, if the provider is a child. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * + * If tracing is enabled, a message is printed indicating that the teardown is + * being called. + */ void ossl_provider_teardown(const OSSL_PROVIDER *prov) { if (prov->teardown != NULL #ifndef FIPS_MODULE && !prov->ischild #endif - ) + ) { +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + BIO_printf(trc_out, "(provider %s) calling teardown\n", + ossl_provider_name(prov)); + } OSSL_TRACE_END(PROVIDER); +#endif prov->teardown(prov->provctx); + } } +/** + * @brief Retrieves the parameters that can be obtained from a provider. + * + * This function calls the `gettable_params` callback of the given provider to + * get a list of parameters that can be retrieved. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * + * @return Pointer to an array of OSSL_PARAM structures that represent the + * gettable parameters, or NULL if the callback is not defined. + * + * If tracing is enabled, the gettable parameters are printed for debugging. + */ const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov) { - return prov->gettable_params == NULL - ? NULL : prov->gettable_params(prov->provctx); + const OSSL_PARAM *ret = NULL; + + if (prov->gettable_params != NULL) + ret = prov->gettable_params(prov->provctx); + +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + char *buf = NULL; + + BIO_printf(trc_out, "(provider %s) gettable params\n", + ossl_provider_name(prov)); + BIO_printf(trc_out, "Parameters:\n"); + if (prov->gettable_params != NULL) { + if (!OSSL_PARAM_print_to_bio(ret, trc_out, 0)) + BIO_printf(trc_out, "Failed to parse param values\n"); + OPENSSL_free(buf); + } else { + BIO_printf(trc_out, "Provider doesn't implement gettable_params\n"); + } + } OSSL_TRACE_END(PROVIDER); +#endif + + return ret; } +/** + * @brief Retrieves parameters from a provider. + * + * This function calls the `get_params` callback of the given provider to + * retrieve its parameters. If the callback is defined, it is invoked with the + * provider context and the parameters array. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * @param params Array of OSSL_PARAM structures to store the retrieved parameters. + * + * @return 1 on success, 0 if the `get_params` callback is not defined or fails. + * + * If tracing is enabled, the retrieved parameters are printed for debugging. + */ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]) -{ - return prov->get_params == NULL - ? 0 : prov->get_params(prov->provctx, params); -} - -int ossl_provider_self_test(const OSSL_PROVIDER *prov) { int ret; - if (prov->self_test == NULL) - return 1; - ret = prov->self_test(prov->provctx); + if (prov->get_params == NULL) + return 0; + + ret = prov->get_params(prov->provctx, params); +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + + BIO_printf(trc_out, + "(provider %s) calling get_params\n", prov->name); + if (ret == 1) { + BIO_printf(trc_out, "Parameters:\n"); + if (!OSSL_PARAM_print_to_bio(params, trc_out, 1)) + BIO_printf(trc_out, "Failed to parse param values\n"); + } else { + BIO_printf(trc_out, "get_params call failed\n"); + } + } OSSL_TRACE_END(PROVIDER); +#endif + return ret; +} + +/** + * @brief Performs a self-test on the given provider. + * + * This function calls the `self_test` callback of the given provider to + * perform a self-test. If the callback is not defined, it assumes the test + * passed. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * + * @return 1 if the self-test passes or the callback is not defined, 0 on failure. + * + * If tracing is enabled, the result of the self-test is printed for debugging. + * If the test fails, the provider's store methods are removed. + */ +int ossl_provider_self_test(const OSSL_PROVIDER *prov) +{ + int ret = 1; + + if (prov->self_test != NULL) + ret = prov->self_test(prov->provctx); + +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + if (prov->self_test != NULL) + BIO_printf(trc_out, + "(provider %s) Calling self_test, ret = %d\n", + prov->name, ret); + else + BIO_printf(trc_out, + "(provider %s) doesn't implement self_test\n", + prov->name); + } OSSL_TRACE_END(PROVIDER); +#endif if (ret == 0) (void)provider_remove_store_methods((OSSL_PROVIDER *)prov); return ret; } +/** + * @brief Retrieves capabilities from the given provider. + * + * This function calls the `get_capabilities` callback of the specified provider + * to retrieve capabilities information. The callback is invoked with the + * provider context, capability name, a callback function, and an argument. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * @param capability String representing the capability to be retrieved. + * @param cb Callback function to process the capability data. + * @param arg Argument to be passed to the callback function. + * + * @return 1 if the capabilities are successfully retrieved or if the callback + * is not defined, otherwise the value returned by `get_capabilities`. + * + * If tracing is enabled, a message is printed indicating the requested + * capabilities. + */ +int ossl_provider_random_bytes(const OSSL_PROVIDER *prov, int which, + void *buf, size_t n, unsigned int strength) +{ + return prov->random_bytes == NULL ? 0 + : prov->random_bytes(prov->provctx, which, + buf, n, strength); +} + int ossl_provider_get_capabilities(const OSSL_PROVIDER *prov, const char *capability, OSSL_CALLBACK *cb, void *arg) { - return prov->get_capabilities == NULL - ? 1 : prov->get_capabilities(prov->provctx, capability, cb, arg); + if (prov->get_capabilities != NULL) { +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + BIO_printf(trc_out, + "(provider %s) Calling get_capabilities " + "with capabilities %s\n", prov->name, + capability == NULL ? "none" : capability); + } OSSL_TRACE_END(PROVIDER); +#endif + return prov->get_capabilities(prov->provctx, capability, cb, arg); + } + return 1; } +/** + * @brief Queries the provider for available algorithms for a given operation. + * + * This function calls the `query_operation` callback of the specified provider + * to obtain a list of algorithms that can perform the given operation. It may + * also set a flag indicating whether the result should be cached. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * @param operation_id Identifier of the operation to query. + * @param no_cache Pointer to an integer flag to indicate whether caching is allowed. + * + * @return Pointer to an array of OSSL_ALGORITHM structures representing the + * available algorithms, or NULL if the callback is not defined or + * there are no available algorithms. + * + * If tracing is enabled, the available algorithms and their properties are + * printed for debugging. + */ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, int operation_id, int *no_cache) { const OSSL_ALGORITHM *res; - if (prov->query_operation == NULL) + if (prov->query_operation == NULL) { +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + BIO_printf(trc_out, "provider %s lacks query operation!\n", + prov->name); + } OSSL_TRACE_END(PROVIDER); +#endif return NULL; + } + res = prov->query_operation(prov->provctx, operation_id, no_cache); +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + const OSSL_ALGORITHM *idx; + if (res != NULL) { + BIO_printf(trc_out, + "(provider %s) Calling query, available algs are:\n", prov->name); + + for (idx = res; idx->algorithm_names != NULL; idx++) { + BIO_printf(trc_out, + "(provider %s) names %s, prop_def %s, desc %s\n", + prov->name, + res->algorithm_names == NULL ? "none" : + res->algorithm_names, + res->property_definition == NULL ? "none" : + res->property_definition, + res->algorithm_description == NULL ? "none" : + res->algorithm_description); + } + } else { + BIO_printf(trc_out, "(provider %s) query_operation failed\n", prov->name); + } + } OSSL_TRACE_END(PROVIDER); +#endif + #if defined(OPENSSL_NO_CACHED_FETCH) /* Forcing the non-caching of queries */ if (no_cache != NULL) @@ -1617,12 +1969,36 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov, return res; } +/** + * @brief Releases resources associated with a queried operation. + * + * This function calls the `unquery_operation` callback of the specified + * provider to release any resources related to a previously queried operation. + * + * @param prov Pointer to the OSSL_PROVIDER structure representing the provider. + * @param operation_id Identifier of the operation to unquery. + * @param algs Pointer to the OSSL_ALGORITHM structures representing the + * algorithms associated with the operation. + * + * If tracing is enabled, a message is printed indicating that the operation + * is being unqueried. + */ void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov, int operation_id, const OSSL_ALGORITHM *algs) { - if (prov->unquery_operation != NULL) + if (prov->unquery_operation != NULL) { +#ifndef FIPS_MODULE + OSSL_TRACE_BEGIN(PROVIDER) { + BIO_printf(trc_out, + "(provider %s) Calling unquery" + " with operation %d\n", + prov->name, + operation_id); + } OSSL_TRACE_END(PROVIDER); +#endif prov->unquery_operation(prov->provctx, operation_id, algs); + } } int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum) @@ -1638,7 +2014,6 @@ int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum) if (tmp == NULL) { CRYPTO_THREAD_unlock(provider->opbits_lock); - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return 0; } provider->operation_bits = tmp; @@ -1880,11 +2255,16 @@ OSSL_FUNC_BIO_up_ref_fn ossl_core_bio_up_ref; OSSL_FUNC_BIO_free_fn ossl_core_bio_free; OSSL_FUNC_BIO_vprintf_fn ossl_core_bio_vprintf; OSSL_FUNC_BIO_vsnprintf_fn BIO_vsnprintf; +static OSSL_FUNC_indicator_cb_fn core_indicator_get_callback; static OSSL_FUNC_self_test_cb_fn core_self_test_get_callback; -OSSL_FUNC_get_entropy_fn ossl_rand_get_entropy; -OSSL_FUNC_cleanup_entropy_fn ossl_rand_cleanup_entropy; -OSSL_FUNC_get_nonce_fn ossl_rand_get_nonce; -OSSL_FUNC_cleanup_nonce_fn ossl_rand_cleanup_nonce; +static OSSL_FUNC_get_entropy_fn rand_get_entropy; +static OSSL_FUNC_get_user_entropy_fn rand_get_user_entropy; +static OSSL_FUNC_cleanup_entropy_fn rand_cleanup_entropy; +static OSSL_FUNC_cleanup_user_entropy_fn rand_cleanup_user_entropy; +static OSSL_FUNC_get_nonce_fn rand_get_nonce; +static OSSL_FUNC_get_user_nonce_fn rand_get_user_nonce; +static OSSL_FUNC_cleanup_nonce_fn rand_cleanup_nonce; +static OSSL_FUNC_cleanup_user_nonce_fn rand_cleanup_user_nonce; #endif OSSL_FUNC_CRYPTO_malloc_fn CRYPTO_malloc; OSSL_FUNC_CRYPTO_zalloc_fn CRYPTO_zalloc; @@ -1917,7 +2297,6 @@ static const OSSL_PARAM *core_gettable_params(const OSSL_CORE_HANDLE *handle) static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]) { - int i; OSSL_PARAM *p; /* * We created this object originally and we know it is actually an @@ -1936,16 +2315,7 @@ static int core_get_params(const OSSL_CORE_HANDLE *handle, OSSL_PARAM params[]) OSSL_PARAM_set_utf8_ptr(p, ossl_provider_module_path(prov)); #endif - if (prov->parameters == NULL) - return 1; - - for (i = 0; i < sk_INFOPAIR_num(prov->parameters); i++) { - INFOPAIR *pair = sk_INFOPAIR_value(prov->parameters, i); - - if ((p = OSSL_PARAM_locate(params, pair->name)) != NULL) - OSSL_PARAM_set_utf8_ptr(p, pair->value); - } - return 1; + return OSSL_PROVIDER_get_conf_parameters(prov, params); } static OPENSSL_CORE_CTX *core_get_libctx(const OSSL_CORE_HANDLE *handle) @@ -2039,12 +2409,106 @@ static int core_pop_error_to_mark(const OSSL_CORE_HANDLE *handle) return ERR_pop_to_mark(); } +static void core_indicator_get_callback(OPENSSL_CORE_CTX *libctx, + OSSL_INDICATOR_CALLBACK **cb) +{ + OSSL_INDICATOR_get_callback((OSSL_LIB_CTX *)libctx, cb); +} + static void core_self_test_get_callback(OPENSSL_CORE_CTX *libctx, OSSL_CALLBACK **cb, void **cbarg) { OSSL_SELF_TEST_get_callback((OSSL_LIB_CTX *)libctx, cb, cbarg); } +# ifdef OPENSSL_NO_FIPS_JITTER +static size_t rand_get_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} +# else +/* + * OpenSSL FIPS providers prior to 3.2 call rand_get_entropy API from + * core, instead of the newer get_user_entropy. Newer API call honors + * runtime configuration of random seed source and can be configured + * to use os getranom() or another seed source, such as + * JITTER. However, 3.0.9 only calls this API. Note that no other + * providers known to use this, and it is core <-> provider only + * API. Public facing EVP and getrandom bytes already correctly honor + * runtime configuration for seed source. There are no other providers + * packaged in Wolfi, or even known to exist that use this api. Thus + * it is safe to say any caller of this API is in fact 3.0.9 FIPS + * provider. Also note that the passed in handle is invalid and cannot + * be safely dereferences in such cases. Due to a bug in FIPS + * providers 3.0.0, 3.0.8 and 3.0.9. See + * https://github.com/openssl/openssl/blob/master/doc/internal/man3/ossl_rand_get_entropy.pod#notes + */ +size_t ossl_rand_jitter_get_seed(unsigned char **, int, size_t, size_t); +static size_t rand_get_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_jitter_get_seed(pout, entropy, min_len, max_len); +} +# endif + +static size_t rand_get_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + return ossl_rand_get_user_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, entropy, min_len, max_len); +} + +static void rand_cleanup_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + +static void rand_cleanup_user_entropy(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_user_entropy((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + +static size_t rand_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) +{ + return ossl_rand_get_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static size_t rand_get_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + return ossl_rand_get_user_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + pout, min_len, max_len, salt, salt_len); +} + +static void rand_cleanup_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + +static void rand_cleanup_user_nonce(const OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len) +{ + ossl_rand_cleanup_user_nonce((OSSL_LIB_CTX *)core_get_libctx(handle), + buf, len); +} + static const char *core_provider_get0_name(const OSSL_CORE_HANDLE *prov) { return OSSL_PROVIDER_get0_name((const OSSL_PROVIDER *)prov); @@ -2138,10 +2602,15 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_BIO_VPRINTF, (void (*)(void))ossl_core_bio_vprintf }, { OSSL_FUNC_BIO_VSNPRINTF, (void (*)(void))BIO_vsnprintf }, { OSSL_FUNC_SELF_TEST_CB, (void (*)(void))core_self_test_get_callback }, - { OSSL_FUNC_GET_ENTROPY, (void (*)(void))ossl_rand_get_entropy }, - { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))ossl_rand_cleanup_entropy }, - { OSSL_FUNC_GET_NONCE, (void (*)(void))ossl_rand_get_nonce }, - { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))ossl_rand_cleanup_nonce }, + { OSSL_FUNC_INDICATOR_CB, (void (*)(void))core_indicator_get_callback }, + { OSSL_FUNC_GET_ENTROPY, (void (*)(void))rand_get_entropy }, + { OSSL_FUNC_GET_USER_ENTROPY, (void (*)(void))rand_get_user_entropy }, + { OSSL_FUNC_CLEANUP_ENTROPY, (void (*)(void))rand_cleanup_entropy }, + { OSSL_FUNC_CLEANUP_USER_ENTROPY, (void (*)(void))rand_cleanup_user_entropy }, + { OSSL_FUNC_GET_NONCE, (void (*)(void))rand_get_nonce }, + { OSSL_FUNC_GET_USER_NONCE, (void (*)(void))rand_get_user_nonce }, + { OSSL_FUNC_CLEANUP_NONCE, (void (*)(void))rand_cleanup_nonce }, + { OSSL_FUNC_CLEANUP_USER_NONCE, (void (*)(void))rand_cleanup_user_nonce }, #endif { OSSL_FUNC_CRYPTO_MALLOC, (void (*)(void))CRYPTO_malloc }, { OSSL_FUNC_CRYPTO_ZALLOC, (void (*)(void))CRYPTO_zalloc }, @@ -2175,6 +2644,6 @@ static const OSSL_DISPATCH core_dispatch_[] = { { OSSL_FUNC_CORE_OBJ_ADD_SIGID, (void (*)(void))core_obj_add_sigid }, { OSSL_FUNC_CORE_OBJ_CREATE, (void (*)(void))core_obj_create }, #endif - { 0, NULL } + OSSL_DISPATCH_END }; static const OSSL_DISPATCH *core_dispatch = core_dispatch_; diff --git a/crypto/punycode.c b/crypto/punycode.c index 2de32dc18873..68fc586e6815 100644 --- a/crypto/punycode.c +++ b/crypto/punycode.c @@ -1,5 +1,5 @@ /* - * 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 @@ -8,10 +8,11 @@ */ #include -#include #include #include #include "crypto/punycode.h" +#include "internal/common.h" /* for HAS_PREFIX */ +#include "internal/packet.h" /* for WPACKET */ static const unsigned int base = 36; static const unsigned int tmin = 1; @@ -239,12 +240,12 @@ static int codepoint2utf8(unsigned char *out, unsigned long utf) /*- * Return values: - * 1 - ok, *outlen contains valid buf length - * 0 - ok but buf was too short, *outlen contains valid buf length - * -1 - bad string passed + * 1 - ok + * 0 - ok but buf was too short + * -1 - bad string passed or other error */ -int ossl_a2ulabel(const char *in, char *out, size_t *outlen) +int ossl_a2ulabel(const char *in, char *out, size_t outlen) { /*- * Domain name has some parts consisting of ASCII chars joined with dot. @@ -252,81 +253,60 @@ int ossl_a2ulabel(const char *in, char *out, size_t *outlen) * If it does not start with xn--, it becomes U-label as is. * Otherwise we try to decode it. */ - char *outptr = out; const char *inptr = in; - size_t size = 0, maxsize; int result = 1; - unsigned int i, j; + unsigned int i; unsigned int buf[LABEL_BUF_SIZE]; /* It's a hostname */ + WPACKET pkt; - if (out == NULL) { - result = 0; - maxsize = 0; - } else { - maxsize = *outlen; - } + /* Internal API, so should not fail */ + if (!ossl_assert(out != NULL)) + return -1; -#define PUSHC(c) \ - do \ - if (size++ < maxsize) \ - *outptr++ = c; \ - else \ - result = 0; \ - while (0) + if (!WPACKET_init_static_len(&pkt, (unsigned char *)out, outlen, 0)) + return -1; while (1) { char *tmpptr = strchr(inptr, '.'); size_t delta = tmpptr != NULL ? (size_t)(tmpptr - inptr) : strlen(inptr); - if (strncmp(inptr, "xn--", 4) != 0) { - for (i = 0; i < delta + 1; i++) - PUSHC(inptr[i]); + if (!HAS_PREFIX(inptr, "xn--")) { + if (!WPACKET_memcpy(&pkt, inptr, delta)) + result = 0; } else { unsigned int bufsize = LABEL_BUF_SIZE; - if (ossl_punycode_decode(inptr + 4, delta - 4, buf, &bufsize) <= 0) - return -1; + if (ossl_punycode_decode(inptr + 4, delta - 4, buf, &bufsize) <= 0) { + result = -1; + goto end; + } for (i = 0; i < bufsize; i++) { unsigned char seed[6]; size_t utfsize = codepoint2utf8(seed, buf[i]); - if (utfsize == 0) - return -1; + if (utfsize == 0) { + result = -1; + goto end; + } - for (j = 0; j < utfsize; j++) - PUSHC(seed[j]); + if (!WPACKET_memcpy(&pkt, seed, utfsize)) + result = 0; } - - PUSHC(tmpptr != NULL ? '.' : '\0'); } if (tmpptr == NULL) break; + if (!WPACKET_put_bytes_u8(&pkt, '.')) + result = 0; + inptr = tmpptr + 1; } -#undef PUSHC - *outlen = size; + if (!WPACKET_put_bytes_u8(&pkt, '\0')) + result = 0; + end: + WPACKET_cleanup(&pkt); return result; } - -/*- - * a MUST be A-label - * u MUST be U-label - * Returns 0 if compared values are equal - * 1 if not - * -1 in case of errors - */ - -int ossl_a2ucompare(const char *a, const char *u) -{ - char a_ulabel[LABEL_BUF_SIZE + 1]; - size_t a_size = sizeof(a_ulabel); - - if (ossl_a2ulabel(a, a_ulabel, &a_size) <= 0) - return -1; - - return strcmp(a_ulabel, u) != 0; -} diff --git a/crypto/rand/build.info b/crypto/rand/build.info index a74282516f24..e4436521e7c4 100644 --- a/crypto/rand/build.info +++ b/crypto/rand/build.info @@ -1,7 +1,7 @@ LIBS=../../libcrypto $COMMON=rand_lib.c -$CRYPTO=randfile.c rand_err.c rand_deprecated.c prov_seed.c rand_pool.c +$CRYPTO=randfile.c rand_err.c rand_deprecated.c prov_seed.c rand_uniform.c IF[{- !$disabled{'egd'} -}] $CRYPTO=$CRYPTO rand_egd.c @@ -10,5 +10,11 @@ IF[{- !$disabled{'deprecated-3.0'} -}] $CRYPTO=$CRYPTO rand_meth.c ENDIF +IF[{- !$disabled{'fips-jitter'} -}] + $COMMON=$COMMON rand_pool.c +ELSE + $CRYPTO=$CRYPTO rand_pool.c +ENDIF + SOURCE[../../libcrypto]=$COMMON $CRYPTO SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/rand/prov_seed.c b/crypto/rand/prov_seed.c index 96c499c95709..2985c7f2d811 100644 --- a/crypto/rand/prov_seed.c +++ b/crypto/rand/prov_seed.c @@ -1,5 +1,5 @@ /* - * 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 @@ -7,12 +7,15 @@ * https://www.openssl.org/source/license.html */ +#include "rand_local.h" +#include "crypto/evp.h" #include "crypto/rand.h" #include "crypto/rand_pool.h" +#include "internal/core.h" #include #include -size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char **pout, int entropy, size_t min_len, size_t max_len) { @@ -22,7 +25,7 @@ size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, pool = ossl_rand_pool_new(entropy, 1, min_len, max_len); if (pool == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB); return 0; } @@ -38,14 +41,39 @@ size_t ossl_rand_get_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_entropy(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len) +{ + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + + if (rng != NULL && evp_rand_can_seed(rng)) + return evp_rand_get_seed(rng, pout, entropy, min_len, max_len, + 0, NULL, 0); + else + return ossl_rand_get_entropy(ctx, pout, entropy, min_len, max_len); +} + +void ossl_rand_cleanup_entropy(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_secure_clear_free(buf, len); } -size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, - unsigned char **pout, size_t min_len, size_t max_len, +void ossl_rand_cleanup_user_entropy(OSSL_LIB_CTX *ctx, + unsigned char *buf, size_t len) +{ + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + + if (rng != NULL && evp_rand_can_seed(rng)) + evp_rand_clear_seed(rng, buf, len); + else + OPENSSL_secure_clear_free(buf, len); +} + +size_t ossl_rand_get_nonce(ossl_unused OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, ossl_unused size_t max_len, const void *salt, size_t salt_len) { size_t ret = 0; @@ -53,7 +81,7 @@ size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, pool = ossl_rand_pool_new(0, 0, min_len, max_len); if (pool == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RAND, ERR_R_RAND_LIB); return 0; } @@ -69,8 +97,36 @@ size_t ossl_rand_get_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, return ret; } -void ossl_rand_cleanup_nonce(ossl_unused const OSSL_CORE_HANDLE *handle, +size_t ossl_rand_get_user_nonce(OSSL_LIB_CTX *ctx, + unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len) +{ + unsigned char *buf; + EVP_RAND_CTX *rng = ossl_rand_get0_seed_noncreating(ctx); + + if (rng == NULL) + return ossl_rand_get_nonce(ctx, pout, min_len, max_len, salt, salt_len); + + if ((buf = OPENSSL_malloc(min_len)) == NULL) + return 0; + + if (!EVP_RAND_generate(rng, buf, min_len, 0, 0, salt, salt_len)) { + OPENSSL_free(buf); + return 0; + } + *pout = buf; + return min_len; +} + +void ossl_rand_cleanup_nonce(ossl_unused OSSL_LIB_CTX *ctx, unsigned char *buf, size_t len) { OPENSSL_clear_free(buf, len); } + +void ossl_rand_cleanup_user_nonce(ossl_unused OSSL_LIB_CTX *ctx, + unsigned char *buf, size_t len) +{ + OPENSSL_clear_free(buf, len); +} diff --git a/crypto/rand/rand_deprecated.c b/crypto/rand/rand_deprecated.c index dd69f1beb726..bd870013f9d8 100644 --- a/crypto/rand/rand_deprecated.c +++ b/crypto/rand/rand_deprecated.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include +#include "internal/e_os.h" #include #include diff --git a/crypto/rand/rand_egd.c b/crypto/rand/rand_egd.c index 1699e7f38f0f..f44b38d1a951 100644 --- a/crypto/rand/rand_egd.c +++ b/crypto/rand/rand_egd.c @@ -83,14 +83,14 @@ int hpns_socket(int family, socket_transport_name_get(AF_UNIX, current_transport, 20); - if (strcmp(current_transport,transport) == 0) + if (strcmp(current_transport, transport) == 0) return socket(family, type, protocol); /* set the requested socket transport */ if (socket_transport_name_set(AF_UNIX, transport)) return -1; - socket_rc = socket(family,type,protocol); + socket_rc = socket(family, type, protocol); /* set mode back to what it was */ if (socket_transport_name_set(AF_UNIX, current_transport)) @@ -133,7 +133,7 @@ int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) setbuf(fp, NULL); /* Try to connect */ - for ( ; ; ) { + for (;;) { if (connect(fd, (struct sockaddr *)&addr, i) == 0) break; # ifdef EISCONN diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index b9c2bf1760f5..6f078935c09e 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,82 +16,86 @@ static const ERR_STRING_DATA RAND_str_reasons[] = { {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ADDITIONAL_INPUT_TOO_LONG), - "additional input too long"}, + "additional input too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ALREADY_INSTANTIATED), - "already instantiated"}, + "already instantiated"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ARGUMENT_OUT_OF_RANGE), - "argument out of range"}, + "argument out of range"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_CANNOT_OPEN_FILE), "Cannot open file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_ALREADY_INITIALIZED), - "drbg already initialized"}, + "drbg already initialized"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_DRBG_NOT_INITIALISED), - "drbg not initialised"}, + "drbg not initialised"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_INPUT_TOO_LONG), - "entropy input too long"}, + "entropy input too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ENTROPY_OUT_OF_RANGE), - "entropy out of range"}, + "entropy out of range"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED), - "error entropy pool was ignored"}, + "error entropy pool was ignored"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INITIALISING_DRBG), - "error initialising drbg"}, + "error initialising drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_INSTANTIATING_DRBG), - "error instantiating drbg"}, + "error instantiating drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ADDITIONAL_INPUT), - "error retrieving additional input"}, + "error retrieving additional input"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_ENTROPY), - "error retrieving entropy"}, + "error retrieving entropy"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_ERROR_RETRIEVING_NONCE), - "error retrieving nonce"}, + "error retrieving nonce"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FAILED_TO_CREATE_LOCK), - "failed to create lock"}, + "failed to create lock"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FUNC_NOT_IMPLEMENTED), - "Function not implemented"}, + "Function not implemented"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_FWRITE_ERROR), "Error writing file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_GENERATE_ERROR), "generate error"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INSUFFICIENT_DRBG_STRENGTH), - "insufficient drbg strength"}, + "insufficient drbg strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INTERNAL_ERROR), "internal error"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_INVALID_PROPERTY_QUERY), + "invalid property query"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_IN_ERROR_STATE), "in error state"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_A_REGULAR_FILE), - "Not a regular file"}, + "Not a regular file"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NOT_INSTANTIATED), "not instantiated"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED), - "no drbg implementation selected"}, + "no drbg implementation selected"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_LOCKING_NOT_ENABLED), - "parent locking not enabled"}, + "parent locking not enabled"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PARENT_STRENGTH_TOO_WEAK), - "parent strength too weak"}, + "parent strength too weak"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PERSONALISATION_STRING_TOO_LONG), - "personalisation string too long"}, + "personalisation string too long"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED), - "prediction resistance not supported"}, + "prediction resistance not supported"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_PRNG_NOT_SEEDED), "PRNG not seeded"}, + {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_IS_EMPTY), + "random pool is empty"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_OVERFLOW), - "random pool overflow"}, + "random pool overflow"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RANDOM_POOL_UNDERFLOW), - "random pool underflow"}, + "random pool underflow"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG), - "request too large for drbg"}, + "request too large for drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_RESEED_ERROR), "reseed error"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_SELFTEST_FAILURE), "selftest failure"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_LITTLE_NONCE_REQUESTED), - "too little nonce requested"}, + "too little nonce requested"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_TOO_MUCH_NONCE_REQUESTED), - "too much nonce requested"}, + "too much nonce requested"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_CREATE_DRBG), - "unable to create drbg"}, + "unable to create drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_FETCH_DRBG), - "unable to fetch drbg"}, + "unable to fetch drbg"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_RESEED_PROP_COUNTER), - "unable to get parent reseed prop counter"}, + "unable to get parent reseed prop counter"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_GET_PARENT_STRENGTH), - "unable to get parent strength"}, + "unable to get parent strength"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNABLE_TO_LOCK_PARENT), - "unable to lock parent"}, + "unable to lock parent"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_FLAGS), - "unsupported drbg flags"}, + "unsupported drbg flags"}, {ERR_PACK(ERR_LIB_RAND, 0, RAND_R_UNSUPPORTED_DRBG_TYPE), - "unsupported drbg type"}, + "unsupported drbg type"}, {0, NULL} }; diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 5fde214448f3..9233322b5ff5 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,11 +13,93 @@ #include #include #include +#include #include "internal/cryptlib.h" +#include "internal/provider.h" #include "internal/thread_once.h" #include "crypto/rand.h" #include "crypto/cryptlib.h" #include "rand_local.h" +#include "crypto/context.h" +#include "internal/provider.h" + +#ifndef OPENSSL_DEFAULT_SEED_SRC +# define OPENSSL_DEFAULT_SEED_SRC SEED-SRC +#endif + +typedef struct rand_global_st { + /* + * The three shared DRBG instances + * + * There are three shared DRBG instances: , , and + * . The and 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 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 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 provider which we'll use to generate randomness. + */ +#ifndef FIPS_MODULE + OSSL_PROVIDER *random_provider; + char *random_provider_name; +#endif /* !FIPS_MODULE */ + + /* + * The DRBG + * + * Used by default for generating random bytes using RAND_bytes(). + * + * The secondary DRBG is thread-local, i.e., there is one instance + * per thread. + */ + CRYPTO_THREAD_LOCAL public; + + /* + * The DRBG + * + * Used by default for generating private keys using RAND_priv_bytes() + * + * The 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; + +static EVP_RAND_CTX *rand_get0_primary(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl); +static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl); +static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl); + +static RAND_GLOBAL *rand_get_global(OSSL_LIB_CTX *libctx) +{ + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_DRBG_INDEX); +} #ifndef FIPS_MODULE # include @@ -28,17 +110,36 @@ # include # include "crypto/rand_pool.h" # include "prov/seeding.h" -# include "e_os.h" +# include "internal/e_os.h" +# include "internal/property.h" + +/* + * The default name for the random provider. + * This ensures that the FIPS provider will supply libcrypto's random byte + * requirements. + */ +static const char random_provider_fips_name[] = "fips"; + +static int set_random_provider_name(RAND_GLOBAL *dgbl, const char *name) +{ + if (dgbl->random_provider_name != NULL + && OPENSSL_strcasecmp(dgbl->random_provider_name, name) == 0) + return 1; + + OPENSSL_free(dgbl->random_provider_name); + dgbl->random_provider_name = OPENSSL_strdup(name); + return dgbl->random_provider_name != NULL; +} # ifndef OPENSSL_NO_ENGINE /* non-NULL if default_RAND_meth is ENGINE-provided */ static ENGINE *funct_ref; static CRYPTO_RWLOCK *rand_engine_lock; -# endif +# endif /* !OPENSSL_NO_ENGINE */ # ifndef OPENSSL_NO_DEPRECATED_3_0 static CRYPTO_RWLOCK *rand_meth_lock; static const RAND_METHOD *default_RAND_meth; -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; static int rand_inited = 0; @@ -49,13 +150,13 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init) rand_engine_lock = CRYPTO_THREAD_lock_new(); if (rand_engine_lock == NULL) return 0; -# endif +# endif /* !OPENSSL_NO_ENGINE */ # ifndef OPENSSL_NO_DEPRECATED_3_0 rand_meth_lock = CRYPTO_THREAD_lock_new(); if (rand_meth_lock == NULL) goto err; -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ if (!ossl_rand_pool_init()) goto err; @@ -67,11 +168,11 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init) # ifndef OPENSSL_NO_DEPRECATED_3_0 CRYPTO_THREAD_lock_free(rand_meth_lock); rand_meth_lock = NULL; -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ # ifndef OPENSSL_NO_ENGINE CRYPTO_THREAD_lock_free(rand_engine_lock); rand_engine_lock = NULL; -# endif +# endif /* !OPENSSL_NO_ENGINE */ return 0; } @@ -86,16 +187,16 @@ void ossl_rand_cleanup_int(void) if (meth != NULL && meth->cleanup != NULL) meth->cleanup(); RAND_set_rand_method(NULL); -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ ossl_rand_pool_cleanup(); # ifndef OPENSSL_NO_ENGINE CRYPTO_THREAD_lock_free(rand_engine_lock); rand_engine_lock = NULL; -# endif +# endif /* !OPENSSL_NO_ENGINE */ # ifndef OPENSSL_NO_DEPRECATED_3_0 CRYPTO_THREAD_lock_free(rand_meth_lock); rand_meth_lock = NULL; -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ ossl_release_default_drbg_ctx(); rand_inited = 0; } @@ -152,7 +253,7 @@ int RAND_poll(void) ossl_rand_pool_free(pool); return ret; } -# endif +# endif /* !OPENSSL_NO_DEPRECATED_3_0 */ RAND_seed(salt, sizeof(salt)); return 1; @@ -188,6 +289,13 @@ const RAND_METHOD *RAND_get_rand_method(void) if (!RUN_ONCE(&rand_init, do_rand_init)) return NULL; + if (!CRYPTO_THREAD_read_lock(rand_meth_lock)) + return NULL; + tmp_meth = default_RAND_meth; + CRYPTO_THREAD_unlock(rand_meth_lock); + if (tmp_meth != NULL) + return tmp_meth; + if (!CRYPTO_THREAD_write_lock(rand_meth_lock)) return NULL; if (default_RAND_meth == NULL) { @@ -325,6 +433,7 @@ const RAND_METHOD *RAND_get_rand_method(void) int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, unsigned int strength) { + RAND_GLOBAL *dgbl; EVP_RAND_CTX *rand; #if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE) const RAND_METHOD *meth = RAND_get_rand_method(); @@ -337,7 +446,16 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - rand = RAND_get0_private(ctx); + dgbl = rand_get_global(ctx); + if (dgbl == NULL) + return 0; +#ifndef FIPS_MODULE + if (dgbl->random_provider != NULL) + return ossl_provider_random_bytes(dgbl->random_provider, + OSSL_PROV_RANDOM_PRIVATE, + buf, num, strength); +#endif /* !FIPS_MODULE */ + rand = rand_get0_private(ctx, dgbl); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -354,6 +472,7 @@ int RAND_priv_bytes(unsigned char *buf, int num) int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, unsigned int strength) { + RAND_GLOBAL *dgbl; EVP_RAND_CTX *rand; #if !defined(OPENSSL_NO_DEPRECATED_3_0) && !defined(FIPS_MODULE) const RAND_METHOD *meth = RAND_get_rand_method(); @@ -366,7 +485,17 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, } #endif - rand = RAND_get0_public(ctx); + dgbl = rand_get_global(ctx); + if (dgbl == NULL) + return 0; +#ifndef FIPS_MODULE + if (dgbl->random_provider != NULL) + return ossl_provider_random_bytes(dgbl->random_provider, + OSSL_PROV_RANDOM_PUBLIC, + buf, num, strength); +#endif /* !FIPS_MODULE */ + + rand = rand_get0_public(ctx, dgbl); if (rand != NULL) return EVP_RAND_generate(rand, buf, num, strength, 0, NULL, 0); @@ -380,68 +509,11 @@ int RAND_bytes(unsigned char *buf, int num) 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: , , and - * . The and 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 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 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 DRBG - * - * Used by default for generating random bytes using RAND_bytes(). - * - * The secondary DRBG is thread-local, i.e., there is one instance - * per thread. - */ - CRYPTO_THREAD_LOCAL public; - - /* - * The DRBG - * - * Used by default for generating private keys using RAND_priv_bytes() - * - * The 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) +void *ossl_rand_ctx_new(OSSL_LIB_CTX *libctx) { RAND_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl)); @@ -453,7 +525,12 @@ static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx) * We need to ensure that base libcrypto thread handling has been * initialised. */ - OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL); + OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL); + + /* Prepopulate the random provider name */ + dgbl->random_provider_name = OPENSSL_strdup(random_provider_fips_name); + if (dgbl->random_provider_name == NULL) + goto err0; #endif dgbl->lock = CRYPTO_THREAD_lock_new(); @@ -472,6 +549,10 @@ static void *rand_ossl_ctx_new(OSSL_LIB_CTX *libctx) CRYPTO_THREAD_cleanup_local(&dgbl->private); err1: CRYPTO_THREAD_lock_free(dgbl->lock); +#ifndef FIPS_MODULE + err0: + OPENSSL_free(dgbl->random_provider_name); +#endif OPENSSL_free(dgbl); return NULL; } @@ -488,6 +569,9 @@ void ossl_rand_ctx_free(void *vdgbl) CRYPTO_THREAD_cleanup_local(&dgbl->public); EVP_RAND_CTX_free(dgbl->primary); EVP_RAND_CTX_free(dgbl->seed); +#ifndef FIPS_MODULE + OPENSSL_free(dgbl->random_provider_name); +#endif /* !FIPS_MODULE */ OPENSSL_free(dgbl->rng_name); OPENSSL_free(dgbl->rng_cipher); OPENSSL_free(dgbl->rng_digest); @@ -498,18 +582,6 @@ void ossl_rand_ctx_free(void *vdgbl) 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; @@ -528,36 +600,64 @@ static void rand_delete_thread_state(void *arg) EVP_RAND_CTX_free(rand); } -#ifndef FIPS_MODULE +#if !defined(FIPS_MODULE) || !defined(OPENSSL_NO_FIPS_JITTER) 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; + const char *propq; char *name; + EVP_RAND_CTX *ctx = NULL; +# ifdef OPENSSL_NO_FIPS_JITTER + RAND_GLOBAL *dgbl = rand_get_global(libctx); if (dgbl == NULL) return NULL; - name = dgbl->seed_name != NULL ? dgbl->seed_name : "SEED-SRC"; - rand = EVP_RAND_fetch(libctx, name, dgbl->seed_propq); + propq = dgbl->seed_propq; + name = dgbl->seed_name != NULL ? dgbl->seed_name + : OPENSSL_MSTR(OPENSSL_DEFAULT_SEED_SRC); +# else /* !OPENSSL_NO_FIPS_JITTER */ + name = "JITTER"; + propq = ""; +# endif /* OPENSSL_NO_FIPS_JITTER */ + + rand = EVP_RAND_fetch(libctx, name, propq); if (rand == NULL) { ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); - return NULL; + goto err; } 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; + goto err; } 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; + goto err; } return ctx; + err: + EVP_RAND_CTX_free(ctx); + return NULL; } -#endif +#endif /* !FIPS_MODULE || !OPENSSL_NO_FIPS_JITTER */ + +#ifndef FIPS_MODULE +EVP_RAND_CTX *ossl_rand_get0_seed_noncreating(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->seed; + CRYPTO_THREAD_unlock(dgbl->lock); + return ret; +} +#endif /* !FIPS_MODULE */ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, unsigned int reseed_interval, @@ -566,8 +666,11 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, EVP_RAND *rand; RAND_GLOBAL *dgbl = rand_get_global(libctx); EVP_RAND_CTX *ctx; - OSSL_PARAM params[7], *p = params; + OSSL_PARAM params[9], *p = params; + const OSSL_PARAM *settables; + const char *prov_name; char *name, *cipher; + int use_df = 1; if (dgbl == NULL) return NULL; @@ -577,6 +680,7 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, ERR_raise(ERR_LIB_RAND, RAND_R_UNABLE_TO_FETCH_DRBG); return NULL; } + prov_name = ossl_provider_name(EVP_RAND_get0_provider(rand)); ctx = EVP_RAND_CTX_new(rand, parent); EVP_RAND_free(rand); if (ctx == NULL) { @@ -584,20 +688,26 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, 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) + settables = EVP_RAND_CTX_settable_params(ctx); + if (OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_CIPHER)) { + 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 + && OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_DIGEST)) *p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST, dgbl->rng_digest, 0); + if (prov_name != NULL) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_CORE_PROV_NAME, + (char *)prov_name, 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); + if (OSSL_PARAM_locate_const(settables, OSSL_ALG_PARAM_MAC)) + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_MAC, "HMAC", 0); + if (OSSL_PARAM_locate_const(settables, OSSL_DRBG_PARAM_USE_DF)) + *p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &use_df); *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_RESEED_REQUESTS, &reseed_interval); *p++ = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, @@ -611,14 +721,40 @@ static EVP_RAND_CTX *rand_new_drbg(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent, return ctx; } +#if defined(FIPS_MODULE) +static EVP_RAND_CTX *rand_new_crngt(OSSL_LIB_CTX *libctx, EVP_RAND_CTX *parent) +{ + EVP_RAND *rand; + EVP_RAND_CTX *ctx; + + rand = EVP_RAND_fetch(libctx, "CRNG-TEST", "-fips"); + 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; + } + + 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 /* FIPS_MODULE */ + /* * 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) +static EVP_RAND_CTX *rand_get0_primary(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) { - RAND_GLOBAL *dgbl = rand_get_global(ctx); EVP_RAND_CTX *ret; if (dgbl == NULL) @@ -642,21 +778,28 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx) return ret; } -#ifndef FIPS_MODULE +#if !defined(FIPS_MODULE) || !defined(OPENSSL_NO_FIPS_JITTER) + /* Create a seed source for libcrypto or jitter enabled FIPS provider */ if (dgbl->seed == NULL) { ERR_set_mark(); dgbl->seed = rand_new_seed(ctx); ERR_pop_to_mark(); } -#endif +#endif /* !FIPS_MODULE || !OPENSSL_NO_FIPS_JITTER */ + +#if defined(FIPS_MODULE) + /* The FIPS provider has entropy health tests instead of the primary */ + ret = rand_new_crngt(ctx, dgbl->seed); +#else /* FIPS_MODULE */ + ret = rand_new_drbg(ctx, dgbl->seed, PRIMARY_RESEED_INTERVAL, + PRIMARY_RESEED_TIME_INTERVAL); +#endif /* FIPS_MODULE */ - 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. - */ + * The primary DRBG may be shared between multiple threads so we must + * enable locking. + */ + dgbl->primary = ret; if (ret != NULL && !EVP_RAND_enable_locking(ret)) { ERR_raise(ERR_LIB_EVP, EVP_R_UNABLE_TO_ENABLE_LOCKING); EVP_RAND_CTX_free(ret); @@ -668,12 +811,19 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx) } /* - * Get the public random generator. + * Get the primary random generator. * Returns pointer to its EVP_RAND_CTX on success, NULL on failure. + * */ -EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx) +EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx) { RAND_GLOBAL *dgbl = rand_get_global(ctx); + + return dgbl == NULL ? NULL : rand_get0_primary(ctx, dgbl); +} + +static EVP_RAND_CTX *rand_get0_public(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) +{ EVP_RAND_CTX *rand, *primary; if (dgbl == NULL) @@ -681,11 +831,14 @@ EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx) rand = CRYPTO_THREAD_get_local(&dgbl->public); if (rand == NULL) { - primary = RAND_get0_primary(ctx); + primary = rand_get0_primary(ctx, dgbl); if (primary == NULL) return NULL; ctx = ossl_lib_ctx_get_concrete(ctx); + + if (ctx == NULL) + return NULL; /* * If the private is also NULL then this is the first time we've * used this thread. @@ -701,24 +854,30 @@ EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx) } /* - * Get the private random generator. + * Get the public random generator. * Returns pointer to its EVP_RAND_CTX on success, NULL on failure. */ -EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx) +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; + return dgbl == NULL ? NULL : rand_get0_public(ctx, dgbl); +} + +static EVP_RAND_CTX *rand_get0_private(OSSL_LIB_CTX *ctx, RAND_GLOBAL *dgbl) +{ + EVP_RAND_CTX *rand, *primary; rand = CRYPTO_THREAD_get_local(&dgbl->private); if (rand == NULL) { - primary = RAND_get0_primary(ctx); + primary = rand_get0_primary(ctx, dgbl); if (primary == NULL) return NULL; ctx = ossl_lib_ctx_get_concrete(ctx); + + if (ctx == NULL) + return NULL; /* * If the public is also NULL then this is the first time we've * used this thread. @@ -733,6 +892,57 @@ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx) 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); + + return dgbl == NULL ? NULL : rand_get0_private(ctx, dgbl); +} + +#ifdef FIPS_MODULE +EVP_RAND_CTX *ossl_rand_get0_private_noncreating(OSSL_LIB_CTX *ctx) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + + if (dgbl == NULL) + return NULL; + + return CRYPTO_THREAD_get_local(&dgbl->private); +} +#endif + +int RAND_set0_public(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + EVP_RAND_CTX *old; + int r; + + if (dgbl == NULL) + return 0; + old = CRYPTO_THREAD_get_local(&dgbl->public); + if ((r = CRYPTO_THREAD_set_local(&dgbl->public, rand)) > 0) + EVP_RAND_CTX_free(old); + return r; +} + +int RAND_set0_private(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + EVP_RAND_CTX *old; + int r; + + if (dgbl == NULL) + return 0; + old = CRYPTO_THREAD_get_local(&dgbl->private); + if ((r = CRYPTO_THREAD_set_local(&dgbl->private, rand)) > 0) + EVP_RAND_CTX_free(old); + return r; +} + #ifndef FIPS_MODULE static int random_set_string(char **p, const char *s) { @@ -740,10 +950,8 @@ static int random_set_string(char **p, const char *s) if (s != NULL) { d = OPENSSL_strdup(s); - if (d == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (d == NULL) return 0; - } } OPENSSL_free(*p); *p = d; @@ -757,7 +965,8 @@ 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)); + OSSL_LIB_CTX *libctx = NCONF_get0_libctx((CONF *)cnf); + RAND_GLOBAL *dgbl = rand_get_global(libctx); int i, r = 1; OSSL_TRACE1(CONF, "Loading random module: section %s\n", @@ -793,6 +1002,31 @@ static int random_conf_init(CONF_IMODULE *md, const CONF *cnf) } else if (OPENSSL_strcasecmp(cval->name, "seed_properties") == 0) { if (!random_set_string(&dgbl->seed_propq, cval->value)) return 0; + } else if (OPENSSL_strcasecmp(cval->name, "random_provider") == 0) { +# ifndef FIPS_MODULE + OSSL_PROVIDER *prov = ossl_provider_find(libctx, cval->value, 0); + + if (prov != NULL) { + if (!RAND_set1_random_provider(libctx, prov)) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); + OSSL_PROVIDER_unload(prov); + return 0; + } + /* + * We need to release the reference from ossl_provider_find because + * we don't want to keep a reference counted handle to the provider. + * + * The provider unload code checks for the random provider and, + * if present, our reference will be NULLed when it is fully freed. + * The provider load code, conversely, checks the provider name + * and re-hooks our reference if required. This means that a load, + * hook random provider, use, unload, reload, reuse sequence will + * work as expected. + */ + OSSL_PROVIDER_unload(prov); + } else if (!set_random_provider_name(dgbl, cval->value)) + return 0; +# endif } else { ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_UNKNOWN_NAME_IN_RANDOM_SECTION, @@ -839,7 +1073,7 @@ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, if (dgbl == NULL) return 0; - if (dgbl->primary != NULL) { + if (dgbl->seed != NULL) { ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED); return 0; } @@ -847,4 +1081,69 @@ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed, && random_set_string(&dgbl->seed_propq, propq); } -#endif +int RAND_set1_random_provider(OSSL_LIB_CTX *ctx, OSSL_PROVIDER *prov) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + + if (dgbl == NULL) + return 0; + + if (prov == NULL) { + OPENSSL_free(dgbl->random_provider_name); + dgbl->random_provider_name = NULL; + dgbl->random_provider = NULL; + return 1; + } + + if (dgbl->random_provider == prov) + return 1; + + if (!set_random_provider_name(dgbl, OSSL_PROVIDER_get0_name(prov))) + return 0; + + dgbl->random_provider = prov; + return 1; +} + +/* + * When a new provider is loaded, we need to check to see if it is the + * designated randomness provider and register it if it is. + */ +int ossl_rand_check_random_provider_on_load(OSSL_LIB_CTX *ctx, + OSSL_PROVIDER *prov) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + + if (dgbl == NULL) + return 0; + + /* No random provider name specified, or one is installed already */ + if (dgbl->random_provider_name == NULL || dgbl->random_provider != NULL) + return 1; + + /* Does this provider match the name we're using? */ + if (strcmp(dgbl->random_provider_name, OSSL_PROVIDER_get0_name(prov)) != 0) + return 1; + + dgbl->random_provider = prov; + return 1; +} + +/* + * When a provider is being unloaded, if it is the randomness provider, + * we need to deregister it. + */ +int ossl_rand_check_random_provider_on_unload(OSSL_LIB_CTX *ctx, + OSSL_PROVIDER *prov) +{ + RAND_GLOBAL *dgbl = rand_get_global(ctx); + + if (dgbl == NULL) + return 0; + + if (dgbl->random_provider == prov) + dgbl->random_provider = NULL; + return 1; +} + +#endif /* !FIPS_MODULE */ diff --git a/crypto/rand/rand_pool.c b/crypto/rand/rand_pool.c index 55f14be60e63..4f258b87ee4b 100644 --- a/crypto/rand/rand_pool.c +++ b/crypto/rand/rand_pool.c @@ -25,10 +25,8 @@ RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); size_t min_alloc_size = RAND_POOL_MIN_ALLOCATION(secure); - if (pool == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + if (pool == NULL) return NULL; - } pool->min_len = min_len; pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ? @@ -42,10 +40,8 @@ RAND_POOL *ossl_rand_pool_new(int entropy_requested, int secure, else pool->buffer = OPENSSL_zalloc(pool->alloc_len); - if (pool->buffer == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + if (pool->buffer == NULL) goto err; - } pool->entropy_requested = entropy_requested; pool->secure = secure; @@ -67,10 +63,8 @@ RAND_POOL *ossl_rand_pool_attach(const unsigned char *buffer, size_t len, { RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); - if (pool == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + if (pool == NULL) return NULL; - } /* * The const needs to be cast away, but attached buffers will not be @@ -222,10 +216,8 @@ static int rand_pool_grow(RAND_POOL *pool, size_t len) p = OPENSSL_secure_zalloc(newlen); else p = OPENSSL_zalloc(newlen); - if (p == NULL) { - ERR_raise(ERR_LIB_RAND, ERR_R_MALLOC_FAILURE); + if (p == NULL) return 0; - } memcpy(p, pool->buffer, pool->len); if (pool->secure) OPENSSL_secure_clear_free(pool->buffer, pool->alloc_len); @@ -257,7 +249,11 @@ size_t ossl_rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor) if (bytes_needed > pool->max_len - pool->len) { /* not enough space left */ - ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW); + ERR_raise_data(ERR_LIB_RAND, RAND_R_RANDOM_POOL_OVERFLOW, + "entropy_factor=%u, entropy_needed=%zu, bytes_needed=%zu," + "pool->max_len=%zu, pool->len=%zu", + entropy_factor, entropy_needed, bytes_needed, + pool->max_len, pool->len); return 0; } @@ -410,3 +406,42 @@ int ossl_rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) return 1; } + +/** + * @brief Mix in the additional input into an existing entropy in the pool + * + * @param pool A RAND_POOL to mix the additional input in + * @param adin A buffer with the additional input + * @param adin_len A length of the additional input + * + * @return 1 if there is any existing entropy in the pool so the additional input + * can be mixed in, 0 otherwise. + */ + +int ossl_rand_pool_adin_mix_in(RAND_POOL *pool, const unsigned char *adin, + size_t adin_len) +{ + if (adin == NULL || adin_len == 0) + /* Nothing to mix in -> success */ + return 1; + + if (pool->buffer == NULL) { + ERR_raise(ERR_LIB_RAND, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (pool->len == 0) { + ERR_raise(ERR_LIB_RAND, RAND_R_RANDOM_POOL_IS_EMPTY); + return 0; + } + + if (adin != NULL && adin_len > 0) { + size_t i; + + /* xor the additional data into the pool */ + for (i = 0; i < adin_len; ++i) + pool->buffer[i % pool->len] ^= adin[i]; + } + + return 1; +} diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c index b4854a4c4eab..9337b36dc8b9 100644 --- a/crypto/rand/randfile.c +++ b/crypto/rand/randfile.c @@ -16,7 +16,7 @@ # include #endif -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include @@ -145,14 +145,14 @@ int RAND_load_file(const char *file, long bytes) # pragma environment restore #endif - for ( ; ; ) { + for (;;) { if (bytes > 0) n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE; else n = RAND_LOAD_BUF_SIZE; i = fread(buf, 1, n, in); #ifdef EINTR - if (ferror(in) && errno == EINTR){ + if (ferror(in) && errno == EINTR) { clearerr(in); if (i == 0) continue; diff --git a/crypto/rc2/rc2_local.h b/crypto/rc2/rc2_local.h index 8faa7b840a54..f9ca888a638c 100644 --- a/crypto/rc2/rc2_local.h +++ b/crypto/rc2/rc2_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -20,19 +20,19 @@ l1=l2=0; \ switch (n) { \ case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((unsigned long)(*(--(c)))); \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((unsigned long)(*(--(c)))); \ } \ } @@ -49,86 +49,20 @@ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } -/* NOTE - c is not incremented as per n2l */ -#define n2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ - case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ - case 6: l2|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ - case 5: l2|=((unsigned long)(*(--(c))))<<24; \ - /* fall thru */ \ - case 4: l1 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ - case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ - case 2: l1|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ - case 1: l1|=((unsigned long)(*(--(c))))<<24; \ - } \ - } - -/* NOTE - c is not incremented as per l2n */ -#define l2nn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ - case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - /* fall thru */ \ - case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - /* fall thru */ \ - case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - /* fall thru */ \ - case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ - /* fall thru */ \ - case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - /* fall thru */ \ - case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - /* fall thru */ \ - case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - } \ - } - -#undef n2l -#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ - l|=((unsigned long)(*((c)++)))<<16L, \ - l|=((unsigned long)(*((c)++)))<< 8L, \ - l|=((unsigned long)(*((c)++)))) - -#undef l2n -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - -#define C_RC2(n) \ - t=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff; \ - x0=(t<<1)|(t>>15); \ - t=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff; \ - x1=(t<<2)|(t>>14); \ - t=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff; \ - x2=(t<<3)|(t>>13); \ - t=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff; \ - x3=(t<<5)|(t>>11); diff --git a/crypto/rc4/asm/rc4-x86_64.pl b/crypto/rc4/asm/rc4-x86_64.pl index 5a903f5739e1..83a1d13635fd 100755 --- a/crypto/rc4/asm/rc4-x86_64.pl +++ b/crypto/rc4/asm/rc4-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 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 @@ -23,7 +23,7 @@ # Presumably it has everything to do with AMD cache architecture and # RAW or whatever penalties. Once again! The module *requires* config # line *without* RC4_CHAR! As for coding "secret," I bet on partial -# register arithmetics. For example instead of 'inc %r8; and $255,%r8' +# register arithmetic. For example instead of 'inc %r8; and $255,%r8' # I simply 'inc %r8b'. Even though optimization manual discourages # to operate on partial registers, it turned out to be the best bet. # At least for AMD... How IA32E would perform remains to be seen... diff --git a/crypto/rc5/rc5_local.h b/crypto/rc5/rc5_local.h index df7df608dc07..4ba8745ca5bb 100644 --- a/crypto/rc5/rc5_local.h +++ b/crypto/rc5/rc5_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -22,19 +22,19 @@ l1=l2=0; \ switch (n) { \ case 8: l2 =((unsigned long)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 7: l2|=((unsigned long)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 5: l2|=((unsigned long)(*(--(c)))); \ - /* fall thru */ \ + /* fall through */ \ case 4: l1 =((unsigned long)(*(--(c))))<<24L; \ - /* fall thru */ \ + /* fall through */ \ case 3: l1|=((unsigned long)(*(--(c))))<<16L; \ - /* fall thru */ \ + /* fall through */ \ case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \ - /* fall thru */ \ + /* fall through */ \ case 1: l1|=((unsigned long)(*(--(c)))); \ } \ } @@ -51,80 +51,23 @@ c+=n; \ switch (n) { \ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \ - /* fall thru */ \ + /* fall through */ \ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ } \ } -/* NOTE - c is not incremented as per n2l */ -#define n2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ - case 7: l2|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ - case 6: l2|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ - case 5: l2|=((unsigned long)(*(--(c))))<<24; \ - /* fall thru */ \ - case 4: l1 =((unsigned long)(*(--(c)))) ; \ - /* fall thru */ \ - case 3: l1|=((unsigned long)(*(--(c))))<< 8; \ - /* fall thru */ \ - case 2: l1|=((unsigned long)(*(--(c))))<<16; \ - /* fall thru */ \ - case 1: l1|=((unsigned long)(*(--(c))))<<24; \ - } \ - } - -/* NOTE - c is not incremented as per l2n */ -#define l2nn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \ - /* fall thru */ \ - case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - /* fall thru */ \ - case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - /* fall thru */ \ - case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - /* fall thru */ \ - case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \ - /* fall thru */ \ - case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - /* fall thru */ \ - case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - /* fall thru */ \ - case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - } \ - } - -#undef n2l -#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \ - l|=((unsigned long)(*((c)++)))<<16L, \ - l|=((unsigned long)(*((c)++)))<< 8L, \ - l|=((unsigned long)(*((c)++)))) - -#undef l2n -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16L)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) - #if (defined(OPENSSL_SYS_WIN32) && defined(_MSC_VER)) # define ROTATE_l32(a,n) _lrotl(a,n) # define ROTATE_r32(a,n) _lrotr(a,n) @@ -158,12 +101,8 @@ #define RC5_32_MASK 0xffffffffL -#define RC5_16_P 0xB7E1 -#define RC5_16_Q 0x9E37 #define RC5_32_P 0xB7E15163L #define RC5_32_Q 0x9E3779B9L -#define RC5_64_P 0xB7E151628AED2A6BLL -#define RC5_64_Q 0x9E3779B97F4A7C15LL #define E_RC5_32(a,b,s,n) \ a^=b; \ diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 07734077e322..42b03fb2fd62 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -154,14 +154,14 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk); if (rklen <= 0) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_ASN1_LIB); ASN1_STRING_free(str); return 0; } if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0, strtype, str, rk, rklen)) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_ASN1_LIB); ASN1_STRING_free(str); OPENSSL_clear_free(rk, rklen); return 0; @@ -220,7 +220,7 @@ static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss, return 0; } } else if (pss == NULL) { - if (BIO_puts(bp,"(INVALID PSS PARAMETERS)\n") <= 0) + if (BIO_puts(bp, "(INVALID PSS PARAMETERS)\n") <= 0) return 0; return 1; } @@ -453,21 +453,39 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) const EVP_MD *sigmd, *mgf1md; EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx); int saltlen; + int saltlenMax = -1; + int md_size; if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0) return NULL; + md_size = EVP_MD_get_size(sigmd); + if (md_size <= 0) + return NULL; if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0) return NULL; if (EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen) <= 0) return NULL; - if (saltlen == -1) { - saltlen = EVP_MD_get_size(sigmd); - } else if (saltlen == -2 || saltlen == -3) { - saltlen = EVP_PKEY_get_size(pk) - EVP_MD_get_size(sigmd) - 2; + if (saltlen == RSA_PSS_SALTLEN_DIGEST) { + saltlen = md_size; + } else if (saltlen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { + /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", + * subsection 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in + * bytes) of the salt (sLen) shall satisfy 0 <= sLen <= hLen, where + * hLen is the length of the hash function output block (in bytes)." + * + * Provide a way to use at most the digest length, so that the default + * does not violate FIPS 186-4. */ + saltlen = RSA_PSS_SALTLEN_MAX; + saltlenMax = md_size; + } + if (saltlen == RSA_PSS_SALTLEN_MAX || saltlen == RSA_PSS_SALTLEN_AUTO) { + saltlen = EVP_PKEY_get_size(pk) - md_size - 2; if ((EVP_PKEY_get_bits(pk) & 0x7) == 1) saltlen--; if (saltlen < 0) return NULL; + if (saltlenMax >= 0 && saltlen > saltlenMax) + saltlen = saltlenMax; } return ossl_rsa_pss_params_create(sigmd, mgf1md, saltlen); @@ -705,7 +723,7 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg, const ASN1_STRING *sig) { int rv = 0; - int mdnid, saltlen; + int mdnid, saltlen, md_size; uint32_t flags; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; @@ -718,6 +736,9 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg, pss = ossl_rsa_pss_decode(sigalg); if (!ossl_rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) goto err; + md_size = EVP_MD_get_size(md); + if (md_size <= 0) + goto err; mdnid = EVP_MD_get_type(md); /* * For TLS need SHA256, SHA384 or SHA512, digest and MGF1 digest must @@ -725,12 +746,12 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg, */ if ((mdnid == NID_sha256 || mdnid == NID_sha384 || mdnid == NID_sha512) && mdnid == EVP_MD_get_type(mgf1md) - && saltlen == EVP_MD_get_size(md)) + && saltlen == md_size) flags = X509_SIG_INFO_TLS; else flags = 0; /* Note: security bits half number of digest bits */ - secbits = EVP_MD_get_size(md) * 4; + secbits = md_size * 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 @@ -836,7 +857,7 @@ static int rsa_int_import_from(const OSSL_PARAM params[], void *vpctx, int ok = 0; if (rsa == NULL) { - ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_DH, ERR_R_RSA_LIB); return 0; } diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c index f9d1cb361d77..d6864dc237cd 100644 --- a/crypto/rsa/rsa_backend.c +++ b/crypto/rsa/rsa_backend.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,7 +44,7 @@ static int collect_numbers(STACK_OF(BIGNUM) *numbers, if (numbers == NULL) return 0; - for (i = 0; names[i] != NULL; i++){ + for (i = 0; names[i] != NULL; i++) { p = OSSL_PARAM_locate_const(params, names[i]); if (p != NULL) { BIGNUM *tmp = NULL; @@ -64,22 +64,56 @@ static int collect_numbers(STACK_OF(BIGNUM) *numbers, int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) { const OSSL_PARAM *param_n, *param_e, *param_d = NULL; - BIGNUM *n = NULL, *e = NULL, *d = NULL; + const OSSL_PARAM *param_p, *param_q = NULL; + const OSSL_PARAM *param_derive = NULL; + BIGNUM *p = NULL, *q = NULL, *n = NULL, *e = NULL, *d = NULL; STACK_OF(BIGNUM) *factors = NULL, *exps = NULL, *coeffs = NULL; int is_private = 0; + int derive_from_pq = 0; + BN_CTX *ctx = NULL; if (rsa == NULL) return 0; param_n = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N); param_e = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E); - if (include_private) - param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); - if ((param_n != NULL && !OSSL_PARAM_get_BN(param_n, &n)) - || (param_e != NULL && !OSSL_PARAM_get_BN(param_e, &e)) - || (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d))) + if ((param_n == NULL || !OSSL_PARAM_get_BN(param_n, &n)) + || (param_e == NULL || !OSSL_PARAM_get_BN(param_e, &e))) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); goto err; + } + + if (include_private) { + + param_derive = OSSL_PARAM_locate_const(params, + OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ); + if ((param_derive != NULL) + && !OSSL_PARAM_get_int(param_derive, &derive_from_pq)) + goto err; + + param_d = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D); + if (param_d != NULL && !OSSL_PARAM_get_BN(param_d, &d)) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + if (derive_from_pq) { + ctx = BN_CTX_new_ex(rsa->libctx); + if (ctx == NULL) + goto err; + + /* we need at minimum p, q */ + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR1); + param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_FACTOR2); + if ((param_p == NULL || !OSSL_PARAM_get_BN(param_p, &p)) + || (param_q == NULL || !OSSL_PARAM_get_BN(param_q, &q))) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + } + } is_private = (d != NULL); @@ -96,25 +130,127 @@ int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private) ossl_rsa_mp_coeff_names)) goto err; - /* It's ok if this private key just has n, e and d */ + if (derive_from_pq && sk_BIGNUM_num(exps) == 0 + && sk_BIGNUM_num(coeffs) == 0) { + /* + * If we want to use crt to derive our exponents/coefficients, we + * need to have at least 2 factors + */ + if (sk_BIGNUM_num(factors) < 2) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + /* + * if we have more than two factors, n and d must also have + * been provided + */ + if (sk_BIGNUM_num(factors) > 2 + && (param_n == NULL || param_d == NULL)) { + ERR_raise(ERR_LIB_RSA, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + /* build our exponents and coefficients here */ + if (sk_BIGNUM_num(factors) == 2) { + /* for 2 factors we can use the sp800 functions to do this */ + if (!RSA_set0_factors(rsa, sk_BIGNUM_value(factors, 0), + sk_BIGNUM_value(factors, 1))) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + /* + * once consumed by RSA_set0_factors, pop those off the stack + * so we don't free them below + */ + sk_BIGNUM_pop(factors); + sk_BIGNUM_pop(factors); + + /* + * Note: Because we only have 2 factors here, there will be no + * additional pinfo fields to hold additional factors, and + * since we set our key and 2 factors above we can skip + * the call to ossl_rsa_set0_all_params + */ + if (!ossl_rsa_sp800_56b_derive_params_from_pq(rsa, + RSA_bits(rsa), + NULL, ctx)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + } else { +#ifndef FIPS_MODULE + /* + * in the multiprime case we have to generate exps/coeffs here + * for each additional prime + */ + if (!ossl_rsa_multiprime_derive(rsa, RSA_bits(rsa), + sk_BIGNUM_num(factors), + rsa->e, factors, exps, + coeffs)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Now we should have all our factors, exponents and + * coefficients + */ + if (!ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + +#else + /* multiprime case is disallowed in FIPS mode, raise an error */ + ERR_raise(ERR_LIB_RSA, ERR_R_UNSUPPORTED); + goto err; +#endif + } + + } else { + /* + * It's ok if this private key just has n, e and d + * but only if we're not using derive_from_pq + */ + if (sk_BIGNUM_num(factors) != 0 + && !ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) + goto err; + } + /* sanity check to ensure we used everything in our stacks */ if (sk_BIGNUM_num(factors) != 0 - && !ossl_rsa_set0_all_params(rsa, factors, exps, coeffs)) + || sk_BIGNUM_num(exps) != 0 + || sk_BIGNUM_num(coeffs) != 0) { + ERR_raise_data(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR, + "There are %d, %d, %d elements left on our factors, exps, coeffs stacks\n", + sk_BIGNUM_num(factors), sk_BIGNUM_num(exps), + sk_BIGNUM_num(coeffs)); goto err; + } } + if (!ossl_rsa_check_factors(rsa)) { + ERR_raise_data(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR, + "RSA factors/exponents are too big for for n-modulus\n"); + goto err; + } + BN_clear_free(p); + BN_clear_free(q); sk_BIGNUM_free(factors); sk_BIGNUM_free(exps); sk_BIGNUM_free(coeffs); + BN_CTX_free(ctx); return 1; err: BN_free(n); BN_free(e); BN_free(d); - sk_BIGNUM_pop_free(factors, BN_free); - sk_BIGNUM_pop_free(exps, BN_free); - sk_BIGNUM_pop_free(coeffs, BN_free); + sk_BIGNUM_pop_free(factors, BN_clear_free); + sk_BIGNUM_pop_free(exps, BN_clear_free); + sk_BIGNUM_pop_free(coeffs, BN_clear_free); + BN_CTX_free(ctx); return 0; } @@ -152,7 +288,7 @@ int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[], || !ossl_param_build_set_multi_key_bn(bld, params, ossl_rsa_mp_coeff_names, coeffs)) - goto err; + goto err; } #if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) @@ -389,10 +525,8 @@ RSA *ossl_rsa_dup(const RSA *rsa, int selection) const RSA_PRIME_INFO *pinfo = NULL; RSA_PRIME_INFO *duppinfo = NULL; - if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if ((duppinfo = OPENSSL_zalloc(sizeof(*duppinfo))) == NULL) goto err; - } /* push first so cleanup in error case works */ (void)sk_RSA_PRIME_INFO_push(dupkey->prime_infos, duppinfo); @@ -514,7 +648,7 @@ int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss, if (pss->trailerField) *ptrailerField = ASN1_INTEGER_get(pss->trailerField); else - *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params);; + *ptrailerField = ossl_rsa_pss_params_30_trailerfield(&pss_params); return 1; } diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c index c2549188f556..0df254676adf 100644 --- a/crypto/rsa/rsa_chk.c +++ b/crypto/rsa/rsa_chk.c @@ -51,7 +51,7 @@ static int rsa_validate_keypair_multiprime(const RSA *key, BN_GENCB *cb) if (i == NULL || j == NULL || k == NULL || l == NULL || m == NULL || ctx == NULL) { ret = -1; - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } diff --git a/crypto/rsa/rsa_crpt.c b/crypto/rsa/rsa_crpt.c index 6bc6aafcc893..21c922e60968 100644 --- a/crypto/rsa/rsa_crpt.c +++ b/crypto/rsa/rsa_crpt.c @@ -129,7 +129,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) BN_CTX_start(ctx); e = BN_CTX_get(ctx); if (e == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } @@ -147,7 +147,7 @@ BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) BIGNUM *n = BN_new(); if (n == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME); diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index e0d139d3121c..f76bb7748369 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -71,38 +71,242 @@ int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes, return rsa_keygen(rsa->libctx, rsa, bits, primes, e_value, cb, 0); } +DEFINE_STACK_OF(BIGNUM) + +/* + * Given input values, q, p, n, d and e, derive the exponents + * and coefficients for each prime in this key, placing the result + * on their respective exps and coeffs stacks + */ #ifndef FIPS_MODULE +int ossl_rsa_multiprime_derive(RSA *rsa, int bits, int primes, + BIGNUM *e_value, + STACK_OF(BIGNUM) *factors, + STACK_OF(BIGNUM) *exps, + STACK_OF(BIGNUM) *coeffs) +{ + STACK_OF(BIGNUM) *pplist = NULL, *pdlist = NULL; + BIGNUM *factor = NULL, *newpp = NULL, *newpd = NULL; + BIGNUM *dval = NULL, *newexp = NULL, *newcoeff = NULL; + BIGNUM *p = NULL, *q = NULL; + BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL; + BN_CTX *ctx = NULL; + BIGNUM *tmp = NULL; + int i; + int ret = 0; + + ctx = BN_CTX_new_ex(rsa->libctx); + if (ctx == NULL) + goto err; + + BN_CTX_start(ctx); + + pplist = sk_BIGNUM_new_null(); + if (pplist == NULL) + goto err; + + pdlist = sk_BIGNUM_new_null(); + if (pdlist == NULL) + goto err; + + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + + if (r2 == NULL) + goto err; + + BN_set_flags(r0, BN_FLG_CONSTTIME); + BN_set_flags(r1, BN_FLG_CONSTTIME); + BN_set_flags(r2, BN_FLG_CONSTTIME); + + if (BN_copy(r1, rsa->n) == NULL) + goto err; + + p = sk_BIGNUM_value(factors, 0); + q = sk_BIGNUM_value(factors, 1); + + /* Build list of partial products of primes */ + for (i = 0; i < sk_BIGNUM_num(factors); i++) { + switch (i) { + case 0: + /* our first prime, p */ + if (!BN_sub(r2, p, BN_value_one())) + goto err; + BN_set_flags(r2, BN_FLG_CONSTTIME); + if (BN_mod_inverse(r1, r2, rsa->e, ctx) == NULL) + goto err; + break; + case 1: + /* second prime q */ + if (!BN_mul(r1, p, q, ctx)) + goto err; + tmp = BN_dup(r1); + if (tmp == NULL) + goto err; + if (!sk_BIGNUM_insert(pplist, tmp, sk_BIGNUM_num(pplist))) + goto err; + tmp = NULL; + break; + default: + factor = sk_BIGNUM_value(factors, i); + /* all other primes */ + if (!BN_mul(r1, r1, factor, ctx)) + goto err; + tmp = BN_dup(r1); + if (tmp == NULL) + goto err; + if (!sk_BIGNUM_insert(pplist, tmp, sk_BIGNUM_num(pplist))) + goto err; + tmp = NULL; + break; + } + } + + /* build list of relative d values */ + /* p -1 */ + if (!BN_sub(r1, p, BN_value_one())) + goto err; + if (!BN_sub(r2, q, BN_value_one())) + goto err; + if (!BN_mul(r0, r1, r2, ctx)) + goto err; + for (i = 2; i < sk_BIGNUM_num(factors); i++) { + factor = sk_BIGNUM_value(factors, i); + dval = BN_new(); + if (dval == NULL) + goto err; + BN_set_flags(dval, BN_FLG_CONSTTIME); + if (!BN_sub(dval, factor, BN_value_one())) + goto err; + if (!BN_mul(r0, r0, dval, ctx)) + goto err; + if (!sk_BIGNUM_insert(pdlist, dval, sk_BIGNUM_num(pdlist))) + goto err; + dval = NULL; + } + + /* Calculate dmp1, dmq1 and additional exponents */ + dmp1 = BN_secure_new(); + if (dmp1 == NULL) + goto err; + dmq1 = BN_secure_new(); + if (dmq1 == NULL) + goto err; + + if (!BN_mod(dmp1, rsa->d, r1, ctx)) + goto err; + if (!sk_BIGNUM_insert(exps, dmp1, sk_BIGNUM_num(exps))) + goto err; + dmp1 = NULL; + + if (!BN_mod(dmq1, rsa->d, r2, ctx)) + goto err; + if (!sk_BIGNUM_insert(exps, dmq1, sk_BIGNUM_num(exps))) + goto err; + dmq1 = NULL; + + for (i = 2; i < sk_BIGNUM_num(factors); i++) { + newpd = sk_BIGNUM_value(pdlist, i - 2); + newexp = BN_new(); + if (newexp == NULL) + goto err; + if (!BN_mod(newexp, rsa->d, newpd, ctx)) + goto err; + if (!sk_BIGNUM_insert(exps, newexp, sk_BIGNUM_num(exps))) + goto err; + newexp = NULL; + } + + /* Calculate iqmp and additional coefficients */ + iqmp = BN_new(); + if (iqmp == NULL) + goto err; + + if (BN_mod_inverse(iqmp, sk_BIGNUM_value(factors, 1), + sk_BIGNUM_value(factors, 0), ctx) == NULL) + goto err; + if (!sk_BIGNUM_insert(coeffs, iqmp, sk_BIGNUM_num(coeffs))) + goto err; + iqmp = NULL; + + for (i = 2; i < sk_BIGNUM_num(factors); i++) { + newpp = sk_BIGNUM_value(pplist, i - 2); + newcoeff = BN_new(); + if (newcoeff == NULL) + goto err; + if (BN_mod_inverse(newcoeff, newpp, sk_BIGNUM_value(factors, i), + ctx) == NULL) + goto err; + if (!sk_BIGNUM_insert(coeffs, newcoeff, sk_BIGNUM_num(coeffs))) + goto err; + newcoeff = NULL; + } + + ret = 1; + err: + BN_free(newcoeff); + BN_free(newexp); + BN_free(dval); + BN_free(tmp); + sk_BIGNUM_pop_free(pplist, BN_free); + sk_BIGNUM_pop_free(pdlist, BN_free); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + BN_clear_free(dmp1); + BN_clear_free(dmq1); + BN_clear_free(iqmp); + return ret; +} + static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value, BN_GENCB *cb) { - BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime; + BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *tmp2, *prime; int n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0; int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0; RSA_PRIME_INFO *pinfo = NULL; STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL; + STACK_OF(BIGNUM) *factors = NULL; + STACK_OF(BIGNUM) *exps = NULL; + STACK_OF(BIGNUM) *coeffs = NULL; BN_CTX *ctx = NULL; BN_ULONG bitst = 0; unsigned long error = 0; int ok = -1; if (bits < RSA_MIN_MODULUS_BITS) { - ok = 0; /* we set our own err */ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL); - goto err; + return 0; + } + if (e_value == NULL) { + ERR_raise(ERR_LIB_RSA, RSA_R_BAD_E_VALUE); + return 0; } - /* A bad value for e can cause infinite loops */ - if (e_value != NULL && !ossl_rsa_check_public_exponent(e_value)) { + if (!ossl_rsa_check_public_exponent(e_value)) { ERR_raise(ERR_LIB_RSA, RSA_R_PUB_EXPONENT_OUT_OF_RANGE); return 0; } if (primes < RSA_DEFAULT_PRIME_NUM || primes > ossl_rsa_multip_cap(bits)) { - ok = 0; /* we set our own err */ ERR_raise(ERR_LIB_RSA, RSA_R_KEY_PRIME_NUM_INVALID); - goto err; + return 0; } + factors = sk_BIGNUM_new_null(); + if (factors == NULL) + return 0; + + exps = sk_BIGNUM_new_null(); + if (exps == NULL) + goto err; + + coeffs = sk_BIGNUM_new_null(); + if (coeffs == NULL) + goto err; + ctx = BN_CTX_new_ex(rsa->libctx); if (ctx == NULL) goto err; @@ -136,15 +340,6 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL)) goto err; BN_set_flags(rsa->q, BN_FLG_CONSTTIME); - if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL)) - goto err; - BN_set_flags(rsa->dmp1, BN_FLG_CONSTTIME); - if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL)) - goto err; - BN_set_flags(rsa->dmq1, BN_FLG_CONSTTIME); - if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL)) - goto err; - BN_set_flags(rsa->iqmp, BN_FLG_CONSTTIME); /* initialize multi-prime components */ if (primes > RSA_DEFAULT_PRIME_NUM) { @@ -219,7 +414,7 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, ERR_set_mark(); BN_set_flags(r2, BN_FLG_CONSTTIME); if (BN_mod_inverse(r1, r2, rsa->e, ctx) != NULL) { - /* GCD == 1 since inverse exists */ + /* GCD == 1 since inverse exists */ break; } error = ERR_peek_last_error(); @@ -249,8 +444,14 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, /* i == 0, do nothing */ if (!BN_GENCB_call(cb, 3, i)) goto err; + tmp = BN_dup(prime); + if (tmp == NULL) + goto err; + if (!sk_BIGNUM_insert(factors, tmp, sk_BIGNUM_num(factors))) + goto err; continue; } + /* * if |r1|, product of factors so far, is not as long as expected * (by checking the first 4 bits are less than 0x9 or greater than @@ -297,6 +498,10 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, */ i = -1; bitse = 0; + sk_BIGNUM_pop_free(factors, BN_clear_free); + factors = sk_BIGNUM_new_null(); + if (factors == NULL) + goto err; continue; } retries++; @@ -309,12 +514,20 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, goto err; if (!BN_GENCB_call(cb, 3, i)) goto err; + tmp = BN_dup(prime); + if (tmp == NULL) + goto err; + if (!sk_BIGNUM_insert(factors, tmp, sk_BIGNUM_num(factors))) + goto err; } if (BN_cmp(rsa->p, rsa->q) < 0) { tmp = rsa->p; rsa->p = rsa->q; rsa->q = tmp; + /* mirror this in our factor stack */ + if (!sk_BIGNUM_insert(factors, sk_BIGNUM_delete(factors, 0), 1)) + goto err; } /* calculate d */ @@ -338,79 +551,51 @@ static int rsa_multiprime_keygen(RSA *rsa, int bits, int primes, goto err; } - { - BIGNUM *pr0 = BN_new(); - if (pr0 == NULL) - goto err; - - BN_with_flags(pr0, r0, BN_FLG_CONSTTIME); - if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) { - BN_free(pr0); - goto err; /* d */ - } - /* We MUST free pr0 before any further use of r0 */ - BN_free(pr0); + BN_set_flags(r0, BN_FLG_CONSTTIME); + if (BN_mod_inverse(rsa->d, rsa->e, r0, ctx) == NULL) { + goto err; /* d */ } - { - BIGNUM *d = BN_new(); + /* derive any missing exponents and coefficients */ + if (!ossl_rsa_multiprime_derive(rsa, bits, primes, e_value, + factors, exps, coeffs)) + goto err; - if (d == NULL) + /* + * first 2 factors/exps are already tracked in p/q/dmq1/dmp1 + * and the first coeff is in iqmp, so pop those off the stack + * Note, the first 2 factors/exponents are already tracked by p and q + * assign dmp1/dmq1 and iqmp + * the remaining pinfo values are separately allocated, so copy and delete + * those + */ + BN_clear_free(sk_BIGNUM_delete(factors, 0)); + BN_clear_free(sk_BIGNUM_delete(factors, 0)); + rsa->dmp1 = sk_BIGNUM_delete(exps, 0); + rsa->dmq1 = sk_BIGNUM_delete(exps, 0); + rsa->iqmp = sk_BIGNUM_delete(coeffs, 0); + for (i = 2; i < primes; i++) { + pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); + tmp = sk_BIGNUM_delete(factors, 0); + BN_copy(pinfo->r, tmp); + BN_clear_free(tmp); + tmp = sk_BIGNUM_delete(exps, 0); + tmp2 = BN_copy(pinfo->d, tmp); + BN_clear_free(tmp); + if (tmp2 == NULL) goto err; - - BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); - - /* calculate d mod (p-1) and d mod (q - 1) */ - if (!BN_mod(rsa->dmp1, d, r1, ctx) - || !BN_mod(rsa->dmq1, d, r2, ctx)) { - BN_free(d); + tmp = sk_BIGNUM_delete(coeffs, 0); + tmp2 = BN_copy(pinfo->t, tmp); + BN_clear_free(tmp); + if (tmp2 == NULL) goto err; - } - - /* calculate CRT exponents */ - for (i = 2; i < primes; i++) { - pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); - /* pinfo->d == r_i - 1 */ - if (!BN_mod(pinfo->d, d, pinfo->d, ctx)) { - BN_free(d); - goto err; - } - } - - /* We MUST free d before any further use of rsa->d */ - BN_free(d); } - - { - BIGNUM *p = BN_new(); - - if (p == NULL) - goto err; - BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); - - /* calculate inverse of q mod p */ - if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) { - BN_free(p); - goto err; - } - - /* calculate CRT coefficient for other primes */ - for (i = 2; i < primes; i++) { - pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2); - BN_with_flags(p, pinfo->r, BN_FLG_CONSTTIME); - if (!BN_mod_inverse(pinfo->t, pinfo->pp, p, ctx)) { - BN_free(p); - goto err; - } - } - - /* We MUST free p before any further use of rsa->p */ - BN_free(p); - } - ok = 1; err: + sk_BIGNUM_free(factors); + sk_BIGNUM_free(exps); + sk_BIGNUM_free(coeffs); if (ok == -1) { ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); ok = 0; @@ -469,47 +654,69 @@ static int rsa_keygen(OSSL_LIB_CTX *libctx, RSA *rsa, int bits, int primes, } /* - * For RSA key generation it is not known whether the key pair will be used - * for key transport or signatures. FIPS 140-2 IG 9.9 states that in this case - * either a signature verification OR an encryption operation may be used to - * perform the pairwise consistency check. The simpler encrypt/decrypt operation - * has been chosen for this case. + * AS10.35 (and its VEs/TEs) of the FIPS 140-3 standard requires a PCT for every + * generated key pair. There are 3 options: + * 1) If the key pair is to be used for key transport (asymmetric cipher), the + * PCT consists of encrypting a plaintext, verifying that the result + * (ciphertext) is not equal to the plaintext, decrypting the ciphertext, and + * verifying that the result is equal to the plaintext. + * 2) If the key pair is to be used for digital signatures, the PCT consists of + * computing and verifying a signature. + * 3) If the key pair is to be used for key agreement, the exact PCT is defined + * in the applicable standards. For RSA-based schemes, this is defined in + * SP 800-56Br2 (Section 6.4.1.1) as: + * "The owner shall perform a pair-wise consistency test by verifying that m + * = (m^e)^d mod n for some integer m satisfying 1 < m < (n - 1)." + * + * OpenSSL implements all three use cases: RSA-OAEP for key transport, + * RSA signatures with PKCS#1 v1.5 or PSS padding, and KAS-IFC-SSC (KAS1/KAS2) + * using RSASVE. + * + * According to FIPS 140-3 IG 10.3.A, if at the time when the PCT is performed + * the keys' intended usage is not known, then any of the three PCTs described + * in AS10.35 shall be performed on this key pair. + * + * Because of this allowance from the IG, the simplest option is 3, i.e. + * RSA_public_encrypt() and RSA_private_decrypt() with RSA_NO_PADDING. */ static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg) { int ret = 0; + unsigned int plaintxt_len; + unsigned char *plaintxt = NULL; unsigned int ciphertxt_len; unsigned char *ciphertxt = NULL; - const unsigned char plaintxt[16] = {0}; unsigned char *decoded = NULL; unsigned int decoded_len; - unsigned int plaintxt_len = (unsigned int)sizeof(plaintxt_len); - int padding = RSA_PKCS1_PADDING; + int padding = RSA_NO_PADDING; OSSL_SELF_TEST *st = NULL; st = OSSL_SELF_TEST_new(cb, cbarg); if (st == NULL) goto err; OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, - OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1); + OSSL_SELF_TEST_DESC_PCT_RSA); - ciphertxt_len = RSA_size(rsa); /* - * RSA_private_encrypt() and RSA_private_decrypt() requires the 'to' - * parameter to be a maximum of RSA_size() - allocate space for both. + * For RSA_NO_PADDING, RSA_public_encrypt() and RSA_private_decrypt() + * require the 'to' and 'from' parameters to have equal length and a + * maximum of RSA_size() - allocate space for plaintxt, ciphertxt, and + * decoded. */ - ciphertxt = OPENSSL_zalloc(ciphertxt_len * 2); - if (ciphertxt == NULL) + plaintxt_len = RSA_size(rsa); + plaintxt = OPENSSL_zalloc(plaintxt_len * 3); + if (plaintxt == NULL) goto err; - decoded = ciphertxt + ciphertxt_len; + ciphertxt = plaintxt + plaintxt_len; + decoded = ciphertxt + plaintxt_len; + + /* SP 800-56Br2 Section 6.4.1.1 requires that plaintext is greater than 1 */ + plaintxt[plaintxt_len - 1] = 2; ciphertxt_len = RSA_public_encrypt(plaintxt_len, plaintxt, ciphertxt, rsa, padding); if (ciphertxt_len <= 0) goto err; - if (ciphertxt_len == plaintxt_len - && memcmp(ciphertxt, plaintxt, plaintxt_len) == 0) - goto err; OSSL_SELF_TEST_oncorrupt_byte(st, ciphertxt); @@ -523,7 +730,7 @@ static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg) err: OSSL_SELF_TEST_onend(st, ret); OSSL_SELF_TEST_free(st); - OPENSSL_free(ciphertxt); + OPENSSL_free(plaintxt); return ret; } diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index c9c661b1ede9..d9ceb8088005 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -76,15 +76,18 @@ static RSA *rsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx) { RSA *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (ret == NULL) + return NULL; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_CRYPTO_LIB); + OPENSSL_free(ret); return NULL; } - ret->references = 1; - ret->lock = CRYPTO_THREAD_lock_new(); - if (ret->lock == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (!CRYPTO_NEW_REF(&ret->references, 1)) { + CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; } @@ -137,8 +140,8 @@ void RSA_free(RSA *r) if (r == NULL) return; - CRYPTO_DOWN_REF(&r->references, &i, r->lock); - REF_PRINT_COUNT("RSA", r); + CRYPTO_DOWN_REF(&r->references, &i); + REF_PRINT_COUNT("RSA", i, r); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -154,9 +157,15 @@ void RSA_free(RSA *r) #endif CRYPTO_THREAD_lock_free(r->lock); + CRYPTO_FREE_REF(&r->references); +#ifdef OPENSSL_PEDANTIC_ZEROIZATION + BN_clear_free(r->n); + BN_clear_free(r->e); +#else BN_free(r->n); BN_free(r->e); +#endif BN_clear_free(r->d); BN_clear_free(r->p); BN_clear_free(r->q); @@ -181,10 +190,10 @@ int RSA_up_ref(RSA *r) { int i; - if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; - REF_PRINT_COUNT("RSA", r); + REF_PRINT_COUNT("RSA", i, r); REF_ASSERT_ISNT(i < 2); return i > 1 ? 1 : 0; } @@ -740,9 +749,13 @@ int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2) DEFINE_STACK_OF(BIGNUM) -int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, - const STACK_OF(BIGNUM) *exps, - const STACK_OF(BIGNUM) *coeffs) +/* + * Note: This function deletes values from the parameter + * stack values as they are consumed and set in the RSA key. + */ +int ossl_rsa_set0_all_params(RSA *r, STACK_OF(BIGNUM) *primes, + STACK_OF(BIGNUM) *exps, + STACK_OF(BIGNUM) *coeffs) { #ifndef FIPS_MODULE STACK_OF(RSA_PRIME_INFO) *prime_infos, *old_infos = NULL; @@ -753,6 +766,8 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, return 0; pnum = sk_BIGNUM_num(primes); + + /* we need at least 2 primes */ if (pnum < 2) return 0; @@ -760,6 +775,17 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, sk_BIGNUM_value(primes, 1))) return 0; + /* + * if we managed to set everything above, remove those elements from the + * stack + * Note, we do this after the above all to ensure that we have taken + * ownership of all the elements in the RSA key to avoid memory leaks + * we also use delete 0 here as we are grabbing items from the end of the + * stack rather than the start, otherwise we could use pop + */ + sk_BIGNUM_delete(primes, 0); + sk_BIGNUM_delete(primes, 0); + if (pnum == sk_BIGNUM_num(exps) && pnum == sk_BIGNUM_num(coeffs) + 1) { @@ -767,6 +793,11 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, sk_BIGNUM_value(exps, 1), sk_BIGNUM_value(coeffs, 0))) return 0; + + /* as above, once we consume the above params, delete them from the list */ + sk_BIGNUM_delete(exps, 0); + sk_BIGNUM_delete(exps, 0); + sk_BIGNUM_delete(coeffs, 0); } #ifndef FIPS_MODULE @@ -782,19 +813,17 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, return 0; for (i = 2; i < pnum; i++) { - BIGNUM *prime = sk_BIGNUM_value(primes, i); - BIGNUM *exp = sk_BIGNUM_value(exps, i); - BIGNUM *coeff = sk_BIGNUM_value(coeffs, i - 1); + BIGNUM *prime = sk_BIGNUM_pop(primes); + BIGNUM *exp = sk_BIGNUM_pop(exps); + BIGNUM *coeff = sk_BIGNUM_pop(coeffs); RSA_PRIME_INFO *pinfo = NULL; if (!ossl_assert(prime != NULL && exp != NULL && coeff != NULL)) goto err; /* Using ossl_rsa_multip_info_new() is wasteful, so allocate directly */ - if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) goto err; - } pinfo->r = prime; pinfo->d = exp; @@ -877,6 +906,56 @@ int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, return 1; } +#define safe_BN_num_bits(_k_) (((_k_) == NULL) ? 0 : BN_num_bits((_k_))) +int ossl_rsa_check_factors(RSA *r) +{ + int valid = 0; + int n, i, bits; + STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); + + if (factors == NULL || exps == NULL || coeffs == NULL) + goto done; + + /* + * Simple sanity check for RSA key. All RSA key parameters + * must be less-than/equal-to RSA parameter n. + */ + ossl_rsa_get0_all_params(r, factors, exps, coeffs); + n = safe_BN_num_bits(RSA_get0_n(r)); + + if (safe_BN_num_bits(RSA_get0_d(r)) > n) + goto done; + + for (i = 0; i < sk_BIGNUM_const_num(exps); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(exps, i)); + if (bits > n) + goto done; + } + + for (i = 0; i < sk_BIGNUM_const_num(factors); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(factors, i)); + if (bits > n) + goto done; + } + + for (i = 0; i < sk_BIGNUM_const_num(coeffs); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(coeffs, i)); + if (bits > n) + goto done; + } + + valid = 1; + +done: + sk_BIGNUM_const_free(factors); + sk_BIGNUM_const_free(exps); + sk_BIGNUM_const_free(coeffs); + + return valid; +} + #ifndef FIPS_MODULE /* Helpers to set or get diverse hash algorithm names */ static int int_set_rsa_md_name(EVP_PKEY_CTX *ctx, @@ -1127,7 +1206,7 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen) if (ret <= 0) return ret; - /* Ownership is supposed to be transfered to the callee. */ + /* Ownership is supposed to be transferred to the callee. */ OPENSSL_free(label); return 1; } diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h index ea70da05ad78..db9eb2a1dfb2 100644 --- a/crypto/rsa/rsa_local.h +++ b/crypto/rsa/rsa_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -150,6 +150,10 @@ struct rsa_meth_st { /* Macros to test if a pkey or ctx is for a PSS key */ #define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS) #define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) +int ossl_rsa_multiprime_derive(RSA *rsa, int bits, int primes, + BIGNUM *e_value, + STACK_OF(BIGNUM) *factors, STACK_OF(BIGNUM) *exps, + STACK_OF(BIGNUM) *coeffs); RSA_PSS_PARAMS *ossl_rsa_pss_params_create(const EVP_MD *sigmd, const EVP_MD *mgf1md, int saltlen); diff --git a/crypto/rsa/rsa_meth.c b/crypto/rsa/rsa_meth.c index 82f13bb35976..f04098bd08cc 100644 --- a/crypto/rsa/rsa_meth.c +++ b/crypto/rsa/rsa_meth.c @@ -31,7 +31,6 @@ RSA_METHOD *RSA_meth_new(const char *name, int flags) OPENSSL_free(meth); } - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); return NULL; } @@ -57,7 +56,6 @@ RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth) OPENSSL_free(ret); } - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); return NULL; } @@ -70,10 +68,8 @@ int RSA_meth_set1_name(RSA_METHOD *meth, const char *name) { char *tmpname = OPENSSL_strdup(name); - if (tmpname == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (tmpname == NULL) return 0; - } OPENSSL_free(meth->name); meth->name = tmpname; diff --git a/crypto/rsa/rsa_mp.c b/crypto/rsa/rsa_mp.c index f827c0a2f8fd..542daecc1f48 100644 --- a/crypto/rsa/rsa_mp.c +++ b/crypto/rsa/rsa_mp.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2017 BaishanCloud. All rights reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use @@ -33,10 +33,8 @@ RSA_PRIME_INFO *ossl_rsa_multip_info_new(void) RSA_PRIME_INFO *pinfo; /* create an RSA_PRIME_INFO structure */ - if ((pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if ((pinfo = OPENSSL_zalloc(sizeof(RSA_PRIME_INFO))) == NULL) return NULL; - } if ((pinfo->r = BN_secure_new()) == NULL) goto err; if ((pinfo->d = BN_secure_new()) == NULL) @@ -99,7 +97,7 @@ int ossl_rsa_multip_calc_product(RSA *rsa) int ossl_rsa_multip_cap(int bits) { - int cap = 5; + int cap = RSA_MAX_PRIME_NUM; if (bits < 1024) cap = 2; diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c index ffe24edcb6ee..5a1c080fcd14 100644 --- a/crypto/rsa/rsa_oaep.c +++ b/crypto/rsa/rsa_oaep.c @@ -76,6 +76,18 @@ int ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(OSSL_LIB_CTX *libctx, if (mgf1md == NULL) mgf1md = md; +#ifdef FIPS_MODULE + /* XOF are approved as standalone; Shake256 in Ed448; MGF */ + if (EVP_MD_xof(md)) { + ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED); + return 0; + } + if (EVP_MD_xof(mgf1md)) { + ERR_raise(ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED); + return 0; + } +#endif + mdlen = EVP_MD_get_size(md); if (mdlen <= 0) { ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_LENGTH); @@ -112,10 +124,8 @@ int ossl_rsa_padding_add_PKCS1_OAEP_mgf1_ex(OSSL_LIB_CTX *libctx, dbmask_len = emlen - mdlen; dbmask = OPENSSL_malloc(dbmask_len); - if (dbmask == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (dbmask == NULL) goto err; - } /* step 3e: dbMask = MGF(mgfSeed, nLen - HLen - 1) */ if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0) @@ -184,6 +194,18 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, if (mgf1md == NULL) mgf1md = md; +#ifdef FIPS_MODULE + /* XOF are approved as standalone; Shake256 in Ed448; MGF */ + if (EVP_MD_xof(md)) { + ERR_raise(ERR_LIB_RSA, RSA_R_DIGEST_NOT_ALLOWED); + return -1; + } + if (EVP_MD_xof(mgf1md)) { + ERR_raise(ERR_LIB_RSA, RSA_R_MGF1_DIGEST_NOT_ALLOWED); + return -1; + } +#endif + mdlen = EVP_MD_get_size(md); if (tlen <= 0 || flen <= 0 || mdlen <= 0) @@ -203,16 +225,12 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, dblen = num - mdlen - 1; db = OPENSSL_malloc(dblen); - if (db == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (db == NULL) goto cleanup; - } em = OPENSSL_malloc(num); - if (em == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (em == NULL) goto cleanup; - } /* * Caller is encouraged to pass zero-padded message created with @@ -342,7 +360,7 @@ int PKCS1_MGF1(unsigned char *mask, long len, if (c == NULL) goto err; mdlen = EVP_MD_get_size(dgst); - if (mdlen < 0) + if (mdlen <= 0) goto err; /* step 4 */ for (i = 0; outlen < len; i++) { diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c index 0fc642e777fd..0c0c73c65c67 100644 --- a/crypto/rsa/rsa_ossl.c +++ b/crypto/rsa/rsa_ossl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,6 +17,9 @@ #include "crypto/bn.h" #include "rsa_local.h" #include "internal/constant_time.h" +#include +#include +#include static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding); @@ -30,6 +33,27 @@ 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); +#ifdef S390X_MOD_EXP +static int rsa_ossl_s390x_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx); +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_s390x_mod_exp, + s390x_mod_exp, + 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 */ +}; +#else static RSA_METHOD rsa_pkcs1_ossl_meth = { "OpenSSL PKCS#1 RSA", rsa_ossl_public_encrypt, @@ -48,6 +72,7 @@ static RSA_METHOD rsa_pkcs1_ossl_meth = { NULL, /* rsa_keygen */ NULL /* rsa_multi_prime_keygen */ }; +#endif static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth; @@ -104,10 +129,8 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, 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); + if (ret == NULL || buf == NULL) goto err; - } switch (padding) { case RSA_PKCS1_PADDING: @@ -132,10 +155,35 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, 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; +#ifdef FIPS_MODULE + /* + * See SP800-56Br2, section 7.1.1.1 + * RSAEP: 1 < f < (n – 1). + * (where f is the plaintext). + */ + if (padding == RSA_NO_PADDING) { + BIGNUM *nminus1 = BN_CTX_get(ctx); + + if (BN_ucmp(f, BN_value_one()) <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL); + goto err; + } + if (nminus1 == NULL + || BN_copy(nminus1, rsa->n) == NULL + || !BN_sub_word(nminus1, 1)) + goto err; + if (BN_ucmp(f, nminus1) >= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + } else +#endif + { + 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) @@ -163,11 +211,21 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) { BN_BLINDING *ret; - if (!CRYPTO_THREAD_write_lock(rsa->lock)) + if (!CRYPTO_THREAD_read_lock(rsa->lock)) return NULL; if (rsa->blinding == NULL) { - rsa->blinding = RSA_setup_blinding(rsa, ctx); + /* + * This dance with upgrading the lock from read to write will be + * slower in cases of a single use RSA object, but should be + * significantly better in multi-thread cases (e.g. servers). It's + * probably worth it. + */ + CRYPTO_THREAD_unlock(rsa->lock); + if (!CRYPTO_THREAD_write_lock(rsa->lock)) + return NULL; + if (rsa->blinding == NULL) + rsa->blinding = RSA_setup_blinding(rsa, ctx); } ret = rsa->blinding; @@ -189,7 +247,11 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) *local = 0; if (rsa->mt_blinding == NULL) { - rsa->mt_blinding = RSA_setup_blinding(rsa, ctx); + CRYPTO_THREAD_unlock(rsa->lock); + if (!CRYPTO_THREAD_write_lock(rsa->lock)) + return NULL; + if (rsa->mt_blinding == NULL) + rsa->mt_blinding = RSA_setup_blinding(rsa, ctx); } ret = rsa->mt_blinding; } @@ -262,10 +324,8 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, 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); + if (ret == NULL || buf == NULL) goto err; - } switch (padding) { case RSA_PKCS1_PADDING: @@ -308,7 +368,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, if (blinding != NULL) { if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } if (!rsa_blinding_convert(blinding, f, unblind, ctx)) @@ -325,7 +385,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, } else { BIGNUM *d = BN_new(); if (d == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } if (rsa->d == NULL) { @@ -371,12 +431,98 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, return r; } +static int derive_kdk(int flen, const unsigned char *from, RSA *rsa, + unsigned char *buf, int num, unsigned char *kdk) +{ + int ret = 0; + HMAC_CTX *hmac = NULL; + EVP_MD *md = NULL; + unsigned int md_len = SHA256_DIGEST_LENGTH; + unsigned char d_hash[SHA256_DIGEST_LENGTH] = {0}; + /* + * because we use d as a handle to rsa->d we need to keep it local and + * free before any further use of rsa->d + */ + BIGNUM *d = BN_new(); + + if (d == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_CRYPTO_LIB); + 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 (BN_bn2binpad(d, buf, num) < 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + BN_free(d); + goto err; + } + BN_free(d); + + /* + * we use hardcoded hash so that migrating between versions that use + * different hash doesn't provide a Bleichenbacher oracle: + * if the attacker can see that different versions return different + * messages for the same ciphertext, they'll know that the message is + * synthetically generated, which means that the padding check failed + */ + md = EVP_MD_fetch(rsa->libctx, "sha256", NULL); + if (md == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_FETCH_FAILED); + goto err; + } + + if (EVP_Digest(buf, num, d_hash, NULL, md, NULL) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + hmac = HMAC_CTX_new(); + if (hmac == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_CRYPTO_LIB); + goto err; + } + + if (HMAC_Init_ex(hmac, d_hash, sizeof(d_hash), md, NULL) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (flen < num) { + memset(buf, 0, num - flen); + if (HMAC_Update(hmac, buf, num - flen) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + } + if (HMAC_Update(hmac, from, flen) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + md_len = SHA256_DIGEST_LENGTH; + if (HMAC_Final(hmac, kdk, &md_len) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + ret = 1; + + err: + HMAC_CTX_free(hmac); + EVP_MD_free(md); + return ret; +} + 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; + unsigned char kdk[SHA256_DIGEST_LENGTH] = {0}; BN_CTX *ctx = NULL; int local_blinding = 0; /* @@ -387,17 +533,25 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, BIGNUM *unblind = NULL; BN_BLINDING *blinding = NULL; + /* + * we need the value of the private exponent to perform implicit rejection + */ + if ((rsa->flags & RSA_FLAG_EXT_PKEY) && (padding == RSA_PKCS1_PADDING)) + padding = RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING; + 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); + if (ret == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (buf == NULL) + goto err; /* * This check was for equality but PGP does evil things and chops off the @@ -408,15 +562,44 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, goto err; } + if (flen < 1) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL); + 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; - } +#ifdef FIPS_MODULE + /* + * See SP800-56Br2, section 7.1.2.1 + * RSADP: 1 < f < (n – 1) + * (where f is the ciphertext). + */ + if (padding == RSA_NO_PADDING) { + BIGNUM *nminus1 = BN_CTX_get(ctx); + if (BN_ucmp(f, BN_value_one()) <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_SMALL); + goto err; + } + if (nminus1 == NULL + || BN_copy(nminus1, rsa->n) == NULL + || !BN_sub_word(nminus1, 1)) + goto err; + if (BN_ucmp(f, nminus1) >= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + } else +#endif + { + 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)) @@ -432,7 +615,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, if (blinding != NULL) { if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } if (!rsa_blinding_convert(blinding, f, unblind, ctx)) @@ -450,7 +633,7 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, } else { BIGNUM *d = BN_new(); if (d == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } if (rsa->d == NULL) { @@ -472,14 +655,26 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) goto err; + /* + * derive the Key Derivation Key from private exponent and public + * ciphertext + */ + if (padding == RSA_PKCS1_PADDING) { + if (derive_kdk(flen, from, rsa, buf, num, kdk) == 0) + goto err; + } + j = BN_bn2binpad(ret, buf, num); if (j < 0) goto err; switch (padding) { - case RSA_PKCS1_PADDING: + case RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING: r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num); break; + case RSA_PKCS1_PADDING: + r = ossl_rsa_padding_check_PKCS1_type_2(rsa->libctx, to, num, buf, j, num, kdk); + break; case RSA_PKCS1_OAEP_PADDING: r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0); break; @@ -539,12 +734,14 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, 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); + if (ret == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_BN_LIB); goto err; } + num = BN_num_bytes(rsa->n); + buf = OPENSSL_malloc(num); + if (buf == NULL) + goto err; /* * This check was for equality but PGP does evil things and chops off the @@ -572,6 +769,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, rsa->_method_mod_n)) goto err; + /* For X9.31: Assuming e is odd it does a 12 mod 16 test */ if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12)) if (!BN_sub(ret, rsa->n, ret)) goto err; @@ -998,3 +1196,16 @@ static int rsa_ossl_finish(RSA *rsa) BN_MONT_CTX_free(rsa->_method_mod_q); return 1; } + +#ifdef S390X_MOD_EXP +static int rsa_ossl_s390x_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa, + BN_CTX *ctx) +{ + if (rsa->version != RSA_ASN1_VERSION_MULTI) { + if (s390x_crt(r0, i, rsa->p, rsa->q, rsa->dmp1, rsa->dmq1, rsa->iqmp) == 1) + return 1; + } + return rsa_ossl_mod_exp(r0, i, rsa, ctx); +} + +#endif diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c index 51507fc030a7..7655ef9a97dc 100644 --- a/crypto/rsa/rsa_pk1.c +++ b/crypto/rsa/rsa_pk1.c @@ -1,5 +1,5 @@ /* - * 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 @@ -21,10 +21,14 @@ #include /* Just for the SSL_MAX_MASTER_KEY_LENGTH value */ #include +#include +#include +#include #include "internal/cryptlib.h" #include "crypto/rsa.h" #include "rsa_local.h" + int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, const unsigned char *from, int flen) { @@ -188,10 +192,8 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, } em = OPENSSL_malloc(num); - if (em == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (em == NULL) return -1; - } /* * Caller is encouraged to pass zero-padded message created with * BN_bn2binpad. Trouble is that since we can't read out of |from|'s @@ -273,6 +275,254 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, return constant_time_select_int(good, mlen, -1); } + +static int ossl_rsa_prf(OSSL_LIB_CTX *ctx, + unsigned char *to, int tlen, + const char *label, int llen, + const unsigned char *kdk, + uint16_t bitlen) +{ + int pos; + int ret = -1; + uint16_t iter = 0; + unsigned char be_iter[sizeof(iter)]; + unsigned char be_bitlen[sizeof(bitlen)]; + HMAC_CTX *hmac = NULL; + EVP_MD *md = NULL; + unsigned char hmac_out[SHA256_DIGEST_LENGTH]; + unsigned int md_len; + + if (tlen * 8 != bitlen) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + return ret; + } + + be_bitlen[0] = (bitlen >> 8) & 0xff; + be_bitlen[1] = bitlen & 0xff; + + hmac = HMAC_CTX_new(); + if (hmac == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * we use hardcoded hash so that migrating between versions that use + * different hash doesn't provide a Bleichenbacher oracle: + * if the attacker can see that different versions return different + * messages for the same ciphertext, they'll know that the message is + * synthetically generated, which means that the padding check failed + */ + md = EVP_MD_fetch(ctx, "sha256", NULL); + if (md == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (HMAC_Init_ex(hmac, kdk, SHA256_DIGEST_LENGTH, md, NULL) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + for (pos = 0; pos < tlen; pos += SHA256_DIGEST_LENGTH, iter++) { + if (HMAC_Init_ex(hmac, NULL, 0, NULL, NULL) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + be_iter[0] = (iter >> 8) & 0xff; + be_iter[1] = iter & 0xff; + + if (HMAC_Update(hmac, be_iter, sizeof(be_iter)) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + if (HMAC_Update(hmac, (unsigned char *)label, llen) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + if (HMAC_Update(hmac, be_bitlen, sizeof(be_bitlen)) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * HMAC_Final requires the output buffer to fit the whole MAC + * value, so we need to use the intermediate buffer for the last + * unaligned block + */ + md_len = SHA256_DIGEST_LENGTH; + if (pos + SHA256_DIGEST_LENGTH > tlen) { + if (HMAC_Final(hmac, hmac_out, &md_len) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + memcpy(to + pos, hmac_out, tlen - pos); + } else { + if (HMAC_Final(hmac, to + pos, &md_len) <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + goto err; + } + } + } + + ret = 0; + +err: + HMAC_CTX_free(hmac); + EVP_MD_free(md); + return ret; +} + +/* + * ossl_rsa_padding_check_PKCS1_type_2() checks and removes the PKCS#1 type 2 + * padding from a decrypted RSA message. Unlike the + * RSA_padding_check_PKCS1_type_2() it will not return an error in case it + * detects a padding error, rather it will return a deterministically generated + * random message. In other words it will perform an implicit rejection + * of an invalid padding. This means that the returned value does not indicate + * if the padding of the encrypted message was correct or not, making + * side channel attacks like the ones described by Bleichenbacher impossible + * without access to the full decrypted value and a brute-force search of + * remaining padding bytes + */ +int ossl_rsa_padding_check_PKCS1_type_2(OSSL_LIB_CTX *ctx, + unsigned char *to, int tlen, + const unsigned char *from, int flen, + int num, unsigned char *kdk) +{ +/* + * We need to generate a random length for the synthetic message, to avoid + * bias towards zero and avoid non-constant timeness of DIV, we prepare + * 128 values to check if they are not too large for the used key size, + * and use 0 in case none of them are small enough, as 2^-128 is a good enough + * safety margin + */ +#define MAX_LEN_GEN_TRIES 128 + unsigned char *synthetic = NULL; + int synthetic_length; + uint16_t len_candidate; + unsigned char candidate_lengths[MAX_LEN_GEN_TRIES * sizeof(len_candidate)]; + uint16_t len_mask; + uint16_t max_sep_offset; + int synth_msg_index = 0; + int ret = -1; + int i, j; + unsigned int good, found_zero_byte; + int zero_index = 0, msg_index; + + /* + * If these checks fail then either the message in publicly invalid, or + * we've been called incorrectly. We can fail immediately. + * Since this code is called only internally by openssl, those are just + * sanity checks + */ + if (num != flen || tlen <= 0 || flen <= 0) { + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Generate a random message to return in case the padding checks fail */ + synthetic = OPENSSL_malloc(flen); + if (synthetic == NULL) { + ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + return -1; + } + + if (ossl_rsa_prf(ctx, synthetic, flen, "message", 7, kdk, flen * 8) < 0) + goto err; + + /* decide how long the random message should be */ + if (ossl_rsa_prf(ctx, candidate_lengths, sizeof(candidate_lengths), + "length", 6, kdk, + MAX_LEN_GEN_TRIES * sizeof(len_candidate) * 8) < 0) + goto err; + + /* + * max message size is the size of the modulus size less 2 bytes for + * version and padding type and a minimum of 8 bytes padding + */ + len_mask = max_sep_offset = flen - 2 - 8; + /* + * we want a mask so lets propagate the high bit to all positions less + * significant than it + */ + len_mask |= len_mask >> 1; + len_mask |= len_mask >> 2; + len_mask |= len_mask >> 4; + len_mask |= len_mask >> 8; + + synthetic_length = 0; + for (i = 0; i < MAX_LEN_GEN_TRIES * (int)sizeof(len_candidate); + i += sizeof(len_candidate)) { + len_candidate = (candidate_lengths[i] << 8) | candidate_lengths[i + 1]; + len_candidate &= len_mask; + + synthetic_length = constant_time_select_int( + constant_time_lt(len_candidate, max_sep_offset), + len_candidate, synthetic_length); + } + + synth_msg_index = flen - synthetic_length; + + /* we have alternative message ready, check the real one */ + good = constant_time_is_zero(from[0]); + good &= constant_time_eq(from[1], 2); + + /* then look for the padding|message separator (the first zero byte) */ + found_zero_byte = 0; + for (i = 2; i < flen; i++) { + unsigned int equals0 = constant_time_is_zero(from[i]); + zero_index = constant_time_select_int(~found_zero_byte & equals0, + i, zero_index); + found_zero_byte |= equals0; + } + + /* + * padding must be at least 8 bytes long, and it starts two bytes into + * |from|. If we never found a 0-byte, then |zero_index| is 0 and the check + * also fails. + */ + good &= constant_time_ge(zero_index, 2 + 8); + + /* + * Skip the zero byte. This is incorrect if we never found a zero-byte + * but in this case we also do not copy the message out. + */ + msg_index = zero_index + 1; + + /* + * old code returned an error in case the decrypted message wouldn't fit + * into the |to|, since that would leak information, return the synthetic + * message instead + */ + good &= constant_time_ge(tlen, num - msg_index); + + msg_index = constant_time_select_int(good, msg_index, synth_msg_index); + + /* + * since at this point the |msg_index| does not provide the signal + * indicating if the padding check failed or not, we don't have to worry + * about leaking the length of returned message, we still need to ensure + * that we read contents of both buffers so that cache accesses don't leak + * the value of |good| + */ + for (i = msg_index, j = 0; i < flen && j < tlen; i++, j++) + to[j] = constant_time_select_8(good, from[i], synthetic[i]); + ret = j; + +err: + /* + * the only time ret < 0 is when the ciphertext is publicly invalid + * or we were called with invalid parameters, so we don't have to perform + * a side-channel secure raising of the error + */ + if (ret < 0) + ERR_raise(ERR_LIB_RSA, ERR_R_INTERNAL_ERROR); + OPENSSL_free(synthetic); + return ret; +} + /* * ossl_rsa_padding_check_PKCS1_type_2_TLS() checks and removes the PKCS1 type 2 * padding from a decrypted RSA message in a TLS signature. The result is stored diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c index 0bf5ac098ac0..8f89f748e7aa 100644 --- a/crypto/rsa/rsa_pmeth.c +++ b/crypto/rsa/rsa_pmeth.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -52,6 +52,8 @@ typedef struct { /* OAEP label */ unsigned char *oaep_label; size_t oaep_labellen; + /* if to use implicit rejection in PKCS#1 v1.5 decryption */ + int implicit_rejection; } RSA_PKEY_CTX; /* True if PSS parameters are restricted */ @@ -72,6 +74,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx) /* Maximum for sign, auto for verify */ rctx->saltlen = RSA_PSS_SALTLEN_AUTO; rctx->min_saltlen = -1; + rctx->implicit_rejection = 1; ctx->data = rctx; ctx->keygen_info = rctx->gentmp; ctx->keygen_info_count = 2; @@ -97,6 +100,7 @@ static int pkey_rsa_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) dctx->md = sctx->md; dctx->mgf1md = sctx->mgf1md; dctx->saltlen = sctx->saltlen; + dctx->implicit_rejection = sctx->implicit_rejection; if (sctx->oaep_label) { OPENSSL_free(dctx->oaep_label); dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen); @@ -112,10 +116,8 @@ static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk) if (ctx->tbuf != NULL) return 1; if ((ctx->tbuf = - OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pk->pkey)))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + OPENSSL_malloc(RSA_size(EVP_PKEY_get0_RSA(pk->pkey)))) == NULL) return 0; - } return 1; } @@ -142,9 +144,16 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, * be reflected back in the "original" key. */ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey); + int md_size; if (rctx->md) { - if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) { + md_size = EVP_MD_get_size(rctx->md); + if (md_size <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } + + if (tbslen != (size_t)md_size) { ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); return -1; } @@ -164,7 +173,7 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, return -1; } if (!setup_tbuf(rctx, ctx)) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_RSA_LIB); return -1; } memcpy(rctx->tbuf, tbs, tbslen); @@ -264,12 +273,18 @@ static int pkey_rsa_verify(EVP_PKEY_CTX *ctx, */ RSA *rsa = (RSA *)EVP_PKEY_get0_RSA(ctx->pkey); size_t rslen; + int md_size; if (rctx->md) { if (rctx->pad_mode == RSA_PKCS1_PADDING) return RSA_verify(EVP_MD_get_type(rctx->md), tbs, tbslen, sig, siglen, rsa); - if (tbslen != (size_t)EVP_MD_get_size(rctx->md)) { + md_size = EVP_MD_get_size(rctx->md); + if (md_size <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } + if (tbslen != (size_t)md_size) { ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); return -1; } @@ -347,6 +362,7 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, const unsigned char *in, size_t inlen) { int ret; + int pad_mode; RSA_PKEY_CTX *rctx = ctx->data; /* * Discard const. Its marked as const because this may be a cached copy of @@ -367,7 +383,12 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, rctx->oaep_labellen, rctx->md, rctx->mgf1md); } else { - ret = RSA_private_decrypt(inlen, in, out, rsa, rctx->pad_mode); + if (rctx->pad_mode == RSA_PKCS1_PADDING && + rctx->implicit_rejection == 0) + pad_mode = RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING; + else + pad_mode = rctx->pad_mode; + ret = RSA_private_decrypt(inlen, in, out, rsa, pad_mode); } *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret); ret = constant_time_select_int(constant_time_msb(ret), ret, 1); @@ -394,7 +415,7 @@ static int check_padding_md(const EVP_MD *md, int padding) return 0; } } else { - switch(mdnid) { + switch (mdnid) { /* List of all supported RSA digests */ case NID_sha1: case NID_sha224: @@ -428,6 +449,7 @@ static int check_padding_md(const EVP_MD *md, int padding) static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { RSA_PKEY_CTX *rctx = ctx->data; + int md_size; switch (type) { case EVP_PKEY_CTRL_RSA_PADDING: @@ -477,8 +499,13 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PSS_SALTLEN); return -2; } + md_size = EVP_MD_get_size(rctx->md); + if (md_size <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); + return -2; + } if ((p1 == RSA_PSS_SALTLEN_DIGEST - && rctx->min_saltlen > EVP_MD_get_size(rctx->md)) + && rctx->min_saltlen > md_size) || (p1 >= 0 && p1 < rctx->min_saltlen)) { ERR_raise(ERR_LIB_RSA, RSA_R_PSS_SALTLEN_TOO_SMALL); return 0; @@ -591,6 +618,14 @@ static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) *(unsigned char **)p2 = rctx->oaep_label; return rctx->oaep_labellen; + case EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION: + if (rctx->pad_mode != RSA_PKCS1_PADDING) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_PADDING_MODE); + return -2; + } + rctx->implicit_rejection = p1; + return 1; + case EVP_PKEY_CTRL_DIGESTINIT: case EVP_PKEY_CTRL_PKCS7_SIGN: #ifndef OPENSSL_NO_CMS @@ -834,7 +869,7 @@ static int pkey_pss_init(EVP_PKEY_CTX *ctx) RSA_PKEY_CTX *rctx = ctx->data; const EVP_MD *md; const EVP_MD *mgf1md; - int min_saltlen, max_saltlen; + int min_saltlen, max_saltlen, md_size; /* Should never happen */ if (!pkey_ctx_is_pss(ctx)) @@ -848,7 +883,12 @@ static int pkey_pss_init(EVP_PKEY_CTX *ctx) return 0; /* See if minimum salt length exceeds maximum possible */ - max_saltlen = RSA_size(rsa) - EVP_MD_get_size(md); + md_size = EVP_MD_get_size(md); + if (md_size <= 0) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_DIGEST_LENGTH); + return 0; + } + max_saltlen = RSA_size(rsa) - md_size; if ((RSA_bits(rsa) & 0x7) == 1) max_saltlen--; if (min_saltlen > max_saltlen) { diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c index 33874bfef8a2..a2bc198a8936 100644 --- a/crypto/rsa/rsa_pss.c +++ b/crypto/rsa/rsa_pss.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -38,9 +38,17 @@ int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash, const unsigned char *EM, int sLen) +{ + return ossl_rsa_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, mgf1Hash, EM, &sLen); +} + +int ossl_rsa_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + const unsigned char *EM, int *sLenOut) { int i; int ret = 0; + int sLen = *sLenOut; int hLen, maskedDBLen, MSBits, emLen; const unsigned char *H; unsigned char *DB = NULL; @@ -54,18 +62,19 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, mgf1Hash = Hash; hLen = EVP_MD_get_size(Hash); - if (hLen < 0) + if (hLen <= 0) goto err; /*- * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is autorecovered from signature * -3 salt length is maximized + * -4 salt length is autorecovered from signature * -N reserved */ if (sLen == RSA_PSS_SALTLEN_DIGEST) { sLen = hLen; - } else if (sLen < RSA_PSS_SALTLEN_MAX) { + } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } @@ -97,10 +106,8 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, maskedDBLen = emLen - hLen - 1; H = EM + maskedDBLen; DB = OPENSSL_malloc(maskedDBLen); - if (DB == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (DB == NULL) goto err; - } if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) goto err; for (i = 0; i < maskedDBLen; i++) @@ -112,18 +119,22 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_RECOVERY_FAILED); goto err; } - if (sLen != RSA_PSS_SALTLEN_AUTO && (maskedDBLen - i) != sLen) { + if (sLen != RSA_PSS_SALTLEN_AUTO + && sLen != RSA_PSS_SALTLEN_AUTO_DIGEST_MAX + && (maskedDBLen - i) != sLen) { ERR_raise_data(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED, "expected: %d retrieved: %d", sLen, maskedDBLen - i); goto err; + } else { + sLen = maskedDBLen - i; } if (!EVP_DigestInit_ex(ctx, Hash, NULL) || !EVP_DigestUpdate(ctx, zeroes, sizeof(zeroes)) || !EVP_DigestUpdate(ctx, mHash, hLen)) goto err; - if (maskedDBLen - i) { - if (!EVP_DigestUpdate(ctx, DB + i, maskedDBLen - i)) + if (sLen != 0) { + if (!EVP_DigestUpdate(ctx, DB + i, sLen)) goto err; } if (!EVP_DigestFinal_ex(ctx, H_, NULL)) @@ -135,6 +146,7 @@ int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, ret = 1; } + *sLenOut = sLen; err: OPENSSL_free(DB); EVP_MD_CTX_free(ctx); @@ -154,31 +166,53 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash, int sLen) +{ + return ossl_rsa_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, mgf1Hash, &sLen); +} + +int ossl_rsa_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int *sLenOut) { int i; int ret = 0; + int sLen = *sLenOut; int hLen, maskedDBLen, MSBits, emLen; unsigned char *H, *salt = NULL, *p; EVP_MD_CTX *ctx = NULL; + int sLenMax = -1; if (mgf1Hash == NULL) mgf1Hash = Hash; hLen = EVP_MD_get_size(Hash); - if (hLen < 0) + if (hLen <= 0) goto err; /*- * Negative sLen has special meanings: * -1 sLen == hLen * -2 salt length is maximized * -3 same as above (on signing) + * -4 salt length is min(hLen, maximum salt length) * -N reserved */ + /* FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection + * 5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the + * salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of + * the hash function output block (in bytes)." + * + * Provide a way to use at most the digest length, so that the default does + * not violate FIPS 186-4. */ if (sLen == RSA_PSS_SALTLEN_DIGEST) { sLen = hLen; - } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN) { + } else if (sLen == RSA_PSS_SALTLEN_MAX_SIGN + || sLen == RSA_PSS_SALTLEN_AUTO) { sLen = RSA_PSS_SALTLEN_MAX; - } else if (sLen < RSA_PSS_SALTLEN_MAX) { + } else if (sLen == RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { + sLen = RSA_PSS_SALTLEN_MAX; + sLenMax = hLen; + } else if (sLen < RSA_PSS_SALTLEN_AUTO_DIGEST_MAX) { ERR_raise(ERR_LIB_RSA, RSA_R_SLEN_CHECK_FAILED); goto err; } @@ -195,16 +229,16 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, } if (sLen == RSA_PSS_SALTLEN_MAX) { sLen = emLen - hLen - 2; + if (sLenMax >= 0 && sLen > sLenMax) + sLen = sLenMax; } else if (sLen > emLen - hLen - 2) { ERR_raise(ERR_LIB_RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); goto err; } if (sLen > 0) { salt = OPENSSL_malloc(sLen); - if (salt == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (salt == NULL) goto err; - } if (RAND_bytes_ex(rsa->libctx, salt, sLen, 0) <= 0) goto err; } @@ -247,6 +281,7 @@ int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, ret = 1; + *sLenOut = sLen; err: EVP_MD_CTX_free(ctx); OPENSSL_clear_free(salt, (size_t)sLen); /* salt != NULL implies sLen > 0 */ @@ -320,15 +355,6 @@ int ossl_rsa_pss_params_30_set_hashalg(RSA_PSS_PARAMS_30 *rsa_pss_params, return 1; } -int ossl_rsa_pss_params_30_set_maskgenalg(RSA_PSS_PARAMS_30 *rsa_pss_params, - int maskgenalg_nid) -{ - if (rsa_pss_params == NULL) - return 0; - rsa_pss_params->mask_gen.algorithm_nid = maskgenalg_nid; - return 1; -} - int ossl_rsa_pss_params_30_set_maskgenhashalg(RSA_PSS_PARAMS_30 *rsa_pss_params, int maskgenhashalg_nid) { diff --git a/crypto/rsa/rsa_saos.c b/crypto/rsa/rsa_saos.c index 58fa50785bd5..dc96b6dada2f 100644 --- a/crypto/rsa/rsa_saos.c +++ b/crypto/rsa/rsa_saos.c @@ -40,10 +40,8 @@ int RSA_sign_ASN1_OCTET_STRING(int type, return 0; } s = OPENSSL_malloc((unsigned int)j + 1); - if (s == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (s == NULL) return 0; - } p = s; i2d_ASN1_OCTET_STRING(&sig, &p); i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING); @@ -72,10 +70,8 @@ int RSA_verify_ASN1_OCTET_STRING(int dtype, } s = OPENSSL_malloc((unsigned int)siglen); - if (s == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (s == NULL) goto err; - } i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING); if (i <= 0) diff --git a/crypto/rsa/rsa_schemes.c b/crypto/rsa/rsa_schemes.c index 98ab13956dbb..435f44e0161c 100644 --- a/crypto/rsa/rsa_schemes.c +++ b/crypto/rsa/rsa_schemes.c @@ -1,5 +1,5 @@ /* - * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -38,7 +38,7 @@ static const char *nid2name(int meth, const OSSL_ITEM *items, size_t items_n) } /* - * The list of permitted hash functions are taken from + * The list of permitted hash functions are taken from * https://tools.ietf.org/html/rfc8017#appendix-A.2.1: * * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= { diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c index 5745513c2f8e..78e4bad69e49 100644 --- a/crypto/rsa/rsa_sign.c +++ b/crypto/rsa/rsa_sign.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -34,6 +34,9 @@ # ifndef OPENSSL_NO_RMD160 # include /* uses RIPEMD160_DIGEST_LENGTH */ # endif +# ifndef OPENSSL_NO_SM3 +# include "internal/sm3.h" /* uses SM3_DIGEST_LENGTH */ +# endif #endif #include /* uses SHA???_DIGEST_LENGTH */ #include "crypto/rsa.h" @@ -123,6 +126,16 @@ static const unsigned char digestinfo_ripemd160_der[] = { ASN1_OCTET_STRING, RIPEMD160_DIGEST_LENGTH }; # endif +# ifndef OPENSSL_NO_SM3 +/* SM3 (1 2 156 10197 1 401) */ +static const unsigned char digestinfo_sm3_der[] = { + ASN1_SEQUENCE, 0x0f + SM3_DIGEST_LENGTH, + ASN1_SEQUENCE, 0x0c, + ASN1_OID, 0x08, 1 * 40 + 2, 0x81, 0x1c, 0xcf, 0x55, 1, 0x83, 0x78, + ASN1_NULL, 0x00, + ASN1_OCTET_STRING, SM3_DIGEST_LENGTH +}; +# endif #endif /* FIPS_MODULE */ /* SHA-1 (1 3 14 3 2 26) */ @@ -169,6 +182,9 @@ const unsigned char *ossl_rsa_digestinfo_encoding(int md_nid, size_t *len) # ifndef OPENSSL_NO_RMD160 MD_CASE(ripemd160) # endif +# ifndef OPENSSL_NO_SM3 + MD_CASE(sm3) +# endif #endif /* FIPS_MODULE */ MD_CASE(sha1) MD_CASE(sha224) @@ -258,10 +274,8 @@ static int encode_pkcs1(unsigned char **out, size_t *out_len, int type, } dig_info_len = di_prefix_len + m_len; dig_info = OPENSSL_malloc(dig_info_len); - if (dig_info == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (dig_info == NULL) return 0; - } memcpy(dig_info, di_prefix, di_prefix_len); memcpy(dig_info + di_prefix_len, m, m_len); @@ -343,10 +357,8 @@ int ossl_rsa_verify(int type, const unsigned char *m, unsigned int m_len, /* Recover the encoded digest. */ decrypt_buf = OPENSSL_malloc(siglen); - if (decrypt_buf == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (decrypt_buf == NULL) goto err; - } len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, rsa, RSA_PKCS1_PADDING); diff --git a/crypto/rsa/rsa_sp800_56b_check.c b/crypto/rsa/rsa_sp800_56b_check.c index df81397f5478..b9aafdfe69d0 100644 --- a/crypto/rsa/rsa_sp800_56b_check.c +++ b/crypto/rsa/rsa_sp800_56b_check.c @@ -409,6 +409,11 @@ int ossl_rsa_sp800_56b_check_keypair(const RSA *rsa, const BIGNUM *efixed, ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR); return 0; } + /* (Step 3.c): check that the modulus length is a positive even integer */ + if (nbits <= 0 || (nbits & 0x1)) { + ERR_raise(ERR_LIB_RSA, RSA_R_INVALID_KEYPAIR); + return 0; + } ctx = BN_CTX_new_ex(rsa->libctx); if (ctx == NULL) diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c index f773d1e149de..c741cf3c3b0c 100644 --- a/crypto/rsa/rsa_sp800_56b_gen.c +++ b/crypto/rsa/rsa_sp800_56b_gen.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2024 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 @@ -30,7 +30,6 @@ * 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 @@ -38,7 +37,6 @@ * 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 @@ -50,7 +48,7 @@ * 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. + * p1, p2, q1, q2 are returned if they are not NULL. * Xp, Xp1, Xp2, Xq, Xq1, Xq2 are optionally passed in. * (Required for CAVS testing). */ @@ -65,7 +63,6 @@ int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, 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; @@ -105,8 +102,8 @@ int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, 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); + Xpo = BN_CTX_get(ctx); + Xqo = BN_CTX_get(ctx); if (tmp == NULL || Xpo == NULL || Xqo == NULL) goto err; BN_set_flags(Xpo, BN_FLG_CONSTTIME); @@ -125,7 +122,7 @@ int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, if (!ossl_bn_rsa_fips186_4_gen_prob_primes(rsa->p, Xpo, p1, p2, Xp, Xp1, Xp2, nbits, e, ctx, cb)) goto err; - for(;;) { + 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)) @@ -150,11 +147,15 @@ int ossl_rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, 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(Xpo); + BN_clear(Xqo); BN_clear(tmp); + if (ret != 1) { + BN_clear_free(rsa->p); + rsa->p = NULL; + BN_clear_free(rsa->q); + rsa->q = NULL; + } BN_CTX_end(ctx); return ret; @@ -228,13 +229,16 @@ static int rsa_validate_rng_strength(EVP_RAND_CTX *rng, int nbits) * Returns: -1 = error, * 0 = d is too small, * 1 = success. + * + * SP800-56b key generation always passes a non NULL value for e. + * For other purposes, if e is NULL then it is assumed that e, n and d are + * already set in the RSA key and do not need to be recalculated. */ 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); @@ -254,33 +258,38 @@ int ossl_rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits, 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; + /* + * if e is provided as a parameter, don't recompute e, d or n + */ + if (e != NULL) { + /* 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; + 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 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 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(); @@ -423,7 +432,7 @@ err: * 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. + * Returns 1 if the RSA key passes the pairwise test or 0 if it fails. */ int ossl_rsa_sp800_56b_pairwise_test(RSA *rsa, BN_CTX *ctx) { diff --git a/crypto/rsa/rsa_x931.c b/crypto/rsa/rsa_x931.c index 9d331ab9a7f3..f84ea9815c8c 100644 --- a/crypto/rsa/rsa_x931.c +++ b/crypto/rsa/rsa_x931.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,27 @@ #include #include +/* + * X9.31 Embeds the hash inside the following data structure + * + * header (4 bits = 0x6) + * padding (consisting of zero or more 4 bit values of a sequence of 0xB, + * ending with the terminator 0xA) + * hash(Msg) hash of a message (the output size is related to the hash function) + * trailer (consists of 2 bytes) + * The 1st byte is related to a part number for a hash algorithm + * (See RSA_X931_hash_id()), followed by the fixed value 0xCC + * + * The RSA modulus size n (which for X9.31 is 1024 + 256*s) is the size of the data + * structure, which determines the padding size. + * i.e. len(padding) = n - len(header) - len(hash) - len(trailer) + * + * Params: + * to The output buffer to write the data structure to. + * tolen The size of 'to' in bytes (it is the size of the n) + * from The input hash followed by the 1st byte of the trailer. + * flen The size of the input hash + 1 (trailer byte) + */ int RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *from, int flen) { @@ -26,10 +47,9 @@ int RSA_padding_add_X931(unsigned char *to, int tlen, unsigned char *p; /* - * Absolute minimum amount of padding is 1 header nibble, 1 padding - * nibble and 2 trailer bytes: but 1 hash if is already in 'from'. + * We need at least 1 byte for header + padding (0x6A) + * And 2 trailer bytes (but we subtract 1 since flen includes 1 trailer byte) */ - j = tlen - flen - 2; if (j < 0) { @@ -101,7 +121,12 @@ int RSA_padding_check_X931(unsigned char *to, int tlen, return j; } -/* Translate between X931 hash ids and NIDs */ +/* + * Translate between X9.31 hash ids and NIDs + * The returned values relate to ISO/IEC 10118 part numbers which consist of + * a hash algorithm and hash number. The returned values are used as the + * first byte of the 'trailer'. + */ int RSA_X931_hash_id(int nid) { diff --git a/crypto/rsa/rsa_x931g.c b/crypto/rsa/rsa_x931g.c index 5a309a98c347..290e95b46854 100644 --- a/crypto/rsa/rsa_x931g.c +++ b/crypto/rsa/rsa_x931g.c @@ -1,5 +1,5 @@ /* - * 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 @@ -31,10 +31,10 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BN_CTX *ctx = NULL, *ctx2 = NULL; int ret = 0; - if (!rsa) + if (rsa == NULL) goto err; - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(rsa->libctx); if (ctx == NULL) goto err; BN_CTX_start(ctx); @@ -145,7 +145,6 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, BN_CTX_free(ctx2); return ret; - } int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, @@ -155,7 +154,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BIGNUM *Xp = NULL, *Xq = NULL; BN_CTX *ctx = NULL; - ctx = BN_CTX_new(); + ctx = BN_CTX_new_ex(rsa->libctx); if (ctx == NULL) goto error; diff --git a/crypto/s390x_arch.h b/crypto/s390x_arch.h index a7bde67d90f5..e8830b7eedc5 100644 --- a/crypto/s390x_arch.h +++ b/crypto/s390x_arch.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,6 +12,8 @@ # ifndef __ASSEMBLER__ +#include "crypto/bn.h" + void s390x_kimd(const unsigned char *in, size_t len, unsigned int fc, void *param); void s390x_klmd(const unsigned char *in, size_t inlen, unsigned char *out, @@ -72,11 +74,22 @@ struct OPENSSL_s390xcap_st { unsigned long long kdsa[2]; }; -#if defined(__GNUC__) && defined(__linux) -__attribute__ ((visibility("hidden"))) -#endif +# if defined(__GNUC__) && defined(__linux) +__attribute__((visibility("hidden"))) +# endif extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; +# ifdef S390X_MOD_EXP +# if defined(__GNUC__) && defined(__linux) +__attribute__((visibility("hidden"))) +# endif +extern int OPENSSL_s390xcex; +# if defined(__GNUC__) && defined(__linux) +__attribute__((visibility("hidden"))) +# endif +extern int OPENSSL_s390xcex_nodev; +# endif + /* Max number of 64-bit words currently returned by STFLE */ # define S390X_STFLE_MAX 3 @@ -106,6 +119,7 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_MSA5 57 /* message-security-assist-ext. 5 */ # define S390X_MSA3 76 /* message-security-assist-ext. 3 */ # define S390X_MSA4 77 /* message-security-assist-ext. 4 */ +# define S390X_MSA12 86 /* message-security-assist-ext. 12 */ # define S390X_VX 129 /* vector */ # define S390X_VXD 134 /* vector packed decimal */ # define S390X_VXE 135 /* vector enhancements 1 */ @@ -125,6 +139,10 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_SHA3_256 33 # define S390X_SHA3_384 34 # define S390X_SHA3_512 35 +# define S390X_KECCAK_224 32 +# define S390X_KECCAK_256 33 +# define S390X_KECCAK_384 34 +# define S390X_KECCAK_512 35 # define S390X_SHAKE_128 36 # define S390X_SHAKE_256 37 # define S390X_GHASH 65 @@ -137,6 +155,14 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; /* km */ # define S390X_XTS_AES_128 50 # define S390X_XTS_AES_256 52 +# define S390X_XTS_AES_128_MSA10 82 +# define S390X_XTS_AES_256_MSA10 84 + +/* kmac */ +# define S390X_HMAC_SHA_224 112 +# define S390X_HMAC_SHA_256 113 +# define S390X_HMAC_SHA_384 114 +# define S390X_HMAC_SHA_512 115 /* prno */ # define S390X_SHA_512_DRNG 3 @@ -169,5 +195,12 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; # define S390X_KMA_LAAD 0x200 # define S390X_KMA_HS 0x400 # define S390X_KDSA_D 0x80 +# define S390X_KIMD_NIP 0x8000 +# define S390X_KLMD_DUFOP 0x4000 +# define S390X_KLMD_NIP 0x8000 +# define S390X_KLMD_PS 0x100 +# define S390X_KMAC_IKP 0x8000 +# define S390X_KMAC_IIMP 0x4000 +# define S390X_KMAC_CCUP 0x2000 #endif diff --git a/crypto/s390xcap.c b/crypto/s390xcap.c index ea38ff8f0856..82b2654fb594 100644 --- a/crypto/s390xcap.c +++ b/crypto/s390xcap.c @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2010-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 @@ -16,6 +16,15 @@ #include "crypto/ctype.h" #include "s390x_arch.h" +#if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE) +# include +# include +# include +# include +# include +# include +#endif + #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) # if __GLIBC_PREREQ(2, 16) # include @@ -48,14 +57,16 @@ cap->NAME[1] = ~cap->NAME[1]; \ } -#define TOK_CPU(NAME) \ +#define TOK_CPU_ALIAS(NAME, STRUCT_NAME) \ (sscanf(tok_begin, \ " %" STR(LEN) "s %" STR(LEN) "s ", \ tok[0], tok[1]) == 1 \ && !strcmp(tok[0], #NAME)) { \ - memcpy(cap, &NAME, sizeof(*cap)); \ + memcpy(cap, &STRUCT_NAME, sizeof(*cap)); \ } +#define TOK_CPU(NAME) TOK_CPU_ALIAS(NAME, NAME) + #ifndef OSSL_IMPLEMENT_GETAUXVAL static sigjmp_buf ill_jmp; static void ill_handler(int sig) @@ -67,19 +78,41 @@ void OPENSSL_vx_probe(void); #endif static const char *env; -static int parse_env(struct OPENSSL_s390xcap_st *cap); +static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex); void OPENSSL_s390x_facilities(void); void OPENSSL_s390x_functions(void); struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P; +#ifdef S390X_MOD_EXP +int OPENSSL_s390xcex; +int OPENSSL_s390xcex_nodev; + +#if defined(__GNUC__) +__attribute__ ((visibility("hidden"))) +#endif +void OPENSSL_s390x_cleanup(void); + +#if defined(__GNUC__) +__attribute__ ((visibility("hidden"))) +#endif +void OPENSSL_s390x_cleanup(void) +{ + if (OPENSSL_s390xcex != -1) { + (void)close(OPENSSL_s390xcex); + OPENSSL_s390xcex = -1; + } +} +#endif + #if defined(__GNUC__) && defined(__linux) __attribute__ ((visibility("hidden"))) #endif void OPENSSL_cpuid_setup(void) { struct OPENSSL_s390xcap_st cap; + int cex = 1; if (OPENSSL_s390xcap_P.stfle[0]) return; @@ -140,7 +173,7 @@ void OPENSSL_cpuid_setup(void) env = getenv("OPENSSL_s390xcap"); if (env != NULL) { - if (!parse_env(&cap)) + if (!parse_env(&cap, &cex)) env = NULL; } @@ -178,9 +211,19 @@ void OPENSSL_cpuid_setup(void) OPENSSL_s390xcap_P.kdsa[0] &= cap.kdsa[0]; OPENSSL_s390xcap_P.kdsa[1] &= cap.kdsa[1]; } + +#ifdef S390X_MOD_EXP + if (cex == 0) { + OPENSSL_s390xcex = -1; + } else { + OPENSSL_s390xcex = open("/dev/z90crypt", O_RDWR | O_CLOEXEC); + OPENSSL_atexit(OPENSSL_s390x_cleanup); + } + OPENSSL_s390xcex_nodev = 0; +#endif } -static int parse_env(struct OPENSSL_s390xcap_st *cap) +static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex) { /*- * CPU model data @@ -670,6 +713,11 @@ static int parse_env(struct OPENSSL_s390xcap_st *cap) 0ULL}, }; + /*- + * z16 (2022) - z/Architecture POP + * Implements MSA and MSA1-9 (same as z15, no need to repeat). + */ + char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1]; int rc, off, i, n; @@ -724,6 +772,14 @@ static int parse_env(struct OPENSSL_s390xcap_st *cap) else if TOK_CPU(z13) else if TOK_CPU(z14) else if TOK_CPU(z15) + else if TOK_CPU_ALIAS(z16, z15) + + /* nocex to deactivate cex support */ + else if (sscanf(tok_begin, " %" STR(LEN) "s %" STR(LEN) "s ", + tok[0], tok[1]) == 1 + && !strcmp(tok[0], "nocex")) { + *cex = 0; + } /* whitespace(ignored) or invalid tokens */ else { diff --git a/crypto/s390xcpuid.pl b/crypto/s390xcpuid.pl index 560a2f09e97e..bb2f68810d52 100755 --- a/crypto/s390xcpuid.pl +++ b/crypto/s390xcpuid.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2009-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -308,7 +308,7 @@ s390x_kimd: llgfr %r0,$fc lgr %r1,$param - .long 0xb93e0002 # kimd %r0,%r2 + .long 0xb93e8002 # kimd %r0,%r2[,M3] brc 1,.-4 # pay attention to "partial completion" br $ra @@ -329,7 +329,7 @@ s390x_klmd: llgfr %r0,$fc l${g} %r1,$stdframe($sp) - .long 0xb93f0042 # klmd %r4,%r2 + .long 0xb93f8042 # klmd %r4,%r2[,M3] brc 1,.-4 # pay attention to "partial completion" br $ra diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c index dad4be208a4a..1496a37b8096 100644 --- a/crypto/self_test_core.c +++ b/crypto/self_test_core.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,15 +11,14 @@ #include #include #include "internal/cryptlib.h" +#include "crypto/context.h" -typedef struct self_test_cb_st -{ +typedef struct self_test_cb_st { OSSL_CALLBACK *cb; void *cbarg; } SELF_TEST_CB; -struct ossl_self_test_st -{ +struct ossl_self_test_st { /* local state variables */ const char *phase; const char *type; @@ -32,7 +31,7 @@ struct ossl_self_test_st }; #ifndef FIPS_MODULE -static void *self_test_set_callback_new(OSSL_LIB_CTX *ctx) +void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *ctx) { SELF_TEST_CB *stcb; @@ -40,21 +39,14 @@ static void *self_test_set_callback_new(OSSL_LIB_CTX *ctx) return stcb; } -static void self_test_set_callback_free(void *stcb) +void ossl_self_test_set_callback_free(void *stcb) { OPENSSL_free(stcb); } -static const OSSL_LIB_CTX_METHOD self_test_set_callback_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - self_test_set_callback_new, - self_test_set_callback_free, -}; - static SELF_TEST_CB *get_self_test_callback(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX, - &self_test_set_callback_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_SELF_TEST_CB_INDEX); } void OSSL_SELF_TEST_set_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK *cb, diff --git a/crypto/sha/asm/keccak1600-armv4.pl b/crypto/sha/asm/keccak1600-armv4.pl index eaad86d39ddf..f9a8cd1f0046 100755 --- a/crypto/sha/asm/keccak1600-armv4.pl +++ b/crypto/sha/asm/keccak1600-armv4.pl @@ -932,7 +932,15 @@ SHA3_absorb: .size SHA3_absorb,.-SHA3_absorb ___ } -{ my ($out,$len,$A_flat,$bsz) = map("r$_", (4,5,10,12)); + +{ my ($out,$len,$A_flat,$bsz,$next) = map("r$_", (4,5,10,12,0)); + + +# void SHA3_squeeze(uint64_t A[5][5], +# unsigned char *out, size_t len, size_t r, int next) +# +# The first 4 parameters are passed in via r0..r3, +# next is passed on the stack [sp, #0] $code.=<<___; .global SHA3_squeeze @@ -945,6 +953,7 @@ SHA3_squeeze: mov $out,r1 mov $len,r2 mov $bsz,r3 + ldr $next, [sp, #40] @ next is after the 10 pushed registers (10*4) #ifdef __thumb2__ mov r9,#0x00ff00ff @@ -966,6 +975,8 @@ SHA3_squeeze: stmdb sp!,{r6-r9} mov r14,$A_flat + cmp $next, #1 + beq .Lnext_block b .Loop_squeeze .align 4 @@ -1037,7 +1048,7 @@ SHA3_squeeze: subs $bsz,$bsz,#8 @ bsz -= 8 bhi .Loop_squeeze - +.Lnext_block: mov r0,r14 @ original $A_flat bl KeccakF1600 diff --git a/crypto/sha/asm/keccak1600-armv8.pl b/crypto/sha/asm/keccak1600-armv8.pl index 65102e7c292f..f49c54c4656b 100755 --- a/crypto/sha/asm/keccak1600-armv8.pl +++ b/crypto/sha/asm/keccak1600-armv8.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -80,7 +80,9 @@ my @rhotates = ([ 0, 1, 62, 28, 27 ], [ 18, 2, 61, 56, 14 ]); $code.=<<___; -.text +#include "arm_arch.h" + +.rodata .align 8 // strategic alignment and padding that allows to use // address value as loop termination condition... @@ -121,11 +123,14 @@ my @A = map([ "x$_", "x".($_+1), "x".($_+2), "x".($_+3), "x".($_+4) ], my @C = map("x$_", (26,27,28,30)); $code.=<<___; +.text + .type KeccakF1600_int,%function .align 5 KeccakF1600_int: - adr $C[2],iotas - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER + adrp $C[2],iotas + add $C[2],$C[2],:lo12:iotas stp $C[2],x30,[sp,#16] // 32 bytes on top are mine b .Loop .align 4 @@ -297,14 +302,14 @@ $code.=<<___; bne .Loop ldr x30,[sp,#24] - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size KeccakF1600_int,.-KeccakF1600_int .type KeccakF1600,%function .align 5 KeccakF1600: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-128]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -354,7 +359,7 @@ KeccakF1600: ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#128 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size KeccakF1600,.-KeccakF1600 @@ -362,7 +367,7 @@ KeccakF1600: .type SHA3_absorb,%function .align 5 SHA3_absorb: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-128]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -460,7 +465,7 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#128 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size SHA3_absorb,.-SHA3_absorb ___ @@ -471,7 +476,7 @@ $code.=<<___; .type SHA3_squeeze,%function .align 5 SHA3_squeeze: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-48]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -481,6 +486,8 @@ SHA3_squeeze: mov $out,x1 mov $len,x2 mov $bsz,x3 + cmp w4, #0 // w4 = 'next' argument + bne .Lnext_block .Loop_squeeze: ldr x4,[x0],#8 @@ -495,7 +502,7 @@ SHA3_squeeze: subs x3,x3,#8 bhi .Loop_squeeze - +.Lnext_block: mov x0,$A_flat bl KeccakF1600 mov x0,$A_flat @@ -534,7 +541,7 @@ SHA3_squeeze: ldp x19,x20,[sp,#16] ldp x21,x22,[sp,#32] ldp x29,x30,[sp],#48 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size SHA3_squeeze,.-SHA3_squeeze ___ @@ -552,7 +559,8 @@ $code.=<<___; .align 5 KeccakF1600_ce: mov x9,#24 - adr x10,iotas + adrp x10,iotas + add x10,x10,:lo12:iotas b .Loop_ce .align 4 .Loop_ce: @@ -653,7 +661,7 @@ KeccakF1600_ce: .type KeccakF1600_cext,%function .align 5 KeccakF1600_cext: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-80]! add x29,sp,#0 stp d8,d9,[sp,#16] // per ABI requirement @@ -686,7 +694,7 @@ $code.=<<___; ldp d12,d13,[sp,#48] ldp d14,d15,[sp,#64] ldr x29,[sp],#80 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size KeccakF1600_cext,.-KeccakF1600_cext ___ @@ -699,7 +707,7 @@ $code.=<<___; .type SHA3_absorb_cext,%function .align 5 SHA3_absorb_cext: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-80]! add x29,sp,#0 stp d8,d9,[sp,#16] // per ABI requirement @@ -771,7 +779,7 @@ $code.=<<___; ldp d12,d13,[sp,#48] ldp d14,d15,[sp,#64] ldp x29,x30,[sp],#80 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size SHA3_absorb_cext,.-SHA3_absorb_cext ___ @@ -783,7 +791,7 @@ $code.=<<___; .type SHA3_squeeze_cext,%function .align 5 SHA3_squeeze_cext: - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-16]! add x29,sp,#0 mov x9,$ctx @@ -839,7 +847,7 @@ SHA3_squeeze_cext: .Lsqueeze_done_ce: ldr x29,[sp],#16 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size SHA3_squeeze_cext,.-SHA3_squeeze_cext ___ diff --git a/crypto/sha/asm/keccak1600-ppc64.pl b/crypto/sha/asm/keccak1600-ppc64.pl index 83f8d8ef337b..54f32e8c9291 100755 --- a/crypto/sha/asm/keccak1600-ppc64.pl +++ b/crypto/sha/asm/keccak1600-ppc64.pl @@ -51,6 +51,16 @@ if ($flavour =~ /64/) { $PUSH ="std"; } else { die "nonsense $flavour"; } +$LITTLE_ENDIAN = ($flavour=~/le$/) ? 1 : 0; + +if ($LITTLE_ENDIAN) { + $DWORD_LE_LOAD = "ldu r0,8(r3)"; + $LE_LOAD_SIZE = "8"; +} else { + $DWORD_LE_LOAD = "bl dword_le_load"; + $LE_LOAD_SIZE = "1"; +} + $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or @@ -384,7 +394,9 @@ KeccakF1600: .byte 0,12,4,1,0x80,18,1,0 .long 0 .size KeccakF1600,.-KeccakF1600 - +___ +if (!$LITTLE_ENDIAN) { +$code.=<<___; .type dword_le_load,\@function .align 5 dword_le_load: @@ -408,7 +420,10 @@ dword_le_load: .byte 0,12,0x14,0,0,0,1,0 .long 0 .size dword_le_load,.-dword_le_load +___ +} +$code.=<<___; .globl SHA3_absorb .type SHA3_absorb,\@function .align 5 @@ -436,7 +451,7 @@ SHA3_absorb: $PUSH r0,`$FRAME+$LRSAVE`($sp) bl PICmeup - subi r4,r4,1 ; prepare for lbzu + subi r4,r4,$LE_LOAD_SIZE ; prepare for ldu or lbzu subi r12,r12,8 ; prepare for ldu $PUSH r3,`$LOCALS+0*$SIZE_T`($sp) ; save A[][] @@ -487,79 +502,79 @@ SHA3_absorb: srwi r5,r5,3 $PUSH r4,`$LOCALS+2*$SIZE_T`($sp) ; save len mtctr r5 - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[0][0],$A[0][0],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[0][1],$A[0][1],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[0][2],$A[0][2],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[0][3],$A[0][3],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[0][4],$A[0][4],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[1][0],$A[1][0],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[1][1],$A[1][1],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[1][2],$A[1][2],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[1][3],$A[1][3],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[1][4],$A[1][4],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[2][0],$A[2][0],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[2][1],$A[2][1],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[2][2],$A[2][2],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[2][3],$A[2][3],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[2][4],$A[2][4],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[3][0],$A[3][0],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[3][1],$A[3][1],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[3][2],$A[3][2],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[3][3],$A[3][3],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[3][4],$A[3][4],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[4][0],$A[4][0],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[4][1],$A[4][1],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[4][2],$A[4][2],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[4][3],$A[4][3],r0 bdz .Lprocess_block - bl dword_le_load ; *inp++ + $DWORD_LE_LOAD ; *inp++ xor $A[4][4],$A[4][4],r0 .Lprocess_block: @@ -653,6 +668,8 @@ SHA3_squeeze: subi $out,r4,1 ; prepare for stbu mr $len,r5 mr $bsz,r6 + cmplwi r7,0 ; r7 = 'next' argument + bne .Lnext_block b .Loop_squeeze .align 4 @@ -683,6 +700,7 @@ SHA3_squeeze: subic. r6,r6,8 bgt .Loop_squeeze +.Lnext_block: mr r3,$A_flat bl KeccakF1600 subi r3,$A_flat,8 ; prepare for ldu diff --git a/crypto/sha/asm/keccak1600-s390x.pl b/crypto/sha/asm/keccak1600-s390x.pl index 86233c7e38f2..7d5ebde11719 100755 --- a/crypto/sha/asm/keccak1600-s390x.pl +++ b/crypto/sha/asm/keccak1600-s390x.pl @@ -472,7 +472,7 @@ SHA3_absorb: .size SHA3_absorb,.-SHA3_absorb ___ } -{ my ($A_flat,$out,$len,$bsz) = map("%r$_",(2..5)); +{ my ($A_flat,$out,$len,$bsz,$next) = map("%r$_",(2..6)); $code.=<<___; .globl SHA3_squeeze @@ -484,6 +484,7 @@ SHA3_squeeze: lghi %r14,8 st${g} $bsz,5*$SIZE_T($sp) la %r1,0($A_flat) + cijne $next,0,.Lnext_block j .Loop_squeeze @@ -501,6 +502,7 @@ SHA3_squeeze: brct $bsz,.Loop_squeeze # bsz-- +.Lnext_block: stm${g} $out,$len,3*$SIZE_T($sp) bras %r14,.LKeccakF1600 lm${g} $out,$bsz,3*$SIZE_T($sp) diff --git a/crypto/sha/asm/keccak1600-x86_64.pl b/crypto/sha/asm/keccak1600-x86_64.pl index 02f0116014d6..3dbf17731e4d 100755 --- a/crypto/sha/asm/keccak1600-x86_64.pl +++ b/crypto/sha/asm/keccak1600-x86_64.pl @@ -1,5 +1,5 @@ #!/usr/bin/env perl -# Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -503,12 +503,12 @@ SHA3_absorb: .size SHA3_absorb,.-SHA3_absorb ___ } -{ my ($A_flat,$out,$len,$bsz) = ("%rdi","%rsi","%rdx","%rcx"); +{ my ($A_flat,$out,$len,$bsz,$next) = ("%rdi","%rsi","%rdx","%rcx","%r8"); ($out,$len,$bsz) = ("%r12","%r13","%r14"); $code.=<<___; .globl SHA3_squeeze -.type SHA3_squeeze,\@function,4 +.type SHA3_squeeze,\@function,5 .align 32 SHA3_squeeze: .cfi_startproc @@ -520,10 +520,12 @@ SHA3_squeeze: .cfi_push %r14 shr \$3,%rcx - mov $A_flat,%r8 + mov $A_flat,%r9 mov %rsi,$out mov %rdx,$len mov %rcx,$bsz + bt \$0,${next}d + jc .Lnext_block jmp .Loop_squeeze .align 32 @@ -531,8 +533,8 @@ SHA3_squeeze: cmp \$8,$len jb .Ltail_squeeze - mov (%r8),%rax - lea 8(%r8),%r8 + mov (%r9),%rax + lea 8(%r9),%r9 mov %rax,($out) lea 8($out),$out sub \$8,$len # len -= 8 @@ -540,14 +542,14 @@ SHA3_squeeze: sub \$1,%rcx # bsz-- jnz .Loop_squeeze - +.Lnext_block: call KeccakF1600 - mov $A_flat,%r8 + mov $A_flat,%r9 mov $bsz,%rcx jmp .Loop_squeeze .Ltail_squeeze: - mov %r8, %rsi + mov %r9, %rsi mov $out,%rdi mov $len,%rcx .byte 0xf3,0xa4 # rep movsb @@ -565,6 +567,7 @@ SHA3_squeeze: ___ } $code.=<<___; +.section .rodata align=256 .align 256 .quad 0,0,0,0,0,0,0,0 .type iotas,\@object diff --git a/crypto/sha/asm/sha1-armv4-large.pl b/crypto/sha/asm/sha1-armv4-large.pl index 6a2e12bf17d7..b3a8ec694145 100644 --- a/crypto/sha/asm/sha1-armv4-large.pl +++ b/crypto/sha/asm/sha1-armv4-large.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# 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 @@ -707,7 +707,8 @@ ___ }}} $code.=<<___; #if __ARM_MAX_ARCH__>=7 -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/sha/asm/sha1-armv8.pl b/crypto/sha/asm/sha1-armv8.pl index cdea8845af85..c3a40b4abd99 100644 --- a/crypto/sha/asm/sha1-armv8.pl +++ b/crypto/sha/asm/sha1-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -175,8 +175,8 @@ ___ } $code.=<<___; +#include "arm_arch.h" #ifndef __KERNEL__ -# include "arm_arch.h" .extern OPENSSL_armcap_P .hidden OPENSSL_armcap_P #endif @@ -187,11 +187,13 @@ $code.=<<___; .type sha1_block_data_order,%function .align 6 sha1_block_data_order: + AARCH64_VALID_CALL_TARGET adrp x16,OPENSSL_armcap_P ldr w16,[x16,#:lo12:OPENSSL_armcap_P] tst w16,#ARMV8_SHA1 b.ne .Lv8_entry + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-96]! add x29,sp,#0 stp x19,x20,[sp,#16] @@ -253,10 +255,12 @@ $code.=<<___; .align 6 sha1_block_armv8: .Lv8_entry: + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 - adr x4,.Lconst + adrp x4,.Lconst + add x4,x4,:lo12:.Lconst eor $E,$E,$E ld1.32 {$ABCD},[$ctx],#16 ld1.32 {$E}[0],[$ctx] @@ -316,6 +320,9 @@ $code.=<<___; ldr x29,[sp],#16 ret .size sha1_block_armv8,.-sha1_block_armv8 + +.rodata + .align 6 .Lconst: .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 //K_00_19 diff --git a/crypto/sha/asm/sha1-mb-x86_64.pl b/crypto/sha/asm/sha1-mb-x86_64.pl index 67faba136d05..d9d1630d16db 100644 --- a/crypto/sha/asm/sha1-mb-x86_64.pl +++ b/crypto/sha/asm/sha1-mb-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1374,7 +1374,7 @@ $code.=<<___; ___ } }}} $code.=<<___; - +.section .rodata align=256 .align 256 .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 @@ -1389,6 +1389,7 @@ K_XX_XX: .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap .byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 .asciz "SHA1 multi-block transform for x86_64, CRYPTOGAMS by " +.previous ___ if ($win64) { diff --git a/crypto/sha/asm/sha1-x86_64.pl b/crypto/sha/asm/sha1-x86_64.pl index c66b8fca875e..30c545cf419a 100755 --- a/crypto/sha/asm/sha1-x86_64.pl +++ b/crypto/sha/asm/sha1-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1832,6 +1832,7 @@ ___ } } $code.=<<___; +.section .rodata align=64 .align 64 K_XX_XX: .long 0x5a827999,0x5a827999,0x5a827999,0x5a827999 # K_00_19 @@ -1845,6 +1846,7 @@ K_XX_XX: .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask .long 0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f # pbswap mask .byte 0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0 +.previous ___ }}} $code.=<<___; diff --git a/crypto/sha/asm/sha256-armv4.pl b/crypto/sha/asm/sha256-armv4.pl index e8af05c2981f..feb1f26109a9 100644 --- a/crypto/sha/asm/sha256-armv4.pl +++ b/crypto/sha/asm/sha256-armv4.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# 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 @@ -693,7 +693,8 @@ $code.=<<___; .asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by " .align 2 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/sha/asm/sha256-mb-x86_64.pl b/crypto/sha/asm/sha256-mb-x86_64.pl index fa2ca86046cc..9398b7954a7f 100644 --- a/crypto/sha/asm/sha256-mb-x86_64.pl +++ b/crypto/sha/asm/sha256-mb-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -1340,6 +1340,7 @@ $code.=<<___; ___ } }}} $code.=<<___; +.section .rodata align=256 .align 256 K256: ___ @@ -1389,6 +1390,7 @@ K256_shaext: .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 .asciz "SHA256 multi-block transform for x86_64, CRYPTOGAMS by " +.previous ___ if ($win64) { diff --git a/crypto/sha/asm/sha512-armv4.pl b/crypto/sha/asm/sha512-armv4.pl index 1751c671e6d8..9aa310ffd05f 100644 --- a/crypto/sha/asm/sha512-armv4.pl +++ b/crypto/sha/asm/sha512-armv4.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# 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 @@ -660,7 +660,8 @@ $code.=<<___; .asciz "SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by " .align 2 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) -.comm OPENSSL_armcap_P,4,4 +.extern OPENSSL_armcap_P +.hidden OPENSSL_armcap_P #endif ___ diff --git a/crypto/sha/asm/sha512-armv8.pl b/crypto/sha/asm/sha512-armv8.pl index 6bcff0b7d3f3..90e2a2e5a7a8 100644 --- a/crypto/sha/asm/sha512-armv8.pl +++ b/crypto/sha/asm/sha512-armv8.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -190,8 +190,8 @@ ___ } $code.=<<___; +#include "arm_arch.h" #ifndef __KERNEL__ -# include "arm_arch.h" .extern OPENSSL_armcap_P .hidden OPENSSL_armcap_P #endif @@ -202,6 +202,7 @@ $code.=<<___; .type $func,%function .align 6 $func: + AARCH64_VALID_CALL_TARGET #ifndef __KERNEL__ adrp x16,OPENSSL_armcap_P ldr w16,[x16,#:lo12:OPENSSL_armcap_P] @@ -218,7 +219,7 @@ $code.=<<___ if ($SZ==8); ___ $code.=<<___; #endif - .inst 0xd503233f // paciasp + AARCH64_SIGN_LINK_REGISTER stp x29,x30,[sp,#-128]! add x29,sp,#0 @@ -234,7 +235,8 @@ $code.=<<___; ldp $E,$F,[$ctx,#4*$SZ] add $num,$inp,$num,lsl#`log(16*$SZ)/log(2)` // end of input ldp $G,$H,[$ctx,#6*$SZ] - adr $Ktbl,.LK$BITS + adrp $Ktbl,.LK$BITS + add $Ktbl,$Ktbl,:lo12:.LK$BITS stp $ctx,$num,[x29,#96] .Loop: @@ -280,10 +282,12 @@ $code.=<<___; ldp x25,x26,[x29,#64] ldp x27,x28,[x29,#80] ldp x29,x30,[sp],#128 - .inst 0xd50323bf // autiasp + AARCH64_VALIDATE_LINK_REGISTER ret .size $func,.-$func +.rodata + .align 6 .type .LK$BITS,%object .LK$BITS: @@ -354,6 +358,8 @@ $code.=<<___; .size .LK$BITS,.-.LK$BITS .asciz "SHA$BITS block transform for ARMv8, CRYPTOGAMS by " .align 2 + +.text ___ if ($SZ==4) { @@ -370,11 +376,13 @@ $code.=<<___; .align 6 sha256_block_armv8: .Lv8_entry: + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later. stp x29,x30,[sp,#-16]! add x29,sp,#0 ld1.32 {$ABCD,$EFGH},[$ctx] - adr $Ktbl,.LK256 + adrp $Ktbl,.LK256 + add $Ktbl,$Ktbl,:lo12:.LK256 .Loop_hw: ld1 {@MSG[0]-@MSG[3]},[$inp],#64 @@ -632,12 +640,15 @@ $code.=<<___; .type sha256_block_neon,%function .align 4 sha256_block_neon: + AARCH64_VALID_CALL_TARGET .Lneon_entry: + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later stp x29, x30, [sp, #-16]! mov x29, sp sub sp,sp,#16*4 - adr $Ktbl,.LK256 + adrp $Ktbl,.LK256 + add $Ktbl,$Ktbl,:lo12:.LK256 add $num,$inp,$num,lsl#6 // len to point at the end of inp ld1.8 {@X[0]},[$inp], #16 @@ -743,6 +754,7 @@ $code.=<<___; .align 6 sha512_block_armv8: .Lv8_entry: + // Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later stp x29,x30,[sp,#-16]! add x29,sp,#0 @@ -750,7 +762,8 @@ sha512_block_armv8: ld1 {@MSG[4]-@MSG[7]},[$inp],#64 ld1.64 {@H[0]-@H[3]},[$ctx] // load context - adr $Ktbl,.LK512 + adrp $Ktbl,.LK512 + add $Ktbl,$Ktbl,:lo12:.LK512 rev64 @MSG[0],@MSG[0] rev64 @MSG[1],@MSG[1] diff --git a/crypto/sha/asm/sha512-x86_64.pl b/crypto/sha/asm/sha512-x86_64.pl index 1bd0256954b3..b37058ae03fa 100755 --- a/crypto/sha/asm/sha512-x86_64.pl +++ b/crypto/sha/asm/sha512-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -418,6 +418,7 @@ ___ if ($SZ==4) { $code.=<<___; +.section .rodata align=64 .align 64 .type $TABLE,\@object $TABLE: @@ -461,9 +462,11 @@ $TABLE: .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 .long 0xffffffff,0xffffffff,0x03020100,0x0b0a0908 .asciz "SHA256 block transform for x86_64, CRYPTOGAMS by " +.previous ___ } else { $code.=<<___; +.section .rodata align=64 .align 64 .type $TABLE,\@object $TABLE: @@ -551,6 +554,7 @@ $TABLE: .quad 0x0001020304050607,0x08090a0b0c0d0e0f .quad 0x0001020304050607,0x08090a0b0c0d0e0f .asciz "SHA512 block transform for x86_64, CRYPTOGAMS by " +.previous ___ } diff --git a/crypto/sha/build.info b/crypto/sha/build.info index 186ec13cc82a..9a3d44f6eaa4 100644 --- a/crypto/sha/build.info +++ b/crypto/sha/build.info @@ -46,6 +46,9 @@ IF[{- !$disabled{asm} -}] $SHA1ASM_c64xplus=sha1-c64xplus.s sha256-c64xplus.s sha512-c64xplus.s $SHA1DEF_c64xplus=SHA1_ASM SHA256_ASM SHA512_ASM + $SHA1ASM_riscv64=sha_riscv.c sha256-riscv64-zvkb-zvknha_or_zvknhb.S sha512-riscv64-zvkb-zvknhb.S + $SHA1DEF_riscv64=SHA256_ASM INCLUDE_C_SHA256 SHA512_ASM INCLUDE_C_SHA512 + # Now that we have defined all the arch specific variables, use the # appropriate one, and define the appropriate macros IF[$SHA1ASM_{- $target{asm_arch} -}] @@ -153,6 +156,7 @@ INCLUDE[sha256-armv8.o]=.. GENERATE[sha512-armv8.S]=asm/sha512-armv8.pl INCLUDE[sha512-armv8.o]=.. GENERATE[keccak1600-armv8.S]=asm/keccak1600-armv8.pl +INCLUDE[keccak1600-armv8.o]=.. GENERATE[sha1-s390x.S]=asm/sha1-s390x.pl INCLUDE[sha1-s390x.o]=.. @@ -165,12 +169,16 @@ GENERATE[keccak1600-s390x.S]=asm/keccak1600-s390x.pl GENERATE[sha1-c64xplus.S]=asm/sha1-c64xplus.pl GENERATE[sha256-c64xplus.S]=asm/sha256-c64xplus.pl GENERATE[sha512-c64xplus.S]=asm/sha512-c64xplus.pl -GENERATE[keccak1600-c64x.S]=asm/keccak1600-c64x.pl -# These are not yet used +GENERATE[sha256-riscv64-zvkb-zvknha_or_zvknhb.S]=asm/sha256-riscv64-zvkb-zvknha_or_zvknhb.pl +GENERATE[sha512-riscv64-zvkb-zvknhb.S]=asm/sha512-riscv64-zvkb-zvknhb.pl + +# These are not yet used and do not support multi-squeeze +GENERATE[keccak1600-c64x.S]=asm/keccak1600-c64x.pl GENERATE[keccak1600-avx2.S]=asm/keccak1600-avx2.pl GENERATE[keccak1600-avx512.S]=asm/keccak1600-avx512.pl GENERATE[keccak1600-avx512vl.S]=asm/keccak1600-avx512vl.pl GENERATE[keccak1600-mmx.S]=asm/keccak1600-mmx.pl GENERATE[keccak1600p8-ppc.S]=asm/keccak1600p8-ppc.pl + GENERATE[sha1-thumb.S]=asm/sha1-thumb.pl diff --git a/crypto/sha/keccak1600.c b/crypto/sha/keccak1600.c index ccbf12b1c60d..5d6abeb463a1 100644 --- a/crypto/sha/keccak1600.c +++ b/crypto/sha/keccak1600.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,9 +11,11 @@ #include #include +#include "internal/nelem.h" + size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, size_t r); -void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r); +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next); #if !defined(KECCAK1600_ASM) || !defined(SELFTEST) @@ -231,7 +233,7 @@ static void Chi(uint64_t A[5][5]) static void Iota(uint64_t A[5][5], size_t i) { - assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + assert(i < OSSL_NELEM(iotas)); A[0][0] ^= iotas[i]; } @@ -264,7 +266,7 @@ static void Round(uint64_t A[5][5], size_t i) uint64_t C[5], E[2]; /* registers */ uint64_t D[5], T[2][5]; /* memory */ - assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + assert(i < OSSL_NELEM(iotas)); C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; @@ -391,7 +393,7 @@ static void Round(uint64_t A[5][5], size_t i) { uint64_t C[5], D[5]; - assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + assert(i < OSSL_NELEM(iotas)); C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; @@ -536,7 +538,7 @@ static void Round(uint64_t R[5][5], uint64_t A[5][5], size_t i) { uint64_t C[5], D[5]; - assert(i < (sizeof(iotas) / sizeof(iotas[0]))); + assert(i < OSSL_NELEM(iotas)); C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1]; @@ -694,7 +696,7 @@ static void FourRounds(uint64_t A[5][5], size_t i) { uint64_t B[5], C[5], D[5]; - assert(i <= (sizeof(iotas) / sizeof(iotas[0]) - 4)); + assert(i <= OSSL_NELEM(iotas) - 4); /* Round 4*n */ C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0]; @@ -1090,10 +1092,16 @@ size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len, } /* - * sha3_squeeze is called once at the end to generate |out| hash value - * of |len| bytes. + * SHA3_squeeze may be called after SHA3_absorb to generate |out| hash value of + * |len| bytes. + * If multiple SHA3_squeeze calls are required the output length |len| must be a + * multiple of the blocksize, with |next| being 0 on the first call and 1 on + * subsequent calls. It is the callers responsibility to buffer the results. + * When only a single call to SHA3_squeeze is required, |len| can be any size + * and |next| must be 0. */ -void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r) +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, + int next) { uint64_t *A_flat = (uint64_t *)A; size_t i, w = r / 8; @@ -1101,6 +1109,9 @@ void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r) assert(r < (25 * sizeof(A[0][0])) && (r % 8) == 0); while (len != 0) { + if (next) + KeccakF1600(A); + next = 1; for (i = 0; i < w && len != 0; i++) { uint64_t Ai = BitDeinterleave(A_flat[i]); @@ -1123,8 +1134,6 @@ void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r) out += 8; len -= 8; } - if (len) - KeccakF1600(A); } } #endif @@ -1153,7 +1162,7 @@ void SHA3_sponge(const unsigned char *inp, size_t len, # include -int main() +int main(void) { /* * This is 5-bit SHAKE128 test from http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing @@ -1242,11 +1251,11 @@ int main() printf(++i % 16 && i != sizeof(out) ? " " : "\n"); } - if (memcmp(out,result,sizeof(out))) { - fprintf(stderr,"failure\n"); + if (memcmp(out, result, sizeof(out))) { + fprintf(stderr, "failure\n"); return 1; } else { - fprintf(stderr,"success\n"); + fprintf(stderr, "success\n"); return 0; } } diff --git a/crypto/sha/sha1dgst.c b/crypto/sha/sha1dgst.c index 65d7e62e58e7..e8f1ef5244d1 100644 --- a/crypto/sha/sha1dgst.c +++ b/crypto/sha/sha1dgst.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,7 +20,7 @@ #include #include -/* The implementation is in ../md32_common.h */ +/* The implementation is in crypto/md32_common.h */ #include "sha_local.h" #include "crypto/sha.h" diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c index 5845c389379e..6a19657bf809 100644 --- a/crypto/sha/sha256.c +++ b/crypto/sha/sha256.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -22,6 +22,7 @@ #include #include #include "internal/endian.h" +#include "crypto/sha.h" int SHA224_Init(SHA256_CTX *c) { @@ -53,6 +54,13 @@ int SHA256_Init(SHA256_CTX *c) return 1; } +int ossl_sha256_192_init(SHA256_CTX *c) +{ + SHA256_Init(c); + c->md_len = SHA256_192_DIGEST_LENGTH; + return 1; +} + int SHA224_Update(SHA256_CTX *c, const void *data, size_t len) { return SHA256_Update(c, data, len); @@ -80,23 +88,31 @@ int SHA224_Final(unsigned char *md, SHA256_CTX *c) #define HASH_MAKE_STRING(c,s) do { \ unsigned long ll; \ unsigned int nn; \ - switch ((c)->md_len) \ - { case SHA224_DIGEST_LENGTH: \ - for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); } \ + switch ((c)->md_len) { \ + case SHA256_192_DIGEST_LENGTH: \ + for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); \ + } \ + break; \ + case SHA224_DIGEST_LENGTH: \ + for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); \ + } \ break; \ case SHA256_DIGEST_LENGTH: \ - for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); } \ + for (nn=0;nnh[nn]; (void)HOST_l2c(ll,(s)); \ + } \ break; \ default: \ if ((c)->md_len > SHA256_DIGEST_LENGTH) \ return 0; \ - for (nn=0;nn<(c)->md_len/4;nn++) \ - { ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); } \ + for (nn=0;nn<(c)->md_len/4;nn++) { \ + ll=(c)->h[nn]; (void)HOST_l2c(ll,(s)); \ + } \ break; \ } \ - } while (0) + } while (0) #define HASH_UPDATE SHA256_Update #define HASH_TRANSFORM SHA256_Transform @@ -104,12 +120,16 @@ int SHA224_Final(unsigned char *md, SHA256_CTX *c) #define HASH_BLOCK_DATA_ORDER sha256_block_data_order #ifndef SHA256_ASM static -#endif +#else +# ifdef INCLUDE_C_SHA256 +void sha256_block_data_order_c(SHA256_CTX *ctx, const void *in, size_t num); +# endif /* INCLUDE_C_SHA256 */ +#endif /* SHA256_ASM */ void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num); #include "crypto/md32_common.h" -#ifndef SHA256_ASM +#if !defined(SHA256_ASM) || defined(INCLUDE_C_SHA256) static const SHA_LONG K256[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, @@ -129,18 +149,63 @@ static const SHA_LONG K256[64] = { 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; +# ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && \ + !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if defined(__riscv_zknh) +# define Sigma0(x) ({ MD32_REG_T ret; \ + asm ("sha256sum0 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define Sigma1(x) ({ MD32_REG_T ret; \ + asm ("sha256sum1 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define sigma0(x) ({ MD32_REG_T ret; \ + asm ("sha256sig0 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define sigma1(x) ({ MD32_REG_T ret; \ + asm ("sha256sig1 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# endif +# if defined(__riscv_zbt) || defined(__riscv_zpn) +# define Ch(x,y,z) ({ MD32_REG_T ret; \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3"\ + : "=r"(ret) \ + : "r"(x), "r"(y), "r"(z)); ret; }) +# define Maj(x,y,z) ({ MD32_REG_T ret; \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3"\ + : "=r"(ret) \ + : "r"(x^z), "r"(y), "r"(x)); ret; }) +# endif +# endif +# endif + /* * FIPS specification refers to right rotations, while our ROTATE macro * is left one. This is why you might notice that rotation coefficients * differ from those observed in FIPS document by 32-N... */ -# define Sigma0(x) (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10)) -# define Sigma1(x) (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7)) -# define sigma0(x) (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3)) -# define sigma1(x) (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10)) - -# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# ifndef Sigma0 +# define Sigma0(x) (ROTATE((x),30) ^ ROTATE((x),19) ^ ROTATE((x),10)) +# endif +# ifndef Sigma1 +# define Sigma1(x) (ROTATE((x),26) ^ ROTATE((x),21) ^ ROTATE((x),7)) +# endif +# ifndef sigma0 +# define sigma0(x) (ROTATE((x),25) ^ ROTATE((x),14) ^ ((x)>>3)) +# endif +# ifndef sigma1 +# define sigma1(x) (ROTATE((x),15) ^ ROTATE((x),13) ^ ((x)>>10)) +# endif +# ifndef Ch +# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +# endif +# ifndef Maj +# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# endif # ifdef OPENSSL_SMALL_FOOTPRINT @@ -222,8 +287,12 @@ static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f]; \ ROUND_00_15(i,a,b,c,d,e,f,g,h); } while (0) +#ifdef INCLUDE_C_SHA256 +void sha256_block_data_order_c(SHA256_CTX *ctx, const void *in, size_t num) +#else static void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num) +#endif { unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1; SHA_LONG X[16]; diff --git a/crypto/sha/sha3.c b/crypto/sha/sha3.c index 633bc2e1208b..951d5c88838b 100644 --- a/crypto/sha/sha3.c +++ b/crypto/sha/sha3.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,14 +8,21 @@ */ #include +#if defined(__s390x__) && defined(OPENSSL_CPUID_OBJ) +# include "crypto/s390x_arch.h" +#endif #include "internal/sha3.h" -void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r); +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r, int next); void ossl_sha3_reset(KECCAK1600_CTX *ctx) { - memset(ctx->A, 0, sizeof(ctx->A)); +#if defined(__s390x__) && defined(OPENSSL_CPUID_OBJ) + if (!(OPENSSL_s390xcap_P.stfle[1] & S390X_CAPBIT(S390X_MSA12))) +#endif + memset(ctx->A, 0, sizeof(ctx->A)); ctx->bufsz = 0; + ctx->xof_state = XOF_STATE_INIT; } int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen) @@ -33,12 +40,12 @@ int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen) return 0; } -int ossl_keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen) +int ossl_keccak_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen, size_t mdlen) { int ret = ossl_sha3_init(ctx, pad, bitlen); if (ret) - ctx->md_size *= 2; + ctx->md_size = mdlen / 8; return ret; } @@ -51,6 +58,10 @@ int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len) if (len == 0) return 1; + if (ctx->xof_state == XOF_STATE_SQUEEZE + || ctx->xof_state == XOF_STATE_FINAL) + return 0; + if ((num = ctx->bufsz) != 0) { /* process intermediate buffer? */ rem = bsz - num; @@ -84,13 +95,21 @@ int ossl_sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len) return 1; } -int ossl_sha3_final(unsigned char *md, KECCAK1600_CTX *ctx) +/* + * ossl_sha3_final()is a single shot method + * (Use ossl_sha3_squeeze for multiple calls). + * outlen is the variable size output. + */ +int ossl_sha3_final(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen) { size_t bsz = ctx->block_size; size_t num = ctx->bufsz; - if (ctx->md_size == 0) + if (outlen == 0) return 1; + if (ctx->xof_state == XOF_STATE_SQUEEZE + || ctx->xof_state == XOF_STATE_FINAL) + return 0; /* * Pad the data with 10*1. Note that |num| can be |bsz - 1| @@ -103,7 +122,86 @@ int ossl_sha3_final(unsigned char *md, KECCAK1600_CTX *ctx) (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz); - SHA3_squeeze(ctx->A, md, ctx->md_size, bsz); + ctx->xof_state = XOF_STATE_FINAL; + SHA3_squeeze(ctx->A, out, outlen, bsz, 0); + return 1; +} + +/* + * This method can be called multiple times. + * Rather than heavily modifying assembler for SHA3_squeeze(), + * we instead just use the limitations of the existing function. + * i.e. Only request multiples of the ctx->block_size when calling + * SHA3_squeeze(). For output length requests smaller than the + * ctx->block_size just request a single ctx->block_size bytes and + * buffer the results. The next request will use the buffer first + * to grab output bytes. + */ +int ossl_sha3_squeeze(KECCAK1600_CTX *ctx, unsigned char *out, size_t outlen) +{ + size_t bsz = ctx->block_size; + size_t num = ctx->bufsz; + size_t len; + int next = 1; + + if (outlen == 0) + return 1; + + if (ctx->xof_state == XOF_STATE_FINAL) + return 0; + + /* + * On the first squeeze call, finish the absorb process, + * by adding the trailing padding and then doing + * a final absorb. + */ + if (ctx->xof_state != XOF_STATE_SQUEEZE) { + /* + * Pad the data with 10*1. Note that |num| can be |bsz - 1| + * in which case both byte operations below are performed on + * same byte... + */ + memset(ctx->buf + num, 0, bsz - num); + ctx->buf[num] = ctx->pad; + ctx->buf[bsz - 1] |= 0x80; + (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz); + ctx->xof_state = XOF_STATE_SQUEEZE; + num = ctx->bufsz = 0; + next = 0; + } + + /* + * Step 1. Consume any bytes left over from a previous squeeze + * (See Step 4 below). + */ + if (num != 0) { + if (outlen > ctx->bufsz) + len = ctx->bufsz; + else + len = outlen; + memcpy(out, ctx->buf + bsz - ctx->bufsz, len); + out += len; + outlen -= len; + ctx->bufsz -= len; + } + if (outlen == 0) + return 1; + + /* Step 2. Copy full sized squeezed blocks to the output buffer directly */ + if (outlen >= bsz) { + len = bsz * (outlen / bsz); + SHA3_squeeze(ctx->A, out, len, bsz, next); + next = 1; + out += len; + outlen -= len; + } + if (outlen > 0) { + /* Step 3. Squeeze one more block into a buffer */ + SHA3_squeeze(ctx->A, ctx->buf, bsz, bsz, next); + memcpy(out, ctx->buf, outlen); + /* Step 4. Remember the leftover part of the squeezed block */ + ctx->bufsz = bsz - outlen; + } return 1; } diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c index ff035c469f94..ac5e9233b9aa 100644 --- a/crypto/sha/sha512.c +++ b/crypto/sha/sha512.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,16 +18,16 @@ /*- * IMPLEMENTATION NOTES. * - * As you might have noticed 32-bit hash algorithms: + * As you might have noticed, 32-bit hash algorithms: * * - permit SHA_LONG to be wider than 32-bit * - optimized versions implement two transform functions: one operating - * on [aligned] data in host byte order and one - on data in input + * on [aligned] data in host byte order, and one operating on data in input * stream byte order; * - share common byte-order neutral collector and padding function - * implementations, ../md32_common.h; + * implementations, crypto/md32_common.h; * - * Neither of the above applies to this SHA-512 implementations. Reasons + * Neither of the above applies to this SHA-512 implementation. Reasons * [in reverse order] are: * * - it's the only 64-bit hash algorithm for the moment of this writing, @@ -149,6 +149,10 @@ int SHA512_Init(SHA512_CTX *c) #ifndef SHA512_ASM static +#else +# ifdef INCLUDE_C_SHA512 +void sha512_block_data_order_c(SHA512_CTX *ctx, const void *in, size_t num); +# endif #endif void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); @@ -338,7 +342,7 @@ void SHA512_Transform(SHA512_CTX *c, const unsigned char *data) sha512_block_data_order(c, data, 1); } -#ifndef SHA512_ASM +#if !defined(SHA512_ASM) || defined(INCLUDE_C_SHA512) static const SHA_LONG64 K512[80] = { U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd), U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc), @@ -432,6 +436,103 @@ static const SHA_LONG64 K512[80] = { : "=r"(ret) \ : "r"(*((const SHA_LONG64 *)(&(x))))); ret; }) # endif +# elif (defined(__riscv_zbkb) || defined(__riscv_zbb)) && __riscv_xlen == 32 +# define PULL64(x) ({ SHA_LONG64 ret; \ + unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + asm ("rev8 %0, %1" \ + : "=r"(r[0]) \ + : "r" (p[1])); \ + asm ("rev8 %0, %1" \ + : "=r"(r[1]) \ + : "r" (p[0])); ret; }) +# elif (defined(__riscv_zbkb) || defined(__riscv_zbb)) && __riscv_xlen == 64 +# define PULL64(x) ({ SHA_LONG64 ret; \ + asm ("rev8 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# endif +# if defined(__riscv_zknh) && __riscv_xlen == 32 +# define Sigma0(x) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + asm ("sha512sum0r %0, %1, %2" \ + : "=r"(r[0]) \ + : "r" (p[0]), "r" (p[1])); \ + asm ("sha512sum0r %0, %2, %1" \ + : "=r"(r[1]) \ + : "r" (p[0]), "r" (p[1])); ret; }) +# define Sigma1(x) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + asm ("sha512sum1r %0, %1, %2" \ + : "=r"(r[0]) \ + : "r" (p[0]), "r" (p[1])); \ + asm ("sha512sum1r %0, %2, %1" \ + : "=r"(r[1]) \ + : "r" (p[0]), "r" (p[1])); ret; }) +# define sigma0(x) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + asm ("sha512sig0l %0, %1, %2" \ + : "=r"(r[0]) \ + : "r" (p[0]), "r" (p[1])); \ + asm ("sha512sig0h %0, %2, %1" \ + : "=r"(r[1]) \ + : "r" (p[0]), "r" (p[1])); ret; }) +# define sigma1(x) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *p = (const unsigned int *)(&(x)); \ + asm ("sha512sig1l %0, %1, %2" \ + : "=r"(r[0]) \ + : "r" (p[0]), "r" (p[1])); \ + asm ("sha512sig1h %0, %2, %1" \ + : "=r"(r[1]) \ + : "r" (p[0]), "r" (p[1])); ret; }) +# elif defined(__riscv_zknh) && __riscv_xlen == 64 +# define Sigma0(x) ({ SHA_LONG64 ret; \ + asm ("sha512sum0 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define Sigma1(x) ({ SHA_LONG64 ret; \ + asm ("sha512sum1 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define sigma0(x) ({ SHA_LONG64 ret; \ + asm ("sha512sig0 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define sigma1(x) ({ SHA_LONG64 ret; \ + asm ("sha512sig1 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# endif +# if (defined(__riscv_zbt) || defined(__riscv_zpn)) && __riscv_xlen == 32 +# define Ch(x,y,z) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *xp = (const unsigned int *)(&(x)); \ + const unsigned int *yp = (const unsigned int *)(&(y)); \ + const unsigned int *zp = (const unsigned int *)(&(z)); \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3\n\t" \ + : "=r"(r[0]) \ + : "r"(xp[0]), "r"(yp[0]), "r"(zp[0])); \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3\n\t" \ + : "=r"(r[1]) \ + : "r"(xp[1]), "r"(yp[1]), "r"(zp[1])); ret; }) +# define Maj(x,y,z) ({ SHA_LONG64 ret; unsigned int *r = (unsigned int *)(&(ret)); \ + const unsigned int *xp = (const unsigned int *)(&(x)); \ + const unsigned int *yp = (const unsigned int *)(&(y)); \ + const unsigned int *zp = (const unsigned int *)(&(z)); \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3\n\t" \ + : "=r"(r[0]) \ + : "r"(xp[0]^zp[0]), "r"(yp[0]), "r"(zp[0])); \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3\n\t" \ + : "=r"(r[1]) \ + : "r"(xp[1]^zp[1]), "r"(yp[1]), "r"(zp[1])); ret; }) +# elif (defined(__riscv_zbt) || defined(__riscv_zpn)) && __riscv_xlen == 64 +# define Ch(x,y,z) ({ SHA_LONG64 ret; \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3"\ + : "=r"(ret) \ + : "r"(x), "r"(y), "r"(z)); ret; }) +# define Maj(x,y,z) ({ SHA_LONG64 ret; \ + asm (".insn r4 0x33, 1, 0x3, %0, %2, %1, %3"\ + : "=r"(ret) \ + : "r"(x^z), "r"(y), "r"(x)); ret; }) # endif # elif defined(_MSC_VER) # if defined(_WIN64) /* applies to both IA-64 and AMD64 */ @@ -472,12 +573,24 @@ static SHA_LONG64 __fastcall __pull64be(const void *x) # ifndef ROTR # define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) # endif -# define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) -# define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) -# define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) -# define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) -# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# ifndef Sigma0 +# define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) +# endif +# ifndef Sigma1 +# define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) +# endif +# ifndef sigma0 +# define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) +# endif +# ifndef sigma1 +# define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) +# endif +# ifndef Ch +# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +# endif +# ifndef Maj +# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +# endif # if defined(__i386) || defined(__i386__) || defined(_M_IX86) /* @@ -628,8 +741,12 @@ static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, T1 = X[(j)&0x0f] += s0 + s1 + X[(j+9)&0x0f]; \ ROUND_00_15(i+j,a,b,c,d,e,f,g,h); } while (0) +#ifdef INCLUDE_C_SHA512 +void sha512_block_data_order_c(SHA512_CTX *ctx, const void *in, size_t num) +#else static void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num) +#endif { const SHA_LONG64 *W = in; SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1; diff --git a/crypto/siphash/siphash.c b/crypto/siphash/siphash.c index 57f61c1db1a5..e2be3ca597fb 100644 --- a/crypto/siphash/siphash.c +++ b/crypto/siphash/siphash.c @@ -210,22 +210,22 @@ int SipHash_Final(SIPHASH *ctx, unsigned char *out, size_t outlen) switch (ctx->len) { case 7: b |= ((uint64_t)ctx->leavings[6]) << 48; - /* fall thru */ + /* fall through */ case 6: b |= ((uint64_t)ctx->leavings[5]) << 40; - /* fall thru */ + /* fall through */ case 5: b |= ((uint64_t)ctx->leavings[4]) << 32; - /* fall thru */ + /* fall through */ case 4: b |= ((uint64_t)ctx->leavings[3]) << 24; - /* fall thru */ + /* fall through */ case 3: b |= ((uint64_t)ctx->leavings[2]) << 16; - /* fall thru */ + /* fall through */ case 2: b |= ((uint64_t)ctx->leavings[1]) << 8; - /* fall thru */ + /* fall through */ case 1: b |= ((uint64_t)ctx->leavings[0]); case 0: diff --git a/crypto/sm2/sm2_crypt.c b/crypto/sm2/sm2_crypt.c index ff8171e39280..0e5017cff608 100644 --- a/crypto/sm2/sm2_crypt.c +++ b/crypto/sm2/sm2_crypt.c @@ -46,25 +46,12 @@ IMPLEMENT_ASN1_FUNCTIONS(SM2_Ciphertext) static size_t ec_field_size(const EC_GROUP *group) { - /* Is there some simpler way to do this? */ - BIGNUM *p = BN_new(); - BIGNUM *a = BN_new(); - BIGNUM *b = BN_new(); - size_t field_size = 0; + const BIGNUM *p = EC_GROUP_get0_field(group); - if (p == NULL || a == NULL || b == NULL) - goto done; + if (p == NULL) + return 0; - if (!EC_GROUP_get_curve(group, p, a, b, NULL)) - goto done; - field_size = (BN_num_bits(p) + 7) / 8; - - done: - BN_free(p); - BN_free(a); - BN_free(b); - - return field_size; + return BN_num_bytes(p); } static int is_all_zeros(const unsigned char *msg, size_t msglen) @@ -104,7 +91,7 @@ int ossl_sm2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, const int md_size = EVP_MD_get_size(digest); size_t sz; - if (field_size == 0 || md_size < 0) + if (field_size == 0 || md_size <= 0) return 0; /* Integer and string are simple type; set constructed = 0, means primitive and definite length encoding. */ @@ -163,9 +150,13 @@ int ossl_sm2_encrypt(const EC_KEY *key, kG = EC_POINT_new(group); kP = EC_POINT_new(group); + if (kG == NULL || kP == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); + goto done; + } ctx = BN_CTX_new_ex(libctx); - if (kG == NULL || kP == NULL || ctx == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (ctx == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -184,18 +175,14 @@ int ossl_sm2_encrypt(const EC_KEY *key, x2y2 = OPENSSL_zalloc(2 * field_size); C3 = OPENSSL_zalloc(C3_size); - if (x2y2 == NULL || C3 == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (x2y2 == NULL || C3 == NULL) goto done; - } memset(ciphertext_buf, 0, *ciphertext_len); msg_mask = OPENSSL_zalloc(msg_len); - if (msg_mask == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (msg_mask == NULL) goto done; - } again: if (!BN_priv_rand_range_ex(k, order, 0, ctx)) { @@ -252,7 +239,7 @@ again: ctext_struct.C2 = ASN1_OCTET_STRING_new(); if (ctext_struct.C3 == NULL || ctext_struct.C2 == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_ASN1_LIB); goto done; } if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size) @@ -337,7 +324,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, ctx = BN_CTX_new_ex(libctx); if (ctx == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -354,14 +341,12 @@ int ossl_sm2_decrypt(const EC_KEY *key, x2y2 = OPENSSL_zalloc(2 * field_size); computed_C3 = OPENSSL_zalloc(hash_size); - if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (msg_mask == NULL || x2y2 == NULL || computed_C3 == NULL) goto done; - } C1 = EC_POINT_new(group); if (C1 == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); goto done; } @@ -392,7 +377,7 @@ int ossl_sm2_decrypt(const EC_KEY *key, hash = EVP_MD_CTX_new(); if (hash == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); goto done; } diff --git a/crypto/sm2/sm2_key.c b/crypto/sm2/sm2_key.c index 9d0b9208facf..e3a10d38e7d2 100644 --- a/crypto/sm2/sm2_key.c +++ b/crypto/sm2/sm2_key.c @@ -29,7 +29,7 @@ int ossl_sm2_key_private_check(const EC_KEY *eckey) if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (priv_key = EC_KEY_get0_private_key(eckey)) == NULL - || (order = EC_GROUP_get0_order(group)) == NULL ) { + || (order = EC_GROUP_get0_order(group)) == NULL) { ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER); return 0; } diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c index 2097cd2fca86..28cf95cc48c9 100644 --- a/crypto/sm2/sm2_sign.c +++ b/crypto/sm2/sm2_sign.c @@ -17,7 +17,6 @@ #include "internal/numbers.h" #include #include -#include #include #include @@ -51,9 +50,13 @@ int ossl_sm2_compute_z_digest(uint8_t *out, } hash = EVP_MD_CTX_new(); + if (hash == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); + goto done; + } 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); + if (ctx == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -66,7 +69,7 @@ int ossl_sm2_compute_z_digest(uint8_t *out, yA = BN_CTX_get(ctx); if (yA == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -108,10 +111,8 @@ int ossl_sm2_compute_z_digest(uint8_t *out, p_bytes = BN_num_bytes(p); buf = OPENSSL_zalloc(p_bytes); - if (buf == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (buf == NULL) goto done; - } if (BN_bn2binpad(a, buf, p_bytes) < 0 || !EVP_DigestUpdate(hash, buf, p_bytes) @@ -159,16 +160,18 @@ static BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest, OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); const char *propq = ossl_ec_key_get0_propq(key); - if (md_size < 0) { + if (md_size <= 0) { ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST); goto done; } + if (hash == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB); + goto done; + } z = OPENSSL_zalloc(md_size); - if (hash == NULL || z == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (z == NULL) goto done; - } fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq); if (fetched_digest == NULL) { @@ -218,9 +221,13 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key); kG = EC_POINT_new(group); + if (kG == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); + goto done; + } ctx = BN_CTX_new_ex(libctx); - if (kG == NULL || ctx == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + if (ctx == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -230,7 +237,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) x1 = BN_CTX_get(ctx); tmp = BN_CTX_get(ctx); if (tmp == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -242,7 +249,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) s = BN_new(); if (r == NULL || s == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } @@ -296,7 +303,7 @@ static ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) sig = ECDSA_SIG_new(); if (sig == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_ECDSA_LIB); goto done; } @@ -332,20 +339,20 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, ctx = BN_CTX_new_ex(libctx); if (ctx == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); 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); + ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); goto done; } pt = EC_POINT_new(group); if (pt == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB); goto done; } @@ -394,6 +401,7 @@ static int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, ret = 1; done: + BN_CTX_end(ctx); EC_POINT_free(pt); BN_CTX_free(ctx); return ret; @@ -498,7 +506,7 @@ int ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen, s = ECDSA_SIG_new(); if (s == NULL) { - ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_SM2, ERR_R_ECDSA_LIB); goto done; } if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { diff --git a/crypto/sm3/build.info b/crypto/sm3/build.info index eca68216f27e..47ee949d8db9 100644 --- a/crypto/sm3/build.info +++ b/crypto/sm3/build.info @@ -1,5 +1,27 @@ LIBS=../../libcrypto IF[{- !$disabled{sm3} -}] - SOURCE[../../libcrypto]=sm3.c legacy_sm3.c -ENDIF \ No newline at end of file + IF[{- !$disabled{asm} -}] + $SM3ASM_aarch64=sm3-armv8.S + $SM3DEF_aarch64=OPENSSL_SM3_ASM + + $SM3ASM_riscv64=sm3_riscv.c sm3-riscv64-zvksh.S + $SM3DEF_riscv64=OPENSSL_SM3_ASM + + # Now that we have defined all the arch specific variables, use the + # appropriate ones, and define the appropriate macros + IF[$SM3ASM_{- $target{asm_arch} -}] + $SM3ASM=$SM3ASM_{- $target{asm_arch} -} + $SM3DEF=$SM3DEF_{- $target{asm_arch} -} + ENDIF + ENDIF + + SOURCE[../../libcrypto]=sm3.c legacy_sm3.c $SM3ASM + DEFINE[../../libcrypto]=$SM3DEF + + GENERATE[sm3-armv8.S]=asm/sm3-armv8.pl + INCLUDE[sm3-armv8.o]=.. + + GENERATE[sm3-riscv64-zvksh.S]=asm/sm3-riscv64-zvksh.pl +ENDIF + diff --git a/crypto/sm3/sm3_local.h b/crypto/sm3/sm3_local.h index 6daeb878a887..897418aee170 100644 --- a/crypto/sm3/sm3_local.h +++ b/crypto/sm3/sm3_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2017 Ribose Inc. All Rights Reserved. * Ported from Ribose contributions from Botan. * @@ -32,15 +32,54 @@ ll=(c)->G; (void)HOST_l2c(ll, (s)); \ ll=(c)->H; (void)HOST_l2c(ll, (s)); \ } while (0) -#define HASH_BLOCK_DATA_ORDER ossl_sm3_block_data_order + +#if defined(OPENSSL_SM3_ASM) +# if defined(__aarch64__) || defined(_M_ARM64) +# include "crypto/arm_arch.h" +# define HWSM3_CAPABLE (OPENSSL_armcap_P & ARMV8_SM3) +void ossl_hwsm3_block_data_order(SM3_CTX *c, const void *p, size_t num); +# endif +# if defined(OPENSSL_CPUID_OBJ) && defined(__riscv) && __riscv_xlen == 64 +# include "crypto/riscv_arch.h" +# define HWSM3_CAPABLE 1 +void ossl_hwsm3_block_data_order(SM3_CTX *c, const void *p, size_t num); +# endif +#endif + +#if defined(HWSM3_CAPABLE) +# define HASH_BLOCK_DATA_ORDER (HWSM3_CAPABLE ? ossl_hwsm3_block_data_order \ + : ossl_sm3_block_data_order) +#else +# define HASH_BLOCK_DATA_ORDER ossl_sm3_block_data_order +#endif void ossl_sm3_block_data_order(SM3_CTX *c, const void *p, size_t num); void ossl_sm3_transform(SM3_CTX *c, const unsigned char *data); #include "crypto/md32_common.h" -#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) -#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) +#ifndef PEDANTIC +# if defined(__GNUC__) && __GNUC__>=2 && \ + !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) +# if defined(__riscv_zksh) +# define P0(x) ({ MD32_REG_T ret; \ + asm ("sm3p0 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# define P1(x) ({ MD32_REG_T ret; \ + asm ("sm3p1 %0, %1" \ + : "=r"(ret) \ + : "r"(x)); ret; }) +# endif +# endif +#endif + +#ifndef P0 +# define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17)) +#endif +#ifndef P1 +# define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23)) +#endif #define FF0(X,Y,Z) (X ^ Y ^ Z) #define GG0(X,Y,Z) (X ^ Y ^ Z) diff --git a/crypto/sm4/build.info b/crypto/sm4/build.info index b65a7d149e58..990797a30e13 100644 --- a/crypto/sm4/build.info +++ b/crypto/sm4/build.info @@ -1,4 +1,40 @@ LIBS=../../libcrypto -SOURCE[../../libcrypto]=\ - sm4.c +IF[{- !$disabled{asm} -}] + $SM4DEF_aarch64=SM4_ASM VPSM4_ASM + $SM4ASM_aarch64=sm4-armv8.S vpsm4-armv8.S vpsm4_ex-armv8.S + + $SM4DEF_riscv64=SM4_ASM + $SM4ASM_riscv64=sm4-riscv64-zvksed.s + + # Now that we have defined all the arch specific variables, use the + # appropriate one, and define the appropriate macros + IF[$SM4ASM_{- $target{asm_arch} -}] + $SM4ASM=$SM4ASM_{- $target{asm_arch} -} + $SM4DEF=$SM4DEF_{- $target{asm_arch} -} + ENDIF +ENDIF + +SOURCE[../../libcrypto]= $SM4ASM sm4.c + + +# Implementations are now spread across several libraries, so the defines +# need to be applied to all affected libraries and modules. +DEFINE[../../libcrypto]=$SM4DEF +DEFINE[../../providers/libfips.a]=$SM4DEF +DEFINE[../../providers/libdefault.a]=$SM4DEF +# We only need to include the SM4DEF 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} -}] + DEFINE[../../providers/liblegacy.a]=$SM4DEF +ENDIF + +GENERATE[sm4-armv8.S]=asm/sm4-armv8.pl +GENERATE[vpsm4-armv8.S]=asm/vpsm4-armv8.pl +GENERATE[vpsm4_ex-armv8.S]=asm/vpsm4_ex-armv8.pl +INCLUDE[sm4-armv8.o]=.. +INCLUDE[vpsm4-armv8.o]=.. +INCLUDE[vpsm4_ex-armv8.o]=.. +GENERATE[sm4-riscv64-zvksed.s]=asm/sm4-riscv64-zvksed.pl diff --git a/crypto/sm4/sm4.c b/crypto/sm4/sm4.c index 1e11ee650632..194ef7e4bbf0 100644 --- a/crypto/sm4/sm4.c +++ b/crypto/sm4/sm4.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2017 Ribose Inc. All Rights Reserved. * Ported from Ribose contributions from Botan. * @@ -40,7 +40,7 @@ static const uint8_t SM4_S[256] = { /* * SM4_SBOX_T[j] == L(SM4_SBOX[j]). */ -static const uint32_t SM4_SBOX_T[256] = { +static const uint32_t SM4_SBOX_T0[256] = { 0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787, 0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B, 0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D, @@ -85,6 +85,141 @@ static const uint32_t SM4_SBOX_T[256] = { 0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8, 0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 }; +static uint32_t SM4_SBOX_T1[256] = { + 0x5B8ED55B, 0x42D09242, 0xA74DEAA7, 0xFB06FDFB, 0x33FCCF33, 0x8765E287, + 0xF4C93DF4, 0xDE6BB5DE, 0x584E1658, 0xDA6EB4DA, 0x50441450, 0x0BCAC10B, + 0xA08828A0, 0xEF17F8EF, 0xB09C2CB0, 0x14110514, 0xAC872BAC, 0x9DFB669D, + 0x6AF2986A, 0xD9AE77D9, 0xA8822AA8, 0xFA46BCFA, 0x10140410, 0x0FCFC00F, + 0xAA02A8AA, 0x11544511, 0x4C5F134C, 0x98BE2698, 0x256D4825, 0x1A9E841A, + 0x181E0618, 0x66FD9B66, 0x72EC9E72, 0x094A4309, 0x41105141, 0xD324F7D3, + 0x46D59346, 0xBF53ECBF, 0x62F89A62, 0xE9927BE9, 0xCCFF33CC, 0x51045551, + 0x2C270B2C, 0x0D4F420D, 0xB759EEB7, 0x3FF3CC3F, 0xB21CAEB2, 0x89EA6389, + 0x9374E793, 0xCE7FB1CE, 0x706C1C70, 0xA60DABA6, 0x27EDCA27, 0x20280820, + 0xA348EBA3, 0x56C19756, 0x02808202, 0x7FA3DC7F, 0x52C49652, 0xEB12F9EB, + 0xD5A174D5, 0x3EB38D3E, 0xFCC33FFC, 0x9A3EA49A, 0x1D5B461D, 0x1C1B071C, + 0x9E3BA59E, 0xF30CFFF3, 0xCF3FF0CF, 0xCDBF72CD, 0x5C4B175C, 0xEA52B8EA, + 0x0E8F810E, 0x653D5865, 0xF0CC3CF0, 0x647D1964, 0x9B7EE59B, 0x16918716, + 0x3D734E3D, 0xA208AAA2, 0xA1C869A1, 0xADC76AAD, 0x06858306, 0xCA7AB0CA, + 0xC5B570C5, 0x91F46591, 0x6BB2D96B, 0x2EA7892E, 0xE318FBE3, 0xAF47E8AF, + 0x3C330F3C, 0x2D674A2D, 0xC1B071C1, 0x590E5759, 0x76E99F76, 0xD4E135D4, + 0x78661E78, 0x90B42490, 0x38360E38, 0x79265F79, 0x8DEF628D, 0x61385961, + 0x4795D247, 0x8A2AA08A, 0x94B12594, 0x88AA2288, 0xF18C7DF1, 0xECD73BEC, + 0x04050104, 0x84A52184, 0xE19879E1, 0x1E9B851E, 0x5384D753, 0x00000000, + 0x195E4719, 0x5D0B565D, 0x7EE39D7E, 0x4F9FD04F, 0x9CBB279C, 0x491A5349, + 0x317C4D31, 0xD8EE36D8, 0x080A0208, 0x9F7BE49F, 0x8220A282, 0x13D4C713, + 0x23E8CB23, 0x7AE69C7A, 0xAB42E9AB, 0xFE43BDFE, 0x2AA2882A, 0x4B9AD14B, + 0x01404101, 0x1FDBC41F, 0xE0D838E0, 0xD661B7D6, 0x8E2FA18E, 0xDF2BF4DF, + 0xCB3AF1CB, 0x3BF6CD3B, 0xE71DFAE7, 0x85E56085, 0x54411554, 0x8625A386, + 0x8360E383, 0xBA16ACBA, 0x75295C75, 0x9234A692, 0x6EF7996E, 0xD0E434D0, + 0x68721A68, 0x55015455, 0xB619AFB6, 0x4EDF914E, 0xC8FA32C8, 0xC0F030C0, + 0xD721F6D7, 0x32BC8E32, 0xC675B3C6, 0x8F6FE08F, 0x74691D74, 0xDB2EF5DB, + 0x8B6AE18B, 0xB8962EB8, 0x0A8A800A, 0x99FE6799, 0x2BE2C92B, 0x81E06181, + 0x03C0C303, 0xA48D29A4, 0x8CAF238C, 0xAE07A9AE, 0x34390D34, 0x4D1F524D, + 0x39764F39, 0xBDD36EBD, 0x5781D657, 0x6FB7D86F, 0xDCEB37DC, 0x15514415, + 0x7BA6DD7B, 0xF709FEF7, 0x3AB68C3A, 0xBC932FBC, 0x0C0F030C, 0xFF03FCFF, + 0xA9C26BA9, 0xC9BA73C9, 0xB5D96CB5, 0xB1DC6DB1, 0x6D375A6D, 0x45155045, + 0x36B98F36, 0x6C771B6C, 0xBE13ADBE, 0x4ADA904A, 0xEE57B9EE, 0x77A9DE77, + 0xF24CBEF2, 0xFD837EFD, 0x44551144, 0x67BDDA67, 0x712C5D71, 0x05454005, + 0x7C631F7C, 0x40501040, 0x69325B69, 0x63B8DB63, 0x28220A28, 0x07C5C207, + 0xC4F531C4, 0x22A88A22, 0x9631A796, 0x37F9CE37, 0xED977AED, 0xF649BFF6, + 0xB4992DB4, 0xD1A475D1, 0x4390D343, 0x485A1248, 0xE258BAE2, 0x9771E697, + 0xD264B6D2, 0xC270B2C2, 0x26AD8B26, 0xA5CD68A5, 0x5ECB955E, 0x29624B29, + 0x303C0C30, 0x5ACE945A, 0xDDAB76DD, 0xF9867FF9, 0x95F16495, 0xE65DBBE6, + 0xC735F2C7, 0x242D0924, 0x17D1C617, 0xB9D66FB9, 0x1BDEC51B, 0x12948612, + 0x60781860, 0xC330F3C3, 0xF5897CF5, 0xB35CEFB3, 0xE8D23AE8, 0x73ACDF73, + 0x35794C35, 0x80A02080, 0xE59D78E5, 0xBB56EDBB, 0x7D235E7D, 0xF8C63EF8, + 0x5F8BD45F, 0x2FE7C82F, 0xE4DD39E4, 0x21684921}; + +static uint32_t SM4_SBOX_T2[256] = { + 0x5B5B8ED5, 0x4242D092, 0xA7A74DEA, 0xFBFB06FD, 0x3333FCCF, 0x878765E2, + 0xF4F4C93D, 0xDEDE6BB5, 0x58584E16, 0xDADA6EB4, 0x50504414, 0x0B0BCAC1, + 0xA0A08828, 0xEFEF17F8, 0xB0B09C2C, 0x14141105, 0xACAC872B, 0x9D9DFB66, + 0x6A6AF298, 0xD9D9AE77, 0xA8A8822A, 0xFAFA46BC, 0x10101404, 0x0F0FCFC0, + 0xAAAA02A8, 0x11115445, 0x4C4C5F13, 0x9898BE26, 0x25256D48, 0x1A1A9E84, + 0x18181E06, 0x6666FD9B, 0x7272EC9E, 0x09094A43, 0x41411051, 0xD3D324F7, + 0x4646D593, 0xBFBF53EC, 0x6262F89A, 0xE9E9927B, 0xCCCCFF33, 0x51510455, + 0x2C2C270B, 0x0D0D4F42, 0xB7B759EE, 0x3F3FF3CC, 0xB2B21CAE, 0x8989EA63, + 0x939374E7, 0xCECE7FB1, 0x70706C1C, 0xA6A60DAB, 0x2727EDCA, 0x20202808, + 0xA3A348EB, 0x5656C197, 0x02028082, 0x7F7FA3DC, 0x5252C496, 0xEBEB12F9, + 0xD5D5A174, 0x3E3EB38D, 0xFCFCC33F, 0x9A9A3EA4, 0x1D1D5B46, 0x1C1C1B07, + 0x9E9E3BA5, 0xF3F30CFF, 0xCFCF3FF0, 0xCDCDBF72, 0x5C5C4B17, 0xEAEA52B8, + 0x0E0E8F81, 0x65653D58, 0xF0F0CC3C, 0x64647D19, 0x9B9B7EE5, 0x16169187, + 0x3D3D734E, 0xA2A208AA, 0xA1A1C869, 0xADADC76A, 0x06068583, 0xCACA7AB0, + 0xC5C5B570, 0x9191F465, 0x6B6BB2D9, 0x2E2EA789, 0xE3E318FB, 0xAFAF47E8, + 0x3C3C330F, 0x2D2D674A, 0xC1C1B071, 0x59590E57, 0x7676E99F, 0xD4D4E135, + 0x7878661E, 0x9090B424, 0x3838360E, 0x7979265F, 0x8D8DEF62, 0x61613859, + 0x474795D2, 0x8A8A2AA0, 0x9494B125, 0x8888AA22, 0xF1F18C7D, 0xECECD73B, + 0x04040501, 0x8484A521, 0xE1E19879, 0x1E1E9B85, 0x535384D7, 0x00000000, + 0x19195E47, 0x5D5D0B56, 0x7E7EE39D, 0x4F4F9FD0, 0x9C9CBB27, 0x49491A53, + 0x31317C4D, 0xD8D8EE36, 0x08080A02, 0x9F9F7BE4, 0x828220A2, 0x1313D4C7, + 0x2323E8CB, 0x7A7AE69C, 0xABAB42E9, 0xFEFE43BD, 0x2A2AA288, 0x4B4B9AD1, + 0x01014041, 0x1F1FDBC4, 0xE0E0D838, 0xD6D661B7, 0x8E8E2FA1, 0xDFDF2BF4, + 0xCBCB3AF1, 0x3B3BF6CD, 0xE7E71DFA, 0x8585E560, 0x54544115, 0x868625A3, + 0x838360E3, 0xBABA16AC, 0x7575295C, 0x929234A6, 0x6E6EF799, 0xD0D0E434, + 0x6868721A, 0x55550154, 0xB6B619AF, 0x4E4EDF91, 0xC8C8FA32, 0xC0C0F030, + 0xD7D721F6, 0x3232BC8E, 0xC6C675B3, 0x8F8F6FE0, 0x7474691D, 0xDBDB2EF5, + 0x8B8B6AE1, 0xB8B8962E, 0x0A0A8A80, 0x9999FE67, 0x2B2BE2C9, 0x8181E061, + 0x0303C0C3, 0xA4A48D29, 0x8C8CAF23, 0xAEAE07A9, 0x3434390D, 0x4D4D1F52, + 0x3939764F, 0xBDBDD36E, 0x575781D6, 0x6F6FB7D8, 0xDCDCEB37, 0x15155144, + 0x7B7BA6DD, 0xF7F709FE, 0x3A3AB68C, 0xBCBC932F, 0x0C0C0F03, 0xFFFF03FC, + 0xA9A9C26B, 0xC9C9BA73, 0xB5B5D96C, 0xB1B1DC6D, 0x6D6D375A, 0x45451550, + 0x3636B98F, 0x6C6C771B, 0xBEBE13AD, 0x4A4ADA90, 0xEEEE57B9, 0x7777A9DE, + 0xF2F24CBE, 0xFDFD837E, 0x44445511, 0x6767BDDA, 0x71712C5D, 0x05054540, + 0x7C7C631F, 0x40405010, 0x6969325B, 0x6363B8DB, 0x2828220A, 0x0707C5C2, + 0xC4C4F531, 0x2222A88A, 0x969631A7, 0x3737F9CE, 0xEDED977A, 0xF6F649BF, + 0xB4B4992D, 0xD1D1A475, 0x434390D3, 0x48485A12, 0xE2E258BA, 0x979771E6, + 0xD2D264B6, 0xC2C270B2, 0x2626AD8B, 0xA5A5CD68, 0x5E5ECB95, 0x2929624B, + 0x30303C0C, 0x5A5ACE94, 0xDDDDAB76, 0xF9F9867F, 0x9595F164, 0xE6E65DBB, + 0xC7C735F2, 0x24242D09, 0x1717D1C6, 0xB9B9D66F, 0x1B1BDEC5, 0x12129486, + 0x60607818, 0xC3C330F3, 0xF5F5897C, 0xB3B35CEF, 0xE8E8D23A, 0x7373ACDF, + 0x3535794C, 0x8080A020, 0xE5E59D78, 0xBBBB56ED, 0x7D7D235E, 0xF8F8C63E, + 0x5F5F8BD4, 0x2F2FE7C8, 0xE4E4DD39, 0x21216849}; + +static uint32_t SM4_SBOX_T3[256] = { + 0xD55B5B8E, 0x924242D0, 0xEAA7A74D, 0xFDFBFB06, 0xCF3333FC, 0xE2878765, + 0x3DF4F4C9, 0xB5DEDE6B, 0x1658584E, 0xB4DADA6E, 0x14505044, 0xC10B0BCA, + 0x28A0A088, 0xF8EFEF17, 0x2CB0B09C, 0x05141411, 0x2BACAC87, 0x669D9DFB, + 0x986A6AF2, 0x77D9D9AE, 0x2AA8A882, 0xBCFAFA46, 0x04101014, 0xC00F0FCF, + 0xA8AAAA02, 0x45111154, 0x134C4C5F, 0x269898BE, 0x4825256D, 0x841A1A9E, + 0x0618181E, 0x9B6666FD, 0x9E7272EC, 0x4309094A, 0x51414110, 0xF7D3D324, + 0x934646D5, 0xECBFBF53, 0x9A6262F8, 0x7BE9E992, 0x33CCCCFF, 0x55515104, + 0x0B2C2C27, 0x420D0D4F, 0xEEB7B759, 0xCC3F3FF3, 0xAEB2B21C, 0x638989EA, + 0xE7939374, 0xB1CECE7F, 0x1C70706C, 0xABA6A60D, 0xCA2727ED, 0x08202028, + 0xEBA3A348, 0x975656C1, 0x82020280, 0xDC7F7FA3, 0x965252C4, 0xF9EBEB12, + 0x74D5D5A1, 0x8D3E3EB3, 0x3FFCFCC3, 0xA49A9A3E, 0x461D1D5B, 0x071C1C1B, + 0xA59E9E3B, 0xFFF3F30C, 0xF0CFCF3F, 0x72CDCDBF, 0x175C5C4B, 0xB8EAEA52, + 0x810E0E8F, 0x5865653D, 0x3CF0F0CC, 0x1964647D, 0xE59B9B7E, 0x87161691, + 0x4E3D3D73, 0xAAA2A208, 0x69A1A1C8, 0x6AADADC7, 0x83060685, 0xB0CACA7A, + 0x70C5C5B5, 0x659191F4, 0xD96B6BB2, 0x892E2EA7, 0xFBE3E318, 0xE8AFAF47, + 0x0F3C3C33, 0x4A2D2D67, 0x71C1C1B0, 0x5759590E, 0x9F7676E9, 0x35D4D4E1, + 0x1E787866, 0x249090B4, 0x0E383836, 0x5F797926, 0x628D8DEF, 0x59616138, + 0xD2474795, 0xA08A8A2A, 0x259494B1, 0x228888AA, 0x7DF1F18C, 0x3BECECD7, + 0x01040405, 0x218484A5, 0x79E1E198, 0x851E1E9B, 0xD7535384, 0x00000000, + 0x4719195E, 0x565D5D0B, 0x9D7E7EE3, 0xD04F4F9F, 0x279C9CBB, 0x5349491A, + 0x4D31317C, 0x36D8D8EE, 0x0208080A, 0xE49F9F7B, 0xA2828220, 0xC71313D4, + 0xCB2323E8, 0x9C7A7AE6, 0xE9ABAB42, 0xBDFEFE43, 0x882A2AA2, 0xD14B4B9A, + 0x41010140, 0xC41F1FDB, 0x38E0E0D8, 0xB7D6D661, 0xA18E8E2F, 0xF4DFDF2B, + 0xF1CBCB3A, 0xCD3B3BF6, 0xFAE7E71D, 0x608585E5, 0x15545441, 0xA3868625, + 0xE3838360, 0xACBABA16, 0x5C757529, 0xA6929234, 0x996E6EF7, 0x34D0D0E4, + 0x1A686872, 0x54555501, 0xAFB6B619, 0x914E4EDF, 0x32C8C8FA, 0x30C0C0F0, + 0xF6D7D721, 0x8E3232BC, 0xB3C6C675, 0xE08F8F6F, 0x1D747469, 0xF5DBDB2E, + 0xE18B8B6A, 0x2EB8B896, 0x800A0A8A, 0x679999FE, 0xC92B2BE2, 0x618181E0, + 0xC30303C0, 0x29A4A48D, 0x238C8CAF, 0xA9AEAE07, 0x0D343439, 0x524D4D1F, + 0x4F393976, 0x6EBDBDD3, 0xD6575781, 0xD86F6FB7, 0x37DCDCEB, 0x44151551, + 0xDD7B7BA6, 0xFEF7F709, 0x8C3A3AB6, 0x2FBCBC93, 0x030C0C0F, 0xFCFFFF03, + 0x6BA9A9C2, 0x73C9C9BA, 0x6CB5B5D9, 0x6DB1B1DC, 0x5A6D6D37, 0x50454515, + 0x8F3636B9, 0x1B6C6C77, 0xADBEBE13, 0x904A4ADA, 0xB9EEEE57, 0xDE7777A9, + 0xBEF2F24C, 0x7EFDFD83, 0x11444455, 0xDA6767BD, 0x5D71712C, 0x40050545, + 0x1F7C7C63, 0x10404050, 0x5B696932, 0xDB6363B8, 0x0A282822, 0xC20707C5, + 0x31C4C4F5, 0x8A2222A8, 0xA7969631, 0xCE3737F9, 0x7AEDED97, 0xBFF6F649, + 0x2DB4B499, 0x75D1D1A4, 0xD3434390, 0x1248485A, 0xBAE2E258, 0xE6979771, + 0xB6D2D264, 0xB2C2C270, 0x8B2626AD, 0x68A5A5CD, 0x955E5ECB, 0x4B292962, + 0x0C30303C, 0x945A5ACE, 0x76DDDDAB, 0x7FF9F986, 0x649595F1, 0xBBE6E65D, + 0xF2C7C735, 0x0924242D, 0xC61717D1, 0x6FB9B9D6, 0xC51B1BDE, 0x86121294, + 0x18606078, 0xF3C3C330, 0x7CF5F589, 0xEFB3B35C, 0x3AE8E8D2, 0xDF7373AC, + 0x4C353579, 0x208080A0, 0x78E5E59D, 0xEDBBBB56, 0x5E7D7D23, 0x3EF8F8C6, + 0xD45F5F8B, 0xC82F2FE7, 0x39E4E4DD, 0x49212168}; + static ossl_inline uint32_t rotl(uint32_t a, uint8_t n) { return (a << n) | (a >> (32 - n)); @@ -106,7 +241,7 @@ static ossl_inline void store_u32_be(uint32_t v, uint8_t *b) b[3] = (uint8_t)(v); } -static ossl_inline uint32_t SM4_T_slow(uint32_t X) +static ossl_inline uint32_t SM4_T_non_lin_sub(uint32_t X) { uint32_t t = 0; @@ -115,6 +250,13 @@ static ossl_inline uint32_t SM4_T_slow(uint32_t X) t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; t |= SM4_S[(uint8_t)X]; + return t; +} + +static ossl_inline uint32_t SM4_T_slow(uint32_t X) +{ + uint32_t t = SM4_T_non_lin_sub(X); + /* * L linear transform */ @@ -123,10 +265,17 @@ static ossl_inline uint32_t SM4_T_slow(uint32_t X) static ossl_inline uint32_t SM4_T(uint32_t X) { - return SM4_SBOX_T[(uint8_t)(X >> 24)] ^ - rotl(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^ - rotl(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^ - rotl(SM4_SBOX_T[(uint8_t)X], 8); + return SM4_SBOX_T0[(uint8_t)(X >> 24)] ^ + SM4_SBOX_T1[(uint8_t)(X >> 16)] ^ + SM4_SBOX_T2[(uint8_t)(X >> 8)] ^ + SM4_SBOX_T3[(uint8_t)X]; +} + +static ossl_inline uint32_t SM4_key_sub(uint32_t X) +{ + uint32_t t = SM4_T_non_lin_sub(X); + + return t ^ rotl(t, 13) ^ rotl(t, 23); } int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks) @@ -134,8 +283,9 @@ int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks) /* * Family Key */ - static const uint32_t FK[4] = - { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc }; + static const uint32_t FK[4] = { + 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc + }; /* * Constant Key @@ -159,18 +309,15 @@ int ossl_sm4_set_key(const uint8_t *key, SM4_KEY *ks) K[2] = load_u32_be(key, 2) ^ FK[2]; K[3] = load_u32_be(key, 3) ^ FK[3]; - for (i = 0; i != SM4_KEY_SCHEDULE; ++i) { - uint32_t X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i]; - uint32_t t = 0; - - t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24; - t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16; - t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8; - t |= SM4_S[(uint8_t)X]; - - t = t ^ rotl(t, 13) ^ rotl(t, 23); - K[i % 4] ^= t; - ks->rk[i] = K[i % 4]; + for (i = 0; i < SM4_KEY_SCHEDULE; i = i + 4) { + K[0] ^= SM4_key_sub(K[1] ^ K[2] ^ K[3] ^ CK[i]); + K[1] ^= SM4_key_sub(K[2] ^ K[3] ^ K[0] ^ CK[i + 1]); + K[2] ^= SM4_key_sub(K[3] ^ K[0] ^ K[1] ^ CK[i + 2]); + K[3] ^= SM4_key_sub(K[0] ^ K[1] ^ K[2] ^ CK[i + 3]); + ks->rk[i ] = K[0]; + ks->rk[i + 1] = K[1]; + ks->rk[i + 2] = K[2]; + ks->rk[i + 3] = K[3]; } return 1; diff --git a/crypto/sparse_array.c b/crypto/sparse_array.c index bbbc9cdb3696..a41936517e72 100644 --- a/crypto/sparse_array.c +++ b/crypto/sparse_array.c @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 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 @@ -19,7 +19,7 @@ * depth of the tree but potentially wastes more memory. That is, this is a * direct space versus time tradeoff. * - * The default is to use four bits which means that the are 16 + * The default is to use four bits which means that there are 16 * pointers in each tree node. * * The library builder is also permitted to define other sizes in the closed diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c index 4b842dfd9129..5f626d70555c 100644 --- a/crypto/srp/srp_vfy.c +++ b/crypto/srp/srp_vfy.c @@ -191,10 +191,8 @@ SRP_user_pwd *SRP_user_pwd_new(void) { SRP_user_pwd *ret; - if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) { - /* ERR_raise(ERR_LIB_SRP, ERR_R_MALLOC_FAILURE); */ /*ckerr_ignore*/ + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) return NULL; - } ret->N = NULL; ret->g = NULL; ret->s = NULL; @@ -396,7 +394,7 @@ static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch) int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) { - int error_code; + int error_code = SRP_ERR_MEMORY; STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null(); char *last_index = NULL; int i; @@ -408,8 +406,16 @@ int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file) TXT_DB *tmpdb = NULL; BIO *in = BIO_new(BIO_s_file()); + if (SRP_gN_tab == NULL) + goto err; + error_code = SRP_ERR_OPEN_FILE; + if (verifier_file == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + if (in == NULL || BIO_read_filename(in, verifier_file) <= 0) goto err; @@ -631,7 +637,7 @@ char *SRP_create_verifier_ex(const char *user, const char *pass, char **salt, if (N_bn_alloc == NULL) goto err; N_bn = N_bn_alloc; - if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0) + if ((len = t_fromb64(tmp, sizeof(tmp), g)) <= 0) goto err; g_bn_alloc = BN_bin2bn(tmp, len, NULL); if (g_bn_alloc == NULL) diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index 51080b876797..e81398962470 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,10 +10,13 @@ #include #include "internal/cryptlib.h" #include "internal/numbers.h" +#include "internal/safe_math.h" #include #include #include /* For ossl_inline */ +OSSL_SAFE_MATH_SIGNED(int, int) + /* * The initial number of nodes in the array. */ @@ -72,7 +75,6 @@ OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) return ret; err: - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); OPENSSL_sk_free(ret); return NULL; } @@ -121,7 +123,6 @@ OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, return ret; err: - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); OPENSSL_sk_free(ret); return NULL; } @@ -139,32 +140,35 @@ OPENSSL_STACK *OPENSSL_sk_new(OPENSSL_sk_compfunc c) /* * Calculate the array growth based on the target size. * - * The growth fraction is a rational number and is defined by a numerator + * The growth factor is a rational number and is defined by a numerator * and a denominator. According to Andrew Koenig in his paper "Why Are * Vectors Efficient?" from JOOP 11(5) 1998, this factor should be less * than the golden ratio (1.618...). * - * We use 3/2 = 1.5 for simplicity of calculation and overflow checking. - * Another option 8/5 = 1.6 allows for slightly faster growth, although safe - * computation is more difficult. + * Considering only the Fibonacci ratios less than the golden ratio, the + * number of steps from the minimum allocation to integer overflow is: + * factor decimal growths + * 3/2 1.5 51 + * 8/5 1.6 45 + * 21/13 1.615... 44 * - * The limit to avoid overflow is spot on. The modulo three correction term - * ensures that the limit is the largest number than can be expanded by the - * growth factor without exceeding the hard limit. + * All larger factors have the same number of growths. * - * Do not call it with |current| lower than 2, or it will infinitely loop. + * 3/2 and 8/5 have nice power of two shifts, so seem like a good choice. */ static ossl_inline int compute_growth(int target, int current) { - const int limit = (max_nodes / 3) * 2 + (max_nodes % 3 ? 1 : 0); + int err = 0; while (current < target) { - /* Check to see if we're at the hard limit */ if (current >= max_nodes) return 0; - /* Expand the size by a factor of 3/2 if it is within range */ - current = current < limit ? current + current / 2 : max_nodes; + current = safe_muldiv_int(current, 8, 5, &err); + if (err != 0) + return 0; + if (current >= max_nodes) + current = max_nodes; } return current; } @@ -192,10 +196,8 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact) * At this point, |st->num_alloc| and |st->num| are 0; * so |num_alloc| value is |n| or |min_nodes| if greater than |n|. */ - if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if ((st->data = OPENSSL_zalloc(sizeof(void *) * num_alloc)) == NULL) return 0; - } st->num_alloc = num_alloc; return 1; } @@ -213,10 +215,8 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact) } tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); - if (tmpdata == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (tmpdata == NULL) return 0; - } st->data = tmpdata; st->num_alloc = num_alloc; @@ -227,10 +227,8 @@ OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) { OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); - if (st == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + if (st == NULL) return NULL; - } st->comp = c; @@ -317,39 +315,54 @@ void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) } static int internal_find(OPENSSL_STACK *st, const void *data, - int ret_val_options, int *pnum) + int ret_val_options, int *pnum_matched) { const void *r; - int i; + int i, count = 0; + int *pnum = pnum_matched; if (st == NULL || st->num == 0) return -1; + if (pnum == NULL) + pnum = &count; + if (st->comp == NULL) { for (i = 0; i < st->num; i++) if (st->data[i] == data) { - if (pnum != NULL) - *pnum = 1; + *pnum = 1; return i; } - if (pnum != NULL) - *pnum = 0; + *pnum = 0; return -1; } - if (!st->sorted) { - if (st->num > 1) - qsort(st->data, st->num, sizeof(void *), st->comp); - st->sorted = 1; /* empty or single-element stack is considered sorted */ - } if (data == NULL) return -1; - if (pnum != NULL) + + if (!st->sorted) { + int res = -1; + + for (i = 0; i < st->num; i++) + if (st->comp(&data, st->data + i) == 0) { + if (res == -1) + res = i; + ++*pnum; + /* Check if only one result is wanted and exit if so */ + if (pnum_matched == NULL) + return i; + } + if (res == -1) + *pnum = 0; + return res; + } + + if (pnum_matched != NULL) ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH; r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, ret_val_options); - if (pnum != NULL) { + if (pnum_matched != NULL) { *pnum = 0; if (r != NULL) { const void **p = (const void **)r; @@ -384,7 +397,7 @@ int OPENSSL_sk_find_all(OPENSSL_STACK *st, const void *data, int *pnum) int OPENSSL_sk_push(OPENSSL_STACK *st, const void *data) { if (st == NULL) - return -1; + return 0; return OPENSSL_sk_insert(st, data, st->num); } diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index bc12d8dd13a2..505d606f4a9b 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,7 +14,7 @@ /* We need to use some STORE deprecated APIs */ #define OPENSSL_SUPPRESS_DEPRECATED -#include "e_os.h" +#include "internal/e_os.h" #include #include @@ -66,6 +66,7 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, OSSL_STORE_post_process_info_fn post_process, void *post_process_data) { + struct ossl_passphrase_data_st pwdata = { 0 }; const OSSL_STORE_LOADER *loader = NULL; OSSL_STORE_LOADER *fetched_loader = NULL; OSSL_STORE_LOADER_CTX *loader_ctx = NULL; @@ -94,7 +95,7 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, if ((p = strchr(scheme_copy, ':')) != NULL) { *p++ = '\0'; if (OPENSSL_strcasecmp(scheme_copy, "file") != 0) { - if (strncmp(p, "//", 2) == 0) + if (HAS_PREFIX(p, "//")) schemes_n--; /* Invalidate the file scheme */ schemes[schemes_n++] = scheme_copy; } @@ -102,6 +103,13 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, ERR_set_mark(); + if (ui_method != NULL + && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data) + || !ossl_pw_enable_passphrase_caching(&pwdata))) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); + goto err; + } + /* * Try each scheme until we find one that could open the URI. * @@ -114,13 +122,17 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, scheme = schemes[i]; OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme); #ifndef OPENSSL_NO_DEPRECATED_3_0 + ERR_set_mark(); if ((loader = ossl_store_get0_loader_int(scheme)) != NULL) { + ERR_clear_last_mark(); no_loader_found = 0; if (loader->open_ex != NULL) loader_ctx = loader->open_ex(loader, uri, libctx, propq, ui_method, ui_data); else loader_ctx = loader->open(loader, uri, ui_method, ui_data); + } else { + ERR_pop_to_mark(); } #endif if (loader == NULL @@ -131,17 +143,28 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider); no_loader_found = 0; - loader_ctx = fetched_loader->p_open(provctx, uri); + if (fetched_loader->p_open_ex != NULL) { + loader_ctx = + fetched_loader->p_open_ex(provctx, uri, params, + ossl_pw_passphrase_callback_dec, + &pwdata); + } else { + if (fetched_loader->p_open != NULL && + (loader_ctx = fetched_loader->p_open(provctx, uri)) != NULL && + !loader_set_params(fetched_loader, loader_ctx, + params, propq)) { + (void)fetched_loader->p_close(loader_ctx); + loader_ctx = NULL; + } + } if (loader_ctx == NULL) { OSSL_STORE_LOADER_free(fetched_loader); fetched_loader = NULL; - } else if(!loader_set_params(fetched_loader, loader_ctx, - params, propq)) { - (void)fetched_loader->p_close(loader_ctx); - OSSL_STORE_LOADER_free(fetched_loader); - fetched_loader = NULL; } loader = fetched_loader; + + /* Clear any internally cached passphrase */ + (void)ossl_pw_clear_passphrase_cache(&pwdata); } } @@ -164,23 +187,16 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx); if ((propq != NULL && (propq_copy = OPENSSL_strdup(propq)) == NULL) - || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) goto err; - } - if (ui_method != NULL - && (!ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data) - || !ossl_pw_enable_passphrase_caching(&ctx->pwdata))) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); - goto err; - } ctx->properties = propq_copy; ctx->fetched_loader = fetched_loader; ctx->loader = loader; ctx->loader_ctx = loader_ctx; ctx->post_process = post_process; ctx->post_process_data = post_process_data; + ctx->pwdata = pwdata; /* * If the attempt to open with the 'file' scheme loader failed and the @@ -211,6 +227,8 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, */ (void)ossl_store_close_it(&tmpctx); } + /* Coverity false positive, the reference counting is confusing it */ + /* coverity[pass_freed_arg] */ OSSL_STORE_LOADER_free(fetched_loader); OPENSSL_free(propq_copy); OPENSSL_free(ctx); @@ -332,7 +350,7 @@ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search) } if ((bld = OSSL_PARAM_BLD_new()) == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); return 0; } @@ -476,6 +494,53 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx) return v; } +int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + const OSSL_PARAM params[]) +{ + OSSL_STORE_LOADER *fetched_loader = NULL; + char scheme[256], *p; + int res = 0; + struct ossl_passphrase_data_st pwdata = {0}; + + OPENSSL_strlcpy(scheme, uri, sizeof(scheme)); + if ((p = strchr(scheme, ':')) != NULL) + *p++ = '\0'; + else /* We don't work without explicit scheme */ + return 0; + + if (ui_method != NULL + && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data) + || !ossl_pw_enable_passphrase_caching(&pwdata))) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); + return 0; + } + + OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme); + fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq); + + if (fetched_loader != NULL && fetched_loader->p_delete != NULL) { + const OSSL_PROVIDER *provider = + OSSL_STORE_LOADER_get0_provider(fetched_loader); + void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider); + + /* + * It's assumed that the loader's delete() method reports its own + * errors + */ + OSSL_TRACE1(STORE, "Performing URI delete %s\n", uri); + res = fetched_loader->p_delete(provctx, uri, params, + ossl_pw_passphrase_callback_dec, + &pwdata); + } + /* Clear any internally cached passphrase */ + (void)ossl_pw_clear_passphrase_cache(&pwdata); + + OSSL_STORE_LOADER_free(fetched_loader); + + return res; +} + int OSSL_STORE_error(OSSL_STORE_CTX *ctx) { int ret = 1; @@ -556,7 +621,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_NAME(char *name) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_NAME, NULL); if (info == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return NULL; } @@ -582,7 +647,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PARAMS(EVP_PKEY *params) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PARAMS, params); if (info == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return info; } @@ -591,7 +656,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PUBKEY(EVP_PKEY *pkey) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PUBKEY, pkey); if (info == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return info; } @@ -600,7 +665,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_PKEY(EVP_PKEY *pkey) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_PKEY, pkey); if (info == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return info; } @@ -609,7 +674,7 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CERT(X509 *x509) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CERT, x509); if (info == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return info; } @@ -618,12 +683,12 @@ OSSL_STORE_INFO *OSSL_STORE_INFO_new_CRL(X509_CRL *crl) OSSL_STORE_INFO *info = OSSL_STORE_INFO_new(OSSL_STORE_INFO_CRL, crl); if (info == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_OSSL_STORE_LIB); return info; } /* - * Functions to try to extract data from a OSSL_STORE_INFO. + * Functions to try to extract data from an OSSL_STORE_INFO. */ int OSSL_STORE_INFO_get_type(const OSSL_STORE_INFO *info) { @@ -646,13 +711,8 @@ const char *OSSL_STORE_INFO_get0_NAME(const OSSL_STORE_INFO *info) char *OSSL_STORE_INFO_get1_NAME(const OSSL_STORE_INFO *info) { - if (info->type == OSSL_STORE_INFO_NAME) { - char *ret = OPENSSL_strdup(info->_.name.name); - - if (ret == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); - return ret; - } + if (info->type == OSSL_STORE_INFO_NAME) + return OPENSSL_strdup(info->_.name.name); ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME); return NULL; } @@ -666,14 +726,8 @@ const char *OSSL_STORE_INFO_get0_NAME_description(const OSSL_STORE_INFO *info) char *OSSL_STORE_INFO_get1_NAME_description(const OSSL_STORE_INFO *info) { - if (info->type == OSSL_STORE_INFO_NAME) { - char *ret = OPENSSL_strdup(info->_.name.desc - ? info->_.name.desc : ""); - - if (ret == NULL) - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); - return ret; - } + if (info->type == OSSL_STORE_INFO_NAME) + return OPENSSL_strdup(info->_.name.desc ? info->_.name.desc : ""); ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_NAME); return NULL; } @@ -688,7 +742,8 @@ EVP_PKEY *OSSL_STORE_INFO_get0_PARAMS(const OSSL_STORE_INFO *info) EVP_PKEY *OSSL_STORE_INFO_get1_PARAMS(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_PARAMS) { - EVP_PKEY_up_ref(info->_.params); + if (!EVP_PKEY_up_ref(info->_.params)) + return NULL; return info->_.params; } ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_PARAMETERS); @@ -705,7 +760,8 @@ EVP_PKEY *OSSL_STORE_INFO_get0_PUBKEY(const OSSL_STORE_INFO *info) EVP_PKEY *OSSL_STORE_INFO_get1_PUBKEY(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_PUBKEY) { - EVP_PKEY_up_ref(info->_.pubkey); + if (!EVP_PKEY_up_ref(info->_.pubkey)) + return NULL; return info->_.pubkey; } ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PUBLIC_KEY); @@ -722,7 +778,8 @@ EVP_PKEY *OSSL_STORE_INFO_get0_PKEY(const OSSL_STORE_INFO *info) EVP_PKEY *OSSL_STORE_INFO_get1_PKEY(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_PKEY) { - EVP_PKEY_up_ref(info->_.pkey); + if (!EVP_PKEY_up_ref(info->_.pkey)) + return NULL; return info->_.pkey; } ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_PRIVATE_KEY); @@ -739,7 +796,8 @@ X509 *OSSL_STORE_INFO_get0_CERT(const OSSL_STORE_INFO *info) X509 *OSSL_STORE_INFO_get1_CERT(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_CERT) { - X509_up_ref(info->_.x509); + if (!X509_up_ref(info->_.x509)) + return NULL; return info->_.x509; } ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CERTIFICATE); @@ -756,7 +814,8 @@ X509_CRL *OSSL_STORE_INFO_get0_CRL(const OSSL_STORE_INFO *info) X509_CRL *OSSL_STORE_INFO_get1_CRL(const OSSL_STORE_INFO *info) { if (info->type == OSSL_STORE_INFO_CRL) { - X509_CRL_up_ref(info->_.crl); + if (!X509_CRL_up_ref(info->_.crl)) + return NULL; return info->_.crl; } ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_NOT_A_CRL); @@ -852,10 +911,8 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_name(X509_NAME *name) { OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); - if (search == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + if (search == NULL) return NULL; - } search->search_type = OSSL_STORE_SEARCH_BY_NAME; search->name = name; @@ -867,10 +924,8 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_issuer_serial(X509_NAME *name, { OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); - if (search == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + if (search == NULL) return NULL; - } search->search_type = OSSL_STORE_SEARCH_BY_ISSUER_SERIAL; search->name = name; @@ -883,17 +938,22 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_key_fingerprint(const EVP_MD *digest, *bytes, size_t len) { OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); + int md_size; - if (search == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + if (search == NULL) + return NULL; + + md_size = EVP_MD_get_size(digest); + if (md_size <= 0) { + OPENSSL_free(search); return NULL; } - if (digest != NULL && len != (size_t)EVP_MD_get_size(digest)) { + if (digest != NULL && len != (size_t)md_size) { ERR_raise_data(ERR_LIB_OSSL_STORE, OSSL_STORE_R_FINGERPRINT_SIZE_DOES_NOT_MATCH_DIGEST, "%s size is %d, fingerprint size is %zu", - EVP_MD_get0_name(digest), EVP_MD_get_size(digest), len); + EVP_MD_get0_name(digest), md_size, len); OPENSSL_free(search); return NULL; } @@ -909,10 +969,8 @@ OSSL_STORE_SEARCH *OSSL_STORE_SEARCH_by_alias(const char *alias) { OSSL_STORE_SEARCH *search = OPENSSL_zalloc(sizeof(*search)); - if (search == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + if (search == NULL) return NULL; - } search->search_type = OSSL_STORE_SEARCH_BY_ALIAS; search->string = (const unsigned char *)alias; @@ -991,6 +1049,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme, OSSL_CORE_BIO *cbio = ossl_core_bio_new_from_bio(bp); if (cbio == NULL + || fetched_loader->p_attach == NULL || (loader_ctx = fetched_loader->p_attach(provctx, cbio)) == NULL) { OSSL_STORE_LOADER_free(fetched_loader); fetched_loader = NULL; @@ -1011,7 +1070,6 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme, if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { ERR_clear_last_mark(); - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); return NULL; } @@ -1029,7 +1087,7 @@ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme, ctx->post_process_data = post_process_data; /* - * ossl_store_get0_loader_int will raise an error if the loader for the + * ossl_store_get0_loader_int will raise an error if the loader for * the scheme cannot be retrieved. But if a loader was successfully * fetched then we remove this error from the error stack. */ diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index 8f817fd514bb..6ad79180a091 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -1,5 +1,5 @@ /* - * 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 @@ -103,7 +103,6 @@ struct ossl_store_loader_st { const char *description; CRYPTO_REF_COUNT refcnt; - CRYPTO_RWLOCK *lock; OSSL_FUNC_store_open_fn *p_open; OSSL_FUNC_store_attach_fn *p_attach; @@ -113,8 +112,10 @@ struct ossl_store_loader_st { OSSL_FUNC_store_eof_fn *p_eof; OSSL_FUNC_store_close_fn *p_close; OSSL_FUNC_store_export_object_fn *p_export_object; + OSSL_FUNC_store_delete_fn *p_delete; + OSSL_FUNC_store_open_ex_fn *p_open_ex; }; -DEFINE_LHASH_OF(OSSL_STORE_LOADER); +DEFINE_LHASH_OF_EX(OSSL_STORE_LOADER); const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme); void ossl_store_destroy_loaders_int(void); @@ -168,9 +169,6 @@ int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx); OSSL_STORE_LOADER *ossl_store_loader_fetch(OSSL_LIB_CTX *libctx, const char *scheme, const char *properties); -OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx, - int scheme_id, - const char *properties); /* Standard function to handle the result from OSSL_FUNC_store_load() */ struct ossl_load_result_data_st { diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c index a5b0d1b0957c..7cf69d229086 100644 --- a/crypto/store/store_meth.c +++ b/crypto/store/store_meth.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,13 +14,14 @@ #include "internal/property.h" #include "internal/provider.h" #include "store_local.h" +#include "crypto/context.h" int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader) { int ref = 0; if (loader->prov != NULL) - CRYPTO_UP_REF(&loader->refcnt, &ref, loader->lock); + CRYPTO_UP_REF(&loader->refcnt, &ref); return 1; } @@ -29,11 +30,11 @@ void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) if (loader != NULL && loader->prov != NULL) { int i; - CRYPTO_DOWN_REF(&loader->refcnt, &i, loader->lock); + CRYPTO_DOWN_REF(&loader->refcnt, &i); if (i > 0) return; ossl_provider_free(loader->prov); - CRYPTO_THREAD_lock_free(loader->lock); + CRYPTO_FREE_REF(&loader->refcnt); } OPENSSL_free(loader); } @@ -47,13 +48,15 @@ static OSSL_STORE_LOADER *new_loader(OSSL_PROVIDER *prov) OSSL_STORE_LOADER *loader; if ((loader = OPENSSL_zalloc(sizeof(*loader))) == NULL - || (loader->lock = CRYPTO_THREAD_lock_new()) == NULL) { + || !CRYPTO_NEW_REF(&loader->refcnt, 1) + || !ossl_provider_up_ref(prov)) { + if (loader != NULL) + CRYPTO_FREE_REF(&loader->refcnt); OPENSSL_free(loader); return NULL; } + loader->prov = prov; - ossl_provider_up_ref(prov); - loader->refcnt = 1; return loader; } @@ -68,25 +71,6 @@ static void free_loader(void *method) OSSL_STORE_LOADER_free(method); } -/* Permanent loader method store, constructor and destructor */ -static void loader_store_free(void *vstore) -{ - ossl_method_store_free(vstore); -} - -static void *loader_store_new(OSSL_LIB_CTX *ctx) -{ - return ossl_method_store_new(ctx); -} - - -static const OSSL_LIB_CTX_METHOD loader_store_method = { - /* We want loader_store to be cleaned up before the provider store */ - OSSL_LIB_CTX_METHOD_PRIORITY_2, - loader_store_new, - loader_store_free, -}; - /* Data to be passed through ossl_method_construct() */ struct loader_data_st { OSSL_LIB_CTX *libctx; @@ -123,8 +107,7 @@ static void *get_tmp_loader_store(void *data) /* Get the permanent loader store */ static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx) { - return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX, - &loader_store_method); + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX); } static int reserve_loader_store(void *store, void *data) @@ -239,6 +222,14 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, if (loader->p_export_object == NULL) loader->p_export_object = OSSL_FUNC_store_export_object(fns); break; + case OSSL_FUNC_STORE_DELETE: + if (loader->p_delete == NULL) + loader->p_delete = OSSL_FUNC_store_delete(fns); + break; + case OSSL_FUNC_STORE_OPEN_EX: + if (loader->p_open_ex == NULL) + loader->p_open_ex = OSSL_FUNC_store_open_ex(fns); + break; } } @@ -246,7 +237,7 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, || loader->p_load == NULL || loader->p_eof == NULL || loader->p_close == NULL) { - /* Only set_ctx_params is optionaal */ + /* Only set_ctx_params is optional */ OSSL_STORE_LOADER_free(loader); ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE); return NULL; @@ -297,39 +288,28 @@ static void destruct_loader(void *method, void *data) /* Fetching support. Can fetch by numeric identity or by scheme */ static OSSL_STORE_LOADER * -inner_loader_fetch(struct loader_data_st *methdata, int id, +inner_loader_fetch(struct loader_data_st *methdata, const char *scheme, const char *properties) { OSSL_METHOD_STORE *store = get_loader_store(methdata->libctx); OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx); const char *const propq = properties != NULL ? properties : ""; void *method = NULL; - int unsupported = 0; + int unsupported, id; if (store == NULL || namemap == NULL) { ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; } - /* - * If we have been passed both an id and a scheme, we have an - * internal programming error. - */ - if (!ossl_assert(id == 0 || scheme == NULL)) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR); - return NULL; - } - /* If we haven't received a name id yet, try to get one for the name */ - if (id == 0 && scheme != NULL) - id = ossl_namemap_name2num(namemap, scheme); + id = scheme != NULL ? ossl_namemap_name2num(namemap, scheme) : 0; /* * If we haven't found the name yet, chances are that the algorithm to * be fetched is unsupported. */ - if (id == 0) - unsupported = 1; + unsupported = id == 0; if (id == 0 || !ossl_method_store_cache_get(store, NULL, id, propq, &method)) { @@ -400,21 +380,7 @@ OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx, methdata.libctx = libctx; methdata.tmp_store = NULL; - method = inner_loader_fetch(&methdata, 0, scheme, properties); - dealloc_tmp_loader_store(methdata.tmp_store); - return method; -} - -OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx, - int scheme_id, - const char *properties) -{ - struct loader_data_st methdata; - void *method; - - methdata.libctx = libctx; - methdata.tmp_store = NULL; - method = inner_loader_fetch(&methdata, scheme_id, NULL, properties); + method = inner_loader_fetch(&methdata, scheme, properties); dealloc_tmp_loader_store(methdata.tmp_store); return method; } @@ -510,7 +476,7 @@ void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx, methdata.libctx = libctx; methdata.tmp_store = NULL; - (void)inner_loader_fetch(&methdata, 0, NULL, NULL /* properties */); + (void)inner_loader_fetch(&methdata, NULL, NULL /* properties */); data.user_fn = user_fn; data.user_arg = user_arg; diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c index 6fa7352ccdc1..6f73e197200d 100644 --- a/crypto/store/store_register.c +++ b/crypto/store/store_register.c @@ -43,10 +43,8 @@ OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme) return NULL; } - if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + if ((res = OPENSSL_zalloc(sizeof(*res))) == NULL) return NULL; - } res->engine = e; res->scheme = scheme; @@ -191,7 +189,8 @@ int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) } if (!RUN_ONCE(®istry_init, do_registry_init)) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + /* Should this error be raised in do_registry_init()? */ + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); return 0; } if (!CRYPTO_THREAD_write_lock(registry_lock)) @@ -224,7 +223,8 @@ const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme) template.open_ex = NULL; if (!RUN_ONCE(®istry_init, do_registry_init)) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + /* Should this error be raised in do_registry_init()? */ + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); return NULL; } if (!CRYPTO_THREAD_write_lock(registry_lock)) @@ -254,7 +254,8 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme) template.closefn = NULL; if (!RUN_ONCE(®istry_init, do_registry_init)) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE); + /* Should this error be raised in do_registry_init()? */ + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); return NULL; } if (!CRYPTO_THREAD_write_lock(registry_lock)) diff --git a/crypto/store/store_result.c b/crypto/store/store_result.c index bbc8f6fef265..b5e50557c238 100644 --- a/crypto/store/store_result.c +++ b/crypto/store/store_result.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include @@ -20,6 +20,7 @@ #include #include "internal/provider.h" #include "internal/passphrase.h" +#include "crypto/decoder.h" #include "crypto/evp.h" #include "crypto/x509.h" #include "store_local.h" @@ -62,6 +63,7 @@ struct extracted_param_data_st { int object_type; const char *data_type; + const char *input_type; const char *data_structure; const char *utf8_data; const void *octet_data; @@ -114,6 +116,10 @@ int ossl_store_handle_load_result(const OSSL_PARAM params[], void *arg) if (p != NULL && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.data_structure)) return 0; + p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_INPUT_TYPE); + if (p != NULL + && !OSSL_PARAM_get_utf8_string_ptr(p, &helper_data.input_type)) + return 0; p = OSSL_PARAM_locate_const(params, OSSL_OBJECT_PARAM_REFERENCE); if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p, &helper_data.ref, &helper_data.ref_size)) @@ -259,7 +265,8 @@ static EVP_PKEY *try_key_ref(struct extracted_param_data_st *data, static EVP_PKEY *try_key_value(struct extracted_param_data_st *data, OSSL_STORE_CTX *ctx, OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg, - OSSL_LIB_CTX *libctx, const char *propq) + OSSL_LIB_CTX *libctx, const char *propq, + int *harderr) { EVP_PKEY *pk = NULL; OSSL_DECODER_CTX *decoderctx = NULL; @@ -286,7 +293,7 @@ static EVP_PKEY *try_key_value(struct extracted_param_data_st *data, } decoderctx = - OSSL_DECODER_CTX_new_for_pkey(&pk, NULL, data->data_structure, + OSSL_DECODER_CTX_new_for_pkey(&pk, data->input_type, data->data_structure, data->data_type, selection, libctx, propq); (void)OSSL_DECODER_CTX_set_passphrase_cb(decoderctx, cb, cbarg); @@ -294,6 +301,8 @@ static EVP_PKEY *try_key_value(struct extracted_param_data_st *data, /* No error if this couldn't be decoded */ (void)OSSL_DECODER_from_data(decoderctx, &pdata, &pdatalen); + /* Save the hard error state. */ + *harderr = ossl_decoder_ctx_get_harderr(decoderctx); OSSL_DECODER_CTX_free(decoderctx); return pk; @@ -388,6 +397,7 @@ static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, OSSL_LIB_CTX *libctx, const char *propq) { store_info_new_fn *store_info_new = NULL; + int harderr = 0; if (data->object_type == OSSL_OBJECT_UNKNOWN || data->object_type == OSSL_OBJECT_PKEY) { @@ -409,7 +419,7 @@ static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, OSSL_PASSPHRASE_CALLBACK *cb = ossl_pw_passphrase_callback_dec; void *cbarg = &ctx->pwdata; - pk = try_key_value(data, ctx, cb, cbarg, libctx, propq); + pk = try_key_value(data, ctx, cb, cbarg, libctx, propq, &harderr); /* * Desperate last maneuver, in case the decoders don't support @@ -418,7 +428,7 @@ static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, * This is the same as der2key_decode() does, but in a limited * way and within the walls of libcrypto. */ - if (pk == NULL) + if (pk == NULL && harderr == 0) pk = try_key_value_legacy(data, &store_info_new, ctx, cb, cbarg, libctx, propq); } @@ -450,7 +460,7 @@ static int try_key(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, EVP_PKEY_free(pk); } - return 1; + return harderr == 0; } static int try_cert(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, @@ -629,7 +639,7 @@ static int try_pkcs12(struct extracted_param_data_st *data, OSSL_STORE_INFO **v, } EVP_PKEY_free(pkey); X509_free(cert); - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); OSSL_STORE_INFO_free(osi_pkey); OSSL_STORE_INFO_free(osi_cert); OSSL_STORE_INFO_free(osi_ca); diff --git a/crypto/store/store_strings.c b/crypto/store/store_strings.c index 3d4a8ea73079..45c3f52acbf4 100644 --- a/crypto/store/store_strings.c +++ b/crypto/store/store_strings.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,8 @@ #include +#include "internal/nelem.h" + static char *type_strings[] = { "Name", /* OSSL_STORE_INFO_NAME */ "Parameters", /* OSSL_STORE_INFO_PARAMS */ @@ -20,7 +22,7 @@ static char *type_strings[] = { const char *OSSL_STORE_INFO_type_string(int type) { - int types = sizeof(type_strings) / sizeof(type_strings[0]); + int types = OSSL_NELEM(type_strings); if (type < 1 || type > types) return NULL; diff --git a/crypto/threads_lib.c b/crypto/threads_lib.c index 0c7162392df8..240ef726ec78 100644 --- a/crypto/threads_lib.c +++ b/crypto/threads_lib.c @@ -8,7 +8,8 @@ */ #include -#ifndef OPENSSL_NO_DEPRECATED_3_0 +#ifdef OPENSSL_SYS_UNIX +# ifndef OPENSSL_NO_DEPRECATED_3_0 void OPENSSL_fork_prepare(void) { @@ -22,4 +23,5 @@ void OPENSSL_fork_child(void) { } +# endif #endif diff --git a/crypto/threads_none.c b/crypto/threads_none.c index 2570efde2378..240b7d9fdcfe 100644 --- a/crypto/threads_none.c +++ b/crypto/threads_none.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,8 @@ #include #include "internal/cryptlib.h" +#include "internal/rcu.h" +#include "rcu_internal.h" #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) @@ -17,14 +19,90 @@ # include # endif +struct rcu_lock_st { + struct rcu_cb_item *cb_items; +}; + +CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, + ossl_unused OSSL_LIB_CTX *ctx) +{ + struct rcu_lock_st *lock; + + lock = OPENSSL_zalloc(sizeof(*lock)); + return lock; +} + +void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock) +{ + OPENSSL_free(lock); +} + +void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock) +{ + return; +} + +void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock) +{ + return; +} + +void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock) +{ + return; +} + +void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock) +{ + return; +} + +void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_cb_item *items = lock->cb_items; + struct rcu_cb_item *tmp; + + lock->cb_items = NULL; + + while (items != NULL) { + tmp = items->next; + items->fn(items->data); + OPENSSL_free(items); + items = tmp; + } +} + +int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data) +{ + struct rcu_cb_item *new = OPENSSL_zalloc(sizeof(*new)); + + if (new == NULL) + return 0; + + new->fn = cb; + new->data = data; + new->next = lock->cb_items; + lock->cb_items = new; + return 1; +} + +void *ossl_rcu_uptr_deref(void **p) +{ + return (void *)*p; +} + +void ossl_rcu_assign_uptr(void **p, void **v) +{ + *(void **)p = *(void **)v; +} + CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) { CRYPTO_RWLOCK *lock; - if ((lock = OPENSSL_zalloc(sizeof(unsigned int))) == NULL) { + if ((lock = CRYPTO_zalloc(sizeof(unsigned int), NULL, 0)) == NULL) /* Don't set error, to avoid recursion blowup. */ return NULL; - } *(unsigned int *)lock = 1; @@ -73,7 +151,7 @@ int CRYPTO_THREAD_run_once(CRYPTO_ONCE *once, void (*init)(void)) return 1; } -#define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256 +# define OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX 256 static void *thread_local_storage[OPENSSL_CRYPTO_THREAD_LOCAL_KEY_MAX]; @@ -133,6 +211,24 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ + *val += op; + *ret = *val; + + return 1; +} + +int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ + *val &= op; + *ret = *val; + + return 1; +} + int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock) { @@ -149,6 +245,20 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock) +{ + *dst = val; + + return 1; +} + +int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ + *ret = *val; + + return 1; +} + int openssl_init_fork_handlers(void) { return 0; diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c index 801855c9306e..750ef201210b 100644 --- a/crypto/threads_pthread.c +++ b/crypto/threads_pthread.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,28 @@ #define OPENSSL_SUPPRESS_DEPRECATED #include +#include #include "internal/cryptlib.h" +#include "internal/rcu.h" +#include "rcu_internal.h" + +#if defined(__clang__) && defined(__has_feature) +# if __has_feature(thread_sanitizer) +# define __SANITIZE_THREAD__ +# endif +#endif + +#if defined(__SANITIZE_THREAD__) +# include +# define TSAN_FAKE_UNLOCK(x) __tsan_mutex_pre_unlock((x), 0); \ +__tsan_mutex_post_unlock((x), 0) + +# define TSAN_FAKE_LOCK(x) __tsan_mutex_pre_lock((x), 0); \ +__tsan_mutex_post_lock((x), 0, 0) +#else +# define TSAN_FAKE_UNLOCK(x) +# define TSAN_FAKE_LOCK(x) +#endif #if defined(__sun) # include @@ -26,7 +47,7 @@ * * See: https://github.com/llvm/llvm-project/commit/a4c2602b714e6c6edb98164550a5ae829b2de760 */ -#define BROKEN_CLANG_ATOMICS +# define BROKEN_CLANG_ATOMICS #endif #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && !defined(OPENSSL_SYS_WINDOWS) @@ -34,23 +55,535 @@ # if defined(OPENSSL_SYS_UNIX) # include # include -#endif +# endif # include -# ifdef PTHREAD_RWLOCK_INITIALIZER +/* + * The Non-Stop KLT thread model currently seems broken in its rwlock + * implementation + */ +# if defined(PTHREAD_RWLOCK_INITIALIZER) && !defined(_KLT_MODEL_) # define USE_RWLOCK # endif +/* + * For all GNU/clang atomic builtins, we also need fallbacks, to cover all + * other compilers. + + * Unfortunately, we can't do that with some "generic type", because there's no + * guarantee that the chosen generic type is large enough to cover all cases. + * Therefore, we implement fallbacks for each applicable type, with composed + * names that include the type they handle. + * + * (an anecdote: we previously tried to use |void *| as the generic type, with + * the thought that the pointer itself is the largest type. However, this is + * not true on 32-bit pointer platforms, as a |uint64_t| is twice as large) + * + * All applicable ATOMIC_ macros take the intended type as first parameter, so + * they can map to the correct fallback function. In the GNU/clang case, that + * parameter is simply ignored. + */ + +/* + * Internal types used with the ATOMIC_ macros, to make it possible to compose + * fallback function names. + */ +typedef void *pvoid; + +# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS) \ + && !defined(USE_ATOMIC_FALLBACKS) +# define ATOMIC_LOAD_N(t, p, o) __atomic_load_n(p, o) +# define ATOMIC_STORE_N(t, p, v, o) __atomic_store_n(p, v, o) +# define ATOMIC_STORE(t, p, v, o) __atomic_store(p, v, o) +# define ATOMIC_ADD_FETCH(p, v, o) __atomic_add_fetch(p, v, o) +# define ATOMIC_SUB_FETCH(p, v, o) __atomic_sub_fetch(p, v, o) +# else +static pthread_mutex_t atomic_sim_lock = PTHREAD_MUTEX_INITIALIZER; + +# define IMPL_fallback_atomic_load_n(t) \ + static ossl_inline t fallback_atomic_load_n_##t(t *p) \ + { \ + t ret; \ + \ + pthread_mutex_lock(&atomic_sim_lock); \ + ret = *p; \ + pthread_mutex_unlock(&atomic_sim_lock); \ + return ret; \ + } +IMPL_fallback_atomic_load_n(uint32_t) +IMPL_fallback_atomic_load_n(uint64_t) +IMPL_fallback_atomic_load_n(pvoid) + +# define ATOMIC_LOAD_N(t, p, o) fallback_atomic_load_n_##t(p) + +# define IMPL_fallback_atomic_store_n(t) \ + static ossl_inline t fallback_atomic_store_n_##t(t *p, t v) \ + { \ + t ret; \ + \ + pthread_mutex_lock(&atomic_sim_lock); \ + ret = *p; \ + *p = v; \ + pthread_mutex_unlock(&atomic_sim_lock); \ + return ret; \ + } +IMPL_fallback_atomic_store_n(uint32_t) + +# define ATOMIC_STORE_N(t, p, v, o) fallback_atomic_store_n_##t(p, v) + +# define IMPL_fallback_atomic_store(t) \ + static ossl_inline void fallback_atomic_store_##t(t *p, t *v) \ + { \ + pthread_mutex_lock(&atomic_sim_lock); \ + *p = *v; \ + pthread_mutex_unlock(&atomic_sim_lock); \ + } +IMPL_fallback_atomic_store(pvoid) + +# define ATOMIC_STORE(t, p, v, o) fallback_atomic_store_##t(p, v) + +/* + * The fallbacks that follow don't need any per type implementation, as + * they are designed for uint64_t only. If there comes a time when multiple + * types need to be covered, it's relatively easy to refactor them the same + * way as the fallbacks above. + */ + +static ossl_inline uint64_t fallback_atomic_add_fetch(uint64_t *p, uint64_t v) +{ + uint64_t ret; + + pthread_mutex_lock(&atomic_sim_lock); + *p += v; + ret = *p; + pthread_mutex_unlock(&atomic_sim_lock); + return ret; +} + +# define ATOMIC_ADD_FETCH(p, v, o) fallback_atomic_add_fetch(p, v) + +static ossl_inline uint64_t fallback_atomic_sub_fetch(uint64_t *p, uint64_t v) +{ + uint64_t ret; + + pthread_mutex_lock(&atomic_sim_lock); + *p -= v; + ret = *p; + pthread_mutex_unlock(&atomic_sim_lock); + return ret; +} + +# define ATOMIC_SUB_FETCH(p, v, o) fallback_atomic_sub_fetch(p, v) +# endif + +/* + * This is the core of an rcu lock. It tracks the readers and writers for the + * current quiescence point for a given lock. Users is the 64 bit value that + * stores the READERS/ID as defined above + * + */ +struct rcu_qp { + uint64_t users; +}; + +struct thread_qp { + struct rcu_qp *qp; + unsigned int depth; + CRYPTO_RCU_LOCK *lock; +}; + +# define MAX_QPS 10 +/* + * This is the per thread tracking data + * that is assigned to each thread participating + * in an rcu qp + * + * qp points to the qp that it last acquired + * + */ +struct rcu_thr_data { + struct thread_qp thread_qps[MAX_QPS]; +}; + +/* + * This is the internal version of a CRYPTO_RCU_LOCK + * it is cast from CRYPTO_RCU_LOCK + */ +struct rcu_lock_st { + /* Callbacks to call for next ossl_synchronize_rcu */ + struct rcu_cb_item *cb_items; + + /* The context we are being created against */ + OSSL_LIB_CTX *ctx; + + /* Array of quiescent points for synchronization */ + struct rcu_qp *qp_group; + + /* rcu generation counter for in-order retirement */ + uint32_t id_ctr; + + /* Number of elements in qp_group array */ + uint32_t group_count; + + /* Index of the current qp in the qp_group array */ + uint32_t reader_idx; + + /* value of the next id_ctr value to be retired */ + uint32_t next_to_retire; + + /* index of the next free rcu_qp in the qp_group */ + uint32_t current_alloc_idx; + + /* number of qp's in qp_group array currently being retired */ + uint32_t writers_alloced; + + /* lock protecting write side operations */ + pthread_mutex_t write_lock; + + /* lock protecting updates to writers_alloced/current_alloc_idx */ + pthread_mutex_t alloc_lock; + + /* signal to wake threads waiting on alloc_lock */ + pthread_cond_t alloc_signal; + + /* lock to enforce in-order retirement */ + pthread_mutex_t prior_lock; + + /* signal to wake threads waiting on prior_lock */ + pthread_cond_t prior_signal; +}; + +/* Read side acquisition of the current qp */ +static struct rcu_qp *get_hold_current_qp(struct rcu_lock_st *lock) +{ + uint32_t qp_idx; + + /* get the current qp index */ + for (;;) { + qp_idx = ATOMIC_LOAD_N(uint32_t, &lock->reader_idx, __ATOMIC_RELAXED); + + /* + * Notes on use of __ATOMIC_ACQUIRE + * We need to ensure the following: + * 1) That subsequent operations aren't optimized by hoisting them above + * this operation. Specifically, we don't want the below re-load of + * qp_idx to get optimized away + * 2) We want to ensure that any updating of reader_idx on the write side + * of the lock is flushed from a local cpu cache so that we see any + * updates prior to the load. This is a non-issue on cache coherent + * systems like x86, but is relevant on other arches + */ + ATOMIC_ADD_FETCH(&lock->qp_group[qp_idx].users, (uint64_t)1, + __ATOMIC_ACQUIRE); + + /* if the idx hasn't changed, we're good, else try again */ + if (qp_idx == ATOMIC_LOAD_N(uint32_t, &lock->reader_idx, + __ATOMIC_RELAXED)) + break; + + ATOMIC_SUB_FETCH(&lock->qp_group[qp_idx].users, (uint64_t)1, + __ATOMIC_RELAXED); + } + + return &lock->qp_group[qp_idx]; +} + +static void ossl_rcu_free_local_data(void *arg) +{ + OSSL_LIB_CTX *ctx = arg; + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(ctx); + struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey); + + OPENSSL_free(data); + CRYPTO_THREAD_set_local(lkey, NULL); +} + +void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_thr_data *data; + int i, available_qp = -1; + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx); + + /* + * we're going to access current_qp here so ask the + * processor to fetch it + */ + data = CRYPTO_THREAD_get_local(lkey); + + if (data == NULL) { + data = OPENSSL_zalloc(sizeof(*data)); + OPENSSL_assert(data != NULL); + CRYPTO_THREAD_set_local(lkey, data); + ossl_init_thread_start(NULL, lock->ctx, ossl_rcu_free_local_data); + } + + for (i = 0; i < MAX_QPS; i++) { + if (data->thread_qps[i].qp == NULL && available_qp == -1) + available_qp = i; + /* If we have a hold on this lock already, we're good */ + if (data->thread_qps[i].lock == lock) { + data->thread_qps[i].depth++; + return; + } + } + + /* + * if we get here, then we don't have a hold on this lock yet + */ + assert(available_qp != -1); + + data->thread_qps[available_qp].qp = get_hold_current_qp(lock); + data->thread_qps[available_qp].depth = 1; + data->thread_qps[available_qp].lock = lock; +} + +void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock) +{ + int i; + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx); + struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey); + uint64_t ret; + + assert(data != NULL); + + for (i = 0; i < MAX_QPS; i++) { + if (data->thread_qps[i].lock == lock) { + /* + * we have to use __ATOMIC_RELEASE here + * to ensure that all preceding read instructions complete + * before the decrement is visible to ossl_synchronize_rcu + */ + data->thread_qps[i].depth--; + if (data->thread_qps[i].depth == 0) { + ret = ATOMIC_SUB_FETCH(&data->thread_qps[i].qp->users, + (uint64_t)1, __ATOMIC_RELEASE); + OPENSSL_assert(ret != UINT64_MAX); + data->thread_qps[i].qp = NULL; + data->thread_qps[i].lock = NULL; + } + return; + } + } + /* + * If we get here, we're trying to unlock a lock that we never acquired - + * that's fatal. + */ + assert(0); +} + +/* + * Write side allocation routine to get the current qp + * and replace it with a new one + */ +static struct rcu_qp *update_qp(CRYPTO_RCU_LOCK *lock, uint32_t *curr_id) +{ + uint32_t current_idx; + + pthread_mutex_lock(&lock->alloc_lock); + + /* + * we need at least one qp to be available with one + * left over, so that readers can start working on + * one that isn't yet being waited on + */ + while (lock->group_count - lock->writers_alloced < 2) + /* we have to wait for one to be free */ + pthread_cond_wait(&lock->alloc_signal, &lock->alloc_lock); + + current_idx = lock->current_alloc_idx; + + /* Allocate the qp */ + lock->writers_alloced++; + + /* increment the allocation index */ + lock->current_alloc_idx = + (lock->current_alloc_idx + 1) % lock->group_count; + + *curr_id = lock->id_ctr; + lock->id_ctr++; + + ATOMIC_STORE_N(uint32_t, &lock->reader_idx, lock->current_alloc_idx, + __ATOMIC_RELAXED); + + /* + * this should make sure that the new value of reader_idx is visible in + * get_hold_current_qp, directly after incrementing the users count + */ + ATOMIC_ADD_FETCH(&lock->qp_group[current_idx].users, (uint64_t)0, + __ATOMIC_RELEASE); + + /* wake up any waiters */ + pthread_cond_signal(&lock->alloc_signal); + pthread_mutex_unlock(&lock->alloc_lock); + return &lock->qp_group[current_idx]; +} + +static void retire_qp(CRYPTO_RCU_LOCK *lock, struct rcu_qp *qp) +{ + pthread_mutex_lock(&lock->alloc_lock); + lock->writers_alloced--; + pthread_cond_signal(&lock->alloc_signal); + pthread_mutex_unlock(&lock->alloc_lock); +} + +static struct rcu_qp *allocate_new_qp_group(CRYPTO_RCU_LOCK *lock, + uint32_t count) +{ + struct rcu_qp *new = + OPENSSL_zalloc(sizeof(*new) * count); + + lock->group_count = count; + return new; +} + +void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock) +{ + pthread_mutex_lock(&lock->write_lock); + TSAN_FAKE_UNLOCK(&lock->write_lock); +} + +void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock) +{ + TSAN_FAKE_LOCK(&lock->write_lock); + pthread_mutex_unlock(&lock->write_lock); +} + +void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_qp *qp; + uint64_t count; + uint32_t curr_id; + struct rcu_cb_item *cb_items, *tmpcb; + + pthread_mutex_lock(&lock->write_lock); + cb_items = lock->cb_items; + lock->cb_items = NULL; + pthread_mutex_unlock(&lock->write_lock); + + qp = update_qp(lock, &curr_id); + + /* retire in order */ + pthread_mutex_lock(&lock->prior_lock); + while (lock->next_to_retire != curr_id) + pthread_cond_wait(&lock->prior_signal, &lock->prior_lock); + + /* + * wait for the reader count to reach zero + * Note the use of __ATOMIC_ACQUIRE here to ensure that any + * prior __ATOMIC_RELEASE write operation in ossl_rcu_read_unlock + * is visible prior to our read + * however this is likely just necessary to silence a tsan warning + * because the read side should not do any write operation + * outside the atomic itself + */ + do { + count = ATOMIC_LOAD_N(uint64_t, &qp->users, __ATOMIC_ACQUIRE); + } while (count != (uint64_t)0); + + lock->next_to_retire++; + pthread_cond_broadcast(&lock->prior_signal); + pthread_mutex_unlock(&lock->prior_lock); + + retire_qp(lock, qp); + + /* handle any callbacks that we have */ + while (cb_items != NULL) { + tmpcb = cb_items; + cb_items = cb_items->next; + tmpcb->fn(tmpcb->data); + OPENSSL_free(tmpcb); + } +} + +/* + * Note: This call assumes its made under the protection of + * ossl_rcu_write_lock + */ +int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data) +{ + struct rcu_cb_item *new = + OPENSSL_zalloc(sizeof(*new)); + + if (new == NULL) + return 0; + + new->data = data; + new->fn = cb; + + new->next = lock->cb_items; + lock->cb_items = new; + + return 1; +} + +void *ossl_rcu_uptr_deref(void **p) +{ + return ATOMIC_LOAD_N(pvoid, p, __ATOMIC_ACQUIRE); +} + +void ossl_rcu_assign_uptr(void **p, void **v) +{ + ATOMIC_STORE(pvoid, p, v, __ATOMIC_RELEASE); +} + +CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx) +{ + struct rcu_lock_st *new; + + /* + * We need a minimum of 2 qp's + */ + if (num_writers < 2) + num_writers = 2; + + ctx = ossl_lib_ctx_get_concrete(ctx); + if (ctx == NULL) + return 0; + + new = OPENSSL_zalloc(sizeof(*new)); + if (new == NULL) + return NULL; + + new->ctx = ctx; + pthread_mutex_init(&new->write_lock, NULL); + pthread_mutex_init(&new->prior_lock, NULL); + pthread_mutex_init(&new->alloc_lock, NULL); + pthread_cond_init(&new->prior_signal, NULL); + pthread_cond_init(&new->alloc_signal, NULL); + + new->qp_group = allocate_new_qp_group(new, num_writers); + if (new->qp_group == NULL) { + OPENSSL_free(new); + new = NULL; + } + + return new; +} + +void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_lock_st *rlock = (struct rcu_lock_st *)lock; + + if (lock == NULL) + return; + + /* make sure we're synchronized */ + ossl_synchronize_rcu(rlock); + + OPENSSL_free(rlock->qp_group); + /* There should only be a single qp left now */ + OPENSSL_free(rlock); +} + CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) { # ifdef USE_RWLOCK CRYPTO_RWLOCK *lock; - if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) { + if ((lock = OPENSSL_zalloc(sizeof(pthread_rwlock_t))) == NULL) /* Don't set error, to avoid recursion blowup. */ return NULL; - } if (pthread_rwlock_init(lock, NULL) != 0) { OPENSSL_free(lock); @@ -60,10 +593,9 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) pthread_mutexattr_t attr; CRYPTO_RWLOCK *lock; - if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) { + if ((lock = OPENSSL_zalloc(sizeof(pthread_mutex_t))) == NULL) /* Don't set error, to avoid recursion blowup. */ return NULL; - } /* * We don't use recursive mutexes, but try to catch errors if we do. @@ -222,6 +754,58 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) return 1; } +int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS) + if (__atomic_is_lock_free(sizeof(*val), val)) { + *ret = __atomic_add_fetch(val, op, __ATOMIC_ACQ_REL); + return 1; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (ret != NULL) { + *ret = atomic_add_64_nv(val, op); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val += op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + +int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS) + if (__atomic_is_lock_free(sizeof(*val), val)) { + *ret = __atomic_and_fetch(val, op, __ATOMIC_ACQ_REL); + return 1; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (ret != NULL) { + *ret = atomic_and_64_nv(val, op); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val &= op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock) { @@ -250,7 +834,7 @@ int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) { -# if defined(__GNUC__) && defined(__ATOMIC_ACQUIRE) && !defined(BROKEN_CLANG_ATOMICS) +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS) if (__atomic_is_lock_free(sizeof(*val), val)) { __atomic_load(val, ret, __ATOMIC_ACQUIRE); return 1; @@ -270,6 +854,53 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) return 1; } + +int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS) + if (__atomic_is_lock_free(sizeof(*dst), dst)) { + __atomic_store(dst, &val, __ATOMIC_RELEASE); + return 1; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (dst != NULL) { + atomic_swap_64(dst, val); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *dst = val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + +int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ +# if defined(__GNUC__) && defined(__ATOMIC_ACQ_REL) && !defined(BROKEN_CLANG_ATOMICS) + if (__atomic_is_lock_free(sizeof(*val), val)) { + __atomic_load(val, ret, __ATOMIC_ACQUIRE); + return 1; + } +# elif defined(__sun) && (defined(__SunOS_5_10) || defined(__SunOS_5_11)) + /* This will work for all future Solaris versions. */ + if (ret != NULL) { + *ret = (int)atomic_or_uint_nv((unsigned int *)val, 0); + return 1; + } +# endif + if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) + return 0; + *ret = *val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +} + # ifndef FIPS_MODULE int openssl_init_fork_handlers(void) { diff --git a/crypto/threads_win.c b/crypto/threads_win.c index 43f36ee6a333..97b6d3eb7398 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,6 +13,7 @@ # define USE_RWLOCK # endif #endif +#include /* * VC++ 2008 or earlier x86 compilers do not have an inline implementation @@ -22,11 +23,16 @@ * only VC++ 2008 or earlier x86 compilers. */ -#if (defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1600) +#if ((defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1600) || (defined(__MINGW32__) && !defined(__MINGW64__))) # define NO_INTERLOCKEDOR64 #endif #include +#include +#include "internal/common.h" +#include "internal/thread_arch.h" +#include "internal/rcu.h" +#include "rcu_internal.h" #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS) @@ -37,6 +43,395 @@ typedef struct { } CRYPTO_win_rwlock; # endif +/* + * This defines a quescent point (qp) + * This is the barrier beyond which a writer + * must wait before freeing data that was + * atomically updated + */ +struct rcu_qp { + volatile uint64_t users; +}; + +struct thread_qp { + struct rcu_qp *qp; + unsigned int depth; + CRYPTO_RCU_LOCK *lock; +}; + +# define MAX_QPS 10 +/* + * This is the per thread tracking data + * that is assigned to each thread participating + * in an rcu qp + * + * qp points to the qp that it last acquired + * + */ +struct rcu_thr_data { + struct thread_qp thread_qps[MAX_QPS]; +}; + +/* + * This is the internal version of a CRYPTO_RCU_LOCK + * it is cast from CRYPTO_RCU_LOCK + */ +struct rcu_lock_st { + /* Callbacks to call for next ossl_synchronize_rcu */ + struct rcu_cb_item *cb_items; + + /* The context we are being created against */ + OSSL_LIB_CTX *ctx; + + /* Array of quiescent points for synchronization */ + struct rcu_qp *qp_group; + + /* rcu generation counter for in-order retirement */ + uint32_t id_ctr; + + /* Number of elements in qp_group array */ + uint32_t group_count; + + /* Index of the current qp in the qp_group array */ + uint32_t reader_idx; + + /* value of the next id_ctr value to be retired */ + uint32_t next_to_retire; + + /* index of the next free rcu_qp in the qp_group */ + uint32_t current_alloc_idx; + + /* number of qp's in qp_group array currently being retired */ + uint32_t writers_alloced; + + /* lock protecting write side operations */ + CRYPTO_MUTEX *write_lock; + + /* lock protecting updates to writers_alloced/current_alloc_idx */ + CRYPTO_MUTEX *alloc_lock; + + /* signal to wake threads waiting on alloc_lock */ + CRYPTO_CONDVAR *alloc_signal; + + /* lock to enforce in-order retirement */ + CRYPTO_MUTEX *prior_lock; + + /* signal to wake threads waiting on prior_lock */ + CRYPTO_CONDVAR *prior_signal; + + /* lock used with NO_INTERLOCKEDOR64: VS2010 x86 */ + CRYPTO_RWLOCK *rw_lock; +}; + +static struct rcu_qp *allocate_new_qp_group(struct rcu_lock_st *lock, + uint32_t count) +{ + struct rcu_qp *new = + OPENSSL_zalloc(sizeof(*new) * count); + + lock->group_count = count; + return new; +} + +CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx) +{ + struct rcu_lock_st *new; + + /* + * We need a minimum of 2 qps + */ + if (num_writers < 2) + num_writers = 2; + + ctx = ossl_lib_ctx_get_concrete(ctx); + if (ctx == NULL) + return 0; + + new = OPENSSL_zalloc(sizeof(*new)); + + if (new == NULL) + return NULL; + + new->ctx = ctx; + new->rw_lock = CRYPTO_THREAD_lock_new(); + new->write_lock = ossl_crypto_mutex_new(); + new->alloc_signal = ossl_crypto_condvar_new(); + new->prior_signal = ossl_crypto_condvar_new(); + new->alloc_lock = ossl_crypto_mutex_new(); + new->prior_lock = ossl_crypto_mutex_new(); + new->qp_group = allocate_new_qp_group(new, num_writers); + if (new->qp_group == NULL + || new->alloc_signal == NULL + || new->prior_signal == NULL + || new->write_lock == NULL + || new->alloc_lock == NULL + || new->prior_lock == NULL + || new->rw_lock == NULL) { + CRYPTO_THREAD_lock_free(new->rw_lock); + OPENSSL_free(new->qp_group); + ossl_crypto_condvar_free(&new->alloc_signal); + ossl_crypto_condvar_free(&new->prior_signal); + ossl_crypto_mutex_free(&new->alloc_lock); + ossl_crypto_mutex_free(&new->prior_lock); + ossl_crypto_mutex_free(&new->write_lock); + OPENSSL_free(new); + new = NULL; + } + + return new; + +} + +void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock) +{ + CRYPTO_THREAD_lock_free(lock->rw_lock); + OPENSSL_free(lock->qp_group); + ossl_crypto_condvar_free(&lock->alloc_signal); + ossl_crypto_condvar_free(&lock->prior_signal); + ossl_crypto_mutex_free(&lock->alloc_lock); + ossl_crypto_mutex_free(&lock->prior_lock); + ossl_crypto_mutex_free(&lock->write_lock); + OPENSSL_free(lock); +} + +/* Read side acquisition of the current qp */ +static ossl_inline struct rcu_qp *get_hold_current_qp(CRYPTO_RCU_LOCK *lock) +{ + uint32_t qp_idx; + uint32_t tmp; + uint64_t tmp64; + + /* get the current qp index */ + for (;;) { + CRYPTO_atomic_load_int((int *)&lock->reader_idx, (int *)&qp_idx, + lock->rw_lock); + CRYPTO_atomic_add64(&lock->qp_group[qp_idx].users, (uint64_t)1, &tmp64, + lock->rw_lock); + CRYPTO_atomic_load_int((int *)&lock->reader_idx, (int *)&tmp, + lock->rw_lock); + if (qp_idx == tmp) + break; + CRYPTO_atomic_add64(&lock->qp_group[qp_idx].users, (uint64_t)-1, &tmp64, + lock->rw_lock); + } + + return &lock->qp_group[qp_idx]; +} + +static void ossl_rcu_free_local_data(void *arg) +{ + OSSL_LIB_CTX *ctx = arg; + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(ctx); + struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey); + OPENSSL_free(data); + CRYPTO_THREAD_set_local(lkey, NULL); +} + +void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_thr_data *data; + int i; + int available_qp = -1; + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx); + + /* + * we're going to access current_qp here so ask the + * processor to fetch it + */ + data = CRYPTO_THREAD_get_local(lkey); + + if (data == NULL) { + data = OPENSSL_zalloc(sizeof(*data)); + OPENSSL_assert(data != NULL); + CRYPTO_THREAD_set_local(lkey, data); + ossl_init_thread_start(NULL, lock->ctx, ossl_rcu_free_local_data); + } + + for (i = 0; i < MAX_QPS; i++) { + if (data->thread_qps[i].qp == NULL && available_qp == -1) + available_qp = i; + /* If we have a hold on this lock already, we're good */ + if (data->thread_qps[i].lock == lock) + return; + } + + /* + * if we get here, then we don't have a hold on this lock yet + */ + assert(available_qp != -1); + + data->thread_qps[available_qp].qp = get_hold_current_qp(lock); + data->thread_qps[available_qp].depth = 1; + data->thread_qps[available_qp].lock = lock; +} + +void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock) +{ + ossl_crypto_mutex_lock(lock->write_lock); +} + +void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock) +{ + ossl_crypto_mutex_unlock(lock->write_lock); +} + +void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock) +{ + CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx); + struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey); + int i; + LONG64 ret; + + assert(data != NULL); + + for (i = 0; i < MAX_QPS; i++) { + if (data->thread_qps[i].lock == lock) { + data->thread_qps[i].depth--; + if (data->thread_qps[i].depth == 0) { + CRYPTO_atomic_add64(&data->thread_qps[i].qp->users, + (uint64_t)-1, (uint64_t *)&ret, + lock->rw_lock); + OPENSSL_assert(ret >= 0); + data->thread_qps[i].qp = NULL; + data->thread_qps[i].lock = NULL; + } + return; + } + } +} + +/* + * Write side allocation routine to get the current qp + * and replace it with a new one + */ +static struct rcu_qp *update_qp(CRYPTO_RCU_LOCK *lock, uint32_t *curr_id) +{ + uint32_t current_idx; + uint32_t tmp; + + ossl_crypto_mutex_lock(lock->alloc_lock); + /* + * we need at least one qp to be available with one + * left over, so that readers can start working on + * one that isn't yet being waited on + */ + while (lock->group_count - lock->writers_alloced < 2) + /* we have to wait for one to be free */ + ossl_crypto_condvar_wait(lock->alloc_signal, lock->alloc_lock); + + current_idx = lock->current_alloc_idx; + + /* Allocate the qp */ + lock->writers_alloced++; + + /* increment the allocation index */ + lock->current_alloc_idx = + (lock->current_alloc_idx + 1) % lock->group_count; + + /* get and insert a new id */ + *curr_id = lock->id_ctr; + lock->id_ctr++; + + /* update the reader index to be the prior qp */ + tmp = lock->current_alloc_idx; +# if (defined(NO_INTERLOCKEDOR64)) + CRYPTO_THREAD_write_lock(lock->rw_lock); + lock->reader_idx = tmp; + CRYPTO_THREAD_unlock(lock->rw_lock); +# else + InterlockedExchange((LONG volatile *)&lock->reader_idx, tmp); +# endif + + /* wake up any waiters */ + ossl_crypto_condvar_broadcast(lock->alloc_signal); + ossl_crypto_mutex_unlock(lock->alloc_lock); + return &lock->qp_group[current_idx]; +} + +static void retire_qp(CRYPTO_RCU_LOCK *lock, + struct rcu_qp *qp) +{ + ossl_crypto_mutex_lock(lock->alloc_lock); + lock->writers_alloced--; + ossl_crypto_condvar_broadcast(lock->alloc_signal); + ossl_crypto_mutex_unlock(lock->alloc_lock); +} + + +void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock) +{ + struct rcu_qp *qp; + uint64_t count; + uint32_t curr_id; + struct rcu_cb_item *cb_items, *tmpcb; + + /* before we do anything else, lets grab the cb list */ + ossl_crypto_mutex_lock(lock->write_lock); + cb_items = lock->cb_items; + lock->cb_items = NULL; + ossl_crypto_mutex_unlock(lock->write_lock); + + qp = update_qp(lock, &curr_id); + + /* retire in order */ + ossl_crypto_mutex_lock(lock->prior_lock); + while (lock->next_to_retire != curr_id) + ossl_crypto_condvar_wait(lock->prior_signal, lock->prior_lock); + + /* wait for the reader count to reach zero */ + do { + CRYPTO_atomic_load(&qp->users, &count, lock->rw_lock); + } while (count != (uint64_t)0); + + lock->next_to_retire++; + ossl_crypto_condvar_broadcast(lock->prior_signal); + ossl_crypto_mutex_unlock(lock->prior_lock); + + retire_qp(lock, qp); + + /* handle any callbacks that we have */ + while (cb_items != NULL) { + tmpcb = cb_items; + cb_items = cb_items->next; + tmpcb->fn(tmpcb->data); + OPENSSL_free(tmpcb); + } + + /* and we're done */ + return; + +} + +/* + * Note, must be called under the protection of ossl_rcu_write_lock + */ +int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data) +{ + struct rcu_cb_item *new; + + new = OPENSSL_zalloc(sizeof(struct rcu_cb_item)); + if (new == NULL) + return 0; + new->data = data; + new->fn = cb; + + new->next = lock->cb_items; + lock->cb_items = new; + + return 1; +} + +void *ossl_rcu_uptr_deref(void **p) +{ + return (void *)*p; +} + +void ossl_rcu_assign_uptr(void **p, void **v) +{ + InterlockedExchangePointer((void * volatile *)p, (void *)*v); +} + + CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) { CRYPTO_RWLOCK *lock; @@ -44,15 +439,15 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void) CRYPTO_win_rwlock *rwlock; if ((lock = OPENSSL_zalloc(sizeof(CRYPTO_win_rwlock))) == NULL) + /* Don't set error, to avoid recursion blowup. */ return NULL; rwlock = lock; InitializeSRWLock(&rwlock->lock); # else - if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) { + if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) /* Don't set error, to avoid recursion blowup. */ return NULL; - } # if !defined(_WIN32_WCE) /* 0x400 is the spin count value suggested in the documentation */ @@ -212,15 +607,65 @@ int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b) int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) { +# if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val += amount; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +# else *ret = (int)InterlockedExchangeAdd((LONG volatile *)val, (LONG)amount) + amount; return 1; +# endif +} + +int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ +# if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val += op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +# else + *ret = (uint64_t)InterlockedAdd64((LONG64 volatile *)val, (LONG64)op); + return 1; +# endif +} + +int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock) +{ +# if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val &= op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +# else + *ret = (uint64_t)InterlockedAnd64((LONG64 volatile *)val, (LONG64)op) & op; + return 1; +# endif } int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock) { -#if (defined(NO_INTERLOCKEDOR64)) +# if (defined(NO_INTERLOCKEDOR64)) if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) return 0; *val |= op; @@ -230,15 +675,15 @@ int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, return 0; return 1; -#else +# else *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op; return 1; -#endif +# endif } int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) { -#if (defined(NO_INTERLOCKEDOR64)) +# if (defined(NO_INTERLOCKEDOR64)) if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) return 0; *ret = *val; @@ -246,10 +691,43 @@ int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) return 0; return 1; -#else +# else *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0); return 1; -#endif +# endif +} + +int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock) +{ +# if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) + return 0; + *dst = val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +# else + InterlockedExchange64(dst, val); + return 1; +# endif +} + +int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock) +{ +# if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) + return 0; + *ret = *val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +# else + /* On Windows, LONG (but not long) is always the same size as int. */ + *ret = (int)InterlockedOr((LONG volatile *)val, 0); + return 1; +# endif } int openssl_init_fork_handlers(void) diff --git a/crypto/trace.c b/crypto/trace.c index 90a6350bebae..fbd4bf291401 100644 --- a/crypto/trace.c +++ b/crypto/trace.c @@ -18,6 +18,7 @@ #include "internal/nelem.h" #include "internal/refcount.h" #include "crypto/cryptlib.h" +#include "crypto/ctype.h" #ifndef OPENSSL_NO_TRACE @@ -137,8 +138,11 @@ static const struct trace_category_st TRACE_CATEGORY_(STORE), TRACE_CATEGORY_(DECODER), TRACE_CATEGORY_(ENCODER), - TRACE_CATEGORY_(REF_COUNT) -}; + TRACE_CATEGORY_(REF_COUNT), + TRACE_CATEGORY_(HTTP), + TRACE_CATEGORY_(PROVIDER), + TRACE_CATEGORY_(QUERY), +}; /* KEEP THIS LIST IN SYNC with #define OSSL_TRACE_CATEGORY_... in trace.h */ const char *OSSL_trace_get_category_name(int num) { @@ -500,7 +504,7 @@ BIO *OSSL_trace_begin(int category) return channel; } -void OSSL_trace_end(int category, BIO * channel) +void OSSL_trace_end(int category, BIO *channel) { #ifndef OPENSSL_NO_TRACE char *suffix = NULL; @@ -529,3 +533,27 @@ void OSSL_trace_end(int category, BIO * channel) } #endif } + +int OSSL_trace_string(BIO *out, int text, int full, + const unsigned char *data, size_t size) +{ + unsigned char buf[OSSL_TRACE_STRING_MAX + 1]; + int len, i; + + if (!full && size > OSSL_TRACE_STRING_MAX) { + BIO_printf(out, "[len %zu limited to %d]: ", + size, OSSL_TRACE_STRING_MAX); + len = OSSL_TRACE_STRING_MAX; + } else { + len = (int)size; + } + if (!text) { /* mask control characters while preserving newlines */ + for (i = 0; i < len; i++, data++) + buf[i] = (char)*data != '\n' && ossl_iscntrl((int)*data) + ? ' ' : *data; + if (len == 0 || data[-1] != '\n') + buf[len++] = '\n'; + data = buf; + } + return BIO_printf(out, "%.*s", len, data); +} diff --git a/crypto/ts/ts_conf.c b/crypto/ts/ts_conf.c index fd2ad90754b0..7e57858f4295 100644 --- a/crypto/ts/ts_conf.c +++ b/crypto/ts/ts_conf.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -50,7 +50,11 @@ X509 *TS_CONF_load_cert(const char *file) BIO *cert = NULL; X509 *x = NULL; +#if defined(OPENSSL_SYS_WINDOWS) + if ((cert = BIO_new_file(file, "rb")) == NULL) +#else if ((cert = BIO_new_file(file, "r")) == NULL) +#endif goto end; x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL); end: @@ -67,7 +71,11 @@ STACK_OF(X509) *TS_CONF_load_certs(const char *file) STACK_OF(X509_INFO) *allcerts = NULL; int i; +#if defined(OPENSSL_SYS_WINDOWS) + if ((certs = BIO_new_file(file, "rb")) == NULL) +#else if ((certs = BIO_new_file(file, "r")) == NULL) +#endif goto end; if ((othercerts = sk_X509_new_null()) == NULL) goto end; @@ -78,7 +86,7 @@ STACK_OF(X509) *TS_CONF_load_certs(const char *file) if (xi->x509 != NULL) { if (!X509_add_cert(othercerts, xi->x509, X509_ADD_FLAG_DEFAULT)) { - sk_X509_pop_free(othercerts, X509_free); + OSSL_STACK_OF_X509_free(othercerts); othercerts = NULL; goto end; } @@ -98,7 +106,11 @@ EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass) BIO *key = NULL; EVP_PKEY *pkey = NULL; +#if defined(OPENSSL_SYS_WINDOWS) + if ((key = BIO_new_file(file, "rb")) == NULL) +#else if ((key = BIO_new_file(file, "r")) == NULL) +#endif goto end; pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *)pass); end: @@ -233,7 +245,7 @@ int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, end: ret = 1; err: - sk_X509_pop_free(certs_obj, X509_free); + OSSL_STACK_OF_X509_free(certs_obj); return ret; } @@ -481,7 +493,7 @@ int TS_CONF_set_ess_cert_id_digest(CONF *conf, const char *section, const char *md = NCONF_get_string(conf, section, ENV_ESS_CERT_ID_ALG); if (md == NULL) - md = "sha1"; + md = "sha256"; cert_md = EVP_get_digestbyname(md); if (cert_md == NULL) { diff --git a/crypto/ts/ts_local.h b/crypto/ts/ts_local.h index 4dcb7af960b2..b0dbd5fdd933 100644 --- a/crypto/ts/ts_local.h +++ b/crypto/ts/ts_local.h @@ -110,7 +110,7 @@ struct TS_resp_ctx { ASN1_INTEGER *seconds; /* accuracy, 0 means not specified. */ ASN1_INTEGER *millis; /* accuracy, 0 means not specified. */ ASN1_INTEGER *micros; /* accuracy, 0 means not specified. */ - unsigned clock_precision_digits; /* fraction of seconds in time stamp + unsigned clock_precision_digits; /* fraction of seconds in timestamp * token. */ unsigned flags; /* Optional info, see values above. */ /* Callback functions. */ diff --git a/crypto/ts/ts_req_utils.c b/crypto/ts/ts_req_utils.c index b560fc7b38a9..89e1bda450a4 100644 --- a/crypto/ts/ts_req_utils.c +++ b/crypto/ts/ts_req_utils.c @@ -32,7 +32,7 @@ int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint) return 1; new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint); if (new_msg_imprint == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); return 0; } TS_MSG_IMPRINT_free(a->msg_imprint); @@ -53,7 +53,7 @@ int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg) return 1; new_alg = X509_ALGOR_dup(alg); if (new_alg == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } X509_ALGOR_free(a->hash_algo); @@ -84,7 +84,7 @@ int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy) return 1; new_policy = OBJ_dup(policy); if (new_policy == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_OBJ_LIB); return 0; } ASN1_OBJECT_free(a->policy_id); @@ -105,7 +105,7 @@ int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce) return 1; new_nonce = ASN1_INTEGER_dup(nonce); if (new_nonce == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } ASN1_INTEGER_free(a->nonce); diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c index 8937bb2d6671..2465aede8560 100644 --- a/crypto/ts/ts_rsp_sign.c +++ b/crypto/ts/ts_rsp_sign.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include @@ -15,6 +15,7 @@ #include #include "internal/cryptlib.h" #include "internal/sizes.h" +#include "internal/time.h" #include "crypto/ess.h" #include "ts_local.h" @@ -51,53 +52,34 @@ static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *ctx, void *data) return serial; err: - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Error during serial number generation."); ASN1_INTEGER_free(serial); return NULL; } -#if defined(OPENSSL_SYS_UNIX) - static int def_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec) { + OSSL_TIME t; struct timeval tv; - if (gettimeofday(&tv, NULL) != 0) { + + t = ossl_time_now(); + if (ossl_time_is_zero(t)) { ERR_raise(ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR); TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Time is not available."); TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE); return 0; } - *sec = tv.tv_sec; - *usec = tv.tv_usec; + tv = ossl_time_to_timeval(t); + *sec = (long int)tv.tv_sec; + *usec = (long int)tv.tv_usec; return 1; } -#else - -static int def_time_cb(struct TS_resp_ctx *ctx, void *data, - long *sec, long *usec) -{ - time_t t; - if (time(&t) == (time_t)-1) { - ERR_raise(ERR_LIB_TS, TS_R_TIME_SYSCALL_ERROR); - TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, - "Time is not available."); - TS_RESP_CTX_add_failure_info(ctx, TS_INFO_TIME_NOT_AVAILABLE); - return 0; - } - *sec = (long)t; - *usec = 0; - - return 1; -} - -#endif - static int def_extension_cb(struct TS_resp_ctx *ctx, X509_EXTENSION *ext, void *data) { @@ -113,16 +95,13 @@ TS_RESP_CTX *TS_RESP_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq) { TS_RESP_CTX *ctx; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) return NULL; - } if (propq != NULL) { ctx->propq = OPENSSL_strdup(propq); if (ctx->propq == NULL) { OPENSSL_free(ctx); - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); return NULL; } } @@ -147,7 +126,7 @@ void TS_RESP_CTX_free(TS_RESP_CTX *ctx) OPENSSL_free(ctx->propq); X509_free(ctx->signer_cert); EVP_PKEY_free(ctx->signer_key); - sk_X509_pop_free(ctx->certs, X509_free); + OSSL_STACK_OF_X509_free(ctx->certs); sk_ASN1_OBJECT_pop_free(ctx->policies, ASN1_OBJECT_free); ASN1_OBJECT_free(ctx->default_policy); sk_EVP_MD_free(ctx->mds); /* No EVP_MD_free method exists. */ @@ -163,17 +142,22 @@ int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer) ERR_raise(ERR_LIB_TS, TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE); return 0; } + if (!X509_up_ref(signer)) + return 0; + X509_free(ctx->signer_cert); ctx->signer_cert = signer; - X509_up_ref(ctx->signer_cert); + return 1; } int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key) { + if (!EVP_PKEY_up_ref(key)) + return 0; + EVP_PKEY_free(ctx->signer_key); ctx->signer_key = key; - EVP_PKEY_up_ref(ctx->signer_key); return 1; } @@ -191,13 +175,13 @@ int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy) goto err; return 1; err: - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_OBJ_LIB); return 0; } int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs) { - sk_X509_pop_free(ctx->certs, X509_free); + OSSL_STACK_OF_X509_free(ctx->certs); ctx->certs = NULL; return certs == NULL || (ctx->certs = X509_chain_up_ref(certs)) != NULL; @@ -208,16 +192,21 @@ int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy) ASN1_OBJECT *copy = NULL; if (ctx->policies == NULL - && (ctx->policies = sk_ASN1_OBJECT_new_null()) == NULL) + && (ctx->policies = sk_ASN1_OBJECT_new_null()) == NULL) { + ERR_raise(ERR_LIB_TS, ERR_R_CRYPTO_LIB); goto err; - if ((copy = OBJ_dup(policy)) == NULL) + } + if ((copy = OBJ_dup(policy)) == NULL) { + ERR_raise(ERR_LIB_TS, ERR_R_OBJ_LIB); goto err; - if (!sk_ASN1_OBJECT_push(ctx->policies, copy)) + } + if (!sk_ASN1_OBJECT_push(ctx->policies, copy)) { + ERR_raise(ERR_LIB_TS, ERR_R_CRYPTO_LIB); goto err; + } return 1; err: - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); ASN1_OBJECT_free(copy); return 0; } @@ -232,7 +221,7 @@ int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md) return 1; err: - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_CRYPTO_LIB); return 0; } @@ -265,7 +254,7 @@ int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, return 1; err: TS_RESP_CTX_accuracy_free(ctx); - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } @@ -300,27 +289,37 @@ int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, ASN1_UTF8STRING *utf8_text = NULL; int ret = 0; - if ((si = TS_STATUS_INFO_new()) == NULL) + if ((si = TS_STATUS_INFO_new()) == NULL) { + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); goto err; - if (!ASN1_INTEGER_set(si->status, status)) + } + if (!ASN1_INTEGER_set(si->status, status)) { + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); goto err; + } if (text) { if ((utf8_text = ASN1_UTF8STRING_new()) == NULL - || !ASN1_STRING_set(utf8_text, text, strlen(text))) + || !ASN1_STRING_set(utf8_text, text, strlen(text))) { + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); goto err; + } if (si->text == NULL - && (si->text = sk_ASN1_UTF8STRING_new_null()) == NULL) + && (si->text = sk_ASN1_UTF8STRING_new_null()) == NULL) { + ERR_raise(ERR_LIB_TS, ERR_R_CRYPTO_LIB); goto err; - if (!sk_ASN1_UTF8STRING_push(si->text, utf8_text)) + } + if (!sk_ASN1_UTF8STRING_push(si->text, utf8_text)) { + ERR_raise(ERR_LIB_TS, ERR_R_CRYPTO_LIB); goto err; + } utf8_text = NULL; /* Ownership is lost. */ } - if (!TS_RESP_set_status_info(ctx->response, si)) + if (!TS_RESP_set_status_info(ctx->response, si)) { + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); goto err; + } ret = 1; err: - if (!ret) - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); TS_STATUS_INFO_free(si); ASN1_UTF8STRING_free(utf8_text); return ret; @@ -348,7 +347,7 @@ int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure) goto err; return 1; err: - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } @@ -381,7 +380,7 @@ TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio) ts_RESP_CTX_init(ctx); if ((ctx->response = TS_RESP_new()) == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); goto end; } if ((ctx->request = d2i_TS_REQ_bio(req_bio, NULL)) == NULL) { @@ -451,7 +450,7 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx) char md_alg_name[OSSL_MAX_NAME_SIZE]; const ASN1_OCTET_STRING *digest; const EVP_MD *md = NULL; - int i; + int i, md_size; if (TS_REQ_get_version(request) != 1) { TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, @@ -476,6 +475,10 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx) return 0; } + md_size = EVP_MD_get_size(md); + if (md_size <= 0) + return 0; + if (md_alg->parameter && ASN1_TYPE_get(md_alg->parameter) != V_ASN1_NULL) { TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Superfluous message digest " @@ -484,7 +487,7 @@ static int ts_RESP_check_request(TS_RESP_CTX *ctx) return 0; } digest = msg_imprint->hashed_msg; - if (digest->length != EVP_MD_get_size(md)) { + if (digest->length != md_size) { TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION, "Bad message digest."); TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT); @@ -691,7 +694,7 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx) } if ((p7 = PKCS7_new_ex(ctx->libctx, ctx->propq)) == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); goto err; } if (!PKCS7_set_type(p7, NID_pkcs7_signed)) @@ -756,7 +759,7 @@ static int ts_RESP_sign(TS_RESP_CTX *ctx) if (!ts_TST_INFO_content_new(p7)) goto err; if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_PKCS7_LIB); goto err; } if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info)) { diff --git a/crypto/ts/ts_rsp_utils.c b/crypto/ts/ts_rsp_utils.c index cae076f21a6a..2352c7adb969 100644 --- a/crypto/ts/ts_rsp_utils.c +++ b/crypto/ts/ts_rsp_utils.c @@ -22,7 +22,7 @@ int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *status_info) return 1; new_status_info = TS_STATUS_INFO_dup(status_info); if (new_status_info == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); return 0; } TS_STATUS_INFO_free(a->status_info); @@ -73,7 +73,7 @@ int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy) return 1; new_policy = OBJ_dup(policy); if (new_policy == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_OBJ_LIB); return 0; } ASN1_OBJECT_free(a->policy_id); @@ -94,7 +94,7 @@ int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint) return 1; new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint); if (new_msg_imprint == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); return 0; } TS_MSG_IMPRINT_free(a->msg_imprint); @@ -115,7 +115,7 @@ int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial) return 1; new_serial = ASN1_INTEGER_dup(serial); if (new_serial == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } ASN1_INTEGER_free(a->serial); @@ -136,7 +136,7 @@ int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime) return 1; new_time = ASN1_STRING_dup(gtime); if (new_time == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } ASN1_GENERALIZEDTIME_free(a->time); @@ -157,7 +157,7 @@ int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy) return 1; new_accuracy = TS_ACCURACY_dup(accuracy); if (new_accuracy == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_TS_LIB); return 0; } TS_ACCURACY_free(a->accuracy); @@ -178,7 +178,7 @@ int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds) return 1; new_seconds = ASN1_INTEGER_dup(seconds); if (new_seconds == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } ASN1_INTEGER_free(a->seconds); @@ -200,7 +200,7 @@ int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis) if (millis != NULL) { new_millis = ASN1_INTEGER_dup(millis); if (new_millis == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } } @@ -223,7 +223,7 @@ int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros) if (micros != NULL) { new_micros = ASN1_INTEGER_dup(micros); if (new_micros == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } } @@ -256,7 +256,7 @@ int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce) return 1; new_nonce = ASN1_INTEGER_dup(nonce); if (new_nonce == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } ASN1_INTEGER_free(a->nonce); @@ -277,7 +277,7 @@ int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa) return 1; new_tsa = GENERAL_NAME_dup(tsa); if (new_tsa == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_ASN1_LIB); return 0; } GENERAL_NAME_free(a->tsa); diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c index 792a27ce572b..0d9fa01e4337 100644 --- a/crypto/ts/ts_rsp_verify.c +++ b/crypto/ts/ts_rsp_verify.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -150,15 +150,17 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, } if (signer_out) { + if (!X509_up_ref(signer)) + goto err; + *signer_out = signer; - X509_up_ref(signer); } ret = 1; err: BIO_free_all(p7bio); sk_X509_free(untrusted); - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); sk_X509_free(signers); return ret; @@ -178,7 +180,7 @@ static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, *chain = NULL; cert_ctx = X509_STORE_CTX_new(); if (cert_ctx == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_X509_LIB); goto err; } if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) @@ -278,7 +280,7 @@ int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token) } /*- - * Verifies whether the 'token' contains a valid time stamp token + * Verifies whether the 'token' contains a valid timestamp token * with regards to the settings of the context. Only those checks are * carried out that are specified in the context: * - Verifies the signature of the TS_TST_INFO. @@ -448,17 +450,15 @@ static int ts_compute_imprint(BIO *data, TS_TST_INFO *tst_info, (void)ERR_pop_to_mark(); length = EVP_MD_get_size(md); - if (length < 0) + if (length <= 0) goto err; *imprint_len = length; - if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + if ((*imprint = OPENSSL_malloc(*imprint_len)) == NULL) goto err; - } md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_TS, ERR_R_EVP_LIB); goto err; } if (!EVP_DigestInit(md_ctx, md)) diff --git a/crypto/ts/ts_verify_ctx.c b/crypto/ts/ts_verify_ctx.c index 2f6f00c0ccd6..4b6a3ada9b2b 100644 --- a/crypto/ts/ts_verify_ctx.c +++ b/crypto/ts/ts_verify_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,8 +16,6 @@ TS_VERIFY_CTX *TS_VERIFY_CTX_new(void) { TS_VERIFY_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) - ERR_raise(ERR_LIB_TS, ERR_R_MALLOC_FAILURE); return ctx; } @@ -48,25 +46,53 @@ int TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int f) return ctx->flags; } +#ifndef OPENSSL_NO_DEPRECATED_3_4 BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *b) { ctx->data = b; return ctx->data; } +#endif +int TS_VERIFY_CTX_set0_data(TS_VERIFY_CTX *ctx, BIO *b) +{ + BIO_free_all(ctx->data); + ctx->data = b; + return 1; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_4 X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *s) { ctx->store = s; return ctx->store; } +#endif +int TS_VERIFY_CTX_set0_store(TS_VERIFY_CTX *ctx, X509_STORE *s) +{ + X509_STORE_free(ctx->store); + ctx->store = s; + return 1; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_4 STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs) { ctx->certs = certs; return ctx->certs; } +#endif +int TS_VERIFY_CTX_set0_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs) +{ + OSSL_STACK_OF_X509_free(ctx->certs); + ctx->certs = certs; + return 1; +} + +#ifndef OPENSSL_NO_DEPRECATED_3_4 unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, unsigned char *hexstr, long len) { @@ -75,6 +101,16 @@ unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, ctx->imprint_len = len; return ctx->imprint; } +#endif + +int TS_VERIFY_CTX_set0_imprint(TS_VERIFY_CTX *ctx, + unsigned char *hexstr, long len) +{ + OPENSSL_free(ctx->imprint); + ctx->imprint = hexstr; + ctx->imprint_len = len; + return 1; +} void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx) { @@ -82,7 +118,7 @@ void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx) return; X509_STORE_free(ctx->store); - sk_X509_pop_free(ctx->certs, X509_free); + OSSL_STACK_OF_X509_free(ctx->certs); ASN1_OBJECT_free(ctx->policy); diff --git a/crypto/txt_db/txt_db.c b/crypto/txt_db/txt_db.c index 2c1cbfb4f129..25fe9bf64bf7 100644 --- a/crypto/txt_db/txt_db.c +++ b/crypto/txt_db/txt_db.c @@ -1,5 +1,5 @@ /* - * 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 @@ -78,7 +78,6 @@ TXT_DB *TXT_DB_read(BIO *in, int num) p += add; n = 0; pp[n++] = p; - i = 0; f = buf->data; esc = 0; diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c index 2ddf76cb5357..a8756af1cdea 100644 --- a/crypto/ui/ui_lib.c +++ b/crypto/ui/ui_lib.c @@ -24,14 +24,12 @@ 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); + if (ret == NULL) return NULL; - } ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_UI, ERR_R_CRYPTO_LIB); OPENSSL_free(ret); return NULL; } @@ -210,10 +208,8 @@ int UI_dup_input_string(UI *ui, const char *prompt, int flags, if (prompt != NULL) { prompt_copy = OPENSSL_strdup(prompt); - if (prompt_copy == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + if (prompt_copy == NULL) return 0; - } } return general_allocate_string(ui, prompt_copy, 1, @@ -238,10 +234,8 @@ int UI_dup_verify_string(UI *ui, const char *prompt, int flags, if (prompt != NULL) { prompt_copy = OPENSSL_strdup(prompt); - if (prompt_copy == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + if (prompt_copy == NULL) return -1; - } } return general_allocate_string(ui, prompt_copy, 1, @@ -269,34 +263,26 @@ int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, if (prompt != NULL) { prompt_copy = OPENSSL_strdup(prompt); - if (prompt_copy == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + if (prompt_copy == NULL) 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); + if (action_desc_copy == NULL) 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); + if (ok_chars_copy == NULL) 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); + if (cancel_chars_copy == NULL) goto err; - } } return general_allocate_boolean(ui, prompt_copy, action_desc_copy, @@ -322,10 +308,8 @@ int UI_dup_info_string(UI *ui, const char *text) if (text != NULL) { text_copy = OPENSSL_strdup(text); - if (text_copy == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + if (text_copy == NULL) return -1; - } } return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, @@ -344,10 +328,8 @@ int UI_dup_error_string(UI *ui, const char *text) if (text != NULL) { text_copy = OPENSSL_strdup(text); - if (text_copy == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + if (text_copy == NULL) return -1; - } } return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, 0, 0, NULL); @@ -373,10 +355,8 @@ char *UI_construct_prompt(UI *ui, const char *phrase_desc, 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); + if ((prompt = OPENSSL_malloc(len + 1)) == NULL) return NULL; - } OPENSSL_strlcpy(prompt, prompt1, len + 1); OPENSSL_strlcat(prompt, phrase_desc, len + 1); if (object_name != NULL) { @@ -413,7 +393,7 @@ int UI_dup_user_data(UI *ui, void *user_data) duplicate = ui->meth->ui_duplicate_data(ui, user_data); if (duplicate == NULL) { - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_UI, ERR_R_UI_LIB); return -1; } @@ -603,10 +583,17 @@ UI_METHOD *UI_create_method(const char *name) || (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) + + if (ui_method != NULL) { + if (ui_method->name != NULL) + /* + * These conditions indicate that the CRYPTO_new_ex_data() + * call failed. + */ + ERR_raise(ERR_LIB_UI, ERR_R_CRYPTO_LIB); OPENSSL_free(ui_method->name); + } OPENSSL_free(ui_method); - ERR_raise(ERR_LIB_UI, ERR_R_MALLOC_FAILURE); return NULL; } return ui_method; diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c index 8007f2f70c87..544415e5b112 100644 --- a/crypto/ui/ui_openssl.c +++ b/crypto/ui/ui_openssl.c @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include #include #include diff --git a/crypto/uid.c b/crypto/uid.c index 698127779f54..45b63a431e08 100644 --- a/crypto/uid.c +++ b/crypto/uid.c @@ -1,5 +1,5 @@ /* - * 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 @@ -10,7 +10,7 @@ #include #include -#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) || defined(__wasi__) int OPENSSL_issetugid(void) { diff --git a/crypto/whrlpool/asm/wp-x86_64.pl b/crypto/whrlpool/asm/wp-x86_64.pl index f94152af9769..e3421dcbdf18 100644 --- a/crypto/whrlpool/asm/wp-x86_64.pl +++ b/crypto/whrlpool/asm/wp-x86_64.pl @@ -1,5 +1,5 @@ #! /usr/bin/env perl -# Copyright 2005-2020 The OpenSSL Project Authors. All Rights Reserved. +# Copyright 2005-2024 The OpenSSL Project Authors. All Rights Reserved. # # Licensed under the Apache License 2.0 (the "License"). You may not use # this file except in compliance with the License. You can obtain a copy @@ -236,6 +236,7 @@ $code.=<<___; .cfi_endproc .size $func,.-$func +.section .rodata align=64 .align 64 .type $table,\@object $table: diff --git a/crypto/whrlpool/wp_dgst.c b/crypto/whrlpool/wp_dgst.c index 4a1d912d6290..3f970deb9c7b 100644 --- a/crypto/whrlpool/wp_dgst.c +++ b/crypto/whrlpool/wp_dgst.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2020 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 @@ -120,7 +120,7 @@ void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c, const void *_inp, size_t bits) } else { unsigned int byteoff = bitoff / 8; - bitrem = WHIRLPOOL_BBLOCK - bitoff; /* re-use bitrem */ + bitrem = WHIRLPOOL_BBLOCK - bitoff; /* reuse bitrem */ if (bits >= bitrem) { bits -= bitrem; bitrem /= 8; diff --git a/crypto/x509/build.info b/crypto/x509/build.info index 8820f983bb3d..c9ed634b86a6 100644 --- a/crypto/x509/build.info +++ b/crypto/x509/build.info @@ -14,7 +14,11 @@ SOURCE[../../libcrypto]=\ v3_info.c v3_akeya.c v3_pmaps.c v3_pcons.c v3_ncons.c \ v3_pcia.c v3_pci.c v3_ist.c \ pcy_cache.c pcy_node.c pcy_data.c pcy_map.c pcy_tree.c pcy_lib.c \ - v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c + v3_asid.c v3_addr.c v3_tlsf.c v3_admis.c v3_no_rev_avail.c \ + v3_soa_id.c v3_no_ass.c v3_group_ac.c v3_single_use.c v3_ind_iss.c \ + x509_acert.c x509aset.c t_acert.c x_ietfatt.c v3_ac_tgt.c v3_sda.c \ + v3_usernotice.c v3_battcons.c v3_audit_id.c v3_iobo.c v3_authattid.c \ + v3_rolespec.c v3_attrdesc.c v3_timespec.c v3_attrmap.c v3_aaa.c IF[{- !$disabled{'deprecated-3.0'} -}] SOURCE[../../libcrypto]=x509type.c diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c index ad871966aa6e..bdcdc4555bdc 100644 --- a/crypto/x509/by_dir.c +++ b/crypto/x509/by_dir.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,7 +16,7 @@ # include #endif -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include #include @@ -109,20 +109,18 @@ static int new_dir(X509_LOOKUP *lu) { BY_DIR *a = OPENSSL_malloc(sizeof(*a)); - if (a == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (a == NULL) return 0; - } if ((a->buffer = BUF_MEM_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_BN_LIB); goto err; } a->dirs = NULL; a->lock = CRYPTO_THREAD_lock_new(); if (a->lock == NULL) { BUF_MEM_free(a->buffer); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } lu->method_data = a; @@ -197,15 +195,13 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) if (ctx->dirs == NULL) { ctx->dirs = sk_BY_DIR_ENTRY_new_null(); if (!ctx->dirs) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); return 0; } } ent = OPENSSL_malloc(sizeof(*ent)); - if (ent == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (ent == NULL) return 0; - } ent->dir_type = type; ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); ent->dir = OPENSSL_strndup(ss, len); @@ -215,7 +211,7 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type) } if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { by_dir_entry_free(ent); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); return 0; } } @@ -272,7 +268,7 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; if (!BUF_MEM_grow(b, j)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB); goto finish; } if (type == X509_LU_CRL && ent->hashes) { @@ -347,13 +343,19 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, /* * we have added it to the cache so now pull it out again + * + * Note: quadratic time find here since the objects won't generally be + * sorted and sorting the would result in O(n^2 log n) complexity. */ - if (!X509_STORE_lock(xl->store_ctx)) - goto finish; - j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); - tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); - X509_STORE_unlock(xl->store_ctx); - + if (k > 0) { + if (!X509_STORE_lock(xl->store_ctx)) + goto finish; + j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); + X509_STORE_unlock(xl->store_ctx); + } else { + tmp = NULL; + } /* * If a CRL, update the last file suffix added for this. * We don't need to add an entry if k is 0 as this is the initial value. @@ -376,7 +378,6 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, hent = OPENSSL_malloc(sizeof(*hent)); if (hent == NULL) { CRYPTO_THREAD_unlock(ctx->lock); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); ok = 0; goto finish; } @@ -385,7 +386,7 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { CRYPTO_THREAD_unlock(ctx->lock); OPENSSL_free(hent); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); ok = 0; goto finish; } @@ -418,6 +419,14 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type, } } finish: + /* If we changed anything, resort the objects for faster lookup */ + if (X509_STORE_lock(xl->store_ctx)) { + if (!sk_X509_OBJECT_is_sorted(xl->store_ctx->objs)) { + sk_X509_OBJECT_sort(xl->store_ctx->objs); + } + X509_STORE_unlock(xl->store_ctx); + } + BUF_MEM_free(b); return ok; } diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c index 37d73ca84c54..f594ab3cf245 100644 --- a/crypto/x509/by_file.c +++ b/crypto/x509/by_file.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -58,15 +58,13 @@ static int by_file_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp, if (file) ok = (X509_load_cert_crl_file_ex(ctx, file, X509_FILETYPE_PEM, libctx, propq) != 0); - else ok = (X509_load_cert_crl_file_ex( ctx, X509_get_default_cert_file(), X509_FILETYPE_PEM, libctx, propq) != 0); - if (!ok) { + if (!ok) ERR_raise(ERR_LIB_X509, X509_R_LOADING_DEFAULTS); - } } else { if (argl == X509_FILETYPE_PEM) ok = (X509_load_cert_crl_file_ex(ctx, argp, X509_FILETYPE_PEM, @@ -89,25 +87,25 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type, OSSL_LIB_CTX *libctx, const char *propq) { - int ret = 0; BIO *in = NULL; - int i, count = 0; + int count = 0; X509 *x = NULL; + if (file == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { - ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); + ERR_raise(ERR_LIB_X509, ERR_R_BIO_LIB); goto err; } - if (type != X509_FILETYPE_PEM && type != X509_FILETYPE_ASN1) { - ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE); - goto err; - } x = X509_new_ex(libctx, propq); if (x == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; } @@ -121,34 +119,47 @@ int X509_load_cert_file_ex(X509_LOOKUP *ctx, const char *file, int type, break; } else { ERR_clear_last_mark(); + if (count == 0) { + ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND); + } else { + ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); + count = 0; + } goto err; } } ERR_clear_last_mark(); - i = X509_STORE_add_cert(ctx->store_ctx, x); - if (!i) + if (!X509_STORE_add_cert(ctx->store_ctx, x)) { + count = 0; goto err; - count++; + } + /* + * X509_STORE_add_cert() added a reference rather than a copy, + * so we need a fresh X509 object. + */ X509_free(x); - x = NULL; + x = X509_new_ex(libctx, propq); + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); + count = 0; + goto err; + } + count++; } - ret = count; } else if (type == X509_FILETYPE_ASN1) { if (d2i_X509_bio(in, &x) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND); goto err; } - i = X509_STORE_add_cert(ctx->store_ctx, x); - if (!i) - goto err; - ret = i; + count = X509_STORE_add_cert(ctx->store_ctx, x); + } else { + ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE); + goto err; } - if (ret == 0) - ERR_raise(ERR_LIB_X509, X509_R_NO_CERTIFICATE_FOUND); err: X509_free(x); BIO_free(in); - return ret; + return count; } int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) @@ -158,15 +169,19 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) { - int ret = 0; BIO *in = NULL; - int i, count = 0; + int count = 0; X509_CRL *x = NULL; + if (file == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + in = BIO_new(BIO_s_file()); if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { - ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); + ERR_raise(ERR_LIB_X509, ERR_R_BIO_LIB); goto err; } @@ -179,71 +194,79 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) ERR_clear_error(); break; } else { - ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); + if (count == 0) { + ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND); + } else { + ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); + count = 0; + } goto err; } } - i = X509_STORE_add_crl(ctx->store_ctx, x); - if (!i) + if (!X509_STORE_add_crl(ctx->store_ctx, x)) { + count = 0; goto err; + } count++; X509_CRL_free(x); x = NULL; } - ret = count; } else if (type == X509_FILETYPE_ASN1) { x = d2i_X509_CRL_bio(in, NULL); if (x == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); + ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND); goto err; } - i = X509_STORE_add_crl(ctx->store_ctx, x); - if (!i) - goto err; - ret = i; + count = X509_STORE_add_crl(ctx->store_ctx, x); } else { ERR_raise(ERR_LIB_X509, X509_R_BAD_X509_FILETYPE); goto err; } - if (ret == 0) - ERR_raise(ERR_LIB_X509, X509_R_NO_CRL_FOUND); err: X509_CRL_free(x); BIO_free(in); - return ret; + return count; } int X509_load_cert_crl_file_ex(X509_LOOKUP *ctx, const char *file, int type, OSSL_LIB_CTX *libctx, const char *propq) { - STACK_OF(X509_INFO) *inf; - X509_INFO *itmp; - BIO *in; + STACK_OF(X509_INFO) *inf = NULL; + X509_INFO *itmp = NULL; + BIO *in = NULL; int i, count = 0; if (type != X509_FILETYPE_PEM) return X509_load_cert_file_ex(ctx, file, type, libctx, propq); +#if defined(OPENSSL_SYS_WINDOWS) + in = BIO_new_file(file, "rb"); +#else in = BIO_new_file(file, "r"); - if (!in) { - ERR_raise(ERR_LIB_X509, ERR_R_SYS_LIB); +#endif + if (in == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_BIO_LIB); return 0; } inf = PEM_X509_INFO_read_bio_ex(in, NULL, NULL, "", libctx, propq); BIO_free(in); - if (!inf) { + if (inf == NULL) { ERR_raise(ERR_LIB_X509, ERR_R_PEM_LIB); return 0; } for (i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { - if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) + if (!X509_STORE_add_cert(ctx->store_ctx, itmp->x509)) { + count = 0; goto err; + } count++; } if (itmp->crl) { - if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) + if (!X509_STORE_add_crl(ctx->store_ctx, itmp->crl)) { + count = 0; goto err; + } count++; } } diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c index 050735ce3247..d1e186f4fc2d 100644 --- a/crypto/x509/by_store.c +++ b/crypto/x509/by_store.c @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -27,7 +27,7 @@ static int cache_objects(X509_LOOKUP *lctx, const char *uri, /* * We try to set the criterion, but don't care if it was valid or not. - * For a OSSL_STORE, it merely serves as an optimization, the expectation + * For an OSSL_STORE, it merely serves as an optimization, the expectation * being that if the criterion couldn't be used, we will get *everything* * from the container that the URI represents rather than the subset that * the criterion indicates, so the biggest harm is that we cache more @@ -111,13 +111,7 @@ static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp, { switch (cmd) { case X509_L_ADD_STORE: - /* If no URI is given, use the default cert dir as default URI */ - if (argp == NULL) - argp = ossl_safe_getenv(X509_get_default_cert_dir_env()); - if (argp == NULL) - argp = X509_get_default_cert_dir(); - - { + if (argp != NULL) { STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx); char *data = OPENSSL_strdup(argp); @@ -128,14 +122,21 @@ static int by_store_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argp, uris = sk_OPENSSL_STRING_new_null(); X509_LOOKUP_set_method_data(ctx, uris); } - return sk_OPENSSL_STRING_push(uris, data) > 0; + if (sk_OPENSSL_STRING_push(uris, data) <= 0) { + OPENSSL_free(data); + return 0; + } + return 1; } + /* NOP if no URI is given. */ + return 1; case X509_L_LOAD_STORE: /* This is a shortcut for quick loading of specific containers */ return cache_objects(ctx, argp, NULL, 0, libctx, propq); + default: + /* Unsupported command */ + return 0; } - - return 0; } static int by_store_ctrl(X509_LOOKUP *ctx, int cmd, diff --git a/crypto/x509/ext_dat.h b/crypto/x509/ext_dat.h index a0a7f88ccd8a..5d4c2fdb86ce 100644 --- a/crypto/x509/ext_dat.h +++ b/crypto/x509/ext_dat.h @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -25,3 +25,27 @@ extern const X509V3_EXT_METHOD ossl_v3_tls_feature; extern const X509V3_EXT_METHOD ossl_v3_ext_admission; extern const X509V3_EXT_METHOD ossl_v3_utf8_list[1]; extern const X509V3_EXT_METHOD ossl_v3_issuer_sign_tool; +extern const X509V3_EXT_METHOD ossl_v3_group_ac; +extern const X509V3_EXT_METHOD ossl_v3_soa_identifier; +extern const X509V3_EXT_METHOD ossl_v3_no_assertion; +extern const X509V3_EXT_METHOD ossl_v3_no_rev_avail; +extern const X509V3_EXT_METHOD ossl_v3_single_use; +extern const X509V3_EXT_METHOD ossl_v3_indirect_issuer; +extern const X509V3_EXT_METHOD ossl_v3_targeting_information; +extern const X509V3_EXT_METHOD ossl_v3_holder_name_constraints; +extern const X509V3_EXT_METHOD ossl_v3_delegated_name_constraints; +extern const X509V3_EXT_METHOD ossl_v3_subj_dir_attrs; +extern const X509V3_EXT_METHOD ossl_v3_associated_info; +extern const X509V3_EXT_METHOD ossl_v3_acc_cert_policies; +extern const X509V3_EXT_METHOD ossl_v3_acc_priv_policies; +extern const X509V3_EXT_METHOD ossl_v3_user_notice; +extern const X509V3_EXT_METHOD ossl_v3_battcons; +extern const X509V3_EXT_METHOD ossl_v3_audit_identity; +extern const X509V3_EXT_METHOD ossl_v3_issued_on_behalf_of; +extern const X509V3_EXT_METHOD ossl_v3_authority_attribute_identifier; +extern const X509V3_EXT_METHOD ossl_v3_role_spec_cert_identifier; +extern const X509V3_EXT_METHOD ossl_v3_attribute_descriptor; +extern const X509V3_EXT_METHOD ossl_v3_time_specification; +extern const X509V3_EXT_METHOD ossl_v3_attribute_mappings; +extern const X509V3_EXT_METHOD ossl_v3_allowed_attribute_assignments; +extern const X509V3_EXT_METHOD ossl_v3_aa_issuing_dist_point; diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c index 1339f994aee1..2d1d4cd367c0 100644 --- a/crypto/x509/pcy_cache.c +++ b/crypto/x509/pcy_cache.c @@ -1,5 +1,5 @@ /* - * 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 @@ -35,14 +35,14 @@ static int policy_cache_create(X509 *x, goto bad_policy; cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp); if (cache->data == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto just_cleanup; } for (i = 0; i < num; i++) { policy = sk_POLICYINFO_value(policies, i); data = ossl_policy_data_new(policy, NULL, crit); if (data == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB); goto just_cleanup; } /* @@ -54,15 +54,17 @@ static int policy_cache_create(X509 *x, goto bad_policy; } cache->anyPolicy = data; - } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0 ) { + } else if (sk_X509_POLICY_DATA_find(cache->data, data) >=0) { ret = -1; goto bad_policy; } else if (!sk_X509_POLICY_DATA_push(cache->data, data)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto bad_policy; } data = NULL; } + /* Sort so we can find more quickly */ + sk_X509_POLICY_DATA_sort(cache->data); ret = 1; bad_policy: @@ -90,10 +92,8 @@ static int policy_cache_new(X509 *x) if (x->policy_cache != NULL) return 1; cache = OPENSSL_malloc(sizeof(*cache)); - if (cache == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (cache == NULL) return 0; - } cache->anyPolicy = NULL; cache->data = NULL; cache->any_skip = -1; diff --git a/crypto/x509/pcy_data.c b/crypto/x509/pcy_data.c index 6fb8f14ba8e8..8e8b91a78135 100644 --- a/crypto/x509/pcy_data.c +++ b/crypto/x509/pcy_data.c @@ -52,14 +52,13 @@ X509_POLICY_DATA *ossl_policy_data_new(POLICYINFO *policy, ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { ASN1_OBJECT_free(id); - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); return NULL; } ret->expected_policy_set = sk_ASN1_OBJECT_new_null(); if (ret->expected_policy_set == NULL) { OPENSSL_free(ret); ASN1_OBJECT_free(id); - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } diff --git a/crypto/x509/pcy_node.c b/crypto/x509/pcy_node.c index 9b77e6e95e05..c6e7af5ab198 100644 --- a/crypto/x509/pcy_node.c +++ b/crypto/x509/pcy_node.c @@ -69,10 +69,8 @@ X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level, return NULL; node = OPENSSL_zalloc(sizeof(*node)); - if (node == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (node == NULL) return NULL; - } node->data = data; node->parent = parent; if (level != NULL) { @@ -85,11 +83,11 @@ X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level, if (level->nodes == NULL) level->nodes = ossl_policy_node_cmp_new(); if (level->nodes == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509_LIB); goto node_error; } if (!sk_X509_POLICY_NODE_push(level->nodes, node)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto node_error; } } @@ -98,12 +96,12 @@ X509_POLICY_NODE *ossl_policy_level_add_node(X509_POLICY_LEVEL *level, 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); + if (tree->extra_data == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto extra_data_error; } if (!sk_X509_POLICY_DATA_push(tree->extra_data, data)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto extra_data_error; } } diff --git a/crypto/x509/pcy_tree.c b/crypto/x509/pcy_tree.c index 2012810303ed..7c5d7e838ec3 100644 --- a/crypto/x509/pcy_tree.c +++ b/crypto/x509/pcy_tree.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -110,6 +110,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, *ptree = NULL; + if (n < 0) + return X509_PCY_TREE_INTERNAL; /* Can't do anything with just a trust anchor */ if (n == 0) return X509_PCY_TREE_EMPTY; @@ -171,10 +173,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, 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); + if ((tree = OPENSSL_zalloc(sizeof(*tree))) == NULL) return X509_PCY_TREE_INTERNAL; - } /* Limit the growth of the tree to mitigate CVE-2023-0464 */ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX; @@ -188,7 +188,6 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, */ 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; @@ -212,7 +211,9 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, /* Access the cache which we now know exists */ cache = ossl_policy_cache_set(x); - X509_up_ref(x); + if (!X509_up_ref(x)) + goto bad_tree; + (++level)->cert = x; if (!cache->anyPolicy) @@ -702,6 +703,7 @@ int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy, if ((calc_ret = tree_calculate_authority_set(tree, &auth_nodes)) == 0) goto error; + sk_X509_POLICY_NODE_sort(auth_nodes); ret = tree_calculate_user_set(tree, policy_oids, auth_nodes); if (calc_ret == TREE_CALC_OK_DOFREE) sk_X509_POLICY_NODE_free(auth_nodes); diff --git a/crypto/x509/standard_exts.h b/crypto/x509/standard_exts.h index 27a99a4b13ed..7449fb0ff62a 100644 --- a/crypto/x509/standard_exts.h +++ b/crypto/x509/standard_exts.h @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -39,6 +39,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = { #endif &ossl_v3_sxnet, &ossl_v3_info, + &ossl_v3_audit_identity, #ifndef OPENSSL_NO_RFC3779 &ossl_v3_addr, &ossl_v3_asid, @@ -53,6 +54,8 @@ static const X509V3_EXT_METHOD *standard_exts[] = { #endif &ossl_v3_sinfo, &ossl_v3_policy_constraints, + &ossl_v3_targeting_information, + &ossl_v3_no_rev_avail, #ifndef OPENSSL_NO_OCSP &ossl_v3_crl_hold, #endif @@ -60,6 +63,7 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &ossl_v3_name_constraints, &ossl_v3_policy_mappings, &ossl_v3_inhibit_anyp, + &ossl_v3_subj_dir_attrs, &ossl_v3_idp, &ossl_v3_alt[2], &ossl_v3_freshest_crl, @@ -71,7 +75,27 @@ static const X509V3_EXT_METHOD *standard_exts[] = { &ossl_v3_utf8_list[0], &ossl_v3_issuer_sign_tool, &ossl_v3_tls_feature, - &ossl_v3_ext_admission + &ossl_v3_ext_admission, + &ossl_v3_authority_attribute_identifier, + &ossl_v3_role_spec_cert_identifier, + &ossl_v3_battcons, + &ossl_v3_delegated_name_constraints, + &ossl_v3_time_specification, + &ossl_v3_attribute_descriptor, + &ossl_v3_user_notice, + &ossl_v3_soa_identifier, + &ossl_v3_acc_cert_policies, + &ossl_v3_acc_priv_policies, + &ossl_v3_indirect_issuer, + &ossl_v3_no_assertion, + &ossl_v3_aa_issuing_dist_point, + &ossl_v3_issued_on_behalf_of, + &ossl_v3_single_use, + &ossl_v3_group_ac, + &ossl_v3_allowed_attribute_assignments, + &ossl_v3_attribute_mappings, + &ossl_v3_holder_name_constraints, + &ossl_v3_associated_info, }; /* Number of standard extensions */ diff --git a/crypto/x509/t_x509.c b/crypto/x509/t_x509.c index 5b0282bc132f..7d693669cd36 100644 --- a/crypto/x509/t_x509.c +++ b/crypto/x509/t_x509.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,6 +17,11 @@ #include "crypto/asn1.h" #include "crypto/x509.h" +void OSSL_STACK_OF_X509_free(STACK_OF(X509) *certs) +{ + sk_X509_pop_free(certs, X509_free); +} + #ifndef OPENSSL_NO_STDIO int X509_print_fp(FILE *fp, X509 *x) { @@ -49,11 +54,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag) { long l; - int ret = 0, i; - char *m = NULL, mlch = ' '; + int ret = 0; + char mlch = ' '; int nmindent = 0, printok = 0; EVP_PKEY *pkey = NULL; - const char *neg; if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; @@ -84,37 +88,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, if (BIO_write(bp, " Serial Number:", 22) <= 0) goto err; - - if (bs->length <= (int)sizeof(long)) { - ERR_set_mark(); - l = ASN1_INTEGER_get(bs); - ERR_pop_to_mark(); - } else { - l = -1; - } - if (l != -1) { - unsigned long ul; - if (bs->type == V_ASN1_NEG_INTEGER) { - ul = 0 - (unsigned long)l; - neg = "-"; - } else { - ul = l; - neg = ""; - } - if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0) - goto err; - } else { - neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; - if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0) - goto err; - - for (i = 0; i < bs->length; i++) { - if (BIO_printf(bp, "%02x%c", bs->data[i], - ((i + 1 == bs->length) ? '\n' : ':')) <= 0) - goto err; - } - } - + if (ossl_serial_number_print(bp, bs, 12) != 0) + goto err; + if (BIO_puts(bp, "\n") <= 0) + goto err; } if (!(cflag & X509_FLAG_NO_SIGNAME)) { @@ -215,7 +192,6 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, } ret = 1; err: - OPENSSL_free(m); return ret; } @@ -454,7 +430,7 @@ static int print_store_certs(BIO *bio, X509_STORE *store) STACK_OF(X509) *certs = X509_STORE_get1_all_certs(store); int ret = print_certs(bio, certs); - sk_X509_pop_free(certs, X509_free); + OSSL_STACK_OF_X509_free(certs); return ret; } else { return BIO_printf(bio, " (no trusted store)\n") >= 0; @@ -468,6 +444,8 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx) int cert_error = X509_STORE_CTX_get_error(ctx); BIO *bio = BIO_new(BIO_s_mem()); /* may be NULL */ + if (bio == NULL) + return 0; BIO_printf(bio, "%s at depth = %d error = %d (%s)\n", X509_STORE_CTX_get0_parent_ctx(ctx) != NULL ? "CRL path validation" @@ -525,3 +503,49 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx) return ok; } + +/* + * Prints serial numbers in decimal and hexadecimal. The indent argument is only + * used if the serial number is too large to fit in an int64_t. + */ +int ossl_serial_number_print(BIO *out, const ASN1_INTEGER *bs, int indent) +{ + int i, ok; + int64_t l; + uint64_t ul; + const char *neg; + + if (bs->length == 0) { + if (BIO_puts(out, " (Empty)") <= 0) + return -1; + return 0; + } + + ERR_set_mark(); + ok = ASN1_INTEGER_get_int64(&l, bs); + ERR_pop_to_mark(); + + if (ok) { /* Reading an int64_t succeeded: print decimal and hex. */ + if (bs->type == V_ASN1_NEG_INTEGER) { + ul = 0 - (uint64_t)l; + neg = "-"; + } else { + ul = l; + neg = ""; + } + if (BIO_printf(out, " %s%ju (%s0x%jx)", neg, ul, neg, ul) <= 0) + return -1; + } else { /* Reading an int64_t failed: just print hex. */ + neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : ""; + if (BIO_printf(out, "\n%*s%s", indent, "", neg) <= 0) + return -1; + + for (i = 0; i < bs->length - 1; i++) { + if (BIO_printf(out, "%02x%c", bs->data[i], ':') <= 0) + return -1; + } + if (BIO_printf(out, "%02x", bs->data[i]) <= 0) + return -1; + } + return 0; +} diff --git a/crypto/x509/v3_addr.c b/crypto/x509/v3_addr.c index 20f3d2ba70de..ac0e1e66d958 100644 --- a/crypto/x509/v3_addr.c +++ b/crypto/x509/v3_addr.c @@ -1,5 +1,5 @@ /* - * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,12 +16,13 @@ #include #include -#include "internal/cryptlib.h" #include #include #include #include #include +#include "internal/cryptlib.h" +#include "crypto/asn1.h" #include "crypto/x509.h" #include "ext_dat.h" #include "x509_local.h" @@ -33,28 +34,28 @@ */ ASN1_SEQUENCE(IPAddressRange) = { - ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), - ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING) + ASN1_SIMPLE(IPAddressRange, min, ASN1_BIT_STRING), + ASN1_SIMPLE(IPAddressRange, max, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(IPAddressRange) ASN1_CHOICE(IPAddressOrRange) = { - ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), - ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange) + ASN1_SIMPLE(IPAddressOrRange, u.addressPrefix, ASN1_BIT_STRING), + ASN1_SIMPLE(IPAddressOrRange, u.addressRange, IPAddressRange) } ASN1_CHOICE_END(IPAddressOrRange) ASN1_CHOICE(IPAddressChoice) = { - ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), - ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange) + ASN1_SIMPLE(IPAddressChoice, u.inherit, ASN1_NULL), + ASN1_SEQUENCE_OF(IPAddressChoice, u.addressesOrRanges, IPAddressOrRange) } ASN1_CHOICE_END(IPAddressChoice) ASN1_SEQUENCE(IPAddressFamily) = { - ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), - ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice) + ASN1_SIMPLE(IPAddressFamily, addressFamily, ASN1_OCTET_STRING), + ASN1_SIMPLE(IPAddressFamily, ipAddressChoice, IPAddressChoice) } ASN1_SEQUENCE_END(IPAddressFamily) ASN1_ITEM_TEMPLATE(IPAddrBlocks) = - ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, - IPAddrBlocks, IPAddressFamily) + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, + IPAddrBlocks, IPAddressFamily) static_ASN1_ITEM_TEMPLATE_END(IPAddrBlocks) IMPLEMENT_ASN1_FUNCTIONS(IPAddressRange) @@ -65,7 +66,7 @@ IMPLEMENT_ASN1_FUNCTIONS(IPAddressFamily) /* * How much buffer space do we need for a raw address? */ -#define ADDR_RAW_BUF_LEN 16 +# define ADDR_RAW_BUF_LEN 16 /* * What's the address length associated with this AFI? @@ -109,6 +110,7 @@ static int addr_expand(unsigned char *addr, memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { unsigned char mask = 0xFF >> (8 - (bs->flags & 7)); + if (fill == 0) addr[bs->length - 1] &= ~mask; else @@ -122,7 +124,7 @@ static int addr_expand(unsigned char *addr, /* * Extract the prefix length from a bitstring. */ -#define addr_prefixlen(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) +# define addr_prefixlen(bs) ((int)((bs)->length * 8 - ((bs)->flags & 7))) /* * i2r handler for one address bitstring. @@ -173,8 +175,10 @@ static int i2r_IPAddressOrRanges(BIO *out, const unsigned afi) { int i; + for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { const IPAddressOrRange *aor = sk_IPAddressOrRange_value(aors, i); + BIO_printf(out, "%*s", indent, ""); switch (aor->type) { case IPAddressOrRange_addressPrefix: @@ -203,9 +207,11 @@ static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, { const IPAddrBlocks *addr = ext; int i; + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); const unsigned int afi = X509v3_addr_get_afi(f); + switch (afi) { case IANA_AFI_IPV4: BIO_printf(out, "%*sIPv4", indent, ""); @@ -294,6 +300,8 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, return -1; prefixlen_a = length * 8; break; + default: + return -1; } switch (b->type) { @@ -307,6 +315,8 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, return -1; prefixlen_b = length * 8; break; + default: + return -1; } if ((r = memcmp(addr_a, addr_b, length)) != 0) @@ -409,12 +419,9 @@ static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, goto err; if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, bytelen)) goto err; - aor->u.addressPrefix->flags &= ~7; - aor->u.addressPrefix->flags |= ASN1_STRING_FLAG_BITS_LEFT; - if (bitlen > 0) { + if (bitlen > 0) aor->u.addressPrefix->data[bytelen - 1] &= ~(0xFF >> bitlen); - aor->u.addressPrefix->flags |= 8 - bitlen; - } + ossl_asn1_string_set_bits_left(aor->u.addressPrefix, 8 - bitlen); *result = aor; return 1; @@ -457,11 +464,11 @@ static int make_addressRange(IPAddressOrRange **result, for (i = length; i > 0 && min[i - 1] == 0x00; --i) ; if (!ASN1_BIT_STRING_set(aor->u.addressRange->min, min, i)) goto err; - aor->u.addressRange->min->flags &= ~7; - aor->u.addressRange->min->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(aor->u.addressRange->min, 0); if (i > 0) { unsigned char b = min[i - 1]; int j = 1; + while ((b & (0xFFU >> j)) != 0) ++j; aor->u.addressRange->min->flags |= 8 - j; @@ -470,11 +477,11 @@ static int make_addressRange(IPAddressOrRange **result, for (i = length; i > 0 && max[i - 1] == 0xFF; --i) ; if (!ASN1_BIT_STRING_set(aor->u.addressRange->max, max, i)) goto err; - aor->u.addressRange->max->flags &= ~7; - aor->u.addressRange->max->flags |= ASN1_STRING_FLAG_BITS_LEFT; + ossl_asn1_string_set_bits_left(aor->u.addressRange->max, 0); if (i > 0) { unsigned char b = max[i - 1]; int j = 1; + while ((b & (0xFFU >> j)) != (0xFFU >> j)) ++j; aor->u.addressRange->max->flags |= 8 - j; @@ -543,6 +550,7 @@ int X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, const unsigned *safi) { IPAddressFamily *f = make_IPAddressFamily(addr, afi, safi); + if (f == NULL || f->ipAddressChoice == NULL || (f->ipAddressChoice->type == IPAddressChoice_addressesOrRanges && @@ -623,6 +631,7 @@ int X509v3_addr_add_range(IPAddrBlocks *addr, IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); IPAddressOrRange *aor; int length = length_from_afi(afi); + if (aors == NULL) return 0; if (!make_addressRange(&aor, min, max, length)) @@ -661,6 +670,7 @@ int X509v3_addr_get_range(IPAddressOrRange *aor, unsigned char *max, const int length) { int afi_length = length_from_afi(afi); + if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && @@ -688,6 +698,7 @@ static int IPAddressFamily_cmp(const IPAddressFamily *const *a_, const ASN1_OCTET_STRING *b = (*b_)->addressFamily; int len = ((a->length <= b->length) ? a->length : b->length); int cmp = memcmp(a->data, b->data, len); + return cmp ? cmp : a->length - b->length; } @@ -799,6 +810,7 @@ int X509v3_addr_is_canonical(IPAddrBlocks *addr) j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { if (!extract_min_max(a, a_min, a_max, length)) return 0; @@ -861,6 +873,7 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) ; if (memcmp(a_max, b_min, length) == 0) { IPAddressOrRange *merged; + if (!make_addressRange(&merged, a_min, b_max, length)) return 0; (void)sk_IPAddressOrRange_set(aors, i, merged); @@ -878,8 +891,10 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + if (!extract_min_max(a, a_min, a_max, length)) return 0; if (memcmp(a_min, a_max, length) > 0) @@ -896,6 +911,12 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, int X509v3_addr_canonize(IPAddrBlocks *addr) { int i; + + if (addr == NULL) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); @@ -929,7 +950,7 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, int i; if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } @@ -988,10 +1009,8 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, } else { s = OPENSSL_strdup(val->value); } - if (s == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (s == NULL) goto err; - } /* * Check for inheritance. Not worth additional complexity to @@ -1031,7 +1050,7 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, goto err; } if (!X509v3_addr_add_prefix(addr, afi, safi, min, prefixlen)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } break; @@ -1054,13 +1073,13 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, goto err; } if (!X509v3_addr_add_range(addr, afi, safi, min, max)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } break; case '\0': if (!X509v3_addr_add_prefix(addr, afi, safi, min, length * 8)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } break; @@ -1110,10 +1129,12 @@ const X509V3_EXT_METHOD ossl_v3_addr = { int X509v3_addr_inherits(IPAddrBlocks *addr) { int i; + if (addr == NULL) return 0; for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); + if (f->ipAddressChoice->type == IPAddressChoice_inherit) return 1; } @@ -1163,11 +1184,14 @@ static int addr_contains(IPAddressOrRanges *parent, int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) { int i; + if (a == NULL || a == b) return 1; if (b == NULL || X509v3_addr_inherits(a) || X509v3_addr_inherits(b)) return 0; (void)sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); + sk_IPAddressFamily_sort(b); + /* Could sort a here too and get O(|a|) running time instead of O(|a| ln |b|) */ for (i = 0; i < sk_IPAddressFamily_num(a); i++) { IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); int j = sk_IPAddressFamily_find(b, fa); @@ -1244,11 +1268,12 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx, validation_err(X509_V_ERR_INVALID_EXTENSION); (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); if (ctx != NULL) ctx->error = X509_V_ERR_OUT_OF_MEM; goto done; } + sk_IPAddressFamily_sort(child); /* * Now walk up the chain. No cert may list resources that its @@ -1274,6 +1299,7 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx, } (void)sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); + sk_IPAddressFamily_sort(x->rfc3779_addr); for (j = 0; j < sk_IPAddressFamily_num(child); j++) { IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); @@ -1326,7 +1352,7 @@ static int addr_validate_path_internal(X509_STORE_CTX *ctx, return ret; } -#undef validation_err +# undef validation_err /* * RFC 3779 2.3 path validation -- called from X509_verify_cert(). @@ -1347,7 +1373,7 @@ int X509v3_addr_validate_path(X509_STORE_CTX *ctx) * Test whether chain covers extension. */ int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, - IPAddrBlocks *ext, int allow_inheritance) + IPAddrBlocks *ext, int allow_inheritance) { if (ext == NULL) return 1; @@ -1358,4 +1384,4 @@ int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, return addr_validate_path_internal(NULL, chain, ext); } -#endif /* OPENSSL_NO_RFC3779 */ +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/crypto/x509/v3_admis.c b/crypto/x509/v3_admis.c index 53259c29f569..8f9e95c44a70 100644 --- a/crypto/x509/v3_admis.c +++ b/crypto/x509/v3_admis.c @@ -102,7 +102,7 @@ static int i2r_NAMING_AUTHORITY(const struct v3_ext_method *method, void *in, || BIO_printf(bp, "\n") <= 0) goto err; } - if (namingAuthority->namingAuthorityUrl != NULL ) { + if (namingAuthority->namingAuthorityUrl != NULL) { if (BIO_printf(bp, "%*s namingAuthorityUrl: ", ind, "") <= 0 || ASN1_STRING_print(bp, namingAuthority->namingAuthorityUrl) <= 0 || BIO_printf(bp, "\n") <= 0) @@ -117,7 +117,7 @@ err: static int i2r_ADMISSION_SYNTAX(const struct v3_ext_method *method, void *in, BIO *bp, int ind) { - ADMISSION_SYNTAX * admission = (ADMISSION_SYNTAX *)in; + ADMISSION_SYNTAX *admission = (ADMISSION_SYNTAX *)in; int i, j, k; if (admission->admissionAuthority != NULL) { diff --git a/crypto/x509/v3_akid.c b/crypto/x509/v3_akid.c index 43b515f50c49..de93dae70edc 100644 --- a/crypto/x509/v3_akid.c +++ b/crypto/x509/v3_akid.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,9 +44,9 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, STACK_OF(CONF_VALUE) *origextlist = extlist, *tmpextlist; if (akeyid->keyid) { - tmp = OPENSSL_buf2hexstr(akeyid->keyid->data, akeyid->keyid->length); + tmp = i2s_ASN1_OCTET_STRING(NULL, akeyid->keyid); if (tmp == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } if (!X509V3_add_value((akeyid->issuer || akeyid->serial) ? "keyid" : NULL, @@ -66,9 +66,9 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, extlist = tmpextlist; } if (akeyid->serial) { - tmp = OPENSSL_buf2hexstr(akeyid->serial->data, akeyid->serial->length); + tmp = i2s_ASN1_OCTET_STRING(NULL, akeyid->serial); if (tmp == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } if (!X509V3_add_value("serial", tmp, &extlist)) { @@ -85,14 +85,14 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, } /*- - * Currently two options: - * keyid: use the issuers subject keyid, the value 'always' means its is - * an error if the issuer certificate doesn't have a key id. - * issuer: use the issuers cert issuer and serial number. The default is - * to only use this if keyid is not present. With the option 'always' + * Three explicit tags may be given, where 'keyid' and 'issuer' may be combined: + * 'none': do not add any authority key identifier. + * 'keyid': use the issuer's subject keyid; the option 'always' means its is + * an error if the issuer certificate doesn't have a subject key id. + * 'issuer': use the issuer's cert issuer and serial number. The default is + * to only use this if 'keyid' is not present. With the option 'always' * this is always included. */ - static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values) @@ -119,16 +119,27 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, for (i = 0; i < n; i++) { cnf = sk_CONF_VALUE_value(values, i); - if (strcmp(cnf->name, "keyid") == 0) { - keyid = 1; - if (cnf->value && strcmp(cnf->value, "always") == 0) - keyid = 2; - } else if (strcmp(cnf->name, "issuer") == 0) { - issuer = 1; - if (cnf->value && strcmp(cnf->value, "always") == 0) - issuer = 2; - } else { + if (cnf->value != NULL && strcmp(cnf->value, "always") != 0) { ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_OPTION, + "name=%s option=%s", cnf->name, cnf->value); + goto err; + } + if (strcmp(cnf->name, "keyid") == 0 && keyid == 0) { + keyid = 1; + if (cnf->value != NULL) + keyid = 2; + } else if (strcmp(cnf->name, "issuer") == 0 && issuer == 0) { + issuer = 1; + if (cnf->value != NULL) + issuer = 2; + } else if (strcmp(cnf->name, "none") == 0 + || strcmp(cnf->name, "keyid") == 0 + || strcmp(cnf->name, "issuer") == 0) { + ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_VALUE, + "name=%s", cnf->name); + goto err; + } else { + ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNKNOWN_VALUE, "name=%s", cnf->name); goto err; } @@ -161,8 +172,13 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, */ i = X509_get_ext_by_NID(issuer_cert, NID_subject_key_identifier, -1); if (i >= 0 && (ext = X509_get_ext(issuer_cert, i)) != NULL - && !(same_issuer && !ss)) + && !(same_issuer && !ss)) { ikeyid = X509V3_EXT_d2i(ext); + if (ASN1_STRING_length(ikeyid) == 0) /* indicating "none" */ { + ASN1_OCTET_STRING_free(ikeyid); + ikeyid = NULL; + } + } if (ikeyid == NULL && same_issuer && ctx->issuer_pkey != NULL) { /* generate fallback AKID, emulating s2i_skey_id(..., "hash") */ X509_PUBKEY *pubkey = NULL; @@ -171,15 +187,13 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, ikeyid = ossl_x509_pubkey_hash(pubkey); X509_PUBKEY_free(pubkey); } - if ((keyid == 2 || issuer == 0) - && (ikeyid == NULL - || ASN1_STRING_length(ikeyid) <= 2) /* indicating "none" */) { + if (keyid == 2 && ikeyid == NULL) { ERR_raise(ERR_LIB_X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); goto err; } } - if (issuer == 2 || (issuer == 1 && ikeyid == NULL)) { + if (issuer == 2 || (issuer == 1 && !ss && ikeyid == NULL)) { isname = X509_NAME_dup(X509_get_issuer_name(issuer_cert)); serial = ASN1_INTEGER_dup(X509_get0_serialNumber(issuer_cert)); if (isname == NULL || serial == NULL) { @@ -190,9 +204,12 @@ static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, if (isname != NULL) { if ((gens = sk_GENERAL_NAME_new_null()) == NULL - || (gen = GENERAL_NAME_new()) == NULL - || !sk_GENERAL_NAME_push(gens, gen)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + || (gen = GENERAL_NAME_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + if (!sk_GENERAL_NAME_push(gens, gen)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } gen->type = GEN_DIRNAME; diff --git a/crypto/x509/v3_asid.c b/crypto/x509/v3_asid.c index c2b6f8a660df..e08e11d587eb 100644 --- a/crypto/x509/v3_asid.c +++ b/crypto/x509/v3_asid.c @@ -310,14 +310,14 @@ static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) if ((bn == NULL && (bn = BN_new()) == NULL) || ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_BN_LIB); goto done; } if ((a_max_plus_one = BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) { a_max_plus_one = orig; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto done; } @@ -431,14 +431,14 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) if ((bn == NULL && (bn = BN_new()) == NULL) || ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_BN_LIB); goto done; } if ((a_max_plus_one = BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) { a_max_plus_one = orig; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto done; } @@ -449,10 +449,8 @@ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) ASRange *r; switch (a->type) { case ASIdOrRange_id: - if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) goto done; - } r->min = a_min; r->max = b_max; a->type = ASIdOrRange_range; @@ -526,7 +524,7 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method, int i; if ((asid = ASIdentifiers_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); return NULL; } @@ -592,21 +590,19 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method, */ if (!is_range) { if (!X509V3_get_value_int(val, &min)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } } else { char *s = OPENSSL_strdup(val->value); - if (s == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (s == NULL) goto err; - } s[i1] = '\0'; min = s2i_ASN1_INTEGER(NULL, s); max = s2i_ASN1_INTEGER(NULL, s + i2); OPENSSL_free(s); if (min == NULL || max == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } if (ASN1_INTEGER_cmp(min, max) > 0) { @@ -615,7 +611,7 @@ static void *v2i_ASIdentifiers(const struct v3_ext_method *method, } } if (!X509v3_asid_add_id_or_range(asid, which, min, max)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); goto err; } min = max = NULL; diff --git a/crypto/x509/v3_bcons.c b/crypto/x509/v3_bcons.c index 6e7a165f26e8..17962ed43f01 100644 --- a/crypto/x509/v3_bcons.c +++ b/crypto/x509/v3_bcons.c @@ -61,7 +61,7 @@ static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, int i; if ((bcons = BASIC_CONSTRAINTS_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } for (i = 0; i < sk_CONF_VALUE_num(values); i++) { diff --git a/crypto/x509/v3_bitst.c b/crypto/x509/v3_bitst.c index b53c5ba3ecd3..d41c95b5138f 100644 --- a/crypto/x509/v3_bitst.c +++ b/crypto/x509/v3_bitst.c @@ -64,7 +64,7 @@ ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, int i; BIT_STRING_BITNAME *bnam; if ((bs = ASN1_BIT_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { @@ -73,7 +73,7 @@ ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, if (strcmp(bnam->sname, val->name) == 0 || strcmp(bnam->lname, val->name) == 0) { if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); ASN1_BIT_STRING_free(bs); return NULL; } diff --git a/crypto/x509/v3_conf.c b/crypto/x509/v3_conf.c index 1c11d671b2ed..c575a43459ea 100644 --- a/crypto/x509/v3_conf.c +++ b/crypto/x509/v3_conf.c @@ -148,34 +148,41 @@ static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, ext_der = NULL; ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it)); - if (ext_len < 0) - goto merr; + if (ext_len < 0) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } } else { unsigned char *p; ext_len = method->i2d(ext_struc, NULL); - if (ext_len <= 0) - goto merr; + if (ext_len <= 0) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } if ((ext_der = OPENSSL_malloc(ext_len)) == NULL) - goto merr; + goto err; p = ext_der; method->i2d(ext_struc, &p); } - if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) - goto merr; + if ((ext_oct = ASN1_OCTET_STRING_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } ext_oct->data = ext_der; ext_der = NULL; ext_oct->length = ext_len; ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); - if (!ext) - goto merr; + if (!ext) { + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); + goto err; + } ASN1_OCTET_STRING_free(ext_oct); return ext; - merr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + err: OPENSSL_free(ext_der); ASN1_OCTET_STRING_free(ext_oct); return NULL; @@ -200,9 +207,8 @@ static int v3_check_critical(const char **value) { const char *p = *value; - if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) + if (!CHECK_AND_SKIP_PREFIX(p, "critical,")) return 0; - p += 9; while (ossl_isspace(*p)) p++; *value = p; @@ -215,11 +221,9 @@ static int v3_check_generic(const char **value) int gen_type = 0; const char *p = *value; - if ((strlen(p) >= 4) && strncmp(p, "DER:", 4) == 0) { - p += 4; + if (CHECK_AND_SKIP_PREFIX(p, "DER:")) { gen_type = 1; - } else if ((strlen(p) >= 5) && strncmp(p, "ASN1:", 5) == 0) { - p += 5; + } else if (CHECK_AND_SKIP_PREFIX(p, "ASN1:")) { gen_type = 2; } else return 0; @@ -259,7 +263,7 @@ static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, } if ((oct = ASN1_OCTET_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } @@ -311,13 +315,27 @@ int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, { X509_EXTENSION *ext; STACK_OF(CONF_VALUE) *nval; - CONF_VALUE *val; - int i; + const CONF_VALUE *val; + int i, akid = -1, skid = -1; if ((nval = NCONF_get_section(conf, section)) == NULL) return 0; for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { val = sk_CONF_VALUE_value(nval, i); + if (strcmp(val->name, "authorityKeyIdentifier") == 0) + akid = i; + else if (strcmp(val->name, "subjectKeyIdentifier") == 0) + skid = i; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (skid > akid && akid >= 0) { + /* make sure SKID is handled before AKID */ + if (i == akid) + val = sk_CONF_VALUE_value(nval, skid); + else if (i == skid) + val = sk_CONF_VALUE_value(nval, akid); + } if ((ext = X509V3_EXT_nconf_int(conf, ctx, val->section, val->name, val->value)) == NULL) return 0; diff --git a/crypto/x509/v3_cpols.c b/crypto/x509/v3_cpols.c index 5353a6916761..fcf8728937db 100644 --- a/crypto/x509/v3_cpols.c +++ b/crypto/x509/v3_cpols.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -105,7 +105,7 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, pols = sk_POLICYINFO_new_reserve(NULL, num); if (pols == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } @@ -144,14 +144,14 @@ static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, pol = POLICYINFO_new(); if (pol == NULL) { ASN1_OBJECT_free(pobj); - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } pol->policyid = pobj; } if (!sk_POLICYINFO_push(pols, pol)) { POLICYINFO_free(pol); - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } } @@ -171,8 +171,10 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, POLICYINFO *pol; POLICYQUALINFO *qual; - if ((pol = POLICYINFO_new()) == NULL) - goto merr; + if ((pol = POLICYINFO_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { cnf = sk_CONF_VALUE_value(polstrs, i); if (strcmp(cnf->name, "policyIdentifier") == 0) { @@ -188,19 +190,28 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, } else if (!ossl_v3_name_cmp(cnf->name, "CPS")) { if (pol->qualifiers == NULL) pol->qualifiers = sk_POLICYQUALINFO_new_null(); - if ((qual = POLICYQUALINFO_new()) == NULL) - goto merr; - if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) - goto merr; + if ((qual = POLICYQUALINFO_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) { + POLICYQUALINFO_free(qual); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_cps)) == NULL) { ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR); goto err; } - if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL) - goto merr; + if ((qual->d.cpsuri = ASN1_IA5STRING_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, - strlen(cnf->value))) - goto merr; + strlen(cnf->value))) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } } else if (!ossl_v3_name_cmp(cnf->name, "userNotice")) { STACK_OF(CONF_VALUE) *unot; if (*cnf->value != '@') { @@ -221,8 +232,11 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, goto err; if (pol->qualifiers == NULL) pol->qualifiers = sk_POLICYQUALINFO_new_null(); - if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) - goto merr; + if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) { + POLICYQUALINFO_free(qual); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } } else { ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_OPTION); X509V3_conf_err(cnf); @@ -236,9 +250,6 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, return pol; - merr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - err: POLICYINFO_free(pol); return NULL; @@ -261,17 +272,17 @@ static int displaytext_str2tag(const char *tagstr, unsigned int *tag_len) if (len == -1) return V_ASN1_VISIBLESTRING; *tag_len = len; - if (len == sizeof("UTF8") - 1 && strncmp(tagstr, "UTF8", len) == 0) + if (len == sizeof("UTF8") - 1 && HAS_PREFIX(tagstr, "UTF8")) return V_ASN1_UTF8STRING; - if (len == sizeof("UTF8String") - 1 && strncmp(tagstr, "UTF8String", len) == 0) + if (len == sizeof("UTF8String") - 1 && HAS_PREFIX(tagstr, "UTF8String")) return V_ASN1_UTF8STRING; - if (len == sizeof("BMP") - 1 && strncmp(tagstr, "BMP", len) == 0) + if (len == sizeof("BMP") - 1 && HAS_PREFIX(tagstr, "BMP")) return V_ASN1_BMPSTRING; - if (len == sizeof("BMPSTRING") - 1 && strncmp(tagstr, "BMPSTRING", len) == 0) + if (len == sizeof("BMPSTRING") - 1 && HAS_PREFIX(tagstr, "BMPSTRING")) return V_ASN1_BMPSTRING; - if (len == sizeof("VISIBLE") - 1 && strncmp(tagstr, "VISIBLE", len) == 0) + if (len == sizeof("VISIBLE") - 1 && HAS_PREFIX(tagstr, "VISIBLE")) return V_ASN1_VISIBLESTRING; - if (len == sizeof("VISIBLESTRING") - 1 && strncmp(tagstr, "VISIBLESTRING", len) == 0) + if (len == sizeof("VISIBLESTRING") - 1 && HAS_PREFIX(tagstr, "VISIBLESTRING")) return V_ASN1_VISIBLESTRING; *tag_len = 0; return V_ASN1_VISIBLESTRING; @@ -287,14 +298,18 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, POLICYQUALINFO *qual; char *value = NULL; - if ((qual = POLICYQUALINFO_new()) == NULL) - goto merr; + if ((qual = POLICYQUALINFO_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } if ((qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice)) == NULL) { ERR_raise(ERR_LIB_X509V3, ERR_R_INTERNAL_ERROR); goto err; } - if ((not = USERNOTICE_new()) == NULL) - goto merr; + if ((not = USERNOTICE_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } qual->d.usernotice = not; for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { cnf = sk_CONF_VALUE_value(unot, i); @@ -302,19 +317,25 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, value = cnf->value; if (strcmp(cnf->name, "explicitText") == 0) { tag = displaytext_str2tag(value, &tag_len); - if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL) - goto merr; + if ((not->exptext = ASN1_STRING_type_new(tag)) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } if (tag_len != 0) value += tag_len + 1; len = strlen(value); - if (!ASN1_STRING_set(not->exptext, value, len)) - goto merr; + if (!ASN1_STRING_set(not->exptext, value, len)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } } else if (strcmp(cnf->name, "organization") == 0) { NOTICEREF *nref; if (!not->noticeref) { - if ((nref = NOTICEREF_new()) == NULL) - goto merr; + if ((nref = NOTICEREF_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } not->noticeref = nref; } else nref = not->noticeref; @@ -323,15 +344,19 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, else nref->organization->type = V_ASN1_VISIBLESTRING; if (!ASN1_STRING_set(nref->organization, cnf->value, - strlen(cnf->value))) - goto merr; + strlen(cnf->value))) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } } else if (strcmp(cnf->name, "noticeNumbers") == 0) { NOTICEREF *nref; STACK_OF(CONF_VALUE) *nos; if (!not->noticeref) { - if ((nref = NOTICEREF_new()) == NULL) - goto merr; + if ((nref = NOTICEREF_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } not->noticeref = nref; } else nref = not->noticeref; @@ -361,9 +386,6 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, return qual; - merr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - err: POLICYQUALINFO_free(qual); return NULL; @@ -380,19 +402,15 @@ static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) cnf = sk_CONF_VALUE_value(nos, i); if ((aint = s2i_ASN1_INTEGER(NULL, cnf->name)) == NULL) { ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NUMBER); - goto err; + return 0; + } + if (!sk_ASN1_INTEGER_push(nnums, aint)) { + ASN1_INTEGER_free(aint); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + return 0; } - if (!sk_ASN1_INTEGER_push(nnums, aint)) - goto merr; } return 1; - - merr: - ASN1_INTEGER_free(aint); - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - - err: - return 0; } static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, diff --git a/crypto/x509/v3_crld.c b/crypto/x509/v3_crld.c index 07c8379d3521..140b279d2f36 100644 --- a/crypto/x509/v3_crld.c +++ b/crypto/x509/v3_crld.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -75,7 +75,7 @@ static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, goto err; } - if (strncmp(cnf->name, "fullname", 9) == 0) { + if (HAS_PREFIX(cnf->name, "fullname")) { fnm = gnames_from_sectname(ctx, cnf->value); if (!fnm) goto err; @@ -249,8 +249,10 @@ static void *v2i_crld(const X509V3_EXT_METHOD *method, int i; crld = sk_DIST_POINT_new_reserve(NULL, num); - if (crld == NULL) - goto merr; + if (crld == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } for (i = 0; i < num; i++) { DIST_POINT *point; @@ -268,16 +270,24 @@ static void *v2i_crld(const X509V3_EXT_METHOD *method, } else { if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) goto err; - if ((gens = GENERAL_NAMES_new()) == NULL) - goto merr; - if (!sk_GENERAL_NAME_push(gens, gen)) - goto merr; + if ((gens = GENERAL_NAMES_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + if (!sk_GENERAL_NAME_push(gens, gen)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } gen = NULL; - if ((point = DIST_POINT_new()) == NULL) - goto merr; + if ((point = DIST_POINT_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */ - if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) - goto merr; + if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } point->distpoint->name.fullname = gens; point->distpoint->type = 0; gens = NULL; @@ -285,8 +295,6 @@ static void *v2i_crld(const X509V3_EXT_METHOD *method, } return crld; - merr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); err: GENERAL_NAME_free(gen); GENERAL_NAMES_free(gens); @@ -319,6 +327,7 @@ ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = { IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME) +IMPLEMENT_ASN1_DUP_FUNCTION(DIST_POINT_NAME) ASN1_SEQUENCE(DIST_POINT) = { ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0), @@ -369,8 +378,10 @@ static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *name, *val; int i, ret; idp = ISSUING_DIST_POINT_new(); - if (idp == NULL) - goto merr; + if (idp == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { cnf = sk_CONF_VALUE_value(nval, i); name = cnf->name; @@ -403,30 +414,17 @@ static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, } return idp; - merr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); err: ISSUING_DIST_POINT_free(idp); return NULL; } -static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) -{ - int i; - for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { - if (i > 0) - BIO_puts(out, "\n"); - BIO_printf(out, "%*s", indent + 2, ""); - GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); - } - return 1; -} - static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) { if (dpn->type == 0) { BIO_printf(out, "%*sFull Name:\n", indent, ""); - print_gens(out, dpn->name.fullname, indent); + OSSL_GENERAL_NAMES_print(out, dpn->name.fullname, indent); + BIO_puts(out, "\n"); } else { X509_NAME ntmp; ntmp.entries = dpn->name.relativename; @@ -477,7 +475,7 @@ static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, print_reasons(out, "Reasons", point->reasons, indent); if (point->CRLissuer) { BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); - print_gens(out, point->CRLissuer, indent); + OSSL_GENERAL_NAMES_print(out, point->CRLissuer, indent); } } return 1; @@ -511,3 +509,173 @@ int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname) dpn->dpname = NULL; return 0; } + +ASN1_SEQUENCE(OSSL_AA_DIST_POINT) = { + ASN1_EXP_OPT(OSSL_AA_DIST_POINT, distpoint, DIST_POINT_NAME, 0), + ASN1_IMP_OPT(OSSL_AA_DIST_POINT, reasons, ASN1_BIT_STRING, 1), + ASN1_IMP_OPT(OSSL_AA_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 2), + ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsUserAttributeCerts, ASN1_TBOOLEAN, 3), + ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsAACerts, ASN1_TBOOLEAN, 4), + ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsSOAPublicKeyCerts, ASN1_TBOOLEAN, 5) +} ASN1_SEQUENCE_END(OSSL_AA_DIST_POINT) + +IMPLEMENT_ASN1_FUNCTIONS(OSSL_AA_DIST_POINT) + +static int print_boolean(BIO *out, ASN1_BOOLEAN b) +{ + return BIO_puts(out, b ? "TRUE" : "FALSE"); +} + +static OSSL_AA_DIST_POINT *aaidp_from_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + int i, ret; + CONF_VALUE *cnf; + OSSL_AA_DIST_POINT *point = OSSL_AA_DIST_POINT_new(); + + if (point == NULL) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + ret = set_dist_point_name(&point->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (strcmp(cnf->name, "reasons") == 0) { + if (!set_reasons(&point->reasons, cnf->value)) + goto err; + } else if (strcmp(cnf->name, "indirectCRL") == 0) { + if (!X509V3_get_value_bool(cnf, &point->indirectCRL)) + goto err; + } else if (strcmp(cnf->name, "containsUserAttributeCerts") == 0) { + if (!X509V3_get_value_bool(cnf, &point->containsUserAttributeCerts)) + goto err; + } else if (strcmp(cnf->name, "containsAACerts") == 0) { + if (!X509V3_get_value_bool(cnf, &point->containsAACerts)) + goto err; + } else if (strcmp(cnf->name, "containsSOAPublicKeyCerts") == 0) { + if (!X509V3_get_value_bool(cnf, &point->containsSOAPublicKeyCerts)) + goto err; + } + } + + return point; + + err: + OSSL_AA_DIST_POINT_free(point); + return NULL; +} + +static void *v2i_aaidp(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + OSSL_AA_DIST_POINT *point = NULL; + STACK_OF(CONF_VALUE) *dpsect; + + cnf = sk_CONF_VALUE_value(nval, 0); + if (cnf == NULL) + return NULL; + if (cnf->value == NULL) { + dpsect = X509V3_get_section(ctx, cnf->name); + if (dpsect == NULL) + goto err; + point = aaidp_from_section(ctx, dpsect); + X509V3_section_free(ctx, dpsect); + if (point == NULL) + goto err; + } else { + if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) + goto err; + if ((gens = GENERAL_NAMES_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + if (!sk_GENERAL_NAME_push(gens, gen)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } + gen = NULL; + if ((point = OSSL_AA_DIST_POINT_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; + gens = NULL; + } + return point; + + err: + OSSL_AA_DIST_POINT_free(point); + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + return NULL; +} + +static int i2r_aaidp(const X509V3_EXT_METHOD *method, void *dp, BIO *out, + int indent) +{ + OSSL_AA_DIST_POINT *pdp = dp; + + if (pdp->distpoint) + if (print_distpoint(out, pdp->distpoint, indent) <= 0) + return 0; + if (pdp->reasons) + if (print_reasons(out, "Reasons", pdp->reasons, indent) <= 0) + return 0; + if (pdp->indirectCRL) { + if (BIO_printf(out, "%*sIndirect CRL: ", indent, "") <= 0) + return 0; + if (print_boolean(out, pdp->indirectCRL) <= 0) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + } + if (pdp->containsUserAttributeCerts) { + if (BIO_printf(out, "%*sContains User Attribute Certificates: ", indent, "") <= 0) + return 0; + if (print_boolean(out, pdp->containsUserAttributeCerts) <= 0) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + } + if (pdp->containsAACerts) { + if (BIO_printf(out, "%*sContains Attribute Authority (AA) Certificates: ", + indent, "") <= 0) + return 0; + if (print_boolean(out, pdp->containsAACerts) <= 0) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + } + if (pdp->containsSOAPublicKeyCerts) { + if (BIO_printf(out, + "%*sContains Source Of Authority (SOA) Public Key Certificates: ", + indent, "") <= 0) + return 0; + if (print_boolean(out, pdp->containsSOAPublicKeyCerts) <= 0) + return 0; + if (BIO_puts(out, "\n") <= 0) + return 0; + } + return 1; +} + +const X509V3_EXT_METHOD ossl_v3_aa_issuing_dist_point = { + NID_id_aa_issuing_distribution_point, 0, + ASN1_ITEM_ref(OSSL_AA_DIST_POINT), + 0, 0, 0, 0, + 0, 0, + 0, + v2i_aaidp, + i2r_aaidp, 0, + NULL +}; diff --git a/crypto/x509/v3_extku.c b/crypto/x509/v3_extku.c index 4f2a86bdcb2b..cb95c5bb79c7 100644 --- a/crypto/x509/v3_extku.c +++ b/crypto/x509/v3_extku.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -44,6 +44,30 @@ const X509V3_EXT_METHOD ossl_v3_ocsp_accresp = { NULL }; +/* Acceptable Certificate Policies also is a SEQUENCE OF OBJECT */ +const X509V3_EXT_METHOD ossl_v3_acc_cert_policies = { + NID_acceptable_cert_policies, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + +/* Acceptable Privilege Policies also is a SEQUENCE OF OBJECT */ +const X509V3_EXT_METHOD ossl_v3_acc_priv_policies = { + NID_acceptable_privilege_policies, 0, + ASN1_ITEM_ref(EXTENDED_KEY_USAGE), + 0, 0, 0, 0, + 0, 0, + i2v_EXTENDED_KEY_USAGE, + v2i_EXTENDED_KEY_USAGE, + 0, 0, + NULL +}; + ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT) ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE) @@ -79,7 +103,7 @@ static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, extku = sk_ASN1_OBJECT_new_reserve(NULL, num); if (extku == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); sk_ASN1_OBJECT_free(extku); return NULL; } diff --git a/crypto/x509/v3_genn.c b/crypto/x509/v3_genn.c index 1f67bf2f63ab..fd48b519278e 100644 --- a/crypto/x509/v3_genn.c +++ b/crypto/x509/v3_genn.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -58,6 +58,35 @@ GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a) (char *)a); } +int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src) +{ + GENERAL_NAME *name; + + if (tgt == NULL) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + + if ((name = GENERAL_NAME_new()) == NULL) + return 0; + name->type = GEN_DIRNAME; + + if (src == NULL) { /* NULL-DN */ + if ((name->d.directoryName = X509_NAME_new()) == NULL) + goto err; + } else if (!X509_NAME_set(&name->d.directoryName, src)) { + goto err; + } + + GENERAL_NAME_free(*tgt); + *tgt = name; + return 1; + + err: + GENERAL_NAME_free(name); + return 0; +} + static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) { int res; diff --git a/crypto/x509/v3_ia5.c b/crypto/x509/v3_ia5.c index 6722b6c01f05..7b799358727e 100644 --- a/crypto/x509/v3_ia5.c +++ b/crypto/x509/v3_ia5.c @@ -31,10 +31,8 @@ char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5) if (ia5 == NULL || ia5->length <= 0) return NULL; - if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((tmp = OPENSSL_malloc(ia5->length + 1)) == NULL) return NULL; - } memcpy(tmp, ia5->data, ia5->length); tmp[ia5->length] = 0; return tmp; @@ -48,8 +46,10 @@ ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT); return NULL; } - if ((ia5 = ASN1_IA5STRING_new()) == NULL) - goto err; + if ((ia5 = ASN1_IA5STRING_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + return NULL; + } if (!ASN1_STRING_set((ASN1_STRING *)ia5, str, strlen(str))) { ASN1_IA5STRING_free(ia5); return NULL; @@ -58,7 +58,4 @@ ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ebcdic2ascii(ia5->data, ia5->data, ia5->length); #endif /* CHARSET_EBCDIC */ return ia5; - err: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - return NULL; } diff --git a/crypto/x509/v3_info.c b/crypto/x509/v3_info.c index 5f21ce11e7d5..7e4d9313d829 100644 --- a/crypto/x509/v3_info.c +++ b/crypto/x509/v3_info.c @@ -73,8 +73,10 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS( desc = sk_ACCESS_DESCRIPTION_value(ainfo, i); tmp = i2v_GENERAL_NAME(method, desc->location, tret); - if (tmp == NULL) + if (tmp == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; + } tret = tmp; vtmp = sk_CONF_VALUE_value(tret, i); i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method); @@ -91,7 +93,6 @@ static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS( return tret; err: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); if (ret == NULL && tret != NULL) sk_CONF_VALUE_pop_free(tret, X509V3_conf_free); return NULL; @@ -111,13 +112,13 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD char *objtmp, *ptmp; if ((ainfo = sk_ACCESS_DESCRIPTION_new_reserve(NULL, num)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } for (i = 0; i < num; i++) { cnf = sk_CONF_VALUE_value(nval, i); if ((acc = ACCESS_DESCRIPTION_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } sk_ACCESS_DESCRIPTION_push(ainfo, acc); /* Cannot fail due to reserve */ @@ -130,10 +131,8 @@ static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD ctmp.value = cnf->value; if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0)) goto err; - if ((objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((objtmp = OPENSSL_strndup(cnf->name, ptmp - cnf->name)) == NULL) goto err; - } acc->method = OBJ_txt2obj(objtmp, 0); if (!acc->method) { ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT, diff --git a/crypto/x509/v3_ist.c b/crypto/x509/v3_ist.c index 96c40a3961a2..b7ce4bb91915 100644 --- a/crypto/x509/v3_ist.c +++ b/crypto/x509/v3_ist.c @@ -17,7 +17,7 @@ /* * Issuer Sign Tool (1.2.643.100.112) The name of the tool used to signs the subject (ASN1_SEQUENCE) - * This extention is required to obtain the status of a qualified certificate at Russian Federation. + * This extension is required to obtain the status of a qualified certificate at Russian Federation. * RFC-style description is available here: https://tools.ietf.org/html/draft-deremin-rfc4491-bis-04#section-5 * Russian Federal Law 63 "Digital Sign" is available here: http://www.consultant.ru/document/cons_doc_LAW_112701/ */ @@ -39,7 +39,7 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ int i; if (ist == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } for (i = 0; i < sk_CONF_VALUE_num(nval); ++i) { @@ -53,7 +53,7 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ if (ist->signTool == NULL || cnf->value == NULL || !ASN1_STRING_set(ist->signTool, cnf->value, strlen(cnf->value))) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "cATool") == 0) { @@ -61,7 +61,7 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ if (ist->cATool == NULL || cnf->value == NULL || !ASN1_STRING_set(ist->cATool, cnf->value, strlen(cnf->value))) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "signToolCert") == 0) { @@ -69,7 +69,7 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ if (ist->signToolCert == NULL || cnf->value == NULL || !ASN1_STRING_set(ist->signToolCert, cnf->value, strlen(cnf->value))) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else if (strcmp(cnf->name, "cAToolCert") == 0) { @@ -77,7 +77,7 @@ static ISSUER_SIGN_TOOL *v2i_issuer_sign_tool(X509V3_EXT_METHOD *method, X509V3_ if (ist->cAToolCert == NULL || cnf->value == NULL || !ASN1_STRING_set(ist->cAToolCert, cnf->value, strlen(cnf->value))) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } else { @@ -103,9 +103,6 @@ static int i2r_issuer_sign_tool(X509V3_EXT_METHOD *method, return 0; } if (ist->signTool != NULL) { - if (new_line == 1) { - BIO_write(out, "\n", 1); - } BIO_printf(out, "%*ssignTool : ", indent, ""); BIO_write(out, ist->signTool->data, ist->signTool->length); new_line = 1; diff --git a/crypto/x509/v3_lib.c b/crypto/x509/v3_lib.c index 5ffeb75d9f5b..077b22c863ec 100644 --- a/crypto/x509/v3_lib.c +++ b/crypto/x509/v3_lib.c @@ -1,5 +1,5 @@ /* - * 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 @@ -26,11 +26,11 @@ int X509V3_EXT_add(X509V3_EXT_METHOD *ext) { if (ext_list == NULL && (ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return 0; } if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return 0; } return 1; @@ -63,7 +63,10 @@ const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) return *ret; if (!ext_list) return NULL; + /* Ideally, this would be done under a lock */ + sk_X509V3_EXT_METHOD_sort(ext_list); idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp); + /* A failure to locate the item is handled by the value method */ return sk_X509V3_EXT_METHOD_value(ext_list, idx); } @@ -92,10 +95,8 @@ int X509V3_EXT_add_alias(int nid_to, int nid_from) ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NOT_FOUND); return 0; } - if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((tmpext = OPENSSL_malloc(sizeof(*tmpext))) == NULL) return 0; - } *tmpext = *ext; tmpext->ext_nid = nid_to; tmpext->ext_flags |= X509V3_EXT_DYNAMIC; @@ -291,7 +292,7 @@ int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, return 1; m_fail: - /* ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); */ + /* ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); */ if (ret != *x) sk_X509_EXTENSION_free(ret); X509_EXTENSION_free(ext); diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index a51354e7fc4c..51208ce78919 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -1,5 +1,5 @@ /* - * Copyright 2003-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2003-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,10 +9,12 @@ #include "internal/cryptlib.h" #include "internal/numbers.h" +#include "internal/safe_math.h" #include #include "crypto/asn1.h" #include #include +#include #include #include @@ -20,6 +22,8 @@ #include "crypto/punycode.h" #include "ext_dat.h" +OSSL_SAFE_MATH_SIGNED(int, int) + static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); @@ -31,8 +35,8 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); -static int nc_match_single(int effective_type, GENERAL_NAME *sub, - GENERAL_NAME *gen); +static int nc_match_single(int effective_type, GENERAL_NAME *gen, + GENERAL_NAME *base); static int nc_dn(const X509_NAME *sub, const X509_NAME *nm); static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); @@ -50,6 +54,26 @@ const X509V3_EXT_METHOD ossl_v3_name_constraints = { NULL }; +const X509V3_EXT_METHOD ossl_v3_holder_name_constraints = { + NID_holder_name_constraints, 0, + ASN1_ITEM_ref(NAME_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + 0, v2i_NAME_CONSTRAINTS, + i2r_NAME_CONSTRAINTS, 0, + NULL +}; + +const X509V3_EXT_METHOD ossl_v3_delegated_name_constraints = { + NID_delegated_name_constraints, 0, + ASN1_ITEM_ref(NAME_CONSTRAINTS), + 0, 0, 0, 0, + 0, 0, + 0, v2i_NAME_CONSTRAINTS, + i2r_NAME_CONSTRAINTS, 0, + NULL +}; + ASN1_SEQUENCE(GENERAL_SUBTREE) = { ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME), ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0), @@ -132,14 +156,16 @@ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, GENERAL_SUBTREE *sub = NULL; ncons = NAME_CONSTRAINTS_new(); - if (ncons == NULL) - goto memerr; + if (ncons == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + goto err; + } for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { val = sk_CONF_VALUE_value(nval, i); - if (strncmp(val->name, "permitted", 9) == 0 && val->name[9]) { + if (HAS_PREFIX(val->name, "permitted") && val->name[9]) { ptree = &ncons->permittedSubtrees; tval.name = val->name + 10; - } else if (strncmp(val->name, "excluded", 8) == 0 && val->name[8]) { + } else if (HAS_PREFIX(val->name, "excluded") && val->name[8]) { ptree = &ncons->excludedSubtrees; tval.name = val->name + 9; } else { @@ -148,21 +174,25 @@ static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, } tval.value = val->value; sub = GENERAL_SUBTREE_new(); - if (sub == NULL) - goto memerr; - if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) + if (sub == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; + } + if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); + goto err; + } if (*ptree == NULL) *ptree = sk_GENERAL_SUBTREE_new_null(); - if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub)) - goto memerr; + if (*ptree == NULL || !sk_GENERAL_SUBTREE_push(*ptree, sub)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); + goto err; + } sub = NULL; } return ncons; - memerr: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); err: NAME_CONSTRAINTS_free(ncons); GENERAL_SUBTREE_free(sub); @@ -223,16 +253,16 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) static int add_lengths(int *out, int a, int b) { + int err = 0; + /* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */ if (a < 0) a = 0; if (b < 0) b = 0; - if (a > INT_MAX - b) - return 0; - *out = a + b; - return 1; + *out = safe_add_int(a, b, &err); + return !err; } /*- @@ -432,7 +462,7 @@ int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc) ne = X509_NAME_get_entry(nm, i); cn = X509_NAME_ENTRY_get_data(ne); - /* Only process attributes that look like host names */ + /* Only process attributes that look like hostnames */ if ((r = cn2dnsid(cn, &idval, &idlen)) != X509_V_OK) return r; if (idlen == 0) @@ -640,7 +670,7 @@ static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base) const char *emlptr; const char *emlat; char ulabel[256]; - size_t size = sizeof(ulabel) - 1; + size_t size = sizeof(ulabel); int ret = X509_V_OK; size_t emlhostlen; @@ -667,18 +697,16 @@ static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base) goto end; } - memset(ulabel, 0, sizeof(ulabel)); /* Special case: initial '.' is RHS match */ if (*baseptr == '.') { ulabel[0] = '.'; - size -= 1; - if (ossl_a2ulabel(baseptr, ulabel + 1, &size) <= 0) { + if (ossl_a2ulabel(baseptr, ulabel + 1, size - 1) <= 0) { ret = X509_V_ERR_UNSPECIFIED; goto end; } if ((size_t)eml->length > strlen(ulabel)) { - emlptr += eml->length - (strlen(ulabel)); + emlptr += eml->length - strlen(ulabel); /* X509_V_OK */ if (ia5ncasecmp(ulabel, emlptr, strlen(ulabel)) == 0) goto end; @@ -687,7 +715,7 @@ static int nc_email_eai(ASN1_TYPE *emltype, ASN1_IA5STRING *base) goto end; } - if (ossl_a2ulabel(baseptr, ulabel, &size) <= 0) { + if (ossl_a2ulabel(baseptr, ulabel, size) <= 0) { ret = X509_V_ERR_UNSPECIFIED; goto end; } @@ -755,50 +783,57 @@ static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) { const char *baseptr = (char *)base->data; - const char *hostptr = (char *)uri->data; - const char *p = ia5memchr(uri, (char *)uri->data, ':'); + char *uri_copy; + char *scheme; + char *host; int hostlen; + int ret; - /* Check for foo:// and skip past it */ - if (p == NULL - || IA5_OFFSET_LEN(uri, p) < 3 - || p[1] != '/' - || p[2] != '/') + if ((uri_copy = OPENSSL_strndup((const char *)uri->data, uri->length)) == NULL) + return X509_V_ERR_UNSPECIFIED; + + if (!OSSL_parse_url(uri_copy, &scheme, NULL, &host, NULL, NULL, NULL, NULL, NULL)) { + OPENSSL_free(uri_copy); return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; - hostptr = p + 3; + } - /* Determine length of hostname part of URI */ + /* Make sure the scheme is there */ + if (scheme == NULL || *scheme == '\0') { + ERR_raise_data(ERR_LIB_X509V3, X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, + "x509: missing scheme in URI: %s\n", uri_copy); + OPENSSL_free(uri_copy); + ret = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto end; + } - /* Look for a port indicator as end of hostname first */ + /* We don't need these anymore */ + OPENSSL_free(scheme); + OPENSSL_free(uri_copy); - p = ia5memchr(uri, hostptr, ':'); - /* Otherwise look for trailing slash */ - if (p == NULL) - p = ia5memchr(uri, hostptr, '/'); - - if (p == NULL) - hostlen = IA5_OFFSET_LEN(uri, hostptr); - else - hostlen = p - hostptr; - - if (hostlen == 0) - return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + hostlen = strlen(host); /* Special case: initial '.' is RHS match */ if (base->length > 0 && *baseptr == '.') { if (hostlen > base->length) { - p = hostptr + hostlen - base->length; - if (ia5ncasecmp(p, baseptr, base->length) == 0) - return X509_V_OK; + if (ia5ncasecmp(host + hostlen - base->length, baseptr, base->length) == 0) { + ret = X509_V_OK; + goto end; + } } - return X509_V_ERR_PERMITTED_VIOLATION; + ret = X509_V_ERR_PERMITTED_VIOLATION; + goto end; } - if ((base->length != (int)hostlen) - || ia5ncasecmp(hostptr, baseptr, hostlen)) - return X509_V_ERR_PERMITTED_VIOLATION; + if ((base->length != hostlen) + || ia5ncasecmp(host, baseptr, hostlen) != 0) { + ret = X509_V_ERR_PERMITTED_VIOLATION; + goto end; + } - return X509_V_OK; + ret = X509_V_OK; +end: + OPENSSL_free(host); + return ret; } diff --git a/crypto/x509/v3_pci.c b/crypto/x509/v3_pci.c index a931e01a9c92..1549a244ac87 100644 --- a/crypto/x509/v3_pci.c +++ b/crypto/x509/v3_pci.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -54,8 +54,8 @@ static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext, static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str); -const X509V3_EXT_METHOD ossl_v3_pci = - { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), +const X509V3_EXT_METHOD ossl_v3_pci = { + NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION), 0, 0, 0, 0, 0, 0, NULL, NULL, @@ -112,21 +112,22 @@ static int process_pci_value(CONF_VALUE *val, return 0; } } else if (strcmp(val->name, "policy") == 0) { + char *valp = val->value; unsigned char *tmp_data = NULL; long val_len; if (*policy == NULL) { *policy = ASN1_OCTET_STRING_new(); if (*policy == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); X509V3_conf_err(val); return 0; } free_policy = 1; } - if (strncmp(val->value, "hex:", 4) == 0) { + if (CHECK_AND_SKIP_PREFIX(valp, "hex:")) { unsigned char *tmp_data2 = - OPENSSL_hexstr2buf(val->value + 4, &val_len); + OPENSSL_hexstr2buf(valp, &val_len); if (!tmp_data2) { X509V3_conf_err(val); @@ -150,15 +151,14 @@ static int process_pci_value(CONF_VALUE *val, OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } OPENSSL_free(tmp_data2); - } else if (strncmp(val->value, "file:", 5) == 0) { + } else if (CHECK_AND_SKIP_PREFIX(valp, "file:")) { unsigned char buf[2048]; int n; - BIO *b = BIO_new_file(val->value + 5, "r"); + BIO *b = BIO_new_file(valp, "r"); if (!b) { ERR_raise(ERR_LIB_X509V3, ERR_R_BIO_LIB); X509V3_conf_err(val); @@ -176,7 +176,6 @@ static int process_pci_value(CONF_VALUE *val, OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); BIO_free_all(b); goto err; @@ -194,8 +193,8 @@ static int process_pci_value(CONF_VALUE *val, X509V3_conf_err(val); goto err; } - } else if (strncmp(val->value, "text:", 5) == 0) { - val_len = strlen(val->value + 5); + } else if (CHECK_AND_SKIP_PREFIX(valp, "text:")) { + val_len = strlen(valp); tmp_data = OPENSSL_realloc((*policy)->data, (*policy)->length + val_len + 1); if (tmp_data) { @@ -212,7 +211,6 @@ static int process_pci_value(CONF_VALUE *val, OPENSSL_free((*policy)->data); (*policy)->data = NULL; (*policy)->length = 0; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } @@ -222,7 +220,6 @@ static int process_pci_value(CONF_VALUE *val, goto err; } if (!tmp_data) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); X509V3_conf_err(val); goto err; } @@ -296,7 +293,7 @@ static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method, pci = PROXY_CERT_INFO_EXTENSION_new(); if (pci == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } diff --git a/crypto/x509/v3_pcia.c b/crypto/x509/v3_pcia.c index 7f5985f5e859..478de610ae92 100644 --- a/crypto/x509/v3_pcia.c +++ b/crypto/x509/v3_pcia.c @@ -47,18 +47,16 @@ #include #include -ASN1_SEQUENCE(PROXY_POLICY) = - { - ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT), - ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING) +ASN1_SEQUENCE(PROXY_POLICY) = { + ASN1_SIMPLE(PROXY_POLICY, policyLanguage, ASN1_OBJECT), + ASN1_OPT(PROXY_POLICY, policy, ASN1_OCTET_STRING) } ASN1_SEQUENCE_END(PROXY_POLICY) IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY) -ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = - { - ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER), - ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY) +ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = { + ASN1_OPT(PROXY_CERT_INFO_EXTENSION, pcPathLengthConstraint, ASN1_INTEGER), + ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION, proxyPolicy, PROXY_POLICY) } ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION) IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION) diff --git a/crypto/x509/v3_pcons.c b/crypto/x509/v3_pcons.c index 128365f572e2..72c2364b0568 100644 --- a/crypto/x509/v3_pcons.c +++ b/crypto/x509/v3_pcons.c @@ -61,7 +61,7 @@ static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, int i; if ((pcons = POLICY_CONSTRAINTS_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } for (i = 0; i < sk_CONF_VALUE_num(values); i++) { diff --git a/crypto/x509/v3_pmaps.c b/crypto/x509/v3_pmaps.c index 2094e9671141..e5d7dddc0ac8 100644 --- a/crypto/x509/v3_pmaps.c +++ b/crypto/x509/v3_pmaps.c @@ -73,7 +73,7 @@ static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, int i; if ((pmaps = sk_POLICY_MAPPING_new_reserve(NULL, num)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } @@ -93,7 +93,7 @@ static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, } pmap = POLICY_MAPPING_new(); if (pmap == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } pmap->issuerDomainPolicy = obj1; diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c index 6461189179f4..4688aaeea412 100644 --- a/crypto/x509/v3_purp.c +++ b/crypto/x509/v3_purp.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -18,28 +18,31 @@ static int check_ssl_ca(const X509 *x); static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int require_ca); -static int purpose_smime(const X509 *x, int require_ca); + int non_leaf); +static int purpose_smime(const X509 *x, int non_leaf); static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); +static int check_purpose_code_sign(const X509_PURPOSE *xp, const X509 *x, + int non_leaf); static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x, - int require_ca); + int non_leaf); static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b); static void xptable_free(X509_PURPOSE *p); +/* note that the id must be unique and for the standard entries == idx + 1 */ static X509_PURPOSE xstandard[] = { {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, "SSL client", "sslclient", NULL}, @@ -61,10 +64,14 @@ static X509_PURPOSE xstandard[] = { {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, "Time Stamp signing", "timestampsign", NULL}, + {X509_PURPOSE_CODE_SIGN, X509_TRUST_OBJECT_SIGN, 0, + check_purpose_code_sign, "Code signing", "codesign", + NULL}, }; #define X509_PURPOSE_COUNT OSSL_NELEM(xstandard) +/* the id must be unique, but there may be gaps and maybe table is not sorted */ static STACK_OF(X509_PURPOSE) *xptable = NULL; static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) @@ -78,7 +85,7 @@ static int xp_cmp(const X509_PURPOSE *const *a, const X509_PURPOSE *const *b) * If id == -1 it just calls x509v3_cache_extensions() for its side-effect. * Returns 1 on success, 0 if x does not allow purpose, -1 on (internal) error. */ -int X509_check_purpose(X509 *x, int id, int require_ca) +int X509_check_purpose(X509 *x, int id, int non_leaf) { int idx; const X509_PURPOSE *pt; @@ -92,12 +99,13 @@ int X509_check_purpose(X509 *x, int id, int require_ca) if (idx == -1) return -1; pt = X509_PURPOSE_get0(idx); - return pt->check_purpose(pt, x, require_ca); + return pt->check_purpose(pt, x, non_leaf); } +/* resets to default (any) purpose if purpose == X509_PURPOSE_DEFAULT_ANY (0) */ int X509_PURPOSE_set(int *p, int purpose) { - if (X509_PURPOSE_get_by_id(purpose) == -1) { + if (purpose != X509_PURPOSE_DEFAULT_ANY && X509_PURPOSE_get_by_id(purpose) == -1) { ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE); return 0; } @@ -112,6 +120,16 @@ int X509_PURPOSE_get_count(void) return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; } +/* find smallest identifier not yet taken - note there might be gaps */ +int X509_PURPOSE_get_unused_id(ossl_unused OSSL_LIB_CTX *libctx) +{ + int id = X509_PURPOSE_MAX + 1; + + while (X509_PURPOSE_get_by_id(id) != -1) + id++; + return id; /* is guaranteed to be unique and > X509_PURPOSE_MAX and != 0 */ +} + X509_PURPOSE *X509_PURPOSE_get0(int idx) { if (idx < 0) @@ -125,6 +143,7 @@ int X509_PURPOSE_get_by_sname(const char *sname) { int i; X509_PURPOSE *xptmp; + for (i = 0; i < X509_PURPOSE_get_count(); i++) { xptmp = X509_PURPOSE_get0(i); if (strcmp(xptmp->sname, sname) == 0) @@ -150,41 +169,61 @@ int X509_PURPOSE_get_by_id(int purpose) return idx + X509_PURPOSE_COUNT; } +/* + * Add purpose entry identified by |sname|. |id| must be >= X509_PURPOSE_MIN. + * May also be used to modify existing entry, including changing its id. + */ int X509_PURPOSE_add(int id, int trust, int flags, int (*ck) (const X509_PURPOSE *, const X509 *, int), const char *name, const char *sname, void *arg) { + int old_id = 0; int idx; X509_PURPOSE *ptmp; + if (id < X509_PURPOSE_MIN) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_PURPOSE); + return 0; + } + if (trust < X509_TRUST_DEFAULT || name == NULL || sname == NULL || ck == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + /* This is set according to what we change: application can't set it */ flags &= ~X509_PURPOSE_DYNAMIC; /* This will always be set for application modified trust entries */ flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ - idx = X509_PURPOSE_get_by_id(id); - /* Need a new entry */ - if (idx == -1) { - if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + idx = X509_PURPOSE_get_by_sname(sname); + if (idx == -1) { /* Need a new entry */ + if (X509_PURPOSE_get_by_id(id) != -1) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE); return 0; } + if ((ptmp = OPENSSL_malloc(sizeof(*ptmp))) == NULL) + return 0; ptmp->flags = X509_PURPOSE_DYNAMIC; - } else + } else { ptmp = X509_PURPOSE_get0(idx); + old_id = ptmp->purpose; + if (id != old_id && X509_PURPOSE_get_by_id(id) != -1) { + ERR_raise(ERR_LIB_X509V3, X509V3_R_PURPOSE_NOT_UNIQUE); + return 0; + } + } /* OPENSSL_free existing name if dynamic */ - if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + if ((ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) != 0) { OPENSSL_free(ptmp->name); OPENSSL_free(ptmp->sname); } /* Dup supplied name */ ptmp->name = OPENSSL_strdup(name); ptmp->sname = OPENSSL_strdup(sname); - if (ptmp->name == NULL|| ptmp->sname == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (ptmp->name == NULL || ptmp->sname == NULL) goto err; - } /* Keep the dynamic flag of existing entry */ ptmp->flags &= X509_PURPOSE_DYNAMIC; /* Set all other flags */ @@ -199,13 +238,16 @@ int X509_PURPOSE_add(int id, int trust, int flags, if (idx == -1) { if (xptable == NULL && (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } if (!sk_X509_PURPOSE_push(xptable, ptmp)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } + } else if (id != old_id) { + /* on changing existing entry id, make sure to reset 'sorted' */ + (void)sk_X509_PURPOSE_set(xptable, idx, ptmp); } return 1; err: @@ -221,8 +263,8 @@ static void xptable_free(X509_PURPOSE *p) { if (p == NULL) return; - if (p->flags & X509_PURPOSE_DYNAMIC) { - if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + if ((p->flags & X509_PURPOSE_DYNAMIC) != 0) { + if ((p->flags & X509_PURPOSE_DYNAMIC_NAME) != 0) { OPENSSL_free(p->name); OPENSSL_free(p->sname); } @@ -372,14 +414,14 @@ static int check_sig_alg_match(const EVP_PKEY *issuer_key, const X509 *subject) return X509_V_ERR_NO_ISSUER_PUBLIC_KEY; if (OBJ_find_sigid_algs(OBJ_obj2nid(subject->cert_info.signature.algorithm), NULL, &subj_sig_nid) == 0) - return X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM; + return X509_V_ERR_UNSUPPORTED_SIGNATURE_ALGORITHM; if (EVP_PKEY_is_a(issuer_key, OBJ_nid2sn(subj_sig_nid)) || (EVP_PKEY_is_a(issuer_key, "RSA") && subj_sig_nid == NID_rsassaPss)) return X509_V_OK; return X509_V_ERR_SIGNATURE_ALGORITHM_MISMATCH; } -#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define V1_ROOT (EXFLAG_V1 | EXFLAG_SS) #define ku_reject(x, usage) \ (((x)->ex_flags & EXFLAG_KUSAGE) != 0 && ((x)->ex_kusage & (usage)) == 0) #define xku_reject(x, usage) \ @@ -412,17 +454,17 @@ int ossl_x509v3_cache_extensions(X509 *x) if (!CRYPTO_THREAD_write_lock(x->lock)) return 0; - if (x->ex_flags & EXFLAG_SET) { /* Cert has already been processed */ + if ((x->ex_flags & EXFLAG_SET) != 0) { /* Cert has already been processed */ CRYPTO_THREAD_unlock(x->lock); return (x->ex_flags & EXFLAG_INVALID) == 0; } + ERR_set_mark(); + /* Cache the SHA1 digest of the cert */ if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL)) x->ex_flags |= EXFLAG_NO_FINGERPRINT; - ERR_set_mark(); - /* V1 should mean no extensions ... */ if (X509_get_version(x) == X509_VERSION_1) x->ex_flags |= EXFLAG_V1; @@ -452,7 +494,7 @@ int ossl_x509v3_cache_extensions(X509 *x) /* Handle proxy certificates */ if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, &i, NULL)) != NULL) { - if (x->ex_flags & EXFLAG_CA + if ((x->ex_flags & EXFLAG_CA) != 0 || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { x->ex_flags |= EXFLAG_INVALID; @@ -573,8 +615,6 @@ int ossl_x509v3_cache_extensions(X509 *x) res = setup_crldp(x); if (res == 0) x->ex_flags |= EXFLAG_INVALID; - else if (res < 0) - goto err; #ifndef OPENSSL_NO_RFC3779 x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL); @@ -627,17 +667,13 @@ int ossl_x509v3_cache_extensions(X509 *x) */ #endif ERR_pop_to_mark(); - if ((x->ex_flags & (EXFLAG_INVALID | EXFLAG_NO_FINGERPRINT)) == 0) { + + if ((x->ex_flags & EXFLAG_INVALID) == 0) { CRYPTO_THREAD_unlock(x->lock); return 1; } - if ((x->ex_flags & EXFLAG_INVALID) != 0) - ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_CERTIFICATE); - /* If computing sha1_hash failed the error queue already reflects this. */ - - err: - x->ex_flags |= EXFLAG_SET; /* indicate that cert has been processed */ CRYPTO_THREAD_unlock(x->lock); + ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_CERTIFICATE); return 0; } @@ -668,10 +704,11 @@ static int check_ca(const X509 *x) /* * If key usage present it must have certSign so tolerate it */ - else if (x->ex_flags & EXFLAG_KUSAGE) + else if ((x->ex_flags & EXFLAG_KUSAGE) != 0) return 4; /* Older certificates could have Netscape-specific CA types */ - else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA) + else if ((x->ex_flags & EXFLAG_NSCERT) != 0 + && (x->ex_nscert & NS_ANY_CA) != 0) return 5; /* Can this still be regarded a CA certificate? I doubt it. */ return 0; @@ -712,11 +749,11 @@ static int check_ssl_ca(const X509 *x) } static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { if (xku_reject(x, XKU_SSL_CLIENT)) return 0; - if (require_ca) + if (non_leaf) return check_ssl_ca(x); /* We need to do digital signatures or key agreement */ if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT)) @@ -733,14 +770,14 @@ static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, * key types. */ #define KU_TLS \ - KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT + KU_DIGITAL_SIGNATURE | KU_KEY_ENCIPHERMENT | KU_KEY_AGREEMENT static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC)) return 0; - if (require_ca) + if (non_leaf) return check_ssl_ca(x); if (ns_reject(x, NS_SSL_SERVER)) @@ -753,82 +790,70 @@ static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, } static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { - int ret; - ret = check_purpose_ssl_server(xp, x, require_ca); - if (!ret || require_ca) + int ret = check_purpose_ssl_server(xp, x, non_leaf); + + if (!ret || non_leaf) return ret; /* We need to encipher or Netscape complains */ - if (ku_reject(x, KU_KEY_ENCIPHERMENT)) - return 0; - return ret; + return ku_reject(x, KU_KEY_ENCIPHERMENT) ? 0 : ret; } /* common S/MIME checks */ -static int purpose_smime(const X509 *x, int require_ca) +static int purpose_smime(const X509 *x, int non_leaf) { if (xku_reject(x, XKU_SMIME)) return 0; - if (require_ca) { - int ca_ret; - ca_ret = check_ca(x); + if (non_leaf) { + int ca_ret = check_ca(x); + if (ca_ret == 0) return 0; /* Check nsCertType if present */ - if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) + if (ca_ret != 5 || (x->ex_nscert & NS_SMIME_CA) != 0) return ca_ret; else return 0; } - if (x->ex_flags & EXFLAG_NSCERT) { - if (x->ex_nscert & NS_SMIME) + if ((x->ex_flags & EXFLAG_NSCERT) != 0) { + if ((x->ex_nscert & NS_SMIME) != 0) return 1; /* Workaround for some buggy certificates */ - if (x->ex_nscert & NS_SSL_CLIENT) - return 2; - return 0; + return (x->ex_nscert & NS_SSL_CLIENT) != 0 ? 2 : 0; } return 1; } static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { - int ret; - ret = purpose_smime(x, require_ca); - if (!ret || require_ca) + int ret = purpose_smime(x, non_leaf); + + if (!ret || non_leaf) return ret; - if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION)) - return 0; - return ret; + return ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION) ? 0 : ret; } static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { - int ret; - ret = purpose_smime(x, require_ca); - if (!ret || require_ca) + int ret = purpose_smime(x, non_leaf); + + if (!ret || non_leaf) return ret; - if (ku_reject(x, KU_KEY_ENCIPHERMENT)) - return 0; - return ret; + return ku_reject(x, KU_KEY_ENCIPHERMENT) ? 0 : ret; } static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { - if (require_ca) { - int ca_ret; - if ((ca_ret = check_ca(x)) != 2) - return ca_ret; - else - return 0; + if (non_leaf) { + int ca_ret = check_ca(x); + + return ca_ret == 2 ? 0 : ca_ret; } - if (ku_reject(x, KU_CRL_SIGN)) - return 0; - return 1; + return !ku_reject(x, KU_CRL_SIGN); } /* @@ -836,55 +861,117 @@ static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, * is valid. Additional checks must be made on the chain. */ static int check_purpose_ocsp_helper(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { /* * Must be a valid CA. Should we really support the "I don't know" value * (2)? */ - if (require_ca) + if (non_leaf) return check_ca(x); /* Leaf certificate is checked in OCSP_verify() */ return 1; } static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { int i_ext; - /* If ca is true we must return if this is a valid CA certificate. */ - if (require_ca) + /* + * If non_leaf is true we must check if this is a valid CA certificate. + * The extra requirements by the CA/Browser Forum are not checked. + */ + if (non_leaf) return check_ca(x); + /* + * Key Usage is checked according to RFC 5280 and + * Extended Key Usage attributes is checked according to RFC 3161. + * The extra (and somewhat conflicting) CA/Browser Forum + * Baseline Requirements for the Issuance and Management of + * Publicly‐Trusted Code Signing Certificates, Version 3.0.0, + * Section 7.1.2.3: Code signing and Timestamp Certificate are not checked. + */ /* * Check the optional key usage field: * if Key Usage is present, it must be one of digitalSignature * and/or nonRepudiation (other values are not consistent and shall * be rejected). */ - if ((x->ex_flags & EXFLAG_KUSAGE) + if ((x->ex_flags & EXFLAG_KUSAGE) != 0 && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) return 0; - /* Only time stamp key usage is permitted and it's required. */ - if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) + /* Only timestamp key usage is permitted and it's required. */ + if ((x->ex_flags & EXFLAG_XKUSAGE) == 0 || x->ex_xkusage != XKU_TIMESTAMP) return 0; /* Extended Key Usage MUST be critical */ i_ext = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); + if (i_ext >= 0 + && !X509_EXTENSION_get_critical(X509_get_ext((X509 *)x, i_ext))) + return 0; + return 1; +} + +static int check_purpose_code_sign(const X509_PURPOSE *xp, const X509 *x, + int non_leaf) +{ + int i_ext; + + /* + * If non_leaf is true we must check if this is a valid CA certificate. + * The extra requirements by the CA/Browser Forum are not checked. + */ + if (non_leaf) + return check_ca(x); + + /* + * Check the key usage and extended key usage fields: + * + * Reference: CA/Browser Forum, + * Baseline Requirements for the Issuance and Management of + * Publicly‐Trusted Code Signing Certificates, Version 3.0.0, + * Section 7.1.2.3: Code signing and Timestamp Certificate + * + * Checking covers Key Usage and Extended Key Usage attributes. + * The certificatePolicies, cRLDistributionPoints (CDP), and + * authorityInformationAccess (AIA) extensions are so far not checked. + */ + /* Key Usage */ + if ((x->ex_flags & EXFLAG_KUSAGE) == 0) + return 0; + if ((x->ex_kusage & KU_DIGITAL_SIGNATURE) == 0) + return 0; + if ((x->ex_kusage & (KU_KEY_CERT_SIGN | KU_CRL_SIGN)) != 0) + return 0; + + /* Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID(x, NID_key_usage, -1); + if (i_ext < 0) + return 0; if (i_ext >= 0) { X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext); if (!X509_EXTENSION_get_critical(ext)) return 0; } + /* Extended Key Usage */ + if ((x->ex_flags & EXFLAG_XKUSAGE) == 0) + return 0; + if ((x->ex_xkusage & XKU_CODE_SIGN) == 0) + return 0; + if ((x->ex_xkusage & (XKU_ANYEKU | XKU_SSL_SERVER)) != 0) + return 0; + return 1; + } static int no_check_purpose(const X509_PURPOSE *xp, const X509 *x, - int require_ca) + int non_leaf) { return 1; } @@ -942,11 +1029,12 @@ int ossl_x509_likely_issued(X509 *issuer, X509 *subject) */ int ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject) { - if (subject->ex_flags & EXFLAG_PROXY) { + if ((subject->ex_flags & EXFLAG_PROXY) != 0) { if (ku_reject(issuer, KU_DIGITAL_SIGNATURE)) return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE; - } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) + } else if (ku_reject(issuer, KU_KEY_CERT_SIGN)) { return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + } return X509_V_OK; } @@ -970,11 +1058,11 @@ int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid) * GeneralName. So look for a DirName. There may be more than one but * we only take any notice of the first. */ - GENERAL_NAMES *gens; + GENERAL_NAMES *gens = akid->issuer; GENERAL_NAME *gen; X509_NAME *nm = NULL; int i; - gens = akid->issuer; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { gen = sk_GENERAL_NAME_value(gens, i); if (gen->type == GEN_DIRNAME) { @@ -1000,9 +1088,7 @@ uint32_t X509_get_key_usage(X509 *x) /* Call for side-effect of computing hash and caching extensions */ if (X509_check_purpose(x, -1, 0) != 1) return 0; - if (x->ex_flags & EXFLAG_KUSAGE) - return x->ex_kusage; - return UINT32_MAX; + return (x->ex_flags & EXFLAG_KUSAGE) != 0 ? x->ex_kusage : UINT32_MAX; } uint32_t X509_get_extended_key_usage(X509 *x) @@ -1010,9 +1096,7 @@ uint32_t X509_get_extended_key_usage(X509 *x) /* Call for side-effect of computing hash and caching extensions */ if (X509_check_purpose(x, -1, 0) != 1) return 0; - if (x->ex_flags & EXFLAG_XKUSAGE) - return x->ex_xkusage; - return UINT32_MAX; + return (x->ex_flags & EXFLAG_XKUSAGE) != 0 ? x->ex_xkusage : UINT32_MAX; } const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x) diff --git a/crypto/x509/v3_san.c b/crypto/x509/v3_san.c index d4999f1fc6c7..bc13c088d549 100644 --- a/crypto/x509/v3_san.c +++ b/crypto/x509/v3_san.c @@ -1,5 +1,5 @@ /* - * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -88,7 +88,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, switch (OBJ_obj2nid(gen->d.otherName->type_id)) { case NID_id_on_SmtpUTF8Mailbox: if (gen->d.otherName->value->type != V_ASN1_UTF8STRING - || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:", + || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox", gen->d.otherName->value->value.utf8string->data, gen->d.otherName->value->value.utf8string->length, &ret)) @@ -96,7 +96,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, break; case NID_XmppAddr: if (gen->d.otherName->value->type != V_ASN1_UTF8STRING - || !x509v3_add_len_value_uchar("othername: XmppAddr:", + || !x509v3_add_len_value_uchar("othername: XmppAddr", gen->d.otherName->value->value.utf8string->data, gen->d.otherName->value->value.utf8string->length, &ret)) @@ -104,7 +104,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, break; case NID_SRVName: if (gen->d.otherName->value->type != V_ASN1_IA5STRING - || !x509v3_add_len_value_uchar("othername: SRVName:", + || !x509v3_add_len_value_uchar("othername: SRVName", gen->d.otherName->value->value.ia5string->data, gen->d.otherName->value->value.ia5string->length, &ret)) @@ -112,7 +112,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, break; case NID_ms_upn: if (gen->d.otherName->value->type != V_ASN1_UTF8STRING - || !x509v3_add_len_value_uchar("othername: UPN:", + || !x509v3_add_len_value_uchar("othername: UPN", gen->d.otherName->value->value.utf8string->data, gen->d.otherName->value->value.utf8string->length, &ret)) @@ -120,32 +120,32 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, break; case NID_NAIRealm: if (gen->d.otherName->value->type != V_ASN1_UTF8STRING - || !x509v3_add_len_value_uchar("othername: NAIRealm:", + || !x509v3_add_len_value_uchar("othername: NAIRealm", gen->d.otherName->value->value.utf8string->data, gen->d.otherName->value->value.utf8string->length, &ret)) return NULL; break; default: - if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0) - BIO_snprintf(othername, sizeof(othername), "othername: %s:", + if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0) + BIO_snprintf(othername, sizeof(othername), "othername: %s", oline); else - OPENSSL_strlcpy(othername, "othername:", sizeof(othername)); + OPENSSL_strlcpy(othername, "othername", sizeof(othername)); /* check if the value is something printable */ if (gen->d.otherName->value->type == V_ASN1_IA5STRING) { if (x509v3_add_len_value_uchar(othername, gen->d.otherName->value->value.ia5string->data, gen->d.otherName->value->value.ia5string->length, - &ret)) + &ret)) return ret; } if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) { if (x509v3_add_len_value_uchar(othername, gen->d.otherName->value->value.utf8string->data, gen->d.otherName->value->value.utf8string->length, - &ret)) + &ret)) return ret; } if (!X509V3_add_value(othername, "", &ret)) @@ -307,8 +307,7 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, int i; if (gens == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - sk_GENERAL_NAME_free(gens); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } for (i = 0; i < num; i++) { @@ -358,7 +357,7 @@ static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) num = sk_GENERAL_NAME_num(ialt); if (!sk_GENERAL_NAME_reserve(gens, num)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } @@ -387,8 +386,7 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, gens = sk_GENERAL_NAME_new_reserve(NULL, num); if (gens == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - sk_GENERAL_NAME_free(gens); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } @@ -450,14 +448,14 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) i--; } if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } gen->d.ia5 = email; email = NULL; gen->type = GEN_EMAIL; if (!sk_GENERAL_NAME_push(gens, gen)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; } gen = NULL; @@ -483,8 +481,7 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, gens = sk_GENERAL_NAME_new_reserve(NULL, num); if (gens == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); - sk_GENERAL_NAME_free(gens); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } @@ -524,7 +521,7 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, else { gen = GENERAL_NAME_new(); if (gen == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } } @@ -584,7 +581,7 @@ GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, strlen(value))) { ASN1_IA5STRING_free(gen->d.ia5); gen->d.ia5 = NULL; - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } } diff --git a/crypto/x509/v3_skid.c b/crypto/x509/v3_skid.c index 18223f2ef496..8657f4cdf2b0 100644 --- a/crypto/x509/v3_skid.c +++ b/crypto/x509/v3_skid.c @@ -37,7 +37,7 @@ ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, long length; if ((oct = ASN1_OCTET_STRING_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } diff --git a/crypto/x509/v3_sxnet.c b/crypto/x509/v3_sxnet.c index 70f5db636c4b..507945f82955 100644 --- a/crypto/x509/v3_sxnet.c +++ b/crypto/x509/v3_sxnet.c @@ -141,7 +141,7 @@ int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user, if ((izone = ASN1_INTEGER_new()) == NULL || !ASN1_INTEGER_set(izone, lzone)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); ASN1_INTEGER_free(izone); return 0; } @@ -174,10 +174,14 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user, return 0; } if (*psx == NULL) { - if ((sx = SXNET_new()) == NULL) + if ((sx = SXNET_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; - if (!ASN1_INTEGER_set(sx->version, 0)) + } + if (!ASN1_INTEGER_set(sx->version, 0)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; + } } else sx = *psx; if (SXNET_get_id_INTEGER(sx, zone)) { @@ -187,22 +191,25 @@ int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, const char *user, return 0; } - if ((id = SXNETID_new()) == NULL) + if ((id = SXNETID_new()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; - if (userlen == -1) - userlen = strlen(user); + } - if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen)) + if (!ASN1_OCTET_STRING_set(id->user, (const unsigned char *)user, userlen)){ + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; - if (!sk_SXNETID_push(sx->ids, id)) + } + if (!sk_SXNETID_push(sx->ids, id)) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; + } ASN1_INTEGER_free(id->zone); id->zone = zone; *psx = sx; return 1; err: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); SXNETID_free(id); if (*psx == NULL) SXNET_free(sx); @@ -230,7 +237,7 @@ ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone) if ((izone = ASN1_INTEGER_new()) == NULL || !ASN1_INTEGER_set(izone, lzone)) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); ASN1_INTEGER_free(izone); return NULL; } diff --git a/crypto/x509/v3_tlsf.c b/crypto/x509/v3_tlsf.c index 3a457fa57bee..85dea65f359c 100644 --- a/crypto/x509/v3_tlsf.c +++ b/crypto/x509/v3_tlsf.c @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include #include @@ -96,7 +96,7 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method, long tlsextid; if ((tlsf = sk_ASN1_INTEGER_new_null()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); return NULL; } @@ -125,7 +125,7 @@ static TLS_FEATURE *v2i_TLS_FEATURE(const X509V3_EXT_METHOD *method, if ((ai = ASN1_INTEGER_new()) == NULL || !ASN1_INTEGER_set(ai, tlsextid) || sk_ASN1_INTEGER_push(tlsf, ai) <= 0) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); goto err; } /* So it doesn't get purged if an error occurs next time around */ diff --git a/crypto/x509/v3_utf8.c b/crypto/x509/v3_utf8.c index 1c4f79c4cd9b..22345c3a65eb 100644 --- a/crypto/x509/v3_utf8.c +++ b/crypto/x509/v3_utf8.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,7 +16,7 @@ /* * Subject Sign Tool (1.2.643.100.111) The name of the tool used to signs the subject (UTF8String) - * This extention is required to obtain the status of a qualified certificate at Russian Federation. + * This extension is required to obtain the status of a qualified certificate at Russian Federation. * RFC-style description is available here: https://tools.ietf.org/html/draft-deremin-rfc4491-bis-04#section-5 * Russian Federal Law 63 "Digital Sign" is available here: http://www.consultant.ru/document/cons_doc_LAW_112701/ */ @@ -35,10 +35,8 @@ char *i2s_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, ERR_raise(ERR_LIB_X509V3, ERR_R_PASSED_NULL_PARAMETER); return NULL; } - if ((tmp = OPENSSL_malloc(utf8->length + 1)) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((tmp = OPENSSL_malloc(utf8->length + 1)) == NULL) return NULL; - } memcpy(tmp, utf8->data, utf8->length); tmp[utf8->length] = 0; return tmp; @@ -53,11 +51,11 @@ ASN1_UTF8STRING *s2i_ASN1_UTF8STRING(X509V3_EXT_METHOD *method, return NULL; } if ((utf8 = ASN1_UTF8STRING_new()) == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); return NULL; } if (!ASN1_STRING_set((ASN1_STRING *)utf8, str, strlen(str))) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); ASN1_UTF8STRING_free(utf8); return NULL; } diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c index 56ee36d4521e..60aa31a7c758 100644 --- a/crypto/x509/v3_utl.c +++ b/crypto/x509/v3_utl.c @@ -9,7 +9,7 @@ /* X509 v3 extension utilities */ -#include "e_os.h" +#include "internal/e_os.h" #include "internal/cryptlib.h" #include #include @@ -47,7 +47,7 @@ static int x509v3_add_len_value(const char *name, const char *value, if (name != NULL && (tname = OPENSSL_strdup(name)) == NULL) goto err; if (value != NULL) { - /* We don't allow embeded NUL characters */ + /* We don't allow embedded NUL characters */ if (memchr(value, 0, vallen) != NULL) goto err; tvalue = OPENSSL_strndup(value, vallen); @@ -56,8 +56,10 @@ static int x509v3_add_len_value(const char *name, const char *value, } if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL) goto err; - if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL) + if (sk_allocated && (*extlist = sk_CONF_VALUE_new_null()) == NULL) { + ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); goto err; + } vtmp->section = NULL; vtmp->name = tname; vtmp->value = tvalue; @@ -65,7 +67,6 @@ static int x509v3_add_len_value(const char *name, const char *value, goto err; return 1; err: - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); if (sk_allocated) { sk_CONF_VALUE_free(*extlist); *extlist = NULL; @@ -146,7 +147,6 @@ static char *bignum_to_string(const BIGNUM *bn) len = strlen(tmp) + 3; ret = OPENSSL_malloc(len); if (ret == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); OPENSSL_free(tmp); return NULL; } @@ -170,9 +170,10 @@ char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) if (!a) return NULL; - if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL - || (strtmp = bignum_to_string(bntmp)) == NULL) - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL) + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + else if ((strtmp = bignum_to_string(bntmp)) == NULL) + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); BN_free(bntmp); return strtmp; } @@ -184,9 +185,10 @@ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) if (!a) return NULL; - if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL - || (strtmp = bignum_to_string(bntmp)) == NULL) - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL) + ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); + else if ((strtmp = bignum_to_string(bntmp)) == NULL) + ERR_raise(ERR_LIB_X509V3, ERR_R_X509V3_LIB); BN_free(bntmp); return strtmp; } @@ -204,7 +206,7 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) } bn = BN_new(); if (bn == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509V3, ERR_R_BN_LIB); return NULL; } if (value[0] == '-') { @@ -320,10 +322,8 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) /* We are going to modify the line so copy it first */ linebuf = OPENSSL_strdup(line); - if (linebuf == NULL) { - ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE); + if (linebuf == NULL) goto err; - } state = HDR_NAME; ntmp = NULL; /* Go through all characters */ @@ -715,7 +715,7 @@ static int wildcard_match(const unsigned char *prefix, size_t prefix_len, } /* IDNA labels cannot match partial wildcards */ if (!allow_idna && - subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0) + subject_len >= 4 && HAS_CASE_PREFIX((const char *)subject, "xn--")) return 0; /* The wildcard may match a literal '*' */ if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') @@ -775,7 +775,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len, || ('A' <= p[i] && p[i] <= 'Z') || ('0' <= p[i] && p[i] <= '9')) { if ((state & LABEL_START) != 0 - && len - i >= 4 && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0) + && len - i >= 4 && HAS_CASE_PREFIX((const char *)&p[i], "xn--")) state |= LABEL_IDNA; state &= ~(LABEL_HYPHEN | LABEL_START); } else if (p[i] == '.') { @@ -1179,23 +1179,60 @@ int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc) } } +/* + * get_ipv4_component consumes one IPv4 component, terminated by either '.' or + * the end of the string, from *str. On success, it returns one, sets *out + * to the component, and advances *str to the first unconsumed character. On + * invalid input, it returns zero. + */ +static int get_ipv4_component(uint8_t *out_byte, const char **str) { + /* Store a slightly larger intermediary so the overflow check is easier. */ + uint32_t out = 0; + + for (;;) { + if (!ossl_isdigit(**str)) { + return 0; + } + out = (out * 10) + (**str - '0'); + if (out > 255) { + /* Components must be 8-bit. */ + return 0; + } + (*str)++; + if ((**str) == '.' || (**str) == '\0') { + *out_byte = (uint8_t)out; + return 1; + } + if (out == 0) { + /* Reject extra leading zeros. Parsers sometimes treat them as + * octal, so accepting them would misinterpret input. + */ + return 0; + } + } +} + +/* + * get_ipv4_dot consumes a '.' from *str and advances it. It returns one on + * success and zero if *str does not point to a '.'. + */ +static int get_ipv4_dot(const char **str) +{ + if (**str != '.') { + return 0; + } + (*str)++; + return 1; +} + static int ipv4_from_asc(unsigned char *v4, const char *in) { - const char *p; - int a0, a1, a2, a3, n; - - if (sscanf(in, "%d.%d.%d.%d%n", &a0, &a1, &a2, &a3, &n) != 4) - return 0; - if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) - || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) - return 0; - p = in + n; - if (!(*p == '\0' || ossl_isspace(*p))) - return 0; - v4[0] = a0; - v4[1] = a1; - v4[2] = a2; - v4[3] = a3; + if (!get_ipv4_component(&v4[0], &in) || !get_ipv4_dot(&in) + || !get_ipv4_component(&v4[1], &in) || !get_ipv4_dot(&in) + || !get_ipv4_component(&v4[2], &in) || !get_ipv4_dot(&in) + || !get_ipv4_component(&v4[3], &in) || *in != '\0') { + return 0; + } return 1; } @@ -1384,3 +1421,33 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, } return 1; } + +int OSSL_GENERAL_NAMES_print(BIO *out, GENERAL_NAMES *gens, int indent) +{ + int i; + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + if (i > 0) + BIO_puts(out, "\n"); + BIO_printf(out, "%*s", indent + 2, ""); + GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); + } + return 1; +} + +int ossl_bio_print_hex(BIO *out, unsigned char *buf, int len) +{ + int result; + char *hexbuf; + + if (len == 0) + return 1; + + hexbuf = OPENSSL_buf2hexstr(buf, len); + if (hexbuf == NULL) + return 0; + result = BIO_puts(out, hexbuf) > 0; + + OPENSSL_free(hexbuf); + return result; +} diff --git a/crypto/x509/v3err.c b/crypto/x509/v3err.c index 6f38034c1afe..b03bc8524ce7 100644 --- a/crypto/x509/v3err.c +++ b/crypto/x509/v3err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,120 +17,125 @@ static const ERR_STRING_DATA X509V3_str_reasons[] = { {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_IP_ADDRESS), "bad ip address"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OBJECT), "bad object"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_OPTION), "bad option"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BAD_VALUE), "bad value"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_DEC2BN_ERROR), "bn dec2bn error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_BN_TO_ASN1_INTEGER_ERROR), - "bn to asn1 integer error"}, + "bn to asn1 integer error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DIRNAME_ERROR), "dirname error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DISTPOINT_ALREADY_SET), - "distpoint already set"}, + "distpoint already set"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_DUPLICATE_ZONE_ID), - "duplicate zone id"}, + "duplicate zone id"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EMPTY_KEY_USAGE), "empty key usage"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CONVERTING_ZONE), - "error converting zone"}, + "error converting zone"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_CREATING_EXTENSION), - "error creating extension"}, + "error creating extension"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ERROR_IN_EXTENSION), - "error in extension"}, + "error in extension"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXPECTED_A_SECTION_NAME), - "expected a section name"}, + "expected a section name"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_EXISTS), - "extension exists"}, + "extension exists"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NAME_ERROR), - "extension name error"}, + "extension name error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_NOT_FOUND), - "extension not found"}, + "extension not found"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED), - "extension setting not supported"}, + "extension setting not supported"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_EXTENSION_VALUE_ERROR), - "extension value error"}, + "extension value error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ILLEGAL_EMPTY_EXTENSION), - "illegal empty extension"}, + "illegal empty extension"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG), - "incorrect policy syntax tag"}, + "incorrect policy syntax tag"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASNUMBER), - "invalid asnumber"}, + "invalid asnumber"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_ASRANGE), "invalid asrange"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_BOOLEAN_STRING), - "invalid boolean string"}, + "invalid boolean string"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_CERTIFICATE), - "invalid certificate"}, + "invalid certificate"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EMPTY_NAME), - "invalid empty name"}, + "invalid empty name"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_EXTENSION_STRING), - "invalid extension string"}, + "invalid extension string"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_INHERITANCE), - "invalid inheritance"}, + "invalid inheritance"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_IPADDRESS), - "invalid ipaddress"}, + "invalid ipaddress"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_MULTIPLE_RDNS), - "invalid multiple rdns"}, + "invalid multiple rdns"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NAME), "invalid name"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_ARGUMENT), - "invalid null argument"}, + "invalid null argument"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NULL_VALUE), - "invalid null value"}, + "invalid null value"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBER), "invalid number"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_NUMBERS), "invalid numbers"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OBJECT_IDENTIFIER), - "invalid object identifier"}, + "invalid object identifier"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_OPTION), "invalid option"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_POLICY_IDENTIFIER), - "invalid policy identifier"}, + "invalid policy identifier"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PROXY_POLICY_SETTING), - "invalid proxy policy setting"}, + "invalid proxy policy setting"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_PURPOSE), "invalid purpose"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SAFI), "invalid safi"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SECTION), "invalid section"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_INVALID_SYNTAX), "invalid syntax"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_ISSUER_DECODE_ERROR), - "issuer decode error"}, + "issuer decode error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_MISSING_VALUE), "missing value"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS), - "need organization and numbers"}, + "need organization and numbers"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NEGATIVE_PATHLEN), - "negative pathlen"}, + "negative pathlen"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_CONFIG_DATABASE), - "no config database"}, + "no config database"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_CERTIFICATE), - "no issuer certificate"}, + "no issuer certificate"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_ISSUER_DETAILS), - "no issuer details"}, + "no issuer details"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_POLICY_IDENTIFIER), - "no policy identifier"}, + "no policy identifier"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED), - "no proxy cert policy language defined"}, + "no proxy cert policy language defined"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_PUBLIC_KEY), "no public key"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_NO_SUBJECT_DETAILS), - "no subject details"}, + "no subject details"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OPERATION_NOT_DEFINED), - "operation not defined"}, + "operation not defined"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_OTHERNAME_ERROR), "othername error"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED), - "policy language already defined"}, + "policy language already defined"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH), - "policy path length"}, + "policy path length"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED), - "policy path length already defined"}, + "policy path length already defined"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY), - "policy when proxy language requires no policy"}, + "policy when proxy language requires no policy"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_PURPOSE_NOT_UNIQUE), + "purpose not unique"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_SECTION_NOT_FOUND), - "section not found"}, + "section not found"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS), - "unable to get issuer details"}, + "unable to get issuer details"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID), - "unable to get issuer keyid"}, + "unable to get issuer keyid"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT), - "unknown bit string argument"}, + "unknown bit string argument"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION), - "unknown extension"}, + "unknown extension"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_EXTENSION_NAME), - "unknown extension name"}, + "unknown extension name"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_OPTION), "unknown option"}, + {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNKNOWN_VALUE), "unknown value"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_OPTION), - "unsupported option"}, + "unsupported option"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_UNSUPPORTED_TYPE), - "unsupported type"}, + "unsupported type"}, {ERR_PACK(ERR_LIB_X509V3, 0, X509V3_R_USER_TOO_LONG), "user too long"}, {0, NULL} }; diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c index 6a541d7980a3..b21aa4d29940 100644 --- a/crypto/x509/x509_att.c +++ b/crypto/x509/x509_att.c @@ -55,50 +55,60 @@ int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) { - if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; - + } + if (sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } return sk_X509_ATTRIBUTE_value(x, loc); } X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) { - X509_ATTRIBUTE *ret; - - if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; - ret = sk_X509_ATTRIBUTE_delete(x, loc); - return ret; + } + if (sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + return sk_X509_ATTRIBUTE_delete(x, loc); } STACK_OF(X509_ATTRIBUTE) *ossl_x509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, - X509_ATTRIBUTE *attr) + const X509_ATTRIBUTE *attr) { X509_ATTRIBUTE *new_attr = NULL; STACK_OF(X509_ATTRIBUTE) *sk = NULL; - if (x == NULL) { + if (x == NULL || attr == NULL) { ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; } if (*x == NULL) { - if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) + if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; + } } else { sk = *x; } if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) - goto err2; - if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) goto err; + if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); + goto err; + } if (*x == NULL) *x = sk; return sk; err: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); - err2: X509_ATTRIBUTE_free(new_attr); if (*x == NULL) sk_X509_ATTRIBUTE_free(sk); @@ -113,7 +123,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, return NULL; } if (*x != NULL && X509at_get_attr_by_OBJ(*x, attr->object, -1) != -1) { - ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE); + ERR_raise_data(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE, + "name=%s", OBJ_nid2sn(OBJ_obj2nid(attr->object))); return NULL; } @@ -148,7 +159,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) return NULL; } if (*x != NULL && X509at_get_attr_by_OBJ(*x, obj, -1) != -1) { - ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE); + ERR_raise_data(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE, + "name=%s", OBJ_nid2sn(OBJ_obj2nid(obj))); return NULL; } @@ -181,7 +193,8 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) return NULL; } if (*x != NULL && X509at_get_attr_by_NID(*x, nid, -1) != -1) { - ERR_raise(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE); + ERR_raise_data(ERR_LIB_X509, X509_R_DUPLICATE_ATTRIBUTE, + "name=%s", OBJ_nid2sn(nid)); return NULL; } @@ -213,8 +226,9 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) { X509_ATTRIBUTE *attr; STACK_OF(X509_ATTRIBUTE) *ret; + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); - if (!attr) + if (attr == NULL) return 0; ret = X509at_add1_attr(x, attr); X509_ATTRIBUTE_free(attr); @@ -224,29 +238,26 @@ STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) void *X509at_get0_data_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *x, const ASN1_OBJECT *obj, int lastpos, int type) { - int i; + int i = X509at_get_attr_by_OBJ(x, obj, lastpos); X509_ATTRIBUTE *at; - i = X509at_get_attr_by_OBJ(x, obj, lastpos); + if (i == -1) return NULL; - if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) + if (lastpos <= -2 && X509at_get_attr_by_OBJ(x, obj, i) != -1) return NULL; at = X509at_get_attr(x, i); - if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) + if (lastpos <= -3 && X509_ATTRIBUTE_count(at) != 1) return NULL; return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); } STACK_OF(X509_ATTRIBUTE) *ossl_x509at_dup(const STACK_OF(X509_ATTRIBUTE) *x) { - int i, n; + int i, n = sk_X509_ATTRIBUTE_num(x); STACK_OF(X509_ATTRIBUTE) *sk = NULL; - n = sk_X509_ATTRIBUTE_num(x); for (i = 0; i < n; ++i) { - X509_ATTRIBUTE *attr = sk_X509_ATTRIBUTE_value(x, i); - - if (X509at_add1_attr(&sk, attr) == NULL) { + if (X509at_add1_attr(&sk, sk_X509_ATTRIBUTE_value(x, i)) == NULL) { sk_X509_ATTRIBUTE_pop_free(sk, X509_ATTRIBUTE_free); return NULL; } @@ -258,10 +269,9 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, int atrtype, const void *data, int len) { - ASN1_OBJECT *obj; + ASN1_OBJECT *obj = OBJ_nid2obj(nid); X509_ATTRIBUTE *ret; - obj = OBJ_nid2obj(nid); if (obj == NULL) { ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_NID); return NULL; @@ -279,24 +289,25 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, { X509_ATTRIBUTE *ret; - if ((attr == NULL) || (*attr == NULL)) { + if (attr == NULL || *attr == NULL) { if ((ret = X509_ATTRIBUTE_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return NULL; } - } else + } else { ret = *attr; + } if (!X509_ATTRIBUTE_set1_object(ret, obj)) goto err; if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) goto err; - if ((attr != NULL) && (*attr == NULL)) + if (attr != NULL && *attr == NULL) *attr = ret; return ret; err: - if ((attr == NULL) || (ret != *attr)) + if (attr == NULL || ret != *attr) X509_ATTRIBUTE_free(ret); return NULL; } @@ -306,10 +317,9 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, const unsigned char *bytes, int len) { - ASN1_OBJECT *obj; + ASN1_OBJECT *obj = OBJ_txt2obj(atrname, 0); X509_ATTRIBUTE *nattr; - obj = OBJ_txt2obj(atrname, 0); if (obj == NULL) { ERR_raise_data(ERR_LIB_X509, X509_R_INVALID_FIELD_NAME, "name=%s", atrname); @@ -322,8 +332,10 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) { - if ((attr == NULL) || (obj == NULL)) + if (attr == NULL || obj == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; + } ASN1_OBJECT_free(attr->object); attr->object = OBJ_dup(obj); return attr->object != NULL; @@ -335,21 +347,25 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, ASN1_TYPE *ttmp = NULL; ASN1_STRING *stmp = NULL; int atype = 0; - if (!attr) + + if (attr == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; - if (attrtype & MBSTRING_FLAG) { + } + if ((attrtype & MBSTRING_FLAG) != 0) { stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, OBJ_obj2nid(attr->object)); - if (!stmp) { + if (stmp == NULL) { ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return 0; } atype = stmp->type; } else if (len != -1) { - if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL) - goto err; - if (!ASN1_STRING_set(stmp, data, len)) + if ((stmp = ASN1_STRING_type_new(attrtype)) == NULL + || !ASN1_STRING_set(stmp, data, len)) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; + } atype = attrtype; } /* @@ -361,20 +377,25 @@ int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, ASN1_STRING_free(stmp); return 1; } - if ((ttmp = ASN1_TYPE_new()) == NULL) + if ((ttmp = ASN1_TYPE_new()) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; - if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { - if (!ASN1_TYPE_set1(ttmp, attrtype, data)) + } + if (len == -1 && (attrtype & MBSTRING_FLAG) == 0) { + if (!ASN1_TYPE_set1(ttmp, attrtype, data)) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; + } } else { ASN1_TYPE_set(ttmp, atype, stmp); stmp = NULL; } - if (!sk_ASN1_TYPE_push(attr->set, ttmp)) + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; + } return 1; err: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); ASN1_TYPE_free(ttmp); ASN1_STRING_free(stmp); return 0; @@ -389,17 +410,19 @@ int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) { - if (attr == NULL) + if (attr == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } return attr->object; } void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, void *data) { - ASN1_TYPE *ttmp; - ttmp = X509_ATTRIBUTE_get0_type(attr, idx); - if (!ttmp) + ASN1_TYPE *ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + + if (ttmp == NULL) return NULL; if (atrtype == V_ASN1_BOOLEAN || atrtype == V_ASN1_NULL @@ -412,7 +435,9 @@ void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) { - if (attr == NULL) + if (attr == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } return sk_ASN1_TYPE_value(attr->set, idx); } diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index f2c3a568198d..de34fa5cc2cd 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -184,7 +184,7 @@ int X509_cmp(const X509 *a, const X509 *b) int ossl_x509_add_cert_new(STACK_OF(X509) **p_sk, X509 *cert, int flags) { if (*p_sk == NULL && (*p_sk = sk_X509_new_null()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); return 0; } return X509_add_cert(*p_sk, cert, flags); @@ -216,13 +216,15 @@ int X509_add_cert(STACK_OF(X509) *sk, X509 *cert, int flags) if (ret != 0) return ret > 0 ? 1 : 0; } + if ((flags & X509_ADD_FLAG_UP_REF) != 0 && !X509_up_ref(cert)) + return 0; if (!sk_X509_insert(sk, cert, (flags & X509_ADD_FLAG_PREPEND) != 0 ? 0 : -1)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if ((flags & X509_ADD_FLAG_UP_REF) != 0) + X509_free(cert); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); return 0; } - if ((flags & X509_ADD_FLAG_UP_REF) != 0) - (void)X509_up_ref(cert); return 1; } @@ -394,30 +396,38 @@ EVP_PKEY *X509_get_pubkey(X509 *x) return X509_PUBKEY_get(x->cert_info.key); } -int X509_check_private_key(const X509 *x, const EVP_PKEY *k) +int X509_check_private_key(const X509 *cert, const EVP_PKEY *pkey) { - const EVP_PKEY *xk; - int ret; + const EVP_PKEY *xk = X509_get0_pubkey(cert); - xk = X509_get0_pubkey(x); if (xk == NULL) { ERR_raise(ERR_LIB_X509, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); return 0; } + return ossl_x509_check_private_key(xk, pkey); +} - switch (ret = EVP_PKEY_eq(xk, k)) { +int ossl_x509_check_private_key(const EVP_PKEY *x, const EVP_PKEY *pkey) +{ + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + switch (EVP_PKEY_eq(x, pkey)) { + case 1: + return 1; case 0: ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH); - break; + return 0; case -1: ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH); - break; + return 0; case -2: ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE); - break; + /* fall thru */ + default: + return 0; } - - return ret > 0; } /* diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c index 62aceb7acade..dd18bcd58634 100644 --- a/crypto/x509/x509_d2.c +++ b/crypto/x509/x509_d2.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -30,6 +30,11 @@ int X509_STORE_set_default_paths_ex(X509_STORE *ctx, OSSL_LIB_CTX *libctx, lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store()); if (lookup == NULL) return 0; + /* + * The NULL URI argument will activate any default URIs (presently none), + * DO NOT pass the default CApath or CAfile, they're already handled above, + * likely much more efficiently. + */ X509_LOOKUP_add_store_ex(lookup, NULL, libctx, propq); /* clear any errors */ diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c index b8bdcb484195..7d5b642c4502 100644 --- a/crypto/x509/x509_def.c +++ b/crypto/x509/x509_def.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,28 +8,101 @@ */ #include +#include "internal/e_os.h" #include "internal/cryptlib.h" +#include "internal/thread_once.h" #include #include +#if defined(_WIN32) + +static char x509_private_dir[MAX_PATH + 1]; +static char *x509_private_dirptr = NULL; + +static char x509_cert_area[MAX_PATH + 1]; +static char *x509_cert_areaptr = NULL; + +static char x509_cert_dir[MAX_PATH + 1]; +static char *x509_cert_dirptr = NULL; + +static char x509_cert_file[MAX_PATH + 1]; +static char *x509_cert_fileptr = NULL; + +static void get_windows_default_path(char *pathname, const char *suffix) +{ + char *ossldir; + + ossldir = ossl_get_openssldir(); + + if (ossldir == NULL) + return; + + OPENSSL_strlcpy(pathname, ossldir, MAX_PATH - 1); + if (MAX_PATH - strlen(pathname) > strlen(suffix)) + strcat(pathname, suffix); +} + +static CRYPTO_ONCE openssldir_setup_init = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(do_openssldir_setup) +{ + get_windows_default_path(x509_private_dir, "\\private"); + if (strlen(x509_private_dir) > 0) + x509_private_dirptr = x509_private_dir; + + get_windows_default_path(x509_cert_area, "\\"); + if (strlen(x509_cert_area) > 0) + x509_cert_areaptr = x509_cert_area; + + get_windows_default_path(x509_cert_dir, "\\certs"); + if (strlen(x509_cert_dir) > 0) + x509_cert_dirptr = x509_cert_dir; + + get_windows_default_path(x509_cert_file, "\\cert.pem"); + if (strlen(x509_cert_file) > 0) + x509_cert_fileptr = x509_cert_file; + + return 1; +} +#endif + const char *X509_get_default_private_dir(void) { +#if defined (_WIN32) + RUN_ONCE(&openssldir_setup_init, do_openssldir_setup); + return x509_private_dirptr; +#else return X509_PRIVATE_DIR; +#endif } const char *X509_get_default_cert_area(void) { +#if defined (_WIN32) + RUN_ONCE(&openssldir_setup_init, do_openssldir_setup); + return x509_cert_areaptr; +#else return X509_CERT_AREA; +#endif } const char *X509_get_default_cert_dir(void) { +#if defined (_WIN32) + RUN_ONCE(&openssldir_setup_init, do_openssldir_setup); + return x509_cert_dirptr; +#else return X509_CERT_DIR; +#endif } const char *X509_get_default_cert_file(void) { +#if defined (_WIN32) + RUN_ONCE(&openssldir_setup_init, do_openssldir_setup); + return x509_cert_fileptr; +#else return X509_CERT_FILE; +#endif } const char *X509_get_default_cert_dir_env(void) diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c index 37467935c997..607d38f3be3c 100644 --- a/crypto/x509/x509_err.c +++ b/crypto/x509/x509_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,7 +20,7 @@ static const ERR_STRING_DATA X509_str_reasons[] = { {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "bad x509 filetype"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), "base64 decode error"}, - {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "cant check dh key"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "can't check dh key"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERTIFICATE_VERIFICATION_FAILED), "certificate verification failed"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), @@ -79,6 +79,8 @@ static const ERR_STRING_DATA X509_str_reasons[] = { {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "unknown trust id"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), "unsupported algorithm"}, + {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_VERSION), + "unsupported version"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "wrong lookup type"}, {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "wrong type"}, {0, NULL} diff --git a/crypto/x509/x509_local.h b/crypto/x509/x509_local.h index 6d602e1d8ef5..1393da201339 100644 --- a/crypto/x509/x509_local.h +++ b/crypto/x509/x509_local.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -157,3 +157,5 @@ DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY) int ossl_x509_likely_issued(X509 *issuer, X509 *subject); int ossl_x509_signing_allowed(const X509 *issuer, const X509 *subject); +int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type, + const X509_NAME *name, X509_OBJECT *ret); diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index d8927bda0706..9270a0745fbb 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,10 +19,8 @@ X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method) { X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->method = method; if (method->new_item != NULL && method->new_item(ret) == 0) { @@ -41,14 +39,19 @@ void X509_LOOKUP_free(X509_LOOKUP *ctx) OPENSSL_free(ctx); } -int X509_STORE_lock(X509_STORE *s) +int X509_STORE_lock(X509_STORE *xs) { - return CRYPTO_THREAD_write_lock(s->lock); + return CRYPTO_THREAD_write_lock(xs->lock); } -int X509_STORE_unlock(X509_STORE *s) +static int x509_store_read_lock(X509_STORE *xs) { - return CRYPTO_THREAD_unlock(s->lock); + return CRYPTO_THREAD_read_lock(xs->lock); +} + +int X509_STORE_unlock(X509_STORE *xs) +{ + return CRYPTO_THREAD_unlock(xs->lock); } int X509_LOOKUP_init(X509_LOOKUP *ctx) @@ -154,7 +157,6 @@ X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx) return ctx->store_ctx; } - static int x509_object_cmp(const X509_OBJECT *const *a, const X509_OBJECT *const *b) { @@ -181,93 +183,95 @@ X509_STORE *X509_STORE_new(void) { X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } ret->cache = 1; if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); goto err; } if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } - ret->references = 1; + + if (!CRYPTO_NEW_REF(&ret->references, 1)) + goto err; return ret; err: X509_VERIFY_PARAM_free(ret->param); sk_X509_OBJECT_free(ret->objs); sk_X509_LOOKUP_free(ret->get_cert_methods); + CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; } -void X509_STORE_free(X509_STORE *vfy) +void X509_STORE_free(X509_STORE *xs) { int i; STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; - if (vfy == NULL) + if (xs == NULL) return; - CRYPTO_DOWN_REF(&vfy->references, &i, vfy->lock); - REF_PRINT_COUNT("X509_STORE", vfy); + CRYPTO_DOWN_REF(&xs->references, &i); + REF_PRINT_COUNT("X509_STORE", i, xs); if (i > 0) return; REF_ASSERT_ISNT(i < 0); - sk = vfy->get_cert_methods; + sk = xs->get_cert_methods; for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { lu = sk_X509_LOOKUP_value(sk, i); X509_LOOKUP_shutdown(lu); X509_LOOKUP_free(lu); } sk_X509_LOOKUP_free(sk); - sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free); + sk_X509_OBJECT_pop_free(xs->objs, X509_OBJECT_free); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data); - X509_VERIFY_PARAM_free(vfy->param); - CRYPTO_THREAD_lock_free(vfy->lock); - OPENSSL_free(vfy); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, xs, &xs->ex_data); + X509_VERIFY_PARAM_free(xs->param); + CRYPTO_THREAD_lock_free(xs->lock); + CRYPTO_FREE_REF(&xs->references); + OPENSSL_free(xs); } -int X509_STORE_up_ref(X509_STORE *vfy) +int X509_STORE_up_ref(X509_STORE *xs) { int i; - if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0) + if (CRYPTO_UP_REF(&xs->references, &i) <= 0) return 0; - REF_PRINT_COUNT("X509_STORE", vfy); + REF_PRINT_COUNT("X509_STORE", i, xs); REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); + return i > 1 ? 1 : 0; } -X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m) { int i; STACK_OF(X509_LOOKUP) *sk; X509_LOOKUP *lu; - sk = v->get_cert_methods; + sk = xs->get_cert_methods; for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { lu = sk_X509_LOOKUP_value(sk, i); if (m == lu->method) { @@ -277,20 +281,21 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) /* a new one */ lu = X509_LOOKUP_new(m); if (lu == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); return NULL; } - lu->store_ctx = v; - if (sk_X509_LOOKUP_push(v->get_cert_methods, lu)) + lu->store_ctx = xs; + if (sk_X509_LOOKUP_push(xs->get_cert_methods, lu)) return lu; - /* malloc failed */ - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + /* sk_X509_LOOKUP_push() failed */ + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); X509_LOOKUP_free(lu); return NULL; } -X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, +/* Also fill the cache (ctx->store->objs) with all matching certificates. */ +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type, const X509_NAME *name) { @@ -298,19 +303,24 @@ X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, if (ret == NULL) return NULL; - if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) { + if (!X509_STORE_CTX_get_by_subject(ctx, type, name, ret)) { X509_OBJECT_free(ret); return NULL; } return ret; } -/* Also fill the cache with all matching certificates */ -int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs, - X509_LOOKUP_TYPE type, - const X509_NAME *name, X509_OBJECT *ret) +/* + * May be called with |ret| == NULL just for the side effect of + * caching all certs matching the given subject DN in |ctx->store->objs|. + * Returns 1 if successful, + * 0 if not found or X509_LOOKUP_by_subject_ex() returns an error, + * -1 on failure + */ +int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type, + const X509_NAME *name, X509_OBJECT *ret) { - X509_STORE *store = vs->store; + X509_STORE *store = ctx->store; X509_LOOKUP *lu; X509_OBJECT stmp, *tmp; int i, j; @@ -319,20 +329,35 @@ int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs, return 0; stmp.type = X509_LU_NONE; - stmp.data.ptr = NULL; + stmp.data.x509 = NULL; - if (!X509_STORE_lock(store)) + if (!x509_store_read_lock(store)) return 0; - + /* Should already be sorted...but just in case */ + if (!sk_X509_OBJECT_is_sorted(store->objs)) { + X509_STORE_unlock(store); + /* Take a write lock instead of a read lock */ + if (!X509_STORE_lock(store)) + return 0; + /* + * Another thread might have sorted it in the meantime. But if so, + * sk_X509_OBJECT_sort() exits early. + */ + sk_X509_OBJECT_sort(store->objs); + } tmp = X509_OBJECT_retrieve_by_subject(store->objs, type, name); X509_STORE_unlock(store); if (tmp == NULL || type == X509_LU_CRL) { for (i = 0; i < sk_X509_LOOKUP_num(store->get_cert_methods); i++) { lu = sk_X509_LOOKUP_value(store->get_cert_methods, i); - j = X509_LOOKUP_by_subject_ex(lu, type, name, &stmp, vs->libctx, - vs->propq); - if (j) { + if (lu->skip) + continue; + if (lu->method == NULL) + return -1; + j = X509_LOOKUP_by_subject_ex(lu, type, name, &stmp, + ctx->libctx, ctx->propq); + if (j != 0) { /* non-zero value is considered success here */ tmp = &stmp; break; } @@ -341,16 +366,25 @@ int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs, return 0; } - if (!X509_OBJECT_up_ref_count(tmp)) - return 0; - - ret->type = tmp->type; - ret->data.ptr = tmp->data.ptr; - + if (ret != NULL) { + if (!X509_OBJECT_up_ref_count(tmp)) + return -1; + ret->type = tmp->type; + ret->data = tmp->data; + } return 1; } -static int x509_store_add(X509_STORE *store, void *x, int crl) { +/* Also fill the cache |ctx->store->objs| with all matching certificates. */ +int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *ctx, + X509_LOOKUP_TYPE type, + const X509_NAME *name, X509_OBJECT *ret) +{ + return ossl_x509_store_ctx_get_by_subject(ctx, type, name, ret) > 0; +} + +static int x509_store_add(X509_STORE *store, void *x, int crl) +{ X509_OBJECT *obj; int ret = 0, added = 0; @@ -393,19 +427,19 @@ static int x509_store_add(X509_STORE *store, void *x, int crl) { return ret; } -int X509_STORE_add_cert(X509_STORE *ctx, X509 *x) +int X509_STORE_add_cert(X509_STORE *xs, X509 *x) { - if (!x509_store_add(ctx, x, 0)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (!x509_store_add(xs, x, 0)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); return 0; } return 1; } -int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x) +int X509_STORE_add_crl(X509_STORE *xs, X509_CRL *x) { - if (!x509_store_add(ctx, x, 1)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (!x509_store_add(xs, x, 1)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); return 0; } return 1; @@ -447,10 +481,8 @@ X509_OBJECT *X509_OBJECT_new(void) { X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } ret->type = X509_LU_NONE; return ret; } @@ -499,13 +531,13 @@ void X509_OBJECT_free(X509_OBJECT *a) OPENSSL_free(a); } +/* Returns -1 if not found, but also on error */ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, const X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; X509_CRL crl_s; - int idx; stmp.type = type; switch (type) { @@ -518,34 +550,67 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */ break; case X509_LU_NONE: + default: /* abort(); */ return -1; } - idx = sk_X509_OBJECT_find_all(h, &stmp, pnmatch); - return idx; + /* Assumes h is locked for read if applicable */ + return sk_X509_OBJECT_find_all(h, &stmp, pnmatch); } +/* Assumes h is locked for read if applicable */ int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, const X509_NAME *name) { return x509_object_idx_cnt(h, type, name, NULL); } +/* Assumes h is locked for read if applicable */ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, const X509_NAME *name) { - int idx; - idx = X509_OBJECT_idx_by_subject(h, type, name); + int idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx == -1) return NULL; return sk_X509_OBJECT_value(h, idx); } -STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *v) +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *xs) { - return v->objs; + return xs->objs; +} + +static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj) +{ + X509_OBJECT *ret = X509_OBJECT_new(); + if (ret == NULL) + return NULL; + + ret->type = obj->type; + ret->data = obj->data; + X509_OBJECT_up_ref_count(ret); + return ret; +} + +STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *store) +{ + STACK_OF(X509_OBJECT) *objs; + + if (store == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!x509_store_read_lock(store)) + return NULL; + + objs = sk_X509_OBJECT_deep_copy(store->objs, x509_object_dup, + X509_OBJECT_free); + X509_STORE_unlock(store); + return objs; } STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store) @@ -563,6 +628,7 @@ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store) if (!X509_STORE_lock(store)) goto out_free; + sk_X509_OBJECT_sort(store->objs); objs = X509_STORE_get0_objects(store); for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i)); @@ -577,10 +643,14 @@ STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store) err: X509_STORE_unlock(store); out_free: - sk_X509_pop_free(sk, X509_free); + OSSL_STACK_OF_X509_free(sk); return NULL; } +/*- + * Collect from |ctx->store| all certs with subject matching |nm|. + * Returns NULL on internal/fatal error, empty stack if not found. + */ STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, const X509_NAME *nm) { @@ -591,79 +661,71 @@ STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_STORE *store = ctx->store; if (store == NULL) - return NULL; + return sk_X509_new_null(); if (!X509_STORE_lock(store)) return NULL; + sk_X509_OBJECT_sort(store->objs); idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt); if (idx < 0) { /* * Nothing found in cache: do lookup to possibly add new objects to * cache */ - X509_OBJECT *xobj = X509_OBJECT_new(); - X509_STORE_unlock(store); - - if (xobj == NULL) - return NULL; - if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) { - X509_OBJECT_free(xobj); - return NULL; - } - X509_OBJECT_free(xobj); + i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, nm, NULL); + if (i <= 0) + return i < 0 ? NULL : sk_X509_new_null(); if (!X509_STORE_lock(store)) return NULL; + sk_X509_OBJECT_sort(store->objs); idx = x509_object_idx_cnt(store->objs, X509_LU_X509, nm, &cnt); - if (idx < 0) { - X509_STORE_unlock(store); - return NULL; - } } sk = sk_X509_new_null(); + if (idx < 0 || sk == NULL) + goto end; for (i = 0; i < cnt; i++, idx++) { obj = sk_X509_OBJECT_value(store->objs, idx); x = obj->data.x509; if (!X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF)) { X509_STORE_unlock(store); - sk_X509_pop_free(sk, X509_free); + OSSL_STACK_OF_X509_free(sk); return NULL; } } + end: X509_STORE_unlock(store); return sk; } +/* Returns NULL on internal/fatal error, empty stack if not found */ STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx, const X509_NAME *nm) { - int i, idx, cnt; - STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null(); + int i = 1, idx, cnt; + STACK_OF(X509_CRL) *sk; X509_CRL *x; - X509_OBJECT *obj, *xobj = X509_OBJECT_new(); + X509_OBJECT *obj; X509_STORE *store = ctx->store; /* Always do lookup to possibly add new CRLs to cache */ - if (sk == NULL - || xobj == NULL - || store == NULL - || !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) { - X509_OBJECT_free(xobj); - sk_X509_CRL_free(sk); + i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_CRL, nm, NULL); + if (i < 0) return NULL; - } - X509_OBJECT_free(xobj); + sk = sk_X509_CRL_new_null(); + if (i == 0) + return sk; if (!X509_STORE_lock(store)) { sk_X509_CRL_free(sk); return NULL; } + sk_X509_OBJECT_sort(store->objs); idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, nm, &cnt); if (idx < 0) { X509_STORE_unlock(store); - sk_X509_CRL_free(sk); - return NULL; + return sk; } for (i = 0; i < cnt; i++, idx++) { @@ -707,266 +769,183 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, } else if (x->type == X509_LU_CRL) { if (X509_CRL_match(obj->data.crl, x->data.crl) == 0) return obj; - } else + } else { return obj; + } } return NULL; } -/*- - * Try to get issuer cert from |ctx->store| matching the subject name of |x|. - * Prefer the first non-expired one, else take the most recently expired one. - * - * Return values are: - * 1 lookup successful. - * 0 certificate not found. - * -1 some other error. - */ -int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags) { - const X509_NAME *xn; - X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL; - X509_STORE *store = ctx->store; - int i, ok, idx, ret, nmatch = 0; - - if (obj == NULL) - return -1; - *issuer = NULL; - xn = X509_get_issuer_name(x); - ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj); - if (ok != 1) { - X509_OBJECT_free(obj); - return 0; - } - /* If certificate matches and is currently valid all OK */ - if (ctx->check_issued(ctx, x, obj->data.x509)) { - if (ossl_x509_check_cert_time(ctx, obj->data.x509, -1)) { - *issuer = obj->data.x509; - /* |*issuer| has taken over the cert reference from |obj| */ - obj->type = X509_LU_NONE; - X509_OBJECT_free(obj); - return 1; - } - } - X509_OBJECT_free(obj); - - /* - * Due to limitations of the API this can only retrieve a single cert. - * However it will fill the cache with all matching certificates, - * so we can examine the cache for all matches. - */ - if (store == NULL) - return 0; - - /* Find index of first currently valid cert accepted by 'check_issued' */ - ret = 0; - if (!X509_STORE_lock(store)) - return 0; - - idx = x509_object_idx_cnt(store->objs, X509_LU_X509, xn, &nmatch); - if (idx != -1) { /* should be true as we've had at least one match */ - /* Look through all matching certs for suitable issuer */ - for (i = idx; i < idx + nmatch; i++) { - pobj = sk_X509_OBJECT_value(store->objs, i); - /* See if we've run past the matches */ - if (pobj->type != X509_LU_X509) - break; - if (ctx->check_issued(ctx, x, pobj->data.x509)) { - ret = 1; - /* If times check fine, exit with match, else keep looking. */ - if (ossl_x509_check_cert_time(ctx, pobj->data.x509, -1)) { - *issuer = pobj->data.x509; - break; - } - /* - * Leave the so far most recently expired match in *issuer - * so we return nearest match if no certificate time is OK. - */ - if (*issuer == NULL - || ASN1_TIME_compare(X509_get0_notAfter(pobj->data.x509), - X509_get0_notAfter(*issuer)) > 0) - *issuer = pobj->data.x509; - } - } - } - if (*issuer != NULL && !X509_up_ref(*issuer)) { - *issuer = NULL; - ret = -1; - } - X509_STORE_unlock(store); - return ret; + return X509_VERIFY_PARAM_set_flags(xs->param, flags); } -int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) +int X509_STORE_set_depth(X509_STORE *xs, int depth) { - return X509_VERIFY_PARAM_set_flags(ctx->param, flags); -} - -int X509_STORE_set_depth(X509_STORE *ctx, int depth) -{ - X509_VERIFY_PARAM_set_depth(ctx->param, depth); + X509_VERIFY_PARAM_set_depth(xs->param, depth); return 1; } -int X509_STORE_set_purpose(X509_STORE *ctx, int purpose) +int X509_STORE_set_purpose(X509_STORE *xs, int purpose) { - return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); + return X509_VERIFY_PARAM_set_purpose(xs->param, purpose); } -int X509_STORE_set_trust(X509_STORE *ctx, int trust) +int X509_STORE_set_trust(X509_STORE *xs, int trust) { - return X509_VERIFY_PARAM_set_trust(ctx->param, trust); + return X509_VERIFY_PARAM_set_trust(xs->param, trust); } -int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *param) +int X509_STORE_set1_param(X509_STORE *xs, const X509_VERIFY_PARAM *param) { - return X509_VERIFY_PARAM_set1(ctx->param, param); + return X509_VERIFY_PARAM_set1(xs->param, param); } -X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx) +X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *xs) { - return ctx->param; + return xs->param; } -void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify) +void X509_STORE_set_verify(X509_STORE *xs, X509_STORE_CTX_verify_fn verify) { - ctx->verify = verify; + xs->verify = verify; } -X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *ctx) +X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *xs) { - return ctx->verify; + return xs->verify; } -void X509_STORE_set_verify_cb(X509_STORE *ctx, +void X509_STORE_set_verify_cb(X509_STORE *xs, X509_STORE_CTX_verify_cb verify_cb) { - ctx->verify_cb = verify_cb; + xs->verify_cb = verify_cb; } -X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *ctx) +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *xs) { - return ctx->verify_cb; + return xs->verify_cb; } -void X509_STORE_set_get_issuer(X509_STORE *ctx, +void X509_STORE_set_get_issuer(X509_STORE *xs, X509_STORE_CTX_get_issuer_fn get_issuer) { - ctx->get_issuer = get_issuer; + xs->get_issuer = get_issuer; } -X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *ctx) +X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *xs) { - return ctx->get_issuer; + return xs->get_issuer; } -void X509_STORE_set_check_issued(X509_STORE *ctx, +void X509_STORE_set_check_issued(X509_STORE *xs, X509_STORE_CTX_check_issued_fn check_issued) { - ctx->check_issued = check_issued; + xs->check_issued = check_issued; } -X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *ctx) +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *xs) { - return ctx->check_issued; + return xs->check_issued; } -void X509_STORE_set_check_revocation(X509_STORE *ctx, - X509_STORE_CTX_check_revocation_fn check_revocation) +void X509_STORE_set_check_revocation(X509_STORE *xs, + X509_STORE_CTX_check_revocation_fn cb) { - ctx->check_revocation = check_revocation; + xs->check_revocation = cb; } -X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *ctx) +X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *xs) { - return ctx->check_revocation; + return xs->check_revocation; } -void X509_STORE_set_get_crl(X509_STORE *ctx, +void X509_STORE_set_get_crl(X509_STORE *xs, X509_STORE_CTX_get_crl_fn get_crl) { - ctx->get_crl = get_crl; + xs->get_crl = get_crl; } -X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *ctx) +X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *xs) { - return ctx->get_crl; + return xs->get_crl; } -void X509_STORE_set_check_crl(X509_STORE *ctx, +void X509_STORE_set_check_crl(X509_STORE *xs, X509_STORE_CTX_check_crl_fn check_crl) { - ctx->check_crl = check_crl; + xs->check_crl = check_crl; } -X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *ctx) +X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *xs) { - return ctx->check_crl; + return xs->check_crl; } -void X509_STORE_set_cert_crl(X509_STORE *ctx, +void X509_STORE_set_cert_crl(X509_STORE *xs, X509_STORE_CTX_cert_crl_fn cert_crl) { - ctx->cert_crl = cert_crl; + xs->cert_crl = cert_crl; } -X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *ctx) +X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *xs) { - return ctx->cert_crl; + return xs->cert_crl; } -void X509_STORE_set_check_policy(X509_STORE *ctx, +void X509_STORE_set_check_policy(X509_STORE *xs, X509_STORE_CTX_check_policy_fn check_policy) { - ctx->check_policy = check_policy; + xs->check_policy = check_policy; } -X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *ctx) +X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *xs) { - return ctx->check_policy; + return xs->check_policy; } -void X509_STORE_set_lookup_certs(X509_STORE *ctx, +void X509_STORE_set_lookup_certs(X509_STORE *xs, X509_STORE_CTX_lookup_certs_fn lookup_certs) { - ctx->lookup_certs = lookup_certs; + xs->lookup_certs = lookup_certs; } -X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *ctx) +X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *xs) { - return ctx->lookup_certs; + return xs->lookup_certs; } -void X509_STORE_set_lookup_crls(X509_STORE *ctx, +void X509_STORE_set_lookup_crls(X509_STORE *xs, X509_STORE_CTX_lookup_crls_fn lookup_crls) { - ctx->lookup_crls = lookup_crls; + xs->lookup_crls = lookup_crls; } -X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *ctx) +X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *xs) { - return ctx->lookup_crls; + return xs->lookup_crls; } -void X509_STORE_set_cleanup(X509_STORE *ctx, - X509_STORE_CTX_cleanup_fn ctx_cleanup) +void X509_STORE_set_cleanup(X509_STORE *xs, + X509_STORE_CTX_cleanup_fn cleanup) { - ctx->cleanup = ctx_cleanup; + xs->cleanup = cleanup; } -X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *ctx) +X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *xs) { - return ctx->cleanup; + return xs->cleanup; } -int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data) +int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data) { - return CRYPTO_set_ex_data(&ctx->ex_data, idx, data); + return CRYPTO_set_ex_data(&xs->ex_data, idx, data); } -void *X509_STORE_get_ex_data(const X509_STORE *ctx, int idx) +void *X509_STORE_get_ex_data(const X509_STORE *xs, int idx) { - return CRYPTO_get_ex_data(&ctx->ex_data, idx); + return CRYPTO_get_ex_data(&xs->ex_data, idx); } X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) diff --git a/crypto/x509/x509_meth.c b/crypto/x509/x509_meth.c index a8eedd9b59af..305fe4c6d390 100644 --- a/crypto/x509/x509_meth.c +++ b/crypto/x509/x509_meth.c @@ -23,10 +23,8 @@ X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name) if (method != NULL) { method->name = OPENSSL_strdup(name); - if (method->name == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (method->name == NULL) goto err; - } } return method; diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c index 12c6d6f78b6e..a55ee1a73e23 100644 --- a/crypto/x509/x509_obj.c +++ b/crypto/x509/x509_obj.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -32,7 +32,6 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) char *p; unsigned char *q; BUF_MEM *b = NULL; - static const char hex[17] = "0123456789ABCDEF"; int gs_doit[4]; char tmp_buf[80]; #ifdef CHARSET_EBCDIC @@ -41,9 +40,9 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) if (buf == NULL) { if ((b = BUF_MEM_new()) == NULL) - goto err; + goto buferr; if (!BUF_MEM_grow(b, 200)) - goto err; + goto buferr; b->data[0] = '\0'; len = 200; } else if (len == 0) { @@ -124,7 +123,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) } if (b != NULL) { if (!BUF_MEM_grow(b, l + 1)) - goto err; + goto buferr; p = &(b->data[lold]); } else if (l > len) { break; @@ -147,8 +146,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) if ((n < ' ') || (n > '~')) { *(p++) = '\\'; *(p++) = 'x'; - *(p++) = hex[(n >> 4) & 0x0f]; - *(p++) = hex[n & 0x0f]; + p += ossl_to_hex(p, n); } else { if (n == '/' || n == '+') *(p++) = '\\'; @@ -159,8 +157,7 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) if ((n < os_toascii[' ']) || (n > os_toascii['~'])) { *(p++) = '\\'; *(p++) = 'x'; - *(p++) = hex[(n >> 4) & 0x0f]; - *(p++) = hex[n & 0x0f]; + p += ossl_to_hex(p, n); } else { if (n == os_toascii['/'] || n == os_toascii['+']) *(p++) = '\\'; @@ -179,8 +176,8 @@ char *X509_NAME_oneline(const X509_NAME *a, char *buf, int len) if (i == 0) *p = '\0'; return p; - err: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + buferr: + ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB); end: BUF_MEM_free(b); return NULL; diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c index c7f6181c4465..a6ea8e36a030 100644 --- a/crypto/x509/x509_r2x.c +++ b/crypto/x509/x509_r2x.c @@ -25,7 +25,7 @@ X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) EVP_PKEY *pubkey = NULL; if ((ret = X509_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return NULL; } diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c index 0434fbbc6b70..4085b587a5e1 100644 --- a/crypto/x509/x509_req.c +++ b/crypto/x509/x509_req.c @@ -28,7 +28,7 @@ X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) ret = X509_REQ_new_ex(x->libctx, x->propq); if (ret == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; } @@ -67,7 +67,7 @@ EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req) return X509_PUBKEY_get(req->req_info.pubkey); } -EVP_PKEY *X509_REQ_get0_pubkey(X509_REQ *req) +EVP_PKEY *X509_REQ_get0_pubkey(const X509_REQ *req) { if (req == NULL) return NULL; @@ -79,28 +79,9 @@ X509_PUBKEY *X509_REQ_get_X509_PUBKEY(X509_REQ *req) return req->req_info.pubkey; } -int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) +int X509_REQ_check_private_key(const X509_REQ *req, EVP_PKEY *pkey) { - EVP_PKEY *xk = NULL; - int ok = 0; - - xk = X509_REQ_get_pubkey(x); - switch (EVP_PKEY_eq(xk, k)) { - case 1: - ok = 1; - break; - case 0: - ERR_raise(ERR_LIB_X509, X509_R_KEY_VALUES_MISMATCH); - break; - case -1: - ERR_raise(ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH); - break; - case -2: - ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_KEY_TYPE); - } - - EVP_PKEY_free(xk); - return ok; + return ossl_x509_check_private_key(X509_REQ_get0_pubkey(req), pkey); } /* @@ -136,33 +117,47 @@ void X509_REQ_set_extension_nids(int *nids) ext_nids = nids; } -STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) +static STACK_OF(X509_EXTENSION) *get_extensions_by_nid(const X509_REQ *req, + int nid) { X509_ATTRIBUTE *attr; ASN1_TYPE *ext = NULL; - int idx, *pnid; const unsigned char *p; + int idx = X509_REQ_get_attr_by_NID(req, nid, -1); - if (req == NULL || !ext_nids) - return NULL; - for (pnid = ext_nids; *pnid != NID_undef; pnid++) { - idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); - if (idx == -1) - continue; - attr = X509_REQ_get_attr(req, idx); - ext = X509_ATTRIBUTE_get0_type(attr, 0); - break; - } - if (ext == NULL) /* no extensions is not an error */ + if (idx < 0) /* no extensions is not an error */ return sk_X509_EXTENSION_new_null(); - if (ext->type != V_ASN1_SEQUENCE) + attr = X509_REQ_get_attr(req, idx); + ext = X509_ATTRIBUTE_get0_type(attr, 0); + if (ext == NULL || ext->type != V_ASN1_SEQUENCE) { + ERR_raise(ERR_LIB_X509, X509_R_WRONG_TYPE); return NULL; + } p = ext->value.sequence->data; return (STACK_OF(X509_EXTENSION) *) ASN1_item_d2i(NULL, &p, ext->value.sequence->length, ASN1_ITEM_rptr(X509_EXTENSIONS)); } +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(OSSL_FUTURE_CONST X509_REQ *req) +{ + STACK_OF(X509_EXTENSION) *exts = NULL; + int *pnid; + + if (req == NULL || ext_nids == NULL) + return NULL; + for (pnid = ext_nids; *pnid != NID_undef; pnid++) { + exts = get_extensions_by_nid(req, *pnid); + if (exts == NULL) + return NULL; + if (sk_X509_EXTENSION_num(exts) > 0) + return exts; + sk_X509_EXTENSION_free(exts); + } + /* no extensions is not an error */ + return sk_X509_EXTENSION_new_null(); +} + /* * Add a STACK_OF extensions to a certificate request: allow alternative OIDs * in case we want to create a non standard one. @@ -173,14 +168,39 @@ int X509_REQ_add_extensions_nid(X509_REQ *req, int extlen; int rv = 0; unsigned char *ext = NULL; + STACK_OF(X509_EXTENSION) *mod_exts = NULL; + int loc; + + if (sk_X509_EXTENSION_num(exts) <= 0) + return 1; /* adding NULL or empty list of exts is a no-op */ + + loc = X509at_get_attr_by_NID(req->req_info.attributes, nid, -1); + if (loc != -1) { + if ((mod_exts = get_extensions_by_nid(req, nid)) == NULL) + return 0; + if (X509v3_add_extensions(&mod_exts, exts) == NULL) + goto end; + } /* Generate encoding of extensions */ - extlen = ASN1_item_i2d((const ASN1_VALUE *)exts, &ext, - ASN1_ITEM_rptr(X509_EXTENSIONS)); + extlen = ASN1_item_i2d((const ASN1_VALUE *) + (mod_exts == NULL ? exts : mod_exts), + &ext, ASN1_ITEM_rptr(X509_EXTENSIONS)); if (extlen <= 0) - return 0; + goto end; + if (mod_exts != NULL) { + X509_ATTRIBUTE *att = X509at_delete_attr(req->req_info.attributes, loc); + + if (att == NULL) + goto end; + X509_ATTRIBUTE_free(att); + } + rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); OPENSSL_free(ext); + + end: + sk_X509_EXTENSION_pop_free(mod_exts, X509_EXTENSION_free); return rv; } diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c index d8ddde8aaa51..0c9df51b3c7e 100644 --- a/crypto/x509/x509_set.c +++ b/crypto/x509/x509_set.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -23,16 +23,22 @@ int X509_set_version(X509 *x, long version) { if (x == NULL) return 0; - if (version == 0) { + if (version == X509_get_version(x)) + return 1; /* avoid needless modification even re-allocation */ + if (version == X509_VERSION_1) { ASN1_INTEGER_free(x->cert_info.version); x->cert_info.version = NULL; + x->cert_info.enc.modified = 1; return 1; } if (x->cert_info.version == NULL) { if ((x->cert_info.version = ASN1_INTEGER_new()) == NULL) return 0; } - return ASN1_INTEGER_set(x->cert_info.version, version); + if (!ASN1_INTEGER_set(x->cert_info.version, version)) + return 0; + x->cert_info.enc.modified = 1; + return 1; } int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) @@ -44,68 +50,78 @@ int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) in = &x->cert_info.serialNumber; if (in != serial) return ASN1_STRING_copy(in, serial); + x->cert_info.enc.modified = 1; return 1; } int X509_set_issuer_name(X509 *x, const X509_NAME *name) { - if (x == NULL) + if (x == NULL || !X509_NAME_set(&x->cert_info.issuer, name)) return 0; - return X509_NAME_set(&x->cert_info.issuer, name); + x->cert_info.enc.modified = 1; + return 1; } int X509_set_subject_name(X509 *x, const X509_NAME *name) { - if (x == NULL) + if (x == NULL || !X509_NAME_set(&x->cert_info.subject, name)) return 0; - return X509_NAME_set(&x->cert_info.subject, name); + x->cert_info.enc.modified = 1; + return 1; } -int ossl_x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm) +int ossl_x509_set1_time(int *modified, ASN1_TIME **ptm, const ASN1_TIME *tm) { - ASN1_TIME *in; - in = *ptm; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(*ptm); - *ptm = in; - } - } - return (in != NULL); + ASN1_TIME *new; + + if (*ptm == tm) + return 1; + new = ASN1_STRING_dup(tm); + if (tm != NULL && new == NULL) + return 0; + ASN1_TIME_free(*ptm); + *ptm = new; + if (modified != NULL) + *modified = 1; + return 1; } int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) { - if (x == NULL) + if (x == NULL || tm == NULL) return 0; - return ossl_x509_set1_time(&x->cert_info.validity.notBefore, tm); + return ossl_x509_set1_time(&x->cert_info.enc.modified, + &x->cert_info.validity.notBefore, tm); } int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) { - if (x == NULL) + if (x == NULL || tm == NULL) return 0; - return ossl_x509_set1_time(&x->cert_info.validity.notAfter, tm); + return ossl_x509_set1_time(&x->cert_info.enc.modified, + &x->cert_info.validity.notAfter, tm); } int X509_set_pubkey(X509 *x, EVP_PKEY *pkey) { if (x == NULL) return 0; - return X509_PUBKEY_set(&(x->cert_info.key), pkey); + if (!X509_PUBKEY_set(&(x->cert_info.key), pkey)) + return 0; + x->cert_info.enc.modified = 1; + return 1; } int X509_up_ref(X509 *x) { int i; - if (CRYPTO_UP_REF(&x->references, &i, x->lock) <= 0) + if (CRYPTO_UP_REF(&x->references, &i) <= 0) return 0; - REF_PRINT_COUNT("X509", x); + REF_PRINT_COUNT("X509", i, x); REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); + return i > 1; } long X509_get_version(const X509 *x) @@ -194,9 +210,9 @@ int X509_get_signature_info(X509 *x, int *mdnid, int *pknid, int *secbits, /* Modify *siginf according to alg and sig. Return 1 on success, else 0. */ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, - const ASN1_STRING *sig) + const ASN1_STRING *sig, const EVP_PKEY *pubkey) { - int pknid, mdnid; + int pknid, mdnid, md_size; const EVP_MD *md; const EVP_PKEY_ASN1_METHOD *ameth; @@ -216,12 +232,20 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, case NID_undef: /* If we have one, use a custom handler for this algorithm */ ameth = EVP_PKEY_asn1_find(NULL, pknid); - if (ameth == NULL || ameth->siginf_set == NULL - || !ameth->siginf_set(siginf, alg, sig)) { - ERR_raise(ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET); - return 0; + if (ameth != NULL && ameth->siginf_set != NULL + && ameth->siginf_set(siginf, alg, sig)) + break; + if (pubkey != NULL) { + int secbits; + + secbits = EVP_PKEY_get_security_bits(pubkey); + if (secbits != 0) { + siginf->secbits = secbits; + break; + } } - break; + ERR_raise(ERR_LIB_X509, X509_R_ERROR_USING_SIGINF_SET); + return 0; /* * SHA1 and MD5 are known to be broken. Reduce security bits so that * they're no longer accepted at security level 1. @@ -255,7 +279,10 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, ERR_raise(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID); return 0; } - siginf->secbits = EVP_MD_get_size(md) * 4; + md_size = EVP_MD_get_size(md); + if (md_size <= 0) + return 0; + siginf->secbits = md_size * 4; break; } switch (mdnid) { @@ -272,5 +299,6 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg, /* Returns 1 on success, 0 on failure */ int ossl_x509_init_sig_info(X509 *x) { - return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature); + return x509_sig_info_init(&x->siginf, &x->sig_alg, &x->signature, + X509_PUBKEY_get0(x->cert_info.key)); } diff --git a/crypto/x509/x509_trust.c b/crypto/x509/x509_trust.c index fd77b0c6fe61..1a4345f2fec0 100644 --- a/crypto/x509/x509_trust.c +++ b/crypto/x509/x509_trust.c @@ -1,5 +1,5 @@ /* - * 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 @@ -62,6 +62,7 @@ int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *, return oldtrust; } +/* Returns X509_TRUST_TRUSTED, X509_TRUST_REJECTED, or X509_TRUST_UNTRUSTED */ int X509_check_trust(X509 *x, int id, int flags) { X509_TRUST *pt; @@ -104,6 +105,8 @@ int X509_TRUST_get_by_id(int id) if (trtable == NULL) return -1; tmp.trust = id; + /* Ideally, this would be done under lock */ + sk_X509_TRUST_sort(trtable); idx = sk_X509_TRUST_find(trtable, &tmp); if (idx < 0) return -1; @@ -135,10 +138,8 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), idx = X509_TRUST_get_by_id(id); /* Need a new entry */ if (idx < 0) { - if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if ((trtmp = OPENSSL_malloc(sizeof(*trtmp))) == NULL) return 0; - } trtmp->flags = X509_TRUST_DYNAMIC; } else trtmp = X509_TRUST_get0(idx); @@ -147,10 +148,8 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name); /* dup supplied name */ - if ((trtmp->name = OPENSSL_strdup(name)) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if ((trtmp->name = OPENSSL_strdup(name)) == NULL) goto err; - } /* Keep the dynamic flag of existing entry */ trtmp->flags &= X509_TRUST_DYNAMIC; /* Set all other flags */ @@ -165,11 +164,11 @@ int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int), if (idx < 0) { if (trtable == NULL && (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); - goto err;; + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); + goto err; } if (!sk_X509_TRUST_push(trtable, trtmp)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } } @@ -253,7 +252,7 @@ static int obj_trust(int id, X509 *x, int flags) X509_CERT_AUX *ax = x->aux; int i; - if (ax && ax->reject) { + if (ax != NULL && ax->reject != NULL) { for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->reject, i); int nid = OBJ_obj2nid(obj); @@ -264,7 +263,7 @@ static int obj_trust(int id, X509 *x, int flags) } } - if (ax && ax->trust) { + if (ax != NULL && ax->trust != NULL) { for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(ax->trust, i); int nid = OBJ_obj2nid(obj); @@ -276,7 +275,7 @@ static int obj_trust(int id, X509 *x, int flags) /* * Reject when explicit trust EKU are set and none match. * - * Returning untrusted is enough for for full chains that end in + * Returning untrusted is enough for full chains that end in * self-signed roots, because when explicit trust is specified it * suppresses the default blanket trust of self-signed objects. * diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c index 61d41117e2c0..e825ce2db8b9 100644 --- a/crypto/x509/x509_txt.c +++ b/crypto/x509/x509_txt.c @@ -212,6 +212,8 @@ const char *X509_verify_cert_error_string(long n) return "Using cert extension requires at least X509v3"; case X509_V_ERR_EC_KEY_EXPLICIT_PARAMS: return "Certificate public key has explicit ECC parameters"; + case X509_V_ERR_RPK_UNTRUSTED: + return "Raw public key untrusted, no trusted keys configured"; /* * Entries must be kept consistent with include/openssl/x509_vfy.h.in diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c index 62ae7d6b8d62..9c4ee2bf5fff 100644 --- a/crypto/x509/x509_v3.c +++ b/crypto/x509/x509_v3.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -61,7 +61,7 @@ int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, int lastpos) { - int n; + int n, c; X509_EXTENSION *ex; if (sk == NULL) @@ -72,7 +72,9 @@ int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, n = sk_X509_EXTENSION_num(sk); for (; lastpos < n; lastpos++) { ex = sk_X509_EXTENSION_value(sk, lastpos); - if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit)) + c = X509_EXTENSION_get_critical(ex); + crit = crit != 0; + if (c == crit) return lastpos; } return -1; @@ -105,12 +107,14 @@ STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, if (x == NULL) { ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); - goto err2; + goto err; } if (*x == NULL) { - if ((sk = sk_X509_EXTENSION_new_null()) == NULL) + if ((sk = sk_X509_EXTENSION_new_null()) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; + } } else sk = *x; @@ -120,22 +124,54 @@ STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, else if (loc < 0) loc = n; - if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) - goto err2; - if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) + if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; + } + if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); + goto err; + } if (*x == NULL) *x = sk; return sk; err: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); - err2: X509_EXTENSION_free(new_ex); if (x != NULL && *x == NULL) sk_X509_EXTENSION_free(sk); return NULL; } +/* This returns NULL also in non-error case *target == NULL && sk_X509_EXTENSION_num(exts) <= 0 */ +STACK_OF(X509_EXTENSION) *X509v3_add_extensions(STACK_OF(X509_EXTENSION) **target, + const STACK_OF(X509_EXTENSION) *exts) +{ + int i; + + if (target == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + 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 NULL; + } + return *target; +} + X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit, ASN1_OCTET_STRING *data) @@ -162,7 +198,7 @@ X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, if ((ex == NULL) || (*ex == NULL)) { if ((ret = X509_EXTENSION_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return NULL; } } else @@ -197,7 +233,7 @@ int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) { if (ex == NULL) return 0; - ex->critical = (crit) ? 0xFF : -1; + ex->critical = (crit) ? 0xFF : 0; return 1; } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index d19efeaa9919..5cdf929e4f1e 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -41,12 +41,15 @@ #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 x509_verify_x509(X509_STORE_CTX *ctx); +static int x509_verify_rpk(X509_STORE_CTX *ctx); static int build_chain(X509_STORE_CTX *ctx); static int verify_chain(X509_STORE_CTX *ctx); +static int verify_rpk(X509_STORE_CTX *ctx); static int dane_verify(X509_STORE_CTX *ctx); +static int dane_verify_rpk(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); @@ -54,9 +57,9 @@ 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_cert_key_level(X509_STORE_CTX *ctx, X509 *cert); +static int check_key_level(X509_STORE_CTX *ctx, EVP_PKEY *pkey); static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert); static int check_curve(X509 *cert); @@ -124,6 +127,7 @@ static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *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); @@ -138,7 +142,7 @@ static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *x) else *result = xtmp; } - sk_X509_pop_free(certs, X509_free); + OSSL_STACK_OF_X509_free(certs); return ret; } @@ -147,7 +151,7 @@ static int lookup_cert_match(X509 **result, X509_STORE_CTX *ctx, X509 *x) * 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. + * The error cert is |x| if not NULL, else the cert in |ctx->chain| at |depth|. * * Returns 0 to abort verification with an error, non-zero to continue. */ @@ -157,7 +161,7 @@ static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err) depth = ctx->error_depth; else ctx->error_depth = depth; - ctx->current_cert = (x != NULL) ? x : sk_X509_value(ctx->chain, 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); @@ -180,6 +184,7 @@ static int verify_cb_crl(X509_STORE_CTX *ctx, int err) return ctx->verify_cb(0, ctx); } +/* Sadly, returns 0 also on internal error in ctx->verify_cb(). */ static int check_auth_level(X509_STORE_CTX *ctx) { int i; @@ -195,7 +200,7 @@ static int check_auth_level(X509_STORE_CTX *ctx) * 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), + CB_FAIL_IF(i > 0 && !check_cert_key_level(ctx, cert), ctx, cert, i, X509_V_ERR_CA_KEY_TOO_SMALL); /* * We also check the signature algorithm security of all certificates @@ -207,7 +212,24 @@ static int check_auth_level(X509_STORE_CTX *ctx) return 1; } -/* Returns -1 on internal error */ +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ +static int verify_rpk(X509_STORE_CTX *ctx) +{ + /* Not much to verify on a RPK */ + if (ctx->verify != NULL) + return ctx->verify(ctx); + + return !!ctx->verify_cb(ctx->error == X509_V_OK, ctx); +} + + +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ static int verify_chain(X509_STORE_CTX *ctx) { int err; @@ -253,19 +275,58 @@ int X509_STORE_CTX_verify(X509_STORE_CTX *ctx) ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return -1; } + if (ctx->rpk != NULL) + return x509_verify_rpk(ctx); if (ctx->cert == NULL && sk_X509_num(ctx->untrusted) >= 1) ctx->cert = sk_X509_value(ctx->untrusted, 0); - return X509_verify_cert(ctx); + return x509_verify_x509(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; } + return (ctx->rpk != NULL) ? x509_verify_rpk(ctx) : x509_verify_x509(ctx); +} + +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ +static int x509_verify_rpk(X509_STORE_CTX *ctx) +{ + int ret; + + /* If the peer's public key is too weak, we can stop early. */ + if (!check_key_level(ctx, ctx->rpk) + && verify_cb_cert(ctx, NULL, 0, X509_V_ERR_EE_KEY_TOO_SMALL) == 0) + return 0; + + /* Barring any data to verify the RPK, simply report it as untrusted */ + ctx->error = X509_V_ERR_RPK_UNTRUSTED; + + ret = DANETLS_ENABLED(ctx->dane) ? dane_verify_rpk(ctx) : verify_rpk(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; +} + +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ +static int x509_verify_x509(X509_STORE_CTX *ctx) +{ + int ret; + 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; @@ -289,7 +350,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) 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), + CB_FAIL_IF(!check_cert_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); @@ -314,33 +375,99 @@ static int sk_X509_contains(STACK_OF(X509) *sk, X509 *cert) 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. +/*- + * Find in |sk| an issuer cert of cert |x| accepted by |ctx->check_issued|. + * If no_dup, 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 match with suitable validity period or latest expiration. */ -static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) +/* + * Note: so far, we do not check during chain building + * whether any key usage extension stands against a candidate issuer cert. + * Likely it would be good if build_chain() sets |check_signing_allowed|. + * Yet if |sk| is a list of trusted certs, as with X509_STORE_CTX_set0_trusted_stack(), + * better not set |check_signing_allowed|. + * Maybe not touch X509_STORE_CTX_get1_issuer(), for API backward compatiblity. + */ +static X509 *get0_best_issuer_sk(X509_STORE_CTX *ctx, int check_signing_allowed, + int no_dup, STACK_OF(X509) *sk, X509 *x) { int i; - X509 *issuer, *rv = NULL; + X509 *candidate, *issuer = 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; + candidate = sk_X509_value(sk, i); + if (no_dup + && !((x->ex_flags & EXFLAG_SI) != 0 && sk_X509_num(ctx->chain) == 1) + && sk_X509_contains(ctx->chain, candidate)) + continue; + if (ctx->check_issued(ctx, x, candidate)) { + if (check_signing_allowed + /* yet better not check key usage for trust anchors */ + && ossl_x509_signing_allowed(candidate, x) != X509_V_OK) + continue; + if (ossl_x509_check_cert_time(ctx, candidate, -1)) + return candidate; + /* + * Leave in *issuer the first match that has the latest expiration + * date so we return nearest match if no certificate time is OK. + */ + if (issuer == NULL + || ASN1_TIME_compare(X509_get0_notAfter(candidate), + X509_get0_notAfter(issuer)) > 0) + issuer = candidate; } } - return rv; + return issuer; } -/* Check that the given certificate 'x' is issued by the certificate 'issuer' */ +/*- + * Try to get issuer cert from |ctx->store| accepted by |ctx->check_issued|. + * Prefer the first match with suitable validity period or latest expiration. + * + * Return values are: + * 1 lookup successful. + * 0 certificate not found. + * -1 some other error. + */ +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + const X509_NAME *xn = X509_get_issuer_name(x); + X509_OBJECT *obj = X509_OBJECT_new(); + STACK_OF(X509) *certs; + int ret; + + *issuer = NULL; + if (obj == NULL) + return -1; + ret = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, xn, obj); + if (ret != 1) + goto end; + + /* quick happy path: certificate matches and is currently valid */ + if (ctx->check_issued(ctx, x, obj->data.x509)) { + if (ossl_x509_check_cert_time(ctx, obj->data.x509, -1)) { + *issuer = obj->data.x509; + /* |*issuer| has taken over the cert reference from |obj| */ + obj->type = X509_LU_NONE; + goto end; + } + } + + ret = -1; + if ((certs = X509_STORE_CTX_get1_certs(ctx, xn)) == NULL) + goto end; + *issuer = get0_best_issuer_sk(ctx, 0, 0 /* allow duplicates */, certs, x); + ret = 0; + if (*issuer != NULL) + ret = X509_up_ref(*issuer) ? 1 : -1; + OSSL_STACK_OF_X509_free(certs); + end: + X509_OBJECT_free(obj); + return ret; +} + +/* 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); @@ -358,20 +485,19 @@ static int check_issued(ossl_unused X509_STORE_CTX *ctx, X509 *x, X509 *issuer) * 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) +static int get1_best_issuer_other_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; + *issuer = get0_best_issuer_sk(ctx, 0, 1 /* no_dup */, ctx->other_ctx, x); + if (*issuer == NULL) + return 0; + return X509_up_ref(*issuer) ? 1 : -1; } /*- * Alternative lookup method: look from a STACK stored in other_ctx. - * Returns NULL on internal error (such as out of memory). + * Returns NULL on internal/fatal error, empty stack if not found. */ -static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, - const X509_NAME *nm) +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; @@ -383,7 +509,7 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, 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); + OSSL_STACK_OF_X509_free(sk); ctx->error = X509_V_ERR_OUT_OF_MEM; return NULL; } @@ -395,7 +521,7 @@ static STACK_OF(X509) *lookup_certs_sk(X509_STORE_CTX *ctx, /* * 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. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). */ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, int must_be_ca) @@ -428,7 +554,7 @@ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, return 1; case X509_TRUST_REJECTED: break; - default: + default: /* can only be X509_TRUST_UNTRUSTED */ switch (X509_check_purpose(x, purpose, must_be_ca > 0)) { case 1: return 1; @@ -444,9 +570,9 @@ static int check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, 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. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). */ static int check_extensions(X509_STORE_CTX *ctx) { @@ -581,7 +707,7 @@ static int check_extensions(X509_STORE_CTX *ctx) } /* check_purpose() makes the callback as needed */ - if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca)) + if (purpose >= X509_PURPOSE_MIN && !check_purpose(ctx, x, purpose, i, must_be_ca)) return 0; /* Check path length */ CB_FAIL_IF(i > 1 && x->ex_pathlen != -1 @@ -642,7 +768,10 @@ static int has_san_id(X509 *x, int gtype) return ret; } -/* Returns -1 on internal error */ +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ static int check_name_constraints(X509_STORE_CTX *ctx) { int i; @@ -703,7 +832,7 @@ static int check_name_constraints(X509_STORE_CTX *ctx) */ tmpsubject = X509_NAME_dup(tmpsubject); if (tmpsubject == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); ctx->error = X509_V_ERR_OUT_OF_MEM; return -1; } @@ -863,7 +992,7 @@ static int check_trust(X509_STORE_CTX *ctx, int num_untrusted) res = lookup_cert_match(&mx, ctx, x); if (res < 0) return res; - if (mx == NULL) + if (res == 0) return X509_TRUST_UNTRUSTED; /* @@ -915,7 +1044,7 @@ static int check_revocation(X509_STORE_CTX *ctx) last = sk_X509_num(ctx->chain) - 1; } else { /* If checking CRL paths this isn't the EE certificate */ - if (ctx->parent) + if (ctx->parent != NULL) return 1; last = 0; } @@ -1090,12 +1219,13 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, } if (best_crl != NULL) { + if (!X509_CRL_up_ref(best_crl)) + return 0; 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); @@ -1181,10 +1311,16 @@ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, for (i = 0; i < sk_X509_CRL_num(crls); i++) { delta = sk_X509_CRL_value(crls, i); if (check_delta_base(delta, base)) { + if (!X509_CRL_up_ref(delta)) { + *dcrl = NULL; + return; + } + + *dcrl = delta; + if (check_crl_time(ctx, delta, 0)) *pscore |= CRL_SCORE_TIME_DELTA; - X509_CRL_up_ref(delta); - *dcrl = delta; + return; } } @@ -1541,6 +1677,8 @@ static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) issuer = sk_X509_value(ctx->chain, cnum + 1); } else { issuer = sk_X509_value(ctx->chain, chnum); + if (!ossl_assert(issuer != NULL)) + return 0; /* 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)) @@ -1626,6 +1764,7 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) return 1; } +/* Sadly, returns 0 also on internal error in ctx->verify_cb(). */ static int check_policy(X509_STORE_CTX *ctx) { int ret; @@ -1643,15 +1782,19 @@ static int check_policy(X509_STORE_CTX *ctx) * 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)) + if (ctx->bare_ta_signed && !sk_X509_push(ctx->chain, NULL)) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); 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) + if (ret == X509_PCY_TREE_INTERNAL) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); goto memerr; + } /* Invalid or inconsistent extensions */ if (ret == X509_PCY_TREE_INVALID) { int i, cbcalled = 0; @@ -1698,7 +1841,6 @@ static int check_policy(X509_STORE_CTX *ctx) return 1; memerr: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); ctx->error = X509_V_ERR_OUT_OF_MEM; return -1; } @@ -1709,6 +1851,7 @@ static int check_policy(X509_STORE_CTX *ctx) * the validation status. * * Return 1 on success, 0 otherwise. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). */ int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) { @@ -1738,13 +1881,23 @@ int ossl_x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int depth) /* * Verify the issuer signatures and cert times of ctx->chain. - * Sadly, returns 0 also on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). */ 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; + int n; + X509 *xi; + X509 *xs; + + /* For RPK: just do the verify callback */ + if (ctx->rpk != NULL) { + if (!ctx->verify_cb(ctx->error == X509_V_OK, ctx)) + return 0; + return 1; + } + n = sk_X509_num(ctx->chain) - 1; + xi = sk_X509_value(ctx->chain, n); + xs = xi; ctx->error_depth = n; if (ctx->bare_ta_signed) { @@ -1853,6 +2006,7 @@ int X509_cmp_current_time(const ASN1_TIME *ctm) return X509_cmp_time(ctm, NULL); } +/* returns 0 on error, otherwise 1 if ctm > cmp_time, else -1 */ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { static const size_t utctime_length = sizeof("YYMMDDHHMMSSZ") - 1; @@ -2022,8 +2176,8 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, { 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); @@ -2062,20 +2216,30 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, } /* 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; + if (crl == NULL || !X509_CRL_set_version(crl, X509_CRL_VERSION_2)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } /* Set issuer name */ - if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) - goto memerr; + if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer))) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } - 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; + if (!X509_CRL_set1_lastUpdate(crl, X509_CRL_get0_lastUpdate(newer))) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } + if (!X509_CRL_set1_nextUpdate(crl, X509_CRL_get0_nextUpdate(newer))) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } /* Set base CRL number: must be critical */ - if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0)) - goto memerr; + if (X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0) <= 0) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } /* * Copy extensions across from newest CRL to delta: this will set CRL @@ -2084,8 +2248,10 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, 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; + if (!X509_CRL_add_ext(crl, ext, -1)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } } /* Go through revoked entries, copying as needed */ @@ -2102,22 +2268,26 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, */ if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) { rvtmp = X509_REVOKED_dup(rvn); - if (rvtmp == NULL) - goto memerr; + if (rvtmp == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); + goto err; + } if (!X509_CRL_add0_revoked(crl, rvtmp)) { X509_REVOKED_free(rvtmp); - goto memerr; + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; } } } - if (skey != NULL && md != NULL && !X509_CRL_sign(crl, skey, md)) - goto memerr; + if (skey != NULL && md != NULL && !X509_CRL_sign(crl, skey, md)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); + goto err; + } return crl; - memerr: - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + err: X509_CRL_free(crl); return NULL; } @@ -2194,6 +2364,11 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) ctx->cert = x; } +void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *rpk) +{ + ctx->rpk = rpk; +} + void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) { ctx->crls = sk; @@ -2283,17 +2458,14 @@ 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); + if (ctx == NULL) 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; } } @@ -2318,6 +2490,15 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx) OPENSSL_free(ctx); } + +int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *store, EVP_PKEY *rpk) +{ + if (!X509_STORE_CTX_init(ctx, store, NULL, NULL)) + return 0; + ctx->rpk = rpk; + return 1; +} + int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { @@ -2347,6 +2528,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->parent = NULL; ctx->dane = NULL; ctx->bare_ta_signed = 0; + ctx->rpk = NULL; /* Zero ex_data to make sure we're cleanup-safe */ memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); @@ -2413,7 +2595,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->param = X509_VERIFY_PARAM_new(); if (ctx->param == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; } @@ -2441,7 +2623,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, 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_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); err: /* @@ -2459,7 +2641,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, 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->get_issuer = get1_best_issuer_other_sk; ctx->lookup_certs = lookup_certs_sk; } @@ -2483,7 +2665,7 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) } X509_policy_tree_free(ctx->tree); ctx->tree = NULL; - sk_X509_pop_free(ctx->chain, X509_free); + OSSL_STACK_OF_X509_free(ctx->chain); 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)); @@ -2505,11 +2687,22 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, X509_VERIFY_PARAM_set_time(ctx->param, t); } +void X509_STORE_CTX_set_current_reasons(X509_STORE_CTX *ctx, + unsigned int current_reasons) +{ + ctx->current_reasons = current_reasons; +} + X509 *X509_STORE_CTX_get0_cert(const X509_STORE_CTX *ctx) { return ctx->cert; } +EVP_PKEY *X509_STORE_CTX_get0_rpk(const X509_STORE_CTX *ctx) +{ + return ctx->rpk; +} + STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) { return ctx->untrusted; @@ -2522,7 +2715,7 @@ void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) { - sk_X509_pop_free(ctx->chain, X509_free); + OSSL_STACK_OF_X509_free(ctx->chain); ctx->chain = sk; } @@ -2571,6 +2764,12 @@ X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(const X509_STORE_CTX *ctx) return ctx->get_crl; } +void X509_STORE_CTX_set_get_crl(X509_STORE_CTX *ctx, + X509_STORE_CTX_get_crl_fn get_crl) +{ + ctx->get_crl = get_crl; +} + X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(const X509_STORE_CTX *ctx) { @@ -2671,7 +2870,7 @@ static unsigned char *dane_i2d(X509 *cert, uint8_t selector, } if (len < 0 || buf == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return NULL; } @@ -2682,7 +2881,7 @@ static unsigned char *dane_i2d(X509 *cert, uint8_t selector, #define DANETLS_NONE 256 /* impossible uint8_t */ /* Returns -1 on internal error */ -static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth) +static int dane_match_cert(X509_STORE_CTX *ctx, X509 *cert, int depth) { SSL_DANE *dane = ctx->dane; unsigned usage = DANETLS_NONE; @@ -2809,11 +3008,15 @@ static int dane_match(X509_STORE_CTX *ctx, X509 *cert, int depth) if (DANETLS_USAGE_BIT(usage) & DANETLS_DANE_MASK) matched = 1; if (matched || dane->mdpth < 0) { - dane->mdpth = depth; - dane->mtlsa = t; + if (!X509_up_ref(cert)) { + matched = -1; + break; + } + OPENSSL_free(dane->mcert); dane->mcert = cert; - X509_up_ref(cert); + dane->mdpth = depth; + dane->mtlsa = t; } break; } @@ -2840,7 +3043,7 @@ static int check_dane_issuer(X509_STORE_CTX *ctx, int depth) * 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) + if (cert != NULL && (matched = dane_match_cert(ctx, cert, depth)) < 0) return matched; if (matched > 0) { ctx->num_untrusted = depth - 1; @@ -2887,6 +3090,62 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx) return X509_TRUST_UNTRUSTED; } +/* + * Only DANE-EE and SPKI are supported + * Returns -1 on internal error + */ +static int dane_match_rpk(X509_STORE_CTX *ctx, EVP_PKEY *rpk) +{ + SSL_DANE *dane = ctx->dane; + danetls_record *t = NULL; + int mtype = DANETLS_MATCHING_FULL; + unsigned char *i2dbuf = NULL; + unsigned int i2dlen = 0; + unsigned char mdbuf[EVP_MAX_MD_SIZE]; + unsigned char *cmpbuf; + unsigned int cmplen = 0; + int len; + int recnum = sk_danetls_record_num(dane->trecs); + int i; + int matched = 0; + + /* Calculate ASN.1 DER of RPK */ + if ((len = i2d_PUBKEY(rpk, &i2dbuf)) <= 0) + return -1; + cmplen = i2dlen = (unsigned int)len; + cmpbuf = i2dbuf; + + for (i = 0; i < recnum; i++) { + t = sk_danetls_record_value(dane->trecs, i); + if (t->usage != DANETLS_USAGE_DANE_EE || t->selector != DANETLS_SELECTOR_SPKI) + continue; + + /* Calculate hash - keep only one around */ + 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; + } + } + } + if (cmplen == t->dlen && memcmp(cmpbuf, t->data, cmplen) == 0) { + matched = 1; + dane->mdpth = 0; + dane->mtlsa = t; + break; + } + } + OPENSSL_free(i2dbuf); + return matched; +} + static void dane_reset(SSL_DANE *dane) { /* Reset state to verify another chain, or clear after failure. */ @@ -2897,6 +3156,7 @@ static void dane_reset(SSL_DANE *dane) dane->pdpth = -1; } +/* Sadly, returns 0 also on internal error in ctx->verify_cb(). */ static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert) { int err = X509_chain_check_suiteb(NULL, cert, NULL, ctx->param->flags); @@ -2905,6 +3165,36 @@ static int check_leaf_suiteb(X509_STORE_CTX *ctx, X509 *cert) return 1; } +/* Returns -1 on internal error */ +static int dane_verify_rpk(X509_STORE_CTX *ctx) +{ + SSL_DANE *dane = ctx->dane; + int matched; + + dane_reset(dane); + + /* + * Look for a DANE record for RPK + * If error, return -1 + * If found, call ctx->verify_cb(1, ctx) + * If not found call ctx->verify_cb(0, ctx) + */ + matched = dane_match_rpk(ctx, ctx->rpk); + ctx->error_depth = 0; + + if (matched < 0) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return -1; + } + + if (matched > 0) + ctx->error = X509_V_OK; + else + ctx->error = X509_V_ERR_DANE_NO_MATCH; + + return verify_rpk(ctx); +} + /* Returns -1 on internal error */ static int dane_verify(X509_STORE_CTX *ctx) { @@ -2927,7 +3217,7 @@ static int dane_verify(X509_STORE_CTX *ctx) * + 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); + matched = dane_match_cert(ctx, ctx->cert, 0); done = matched != 0 || (!DANETLS_HAS_TA(dane) && dane->mdpth < 0); if (done && !X509_get_pubkey_parameters(NULL, ctx->chain)) @@ -2984,7 +3274,10 @@ static int get1_trusted_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *cert) return ok; } -/* Returns -1 on internal error */ +/*- + * Returns -1 on internal error. + * Sadly, returns 0 also on internal error in ctx->verify_cb(). + */ static int build_chain(X509_STORE_CTX *ctx) { SSL_DANE *dane = ctx->dane; @@ -3024,24 +3317,30 @@ static int build_chain(X509_STORE_CTX *ctx) } /* Initialize empty untrusted stack. */ - if ((sk_untrusted = sk_X509_new_null()) == NULL) + if ((sk_untrusted = sk_X509_new_null()) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); 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)) + && !X509_add_certs(sk_untrusted, dane->certs, X509_ADD_FLAG_DEFAULT)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); 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)) + if (!X509_add_certs(sk_untrusted, ctx->untrusted, X509_ADD_FLAG_DEFAULT)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); goto memerr; + } /* * Still absurdly large, but arithmetically safe, a lower hard upper bound @@ -3149,20 +3448,18 @@ static int build_chain(X509_STORE_CTX *ctx) dane->pdpth = -1; } - /* - * Self-signed untrusted certificates get replaced by their - * trusted matching issuer. Otherwise, grow the chain. - */ - if (!self_signed) { + if (!self_signed) { /* untrusted not self-signed certificate */ + /* Grow the chain by trusted issuer */ if (!sk_X509_push(ctx->chain, issuer)) { X509_free(issuer); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); 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 + * We have a self-signed untrusted cert 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. @@ -3172,6 +3469,10 @@ static int build_chain(X509_STORE_CTX *ctx) X509_free(issuer); ok = 0; } else { /* curr "==" issuer */ + /* + * Replace self-signed untrusted certificate + * by its trusted matching issuer. + */ X509_free(curr); ctx->num_untrusted = --num; (void)sk_X509_set(ctx->chain, num, issuer); @@ -3224,7 +3525,7 @@ static int build_chain(X509_STORE_CTX *ctx) } /* - * Extend chain with peer-provided untrusted certificates + * Try to extend chain with peer-provided untrusted certificate */ if ((search & S_DOUNTRUSTED) != 0) { num = sk_X509_num(ctx->chain); @@ -3232,7 +3533,7 @@ static int build_chain(X509_STORE_CTX *ctx) 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); + NULL : get0_best_issuer_sk(ctx, 0, 1 /* no_dup */, sk_untrusted, curr); if (issuer == NULL) { /* * Once we have reached a self-signed cert or num > max_depth @@ -3248,6 +3549,7 @@ static int build_chain(X509_STORE_CTX *ctx) /* Drop this issuer from future consideration */ (void)sk_X509_delete_ptr(sk_untrusted, issuer); + /* Grow the chain by untrusted issuer */ if (!X509_add_cert(ctx->chain, issuer, X509_ADD_FLAG_UP_REF)) goto int_err; @@ -3284,12 +3586,12 @@ static int build_chain(X509_STORE_CTX *ctx) return 0; case X509_TRUST_UNTRUSTED: default: - switch(ctx->error) { + 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() */ + return 0; /* Callback already done 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: @@ -3318,7 +3620,6 @@ static int build_chain(X509_STORE_CTX *ctx) 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; @@ -3374,12 +3675,11 @@ 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`. + * Check whether the given public key meets the security level of `ctx`. * Returns 1 on success, 0 otherwise. */ -static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) +static int check_key_level(X509_STORE_CTX *ctx, EVP_PKEY *pkey) { - EVP_PKEY *pkey = X509_get0_pubkey(cert); int level = ctx->param->auth_level; /* @@ -3401,6 +3701,15 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) return EVP_PKEY_get_security_bits(pkey) >= minbits_table[level - 1]; } +/*- + * Check whether the public key of `cert` meets the security level of `ctx`. + * Returns 1 on success, 0 otherwise. + */ +static int check_cert_key_level(X509_STORE_CTX *ctx, X509 *cert) +{ + return check_key_level(ctx, X509_get0_pubkey(cert)); +} + /*- * Check whether the public key of ``cert`` does not use explicit params * for an elliptic curve. @@ -3410,21 +3719,19 @@ static int check_key_level(X509_STORE_CTX *ctx, X509 *cert) static int check_curve(X509 *cert) { EVP_PKEY *pkey = X509_get0_pubkey(cert); + int ret, val; /* Unsupported or malformed key */ if (pkey == NULL) return -1; + if (EVP_PKEY_get_id(pkey) != EVP_PKEY_EC) + 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 == 1 ? !val : -1; - } - - return 1; + ret = + EVP_PKEY_get_int_param(pkey, + OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, + &val); + return ret == 1 ? !val : -1; } /*- diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index 998ce8ac1ba1..6f1cfd9320ee 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -1,5 +1,5 @@ /* - * Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -84,10 +84,8 @@ X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) X509_VERIFY_PARAM *param; param = OPENSSL_zalloc(sizeof(*param)); - if (param == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (param == NULL) return NULL; - } param->trust = X509_TRUST_DEFAULT; /* param->inh_flags = X509_VP_FLAG_DEFAULT; */ param->depth = -1; @@ -298,11 +296,17 @@ int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags) return 1; } +/* resets to default (any) purpose if |purpose| == X509_PURPOSE_DEFAULT_ANY */ int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) { return X509_PURPOSE_set(¶m->purpose, purpose); } +int X509_VERIFY_PARAM_get_purpose(const X509_VERIFY_PARAM *param) +{ + return param->purpose; +} + int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) { return X509_TRUST_set(¶m->trust, trust); @@ -506,6 +510,18 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) */ static const X509_VERIFY_PARAM default_table[] = { + { + "code_sign", /* Code sign parameters */ + 0, /* check time to use */ + 0, /* inheritance flags */ + 0, /* flags */ + X509_PURPOSE_CODE_SIGN, /* purpose */ + X509_TRUST_OBJECT_SIGN, /* trust */ + -1, /* depth */ + -1, /* auth_level */ + NULL, /* policies */ + vpm_empty_id + }, { "default", /* X509 default parameters */ 0, /* check time to use */ @@ -516,7 +532,8 @@ static const X509_VERIFY_PARAM default_table[] = { 100, /* depth */ -1, /* auth_level */ NULL, /* policies */ - vpm_empty_id}, + vpm_empty_id + }, { "pkcs7", /* S/MIME sign parameters */ 0, /* check time to use */ @@ -527,7 +544,8 @@ static const X509_VERIFY_PARAM default_table[] = { -1, /* depth */ -1, /* auth_level */ NULL, /* policies */ - vpm_empty_id}, + vpm_empty_id + }, { "smime_sign", /* S/MIME sign parameters */ 0, /* check time to use */ @@ -538,7 +556,8 @@ static const X509_VERIFY_PARAM default_table[] = { -1, /* depth */ -1, /* auth_level */ NULL, /* policies */ - vpm_empty_id}, + vpm_empty_id + }, { "ssl_client", /* SSL/TLS client parameters */ 0, /* check time to use */ @@ -549,7 +568,8 @@ static const X509_VERIFY_PARAM default_table[] = { -1, /* depth */ -1, /* auth_level */ NULL, /* policies */ - vpm_empty_id}, + vpm_empty_id + }, { "ssl_server", /* SSL/TLS server parameters */ 0, /* check time to use */ @@ -560,7 +580,8 @@ static const X509_VERIFY_PARAM default_table[] = { -1, /* depth */ -1, /* auth_level */ NULL, /* policies */ - vpm_empty_id} + vpm_empty_id + } }; static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; @@ -626,6 +647,8 @@ const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) pm.name = (char *)name; if (param_table != NULL) { + /* Ideally, this would be done under a lock */ + sk_X509_VERIFY_PARAM_sort(param_table); idx = sk_X509_VERIFY_PARAM_find(param_table, &pm); if (idx >= 0) return sk_X509_VERIFY_PARAM_value(param_table, idx); diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c index 2746b9892506..e5dd4d5c3a3d 100644 --- a/crypto/x509/x509cset.c +++ b/crypto/x509/x509cset.c @@ -1,5 +1,5 @@ /* - * 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 @@ -24,34 +24,41 @@ int X509_CRL_set_version(X509_CRL *x, long version) if ((x->crl.version = ASN1_INTEGER_new()) == NULL) return 0; } - return ASN1_INTEGER_set(x->crl.version, version); + if (!ASN1_INTEGER_set(x->crl.version, version)) + return 0; + x->crl.enc.modified = 1; + return 1; } int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name) { if (x == NULL) return 0; - return X509_NAME_set(&x->crl.issuer, name); + if (!X509_NAME_set(&x->crl.issuer, name)) + return 0; + x->crl.enc.modified = 1; + return 1; } int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) { - if (x == NULL) + if (x == NULL || tm == NULL) return 0; - return ossl_x509_set1_time(&x->crl.lastUpdate, tm); + return ossl_x509_set1_time(&x->crl.enc.modified, &x->crl.lastUpdate, tm); } int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) { if (x == NULL) return 0; - return ossl_x509_set1_time(&x->crl.nextUpdate, tm); + return ossl_x509_set1_time(&x->crl.enc.modified, &x->crl.nextUpdate, tm); } int X509_CRL_sort(X509_CRL *c) { int i; X509_REVOKED *r; + /* * sort the data so it will be written in serial number order */ @@ -68,12 +75,12 @@ int X509_CRL_up_ref(X509_CRL *crl) { int i; - if (CRYPTO_UP_REF(&crl->references, &i, crl->lock) <= 0) + if (CRYPTO_UP_REF(&crl->references, &i) <= 0) return 0; - REF_PRINT_COUNT("X509_CRL", crl); + REF_PRINT_COUNT("X509_CRL", i, crl); REF_ASSERT_ISNT(i < 2); - return ((i > 1) ? 1 : 0); + return i > 1; } long X509_CRL_get_version(const X509_CRL *crl) @@ -139,19 +146,9 @@ const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x) int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) { - ASN1_TIME *in; - - if (x == NULL) + if (x == NULL || tm == NULL) return 0; - in = x->revocationDate; - if (in != tm) { - in = ASN1_STRING_dup(tm); - if (in != NULL) { - ASN1_TIME_free(x->revocationDate); - x->revocationDate = in; - } - } - return (in != NULL); + return ossl_x509_set1_time(NULL, &x->revocationDate, tm); } const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x) @@ -171,7 +168,8 @@ int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) return 1; } -const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r) +const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const + X509_REVOKED *r) { return r->extensions; } diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c index 9ae0dc5de48f..75ff07d899da 100644 --- a/crypto/x509/x509name.c +++ b/crypto/x509/x509name.c @@ -225,7 +225,7 @@ int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, goto err; new_name->set = set; if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } if (inc) { diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c index 344993d4c78c..1dd61f1f86a6 100644 --- a/crypto/x509/x509rset.c +++ b/crypto/x509/x509rset.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -17,8 +17,10 @@ int X509_REQ_set_version(X509_REQ *x, long version) { - if (x == NULL) + if (x == NULL || version != X509_REQ_VERSION_1) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); return 0; + } x->req_info.enc.modified = 1; return ASN1_INTEGER_set(x->req_info.version, version); } diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index 1d66697db00d..142eeb79bd5d 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -35,10 +35,8 @@ NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len) NETSCAPE_SPKI *spki; if (len <= 0) len = strlen(str); - if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if ((spki_der = OPENSSL_malloc(len + 1)) == NULL) return NULL; - } spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len); if (spki_len < 0) { ERR_raise(ERR_LIB_X509, X509_R_BASE64_DECODE_ERROR); @@ -65,7 +63,6 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) der_spki = OPENSSL_malloc(der_len); b64_str = OPENSSL_malloc(der_len * 2); if (der_spki == NULL || b64_str == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); OPENSSL_free(der_spki); OPENSSL_free(b64_str); return NULL; diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 158e11a8649c..845b53837edc 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "internal/asn1.h" #include "crypto/pkcs7.h" #include "crypto/x509.h" +#include "crypto/x509_acert.h" #include "crypto/rsa.h" int X509_verify(X509 *a, EVP_PKEY *r) @@ -41,6 +43,11 @@ int X509_verify(X509 *a, EVP_PKEY *r) int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OSSL_LIB_CTX *libctx, const char *propq) { + if (X509_REQ_get_version(a) != X509_REQ_VERSION_1) { + ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_VERSION); + return -1; + } + return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &a->sig_alg, a->signature, &a->req_info, a->distinguishing_id, r, libctx, propq); @@ -51,6 +58,16 @@ int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) return X509_REQ_verify_ex(a, r, NULL, NULL); } +int X509_ACERT_verify(X509_ACERT *a, EVP_PKEY *r) +{ + if (X509_ALGOR_cmp(&a->sig_alg, &a->acinfo->signature) != 0) + return 0; + + return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_ACERT_INFO), &a->sig_alg, + &a->signature, a->acinfo, + NULL, r, NULL, NULL); +} + int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) { return ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), @@ -63,6 +80,9 @@ int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; } + if (sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0 + && !X509_set_version(x, X509_VERSION_3)) + return 0; /* * Setting the modified flag before signing it. This makes the cached @@ -83,6 +103,9 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; } + if (sk_X509_EXTENSION_num(X509_get0_extensions(x)) > 0 + && !X509_set_version(x, X509_VERSION_3)) + return 0; x->cert_info.enc.modified = 1; return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature, @@ -92,6 +115,7 @@ int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio, int timeout, const ASN1_ITEM *it) { +#ifndef OPENSSL_NO_HTTP size_t max_resp_len = (it == ASN1_ITEM_rptr(X509_CRL)) ? OSSL_HTTP_DEFAULT_MAX_CRL_LEN : OSSL_HTTP_DEFAULT_MAX_RESP_LEN; BIO *mem = OSSL_HTTP_get(url, NULL /* proxy */, NULL /* no_proxy */, @@ -103,6 +127,9 @@ static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio, BIO_free(mem); return res; +#else + return 0; +#endif } X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) @@ -165,6 +192,21 @@ X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) ASN1_ITEM_rptr(X509_CRL)); } +int X509_ACERT_sign(X509_ACERT *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_ACERT_INFO), &x->sig_alg, + &x->acinfo->signature, + &x->signature, x->acinfo, NULL, + pkey, md, NULL, NULL); +} + +int X509_ACERT_sign_ctx(X509_ACERT *x, EVP_MD_CTX *ctx) +{ + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_ACERT_INFO), + &x->sig_alg, &x->acinfo->signature, &x->signature, + x->acinfo, ctx); +} + int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { return @@ -284,7 +326,8 @@ X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) propq = (*req)->propq; } - return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(X509_REQ), bp, req, libctx, propq); + return + ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(X509_REQ), bp, req, libctx, propq); } int i2d_X509_REQ_bio(BIO *bp, const X509_REQ *req) @@ -577,15 +620,17 @@ int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, memcpy(md, data->sha1_hash, sizeof(data->sha1_hash)); return 1; } - return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_CRL), type, (char *)data, - md, len, data->libctx, data->propq); + return + ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_CRL), type, (char *)data, + md, len, data->libctx, data->propq); } int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { - return ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_REQ), type, (char *)data, - md, len, data->libctx, data->propq); + return + ossl_asn1_item_digest_ex(ASN1_ITEM_rptr(X509_REQ), type, (char *)data, + md, len, data->libctx, data->propq); } int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, @@ -707,6 +752,22 @@ int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey) return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey); } +EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, + const char *propq) +{ + BIO *b; + void *ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB); + return NULL; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = d2i_PUBKEY_ex_bio(b, a, libctx, propq); + BIO_free(b); + return ret; +} + EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a) { return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a); @@ -774,7 +835,48 @@ int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey) return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey); } +EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, + const char *propq) +{ + BUF_MEM *b = NULL; + const unsigned char *p; + void *ret = NULL; + int len; + + len = asn1_d2i_read_bio(bp, &b); + if (len < 0) + goto err; + + p = (unsigned char *)b->data; + ret = d2i_PUBKEY_ex(a, &p, len, libctx, propq); + err: + BUF_MEM_free(b); + return ret; +} + EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a) { return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a); } + +#ifndef OPENSSL_NO_STDIO +X509_ACERT *d2i_X509_ACERT_fp(FILE *fp, X509_ACERT **acert) +{ + return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_ACERT), fp, acert); +} + +int i2d_X509_ACERT_fp(FILE *fp, const X509_ACERT *acert) +{ + return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_ACERT), fp, acert); +} +#endif + +X509_ACERT *d2i_X509_ACERT_bio(BIO *bp, X509_ACERT **acert) +{ + return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_ACERT), bp, acert); +} + +int i2d_X509_ACERT_bio(BIO *bp, const X509_ACERT *acert) +{ + return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_ACERT), bp, acert); +} diff --git a/crypto/x509/x_attrib.c b/crypto/x509/x_attrib.c index 5c7e622d1a0b..0bae13dd7377 100644 --- a/crypto/x509/x_attrib.c +++ b/crypto/x509/x_attrib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,6 +13,7 @@ #include #include #include "x509_local.h" +#include /*- * X509_ATTRIBUTE: this has the following form: @@ -56,3 +57,183 @@ X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value) ASN1_TYPE_free(val); return NULL; } + +static int print_oid(BIO *out, const ASN1_OBJECT *oid) { + const char *ln; + char objbuf[80]; + int rc; + + if (OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1) <= 0) + return 0; + ln = OBJ_nid2ln(OBJ_obj2nid(oid)); + rc = (ln != NULL) + ? BIO_printf(out, "%s (%s)", objbuf, ln) + : BIO_printf(out, "%s", objbuf); + return (rc >= 0); +} + +int ossl_print_attribute_value(BIO *out, + int obj_nid, + const ASN1_TYPE *av, + int indent) +{ + ASN1_STRING *str; + unsigned char *value; + X509_NAME *xn = NULL; + int64_t int_val; + int ret = 1; + + switch (av->type) { + case V_ASN1_BOOLEAN: + if (av->value.boolean) { + return BIO_printf(out, "%*sTRUE", indent, "") >= 4; + } else { + return BIO_printf(out, "%*sFALSE", indent, "") >= 5; + } + + case V_ASN1_INTEGER: + case V_ASN1_ENUMERATED: + if (BIO_printf(out, "%*s", indent, "") < 0) + return 0; + if (ASN1_ENUMERATED_get_int64(&int_val, av->value.integer) > 0) { + return BIO_printf(out, "%lld", (long long int)int_val) > 0; + } + str = av->value.integer; + return ossl_bio_print_hex(out, str->data, str->length); + + case V_ASN1_BIT_STRING: + if (BIO_printf(out, "%*s", indent, "") < 0) + return 0; + return ossl_bio_print_hex(out, av->value.bit_string->data, + av->value.bit_string->length); + + case V_ASN1_OCTET_STRING: + case V_ASN1_VIDEOTEXSTRING: + if (BIO_printf(out, "%*s", indent, "") < 0) + return 0; + return ossl_bio_print_hex(out, av->value.octet_string->data, + av->value.octet_string->length); + + case V_ASN1_NULL: + return BIO_printf(out, "%*sNULL", indent, "") >= 4; + + case V_ASN1_OBJECT: + if (BIO_printf(out, "%*s", indent, "") < 0) + return 0; + return print_oid(out, av->value.object); + + /* + * ObjectDescriptor is an IMPLICIT GraphicString, but GeneralString is a + * superset supported by OpenSSL, so we will use that anywhere a + * GraphicString is needed here. + */ + case V_ASN1_GENERALSTRING: + case V_ASN1_GRAPHICSTRING: + case V_ASN1_OBJECT_DESCRIPTOR: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.generalstring->length, + av->value.generalstring->data) >= 0; + + /* EXTERNAL would go here. */ + /* EMBEDDED PDV would go here. */ + + case V_ASN1_UTF8STRING: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.utf8string->length, + av->value.utf8string->data) >= 0; + + case V_ASN1_REAL: + return BIO_printf(out, "%*sREAL", indent, "") >= 4; + + /* RELATIVE-OID would go here. */ + /* TIME would go here. */ + + case V_ASN1_SEQUENCE: + switch (obj_nid) { + case NID_undef: /* Unrecognized OID. */ + break; + /* Attribute types with DN syntax. */ + case NID_member: + case NID_roleOccupant: + case NID_seeAlso: + case NID_manager: + case NID_documentAuthor: + case NID_secretary: + case NID_associatedName: + case NID_dITRedirect: + case NID_owner: + /* + * d2i_ functions increment the ppin pointer. See doc/man3/d2i_X509.pod. + * This preserves the original pointer. We don't want to corrupt this + * value. + */ + value = av->value.sequence->data; + xn = d2i_X509_NAME(NULL, + (const unsigned char **)&value, + av->value.sequence->length); + if (xn == NULL) { + BIO_puts(out, "(COULD NOT DECODE DISTINGUISHED NAME)\n"); + return 0; + } + if (X509_NAME_print_ex(out, xn, indent, XN_FLAG_SEP_CPLUS_SPC) <= 0) + ret = 0; + X509_NAME_free(xn); + return ret; + + default: + break; + } + return ASN1_parse_dump(out, av->value.sequence->data, + av->value.sequence->length, indent, 1) > 0; + + case V_ASN1_SET: + return ASN1_parse_dump(out, av->value.set->data, + av->value.set->length, indent, 1) > 0; + + /* + * UTCTime ::= [UNIVERSAL 23] IMPLICIT VisibleString + * GeneralizedTime ::= [UNIVERSAL 24] IMPLICIT VisibleString + * VisibleString is a superset for NumericString, so it will work for that. + */ + case V_ASN1_VISIBLESTRING: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_NUMERICSTRING: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.visiblestring->length, + av->value.visiblestring->data) >= 0; + + case V_ASN1_PRINTABLESTRING: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.printablestring->length, + av->value.printablestring->data) >= 0; + + case V_ASN1_T61STRING: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.t61string->length, + av->value.t61string->data) >= 0; + + case V_ASN1_IA5STRING: + return BIO_printf(out, "%*s%.*s", indent, "", + av->value.ia5string->length, + av->value.ia5string->data) >= 0; + + /* UniversalString would go here. */ + /* CHARACTER STRING would go here. */ + /* BMPString would go here. */ + /* DATE would go here. */ + /* TIME-OF-DAY would go here. */ + /* DATE-TIME would go here. */ + /* DURATION would go here. */ + /* OID-IRI would go here. */ + /* RELATIVE-OID-IRI would go here. */ + + /* Would it be appropriate to just hexdump? */ + default: + return BIO_printf(out, + "%*s", + indent, + "", + av->type) >= 0; + } +} diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c index fd98ad6926cf..2601a019f87e 100644 --- a/crypto/x509/x_crl.c +++ b/crypto/x509/x_crl.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -20,9 +20,9 @@ static int X509_REVOKED_cmp(const X509_REVOKED *const *a, static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); ASN1_SEQUENCE(X509_REVOKED) = { - ASN1_EMBED(X509_REVOKED,serialNumber, ASN1_INTEGER), - ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME), - ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION) + ASN1_EMBED(X509_REVOKED, serialNumber, ASN1_INTEGER), + ASN1_SIMPLE(X509_REVOKED, revocationDate, ASN1_TIME), + ASN1_SEQUENCE_OF_OPT(X509_REVOKED, extensions, X509_EXTENSION) } ASN1_SEQUENCE_END(X509_REVOKED) static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r); @@ -94,15 +94,15 @@ static int crl_set_issuers(X509_CRL *crl) STACK_OF(X509_EXTENSION) *exts; ASN1_ENUMERATED *reason; X509_EXTENSION *ext; + gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer, &j, NULL); - if (!gtmp && (j != -1)) { + if (gtmp == NULL && j != -1) { crl->flags |= EXFLAG_INVALID; return 1; } - if (gtmp) { - gens = gtmp; + if (gtmp != NULL) { if (crl->issuers == NULL) { crl->issuers = sk_GENERAL_NAMES_new_null(); if (crl->issuers == NULL) { @@ -114,16 +114,17 @@ static int crl_set_issuers(X509_CRL *crl) GENERAL_NAMES_free(gtmp); return 0; } + gens = gtmp; } rev->issuer = gens; reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); - if (!reason && (j != -1)) { + if (reason == NULL && j != -1) { crl->flags |= EXFLAG_INVALID; return 1; } - if (reason) { + if (reason != NULL) { rev->reason = ASN1_ENUMERATED_get(reason); ASN1_ENUMERATED_free(reason); } else @@ -136,7 +137,8 @@ static int crl_set_issuers(X509_CRL *crl) for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) { ext = sk_X509_EXTENSION_value(exts, j); if (X509_EXTENSION_get_critical(ext)) { - if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) == NID_certificate_issuer) + if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) + == NID_certificate_issuer) continue; crl->flags |= EXFLAG_CRITICAL; break; @@ -172,7 +174,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ASN1_INTEGER_free(crl->crl_number); ASN1_INTEGER_free(crl->base_crl_number); sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); - /* fall thru */ + /* fall through */ case ASN1_OP_NEW_POST: crl->idp = NULL; @@ -364,7 +366,7 @@ int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) if (inf->revoked == NULL) inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp); if (inf->revoked == NULL || !sk_X509_REVOKED_push(inf->revoked, rev)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); return 0; } inf->enc.modified = 1; @@ -488,10 +490,8 @@ X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl), { X509_CRL_METHOD *m = OPENSSL_malloc(sizeof(*m)); - if (m == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (m == NULL) return NULL; - } m->crl_init = crl_init; m->crl_free = crl_free; m->crl_lookup = crl_lookup; diff --git a/crypto/x509/x_exten.c b/crypto/x509/x_exten.c index 4e63b50caa62..f4be4dd0d6b8 100644 --- a/crypto/x509/x_exten.c +++ b/crypto/x509/x_exten.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -15,7 +15,7 @@ ASN1_SEQUENCE(X509_EXTENSION) = { ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT), - ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN), + ASN1_OPT(X509_EXTENSION, critical, ASN1_FBOOLEAN), ASN1_EMBED(X509_EXTENSION, value, ASN1_OCTET_STRING) } ASN1_SEQUENCE_END(X509_EXTENSION) diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c index eded80246df9..bcb480f58fd9 100644 --- a/crypto/x509/x_name.c +++ b/crypto/x509/x_name.c @@ -92,17 +92,20 @@ static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it) X509_NAME *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) - goto memerr; - if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) - goto memerr; - if ((ret->bytes = BUF_MEM_new()) == NULL) - goto memerr; + return 0; + if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); + goto err; + } + if ((ret->bytes = BUF_MEM_new()) == NULL) { + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); + goto err; + } ret->modified = 1; *val = (ASN1_VALUE *)ret; return 1; - memerr: - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + err: if (ret) { sk_X509_NAME_ENTRY_free(ret->entries); OPENSSL_free(ret); @@ -246,26 +249,28 @@ static int x509_name_encode(X509_NAME *a) intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null(); if (!intname.s) - goto memerr; + goto cerr; for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { entry = sk_X509_NAME_ENTRY_value(a->entries, i); if (entry->set != set) { entries = sk_X509_NAME_ENTRY_new_null(); if (!entries) - goto memerr; + goto cerr; if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) { sk_X509_NAME_ENTRY_free(entries); - goto memerr; + goto cerr; } set = entry->set; } if (!sk_X509_NAME_ENTRY_push(entries, entry)) - goto memerr; + goto cerr; } len = ASN1_item_ex_i2d(&intname.a, NULL, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); - if (!BUF_MEM_grow(a->bytes, len)) - goto memerr; + if (!BUF_MEM_grow(a->bytes, len)) { + ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB); + goto err; + } p = (unsigned char *)a->bytes->data; ASN1_item_ex_i2d(&intname.a, &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1); @@ -273,10 +278,11 @@ static int x509_name_encode(X509_NAME *a) local_sk_X509_NAME_ENTRY_free); a->modified = 0; return len; - memerr: + cerr: + ERR_raise(ERR_LIB_ASN1, ERR_R_CRYPTO_LIB); + err: sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, local_sk_X509_NAME_ENTRY_free); - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); return -1; } @@ -318,7 +324,7 @@ static int x509_name_canon(X509_NAME *a) } intname = sk_STACK_OF_X509_NAME_ENTRY_new_null(); if (intname == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { @@ -329,25 +335,25 @@ static int x509_name_canon(X509_NAME *a) goto err; if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) { sk_X509_NAME_ENTRY_free(entries); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } set = entry->set; } tmpentry = X509_NAME_ENTRY_new(); if (tmpentry == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto err; } tmpentry->object = OBJ_dup(entry->object); if (tmpentry->object == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_OBJ_LIB); goto err; } if (!asn1_string_canon(tmpentry->value, entry->value)) goto err; if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB); goto err; } tmpentry = NULL; @@ -360,10 +366,8 @@ static int x509_name_canon(X509_NAME *a) a->canon_enclen = len; p = OPENSSL_malloc(a->canon_enclen); - if (p == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (p == NULL) goto err; - } a->canon_enc = p; diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index b290075c8589..53639b2bfaba 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -66,7 +66,8 @@ ASN1_SEQUENCE(X509_PUBKEY_INTERNAL) = { } static_ASN1_SEQUENCE_END_name(X509_PUBKEY, X509_PUBKEY_INTERNAL) X509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp, - long len, OSSL_LIB_CTX *libctx) + long len, OSSL_LIB_CTX *libctx, + const char *propq) { X509_PUBKEY *xpub = OPENSSL_zalloc(sizeof(*xpub)); @@ -74,7 +75,7 @@ X509_PUBKEY *ossl_d2i_X509_PUBKEY_INTERNAL(const unsigned char **pp, return NULL; return (X509_PUBKEY *)ASN1_item_d2i_ex((ASN1_VALUE **)&xpub, pp, len, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL), - libctx, NULL); + libctx, propq); } void ossl_X509_PUBKEY_INTERNAL_free(X509_PUBKEY *xpub) @@ -112,12 +113,13 @@ static int x509_pubkey_ex_new_ex(ASN1_VALUE **pval, const ASN1_ITEM *it, { X509_PUBKEY *ret; - if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL - || !x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL) + if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) + return 0; + if (!x509_pubkey_ex_populate((ASN1_VALUE **)&ret, NULL) || !x509_pubkey_set0_libctx(ret, libctx, propq)) { x509_pubkey_ex_free((ASN1_VALUE **)&ret, NULL); ret = NULL; - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); } else { *pval = (ASN1_VALUE *)ret; } @@ -141,7 +143,7 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval, if (*pval == NULL && !x509_pubkey_ex_new_ex(pval, it, libctx, propq)) return 0; if (!x509_pubkey_ex_populate(pval, NULL)) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_X509_LIB); return 0; } @@ -170,7 +172,7 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval, /* * Try to decode with legacy method first. This ensures that engines - * aren't overriden by providers. + * aren't overridden by providers. */ if ((ret = x509_pubkey_decode(&pubkey->pkey, pubkey)) == -1) { /* -1 indicates a fatal error, like malloc failure */ @@ -190,10 +192,8 @@ static int x509_pubkey_ex_d2i_ex(ASN1_VALUE **pval, */ if (aclass != V_ASN1_UNIVERSAL) { tmpbuf = OPENSSL_memdup(in_saved, publen); - if (tmpbuf == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + if (tmpbuf == NULL) return 0; - } in_saved = tmpbuf; *tmpbuf = V_ASN1_CONSTRUCTED | V_ASN1_SEQUENCE; } @@ -284,16 +284,22 @@ X509_PUBKEY *X509_PUBKEY_dup(const X509_PUBKEY *a) { X509_PUBKEY *pubkey = OPENSSL_zalloc(sizeof(*pubkey)); - if (pubkey == NULL - || !x509_pubkey_set0_libctx(pubkey, a->libctx, a->propq) - || (pubkey->algor = X509_ALGOR_dup(a->algor)) == NULL - || (pubkey->public_key = ASN1_BIT_STRING_new()) == NULL - || !ASN1_BIT_STRING_set(pubkey->public_key, - a->public_key->data, - a->public_key->length)) { + if (pubkey == NULL) + return NULL; + if (!x509_pubkey_set0_libctx(pubkey, a->libctx, a->propq)) { + ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB); x509_pubkey_ex_free((ASN1_VALUE **)&pubkey, ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL)); - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + return NULL; + } + if ((pubkey->algor = X509_ALGOR_dup(a->algor)) == NULL + || (pubkey->public_key = ASN1_BIT_STRING_new()) == NULL + || !ASN1_BIT_STRING_set(pubkey->public_key, + a->public_key->data, + a->public_key->length)) { + x509_pubkey_ex_free((ASN1_VALUE **)&pubkey, + ASN1_ITEM_rptr(X509_PUBKEY_INTERNAL)); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); return NULL; } @@ -325,7 +331,7 @@ int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) if (pkey->ameth != NULL) { if ((pk = X509_PUBKEY_new()) == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_ASN1_LIB); goto error; } if (pkey->ameth->pub_encode != NULL) { @@ -416,7 +422,7 @@ static int x509_pubkey_decode(EVP_PKEY **ppkey, const X509_PUBKEY *key) pkey = EVP_PKEY_new(); if (pkey == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_EVP_LIB); return -1; } @@ -499,10 +505,8 @@ static EVP_PKEY *d2i_PUBKEY_int(EVP_PKEY **a, */ if (libctx != NULL || propq != NULL || force_legacy) { xpk2 = OPENSSL_zalloc(sizeof(*xpk2)); - if (xpk2 == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (xpk2 == NULL) return NULL; - } if (!x509_pubkey_set0_libctx(xpk2, libctx, propq)) goto end; xpk2->flag_force_legacy = !!force_legacy; @@ -628,7 +632,7 @@ int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp) return 0; pktmp = EVP_PKEY_new(); if (pktmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign_RSA(pktmp, (RSA *)a); @@ -670,7 +674,7 @@ int ossl_i2d_DH_PUBKEY(const DH *a, unsigned char **pp) return 0; pktmp = EVP_PKEY_new(); if (pktmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign_DH(pktmp, (DH *)a); @@ -711,7 +715,7 @@ int ossl_i2d_DHx_PUBKEY(const DH *a, unsigned char **pp) return 0; pktmp = EVP_PKEY_new(); if (pktmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign(pktmp, EVP_PKEY_DHX, (DH *)a); @@ -777,7 +781,7 @@ int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp) return 0; pktmp = EVP_PKEY_new(); if (pktmp == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign_DSA(pktmp, (DSA *)a); @@ -822,7 +826,7 @@ int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp) if (a == NULL) return 0; if ((pktmp = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign_EC_KEY(pktmp, (EC_KEY *)a); @@ -832,6 +836,7 @@ int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp) return ret; } +# ifndef OPENSSL_NO_ECX ECX_KEY *ossl_d2i_ED25519_PUBKEY(ECX_KEY **a, const unsigned char **pp, long length) { @@ -863,7 +868,7 @@ int ossl_i2d_ED25519_PUBKEY(const ECX_KEY *a, unsigned char **pp) if (a == NULL) return 0; if ((pktmp = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED25519, (ECX_KEY *)a); @@ -905,7 +910,7 @@ int ossl_i2d_ED448_PUBKEY(const ECX_KEY *a, unsigned char **pp) if (a == NULL) return 0; if ((pktmp = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign(pktmp, EVP_PKEY_ED448, (ECX_KEY *)a); @@ -947,7 +952,7 @@ int ossl_i2d_X25519_PUBKEY(const ECX_KEY *a, unsigned char **pp) if (a == NULL) return 0; if ((pktmp = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X25519, (ECX_KEY *)a); @@ -989,7 +994,7 @@ int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp) if (a == NULL) return 0; if ((pktmp = EVP_PKEY_new()) == NULL) { - ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB); return -1; } (void)EVP_PKEY_assign(pktmp, EVP_PKEY_X448, (ECX_KEY *)a); @@ -999,22 +1004,24 @@ int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp) return ret; } +# endif /* OPENSSL_NO_ECX */ #endif +void X509_PUBKEY_set0_public_key(X509_PUBKEY *pub, + unsigned char *penc, int penclen) +{ + ASN1_STRING_set0(pub->public_key, penc, penclen); + ossl_asn1_string_set_bits_left(pub->public_key, 0); +} + int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, int ptype, void *pval, unsigned char *penc, int penclen) { if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval)) return 0; - if (penc) { - OPENSSL_free(pub->public_key->data); - pub->public_key->data = penc; - pub->public_key->length = penclen; - /* Set number of unused bits to zero */ - pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - } + if (penc != NULL) + X509_PUBKEY_set0_public_key(pub, penc, penclen); return 1; } diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c index 293d4be71335..ca712386bd22 100644 --- a/crypto/x509/x_req.c +++ b/crypto/x509/x_req.c @@ -53,7 +53,7 @@ static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, switch (operation) { case ASN1_OP_D2I_PRE: ASN1_OCTET_STRING_free(ret->distinguishing_id); - /* fall thru */ + /* fall through */ case ASN1_OP_NEW_POST: ret->distinguishing_id = NULL; break; @@ -74,7 +74,7 @@ static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, if (pkey != NULL) { pkey = EVP_PKEY_dup(pkey); if (pkey == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_X509, ERR_R_EVP_LIB); return 0; } if (!X509_PUBKEY_set(&ret->req_info.pubkey, pkey)) { diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c index 010578b19a31..75c5c9223acc 100644 --- a/crypto/x509/x_x509.c +++ b/crypto/x509/x_x509.c @@ -55,7 +55,7 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, #endif ASN1_OCTET_STRING_free(ret->distinguishing_id); - /* fall thru */ + /* fall through */ case ASN1_OP_NEW_POST: ret->ex_cached = 0; @@ -272,10 +272,8 @@ int i2d_X509_AUX(const X509 *a, unsigned char **pp) /* Allocate requisite combined storage */ *pp = tmp = OPENSSL_malloc(length); - if (tmp == NULL) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (tmp == NULL) return -1; - } /* Encode, but keep *pp at the originally malloced pointer */ length = i2d_x509_aux_internal(a, &tmp); diff --git a/crypto/x86_64cpuid.pl b/crypto/x86_64cpuid.pl index 53685ec26390..f0eb8510ed2e 100644 --- a/crypto/x86_64cpuid.pl +++ b/crypto/x86_64cpuid.pl @@ -27,14 +27,14 @@ open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"" ("%rdi","%rsi","%rdx","%rcx"); # Unix order print<<___; +#include crypto/cryptlib.h .extern OPENSSL_cpuid_setup .hidden OPENSSL_cpuid_setup .section .init call OPENSSL_cpuid_setup .hidden OPENSSL_ia32cap_P -.comm OPENSSL_ia32cap_P,16,4 - +.comm OPENSSL_ia32cap_P,40,4 # <--Should match with internal/cryptlib.h OPENSSL_IA32CAP_P_MAX_INDEXES .text .globl OPENSSL_atomic_add @@ -192,6 +192,7 @@ OPENSSL_ia32_cpuid: mov \$7,%eax xor %ecx,%ecx cpuid + movd %eax,%xmm1 # put aside leaf 07H Max Sub-leaves bt \$26,%r9d # check XSAVE bit, cleared on Knights jc .Lnotknights and \$0xfff7ffff,%ebx # clear ADCX/ADOX flag @@ -202,9 +203,31 @@ OPENSSL_ia32_cpuid: jne .Lnotskylakex and \$0xfffeffff,%ebx # ~(1<<16) # suppress AVX512F flag on Skylake-X -.Lnotskylakex: - mov %ebx,8(%rdi) # save extended feature flags - mov %ecx,12(%rdi) + +.Lnotskylakex: # save extended feature flags + mov %ebx,8(%rdi) # save cpuid(EAX=0x7, ECX=0x0).EBX to OPENSSL_ia32cap_P[2] + mov %ecx,12(%rdi) # save cpuid(EAX=0x7, ECX=0x0).ECX to OPENSSL_ia32cap_P[3] + mov %edx,16(%rdi) # save cpuid(EAX=0x7, ECX=0x0).EDX to OPENSSL_ia32cap_P[4] + + movd %xmm1,%eax # Restore leaf 07H Max Sub-leaves + cmp \$0x1,%eax # Do we have cpuid(EAX=0x7, ECX=0x1)? + jb .Lno_extended_info + mov \$0x7,%eax + mov \$0x1,%ecx + cpuid # cpuid(EAX=0x7, ECX=0x1) + mov %eax,20(%rdi) # save cpuid(EAX=0x7, ECX=0x1).EAX to OPENSSL_ia32cap_P[5] + mov %edx,24(%rdi) # save cpuid(EAX=0x7, ECX=0x1).EDX to OPENSSL_ia32cap_P[6] + mov %ebx,28(%rdi) # save cpuid(EAX=0x7, ECX=0x1).EBX to OPENSSL_ia32cap_P[7] + mov %ecx,32(%rdi) # save cpuid(EAX=0x7, ECX=0x1).ECX to OPENSSL_ia32cap_P[8] + + and \$0x80000,%edx # Mask cpuid(EAX=0x7, ECX=0x1).EDX bit 19 to detect AVX10 support + cmp \$0x0,%edx + je .Lno_extended_info + mov \$0x24,%eax # Have AVX10 Support, query for details + mov \$0x0,%ecx + cpuid # cpuid(EAX=0x24, ECX=0x0) AVX10 Leaf + mov %ebx,36(%rdi) # save cpuid(EAX=0x24, ECX=0x0).EBX to OPENSSL_ia32cap_P[9] + .Lno_extended_info: bt \$27,%r9d # check OSXSAVE bit @@ -223,6 +246,9 @@ OPENSSL_ia32_cpuid: cmp \$6,%eax je .Ldone .Lclear_avx: + andl \$0xff7fffff,20(%rdi) # ~(1<<23) + # clear AVXIFMA, which is VEX-encoded + # and requires YMM state support mov \$0xefffe7ff,%eax # ~(1<<28|1<<12|1<<11) and %eax,%r9d # clear AVX, FMA and AMD XOP bits mov \$0x3fdeffdf,%eax # ~(1<<31|1<<30|1<<21|1<<16|1<<5) diff --git a/crypto/x86cpuid.pl b/crypto/x86cpuid.pl index a7bcb27e262d..35e2c5b0a540 100644 --- a/crypto/x86cpuid.pl +++ b/crypto/x86cpuid.pl @@ -137,7 +137,28 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } &mov ("eax",7); &xor ("ecx","ecx"); &cpuid (); - &mov (&DWP(8,"edi"),"ebx"); # save extended feature flag + &mov (&DWP(8,"edi"),"ebx"); # save cpuid(EAX=0x7, ECX=0x0).EBX to OPENSSL_ia32cap_P[2] + &mov (&DWP(12,"edi"),"ecx"); # save cpuid(EAX=0x7, ECX=0x0).ECX to OPENSSL_ia32cap_P[3] + &mov (&DWP(16,"edi"),"edx"); # save cpuid(EAX=0x7, ECX=0x0).EDX to OPENSSL_ia32cap_P[4] + &cmp ("eax",1); # Do we have cpuid(EAX=0x7, ECX=0x1)? + &jb (&label("no_extended_info")); + &mov ("eax",7); + &mov ("ecx",1); + &cpuid (); # cpuid(EAX=0x7, ECX=0x1) + &mov (&DWP(20,"edi"),"eax"); # save cpuid(EAX=0x7, ECX=0x1).EAX to OPENSSL_ia32cap_P[5] + &mov (&DWP(24,"edi"),"edx"); # save cpuid(EAX=0x7, ECX=0x1).EDX to OPENSSL_ia32cap_P[6] + &mov (&DWP(28,"edi"),"ebx"); # save cpuid(EAX=0x7, ECX=0x1).EBX to OPENSSL_ia32cap_P[7] + &mov (&DWP(32,"edi"),"ecx"); # save cpuid(EAX=0x7, ECX=0x1).ECX to OPENSSL_ia32cap_P[8] + + &and ("edx",0x80000); # Mask cpuid(EAX=0x7, ECX=0x1).EDX bit 19 to detect AVX10 support + &cmp ("edx",0x0); + &je (&label("no_extended_info")); + + &mov ("eax",0x24); # Have AVX10 Support, query for details + &mov ("ecx",0x0); + &cpuid (); # cpuid(EAX=0x24, ECX=0x0) AVX10 Leaf + &mov (&DWP(36,"edi"),"ebx"); # save cpuid(EAX=0x24, ECX=0x0).EBX to OPENSSL_ia32cap_P[9] + &set_label("no_extended_info"); &bt ("ebp",27); # check OSXSAVE bit @@ -154,6 +175,9 @@ for (@ARGV) { $sse2=1 if (/-DOPENSSL_IA32_SSE2/); } &and ("esi",0xfeffffff); # clear FXSR &set_label("clear_avx"); &and ("ebp",0xefffe7ff); # clear AVX, FMA and AMD XOP bits + &and (&DWP(20,"edi"),0xff7fffff); # ~(1<<23) clear AVXIFMA, + # which is VEX-encoded + # and requires YMM state support &and (&DWP(8,"edi"),0xffffffdf); # clear AVX2 &set_label("done"); &mov ("eax","esi"); diff --git a/demos/README.txt b/demos/README.txt index e10239173faa..1a7d4f447f2c 100644 --- a/demos/README.txt +++ b/demos/README.txt @@ -3,6 +3,10 @@ OpenSSL Demonstration Applications This folder contains source code that demonstrates the proper use of the OpenSSL library API. +Note: Makefiles are provided in the demo subfolders to demonstrate how to build +them, but are not frequently used. Configure openssl with enable-demos to build +them automatically through the perl based build system + bio: Demonstration of a simple TLS client and server certs: Demonstration of creating certs, using OCSP @@ -12,7 +16,8 @@ aesgcm.c Demonstration of symmetric cipher GCM mode encrypt/decryp aesccm.c Demonstration of symmetric cipher CCM mode encrypt/decrypt ariacbc.c Demonstration of symmetric cipher CBC mode encrypt/decrypt -cms: +cms: Demonstrations related to the Cryptographic Message + Syntax (CMS) standard digest: EVP_MD_demo.c Compute a digest from multiple buffers @@ -20,16 +25,41 @@ EVP_MD_stdin.c Compute a digest with data read from stdin EVP_MD_xof.c Compute a digest using the SHAKE256 XOF EVP_f_md.c Compute a digest using BIO and EVP_f_md +encode: +rsa_encode.c Encode and decode PEM-encoded RSA keys + +encrypt: +rsa_encrypt.c Encrypt and decrypt data using an RSA keypair. + +guide: Sample code from the OpenSSL Guide tutorials. See + the oss-guide-quic-introduction(7) man page. +quic-client-block.c: A simple blocking QUIC client +quic-client-non-block.c: A simple non-blocking QUIC client +quic-multi-stream.c: A simple QUIC client using multiple streams +tls-client-block.c: A simple blocking SSL/TLS client +tls-client-non-block.c: A simple non-blocking SSL/TLS client + +http3: Demonstration of how to use OpenSSL's QUIC capabilities + for HTTP/3. + kdf: hkdf.c Demonstration of HMAC based key derivation pbkdf2.c Demonstration of PBKDF2 password based key derivation scrypt.c Demonstration of SCRYPT password based key derivation +keyexch: +x25519.c Demonstration of X25519 based key exchange +ecdh.c Demonstration of ECDH key exchange + mac: gmac.c Demonstration of GMAC message authentication poly1305.c Demonstration of Poly1305-AES message authentication siphash.c Demonstration of SIPHASH message authentication +pkcs12: +pkread.c Print out a description of a PKCS12 file. +pkwrite.c Add a password to an existing PKCS12 file. + pkey: EVP_PKEY_EC_keygen.c Generate an EC key. EVP_PKEY_RSA_keygen.c Generate an RSA key. @@ -38,13 +68,14 @@ EVP_PKEY_DSA_paramgen.c Generate a DSA param key. EVP_PKEY_DSA_paramvalidate.c Validate a DSA param key. EVP_PKEY_DSA_paramfromdata.c Load a DSA param key using raw data. -smime: - -pkcs12: -pkread.c Print out a description of a PKCS12 file. -pkwrite.c Add a password to an existing PKCS12 file. - signature: -EVP_Signature_demo.c Compute and verify a signature from multiple buffers -rsa_pss_direct.c Compute and verify an RSA-PSS signature from a hash -rsa_pss_hash.c Compute and verify an RSA-PSS signature over a buffer +EVP_EC_Signature_demo.c Compute and verify an EC signature. +EVP_DSA_Signature_demo.c Compute and verify a DSA signature. +EVP_ED_Signature_demo.c Compute and verify an ED25519 signature. +rsa_pss_direct.c Compute and verify an RSA-PSS signature from a hash +rsa_pss_hash.c Compute and verify an RSA-PSS signature over a buffer + +smime: Demonstrations related to S/MIME + +sslecho: +main.c Simple SSL/TLS echo client/server. diff --git a/demos/bio/Makefile b/demos/bio/Makefile index 86f19d4df3af..5171e75e5981 100644 --- a/demos/bio/Makefile +++ b/demos/bio/Makefile @@ -1,22 +1,22 @@ -# Quick instruction: -# To build against an OpenSSL built in the source tree, do this: # -# make OPENSSL_INCS_LOCATION=-I../../include OPENSSL_LIBS_LOCATION=-L../.. -# -# To run the demos when linked with a shared library (default): +# To run the demos when linked with a shared library (default) ensure that +# libcrypto and libssl are on the library path. For example: # # LD_LIBRARY_PATH=../.. ./server-arg -# LD_LIBRARY_PATH=../.. ./server-cmod -# LD_LIBRARY_PATH=../.. ./server-conf -# LD_LIBRARY_PATH=../.. ./client-arg -# LD_LIBRARY_PATH=../.. ./client-conf -# LD_LIBRARY_PATH=../.. ./saccept -# LD_LIBRARY_PATH=../.. ./sconnect -CFLAGS = $(OPENSSL_INCS_LOCATION) -LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto $(EX_LIBS) +TESTS = client-arg \ + client-conf \ + saccept \ + sconnect \ + server-arg \ + server-cmod \ + server-conf -all: client-arg client-conf saccept sconnect server-arg server-cmod server-conf +CFLAGS = -I../../include -g -Wall +LDFLAGS = -L../.. +LDLIBS = -lssl -lcrypto + +all: $(TESTS) client-arg: client-arg.o client-conf: client-conf.o @@ -26,8 +26,12 @@ server-arg: server-arg.o server-cmod: server-cmod.o server-conf: server-conf.o -client-arg client-conf saccept sconnect server-arg server-cmod server-conf: - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) +$(TESTS): + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) clean: - $(RM) *.o client-arg client-conf saccept sconnect server-arg server-cmod server-conf + $(RM) $(TESTS) *.o + +test: all + @echo "\nBIO tests:" + @echo "skipped" diff --git a/demos/bio/client-arg.c b/demos/bio/client-arg.c index 202afa1ee8ec..c4abdf5cd351 100644 --- a/demos/bio/client-arg.c +++ b/demos/bio/client-arg.c @@ -1,5 +1,5 @@ /* - * 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 @@ -22,6 +22,7 @@ int main(int argc, char **argv) char **args = argv + 1; const char *connect_str = "localhost:4433"; int nargs = argc - 1; + int ret = EXIT_FAILURE; ctx = SSL_CTX_new(TLS_client_method()); cctx = SSL_CONF_CTX_new(); @@ -100,9 +101,10 @@ int main(int argc, char **argv) break; BIO_write(out, tmpbuf, len); } + ret = EXIT_SUCCESS; end: SSL_CONF_CTX_free(cctx); BIO_free_all(sbio); BIO_free(out); - return 0; + return ret; } diff --git a/demos/bio/client-conf.c b/demos/bio/client-conf.c index 916876bfab94..766f1b5299a5 100644 --- a/demos/bio/client-conf.c +++ b/demos/bio/client-conf.c @@ -1,5 +1,5 @@ /* - * 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 @@ -25,6 +25,7 @@ int main(int argc, char **argv) CONF_VALUE *cnf; const char *connect_str = "localhost:4433"; long errline = -1; + int ret = EXIT_FAILURE; conf = NCONF_new(NULL); @@ -108,10 +109,12 @@ int main(int argc, char **argv) break; BIO_write(out, tmpbuf, len); } + ret = EXIT_SUCCESS; + end: SSL_CONF_CTX_free(cctx); BIO_free_all(sbio); BIO_free(out); NCONF_free(conf); - return 0; + return ret; } diff --git a/demos/bio/saccept.c b/demos/bio/saccept.c index 6da22ea44091..604051cda966 100644 --- a/demos/bio/saccept.c +++ b/demos/bio/saccept.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -27,13 +27,16 @@ static volatile int done = 0; -void interrupt(int sig) +static void interrupt(int sig) { done = 1; } -void sigsetup(void) +static void sigsetup(void) { +#if defined(OPENSSL_SYS_WINDOWS) + signal(SIGINT, interrupt); +#else struct sigaction sa; /* @@ -43,6 +46,7 @@ void sigsetup(void) sa.sa_handler = interrupt; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); +#endif } int main(int argc, char *argv[]) diff --git a/demos/bio/sconnect.c b/demos/bio/sconnect.c index 18f7007ce708..b4ad3df14b37 100644 --- a/demos/bio/sconnect.c +++ b/demos/bio/sconnect.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -16,11 +16,16 @@ */ #include #include -#include #include #include #include #include +#if !defined(OPENSSL_SYS_WINDOWS) +#include +#else +#include +# define sleep(x) Sleep(x*1000) +#endif #define HOSTPORT "localhost:4433" #define CAFILE "root.pem" @@ -30,7 +35,6 @@ int main(int argc, char *argv[]) const char *hostport = HOSTPORT; const char *CAfile = CAFILE; const char *hostname; - char *cp; BIO *out = NULL; char buf[1024 * 10], *p; SSL_CTX *ssl_ctx = NULL; @@ -52,9 +56,10 @@ int main(int argc, char *argv[]) /* Enable trust chain verification */ SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); - SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL); + if (!SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL)) + goto err; - /* Lets make a SSL structure */ + /* Let's make an SSL structure */ ssl = SSL_new(ssl_ctx); SSL_set_connect_state(ssl); diff --git a/demos/certs/apps/mkacerts.sh b/demos/certs/apps/mkacerts.sh index 70984969f44b..996747f2cd90 100644 --- a/demos/certs/apps/mkacerts.sh +++ b/demos/certs/apps/mkacerts.sh @@ -2,38 +2,42 @@ # Recreate the demo certificates in the apps directory. -OPENSSL=openssl +opensslcmd() { + LD_LIBRARY_PATH=../../.. ../../../apps/openssl $@ +} + +opensslcmd version # Root CA: create certificate directly -CN="OpenSSL Test Root CA" $OPENSSL req -config apps.cnf -x509 -nodes \ +CN="OpenSSL Test Root CA" opensslcmd req -config apps.cnf -x509 -nodes \ -keyout root.pem -out root.pem -key rootkey.pem -new -days 3650 # Intermediate CA: request first -CN="OpenSSL Test Intermediate CA" $OPENSSL req -config apps.cnf -nodes \ +CN="OpenSSL Test Intermediate CA" opensslcmd req -config apps.cnf -nodes \ -key intkey.pem -out intreq.pem -new # Sign request: CA extensions -$OPENSSL x509 -req -in intreq.pem -CA root.pem -CAkey rootkey.pem -days 3630 \ +opensslcmd x509 -req -in intreq.pem -CA root.pem -CAkey rootkey.pem -days 3630 \ -extfile apps.cnf -extensions v3_ca -CAcreateserial -out intca.pem # Client certificate: request first -CN="Test Client Cert" $OPENSSL req -config apps.cnf -nodes \ +CN="Test Client Cert" opensslcmd req -config apps.cnf -nodes \ -key ckey.pem -out creq.pem -new # Sign using intermediate CA -$OPENSSL x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile apps.cnf -extensions usr_cert -CAcreateserial | \ - $OPENSSL x509 -nameopt oneline -subject -issuer >client.pem + opensslcmd x509 -nameopt oneline -subject -issuer >client.pem # Server certificate: request first -CN="Test Server Cert" $OPENSSL req -config apps.cnf -nodes \ +CN="Test Server Cert" opensslcmd req -config apps.cnf -nodes \ -key skey.pem -out sreq.pem -new # Sign using intermediate CA -$OPENSSL x509 -req -in sreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in sreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile apps.cnf -extensions usr_cert -CAcreateserial | \ - $OPENSSL x509 -nameopt oneline -subject -issuer >server.pem + opensslcmd x509 -nameopt oneline -subject -issuer >server.pem # Server certificate #2: request first -CN="Test Server Cert #2" $OPENSSL req -config apps.cnf -nodes \ +CN="Test Server Cert #2" opensslcmd req -config apps.cnf -nodes \ -key skey2.pem -out sreq2.pem -new # Sign using intermediate CA -$OPENSSL x509 -req -in sreq2.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in sreq2.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile apps.cnf -extensions usr_cert -CAcreateserial | \ - $OPENSSL x509 -nameopt oneline -subject -issuer >server2.pem + opensslcmd x509 -nameopt oneline -subject -issuer >server2.pem # Append keys to file. @@ -41,5 +45,5 @@ cat skey.pem >>server.pem cat skey2.pem >>server2.pem cat ckey.pem >>client.pem -$OPENSSL verify -CAfile root.pem -untrusted intca.pem \ +opensslcmd verify -CAfile root.pem -untrusted intca.pem \ server2.pem server.pem client.pem diff --git a/demos/certs/apps/mkxcerts.sh b/demos/certs/apps/mkxcerts.sh index ebe1920432be..39d45605e1fe 100644 --- a/demos/certs/apps/mkxcerts.sh +++ b/demos/certs/apps/mkxcerts.sh @@ -1,29 +1,35 @@ +#!/bin/sh # Create certificates using various algorithms to test multi-certificate # functionality. -OPENSSL=../../../apps/openssl -CN="OpenSSL Test RSA SHA-1 cert" $OPENSSL req \ +opensslcmd() { + LD_LIBRARY_PATH=../../.. ../../../apps/openssl $@ +} + +opensslcmd version + +CN="OpenSSL Test RSA SHA-1 cert" opensslcmd req \ -config apps.cnf -extensions usr_cert -x509 -nodes \ -keyout tsha1.pem -out tsha1.pem -new -days 3650 -sha1 -CN="OpenSSL Test RSA SHA-256 cert" $OPENSSL req \ +CN="OpenSSL Test RSA SHA-256 cert" opensslcmd req \ -config apps.cnf -extensions usr_cert -x509 -nodes \ -keyout tsha256.pem -out tsha256.pem -new -days 3650 -sha256 -CN="OpenSSL Test RSA SHA-512 cert" $OPENSSL req \ +CN="OpenSSL Test RSA SHA-512 cert" opensslcmd req \ -config apps.cnf -extensions usr_cert -x509 -nodes \ -keyout tsha512.pem -out tsha512.pem -new -days 3650 -sha512 # Create EC parameters -$OPENSSL ecparam -name P-256 -out ecp256.pem -$OPENSSL ecparam -name P-384 -out ecp384.pem +opensslcmd ecparam -name P-256 -out ecp256.pem +opensslcmd ecparam -name P-384 -out ecp384.pem -CN="OpenSSL Test P-256 SHA-256 cert" $OPENSSL req \ +CN="OpenSSL Test P-256 SHA-256 cert" opensslcmd req \ -config apps.cnf -extensions ec_cert -x509 -nodes \ -nodes -keyout tecp256.pem -out tecp256.pem -newkey ec:ecp256.pem \ -days 3650 -sha256 -CN="OpenSSL Test P-384 SHA-384 cert" $OPENSSL req \ +CN="OpenSSL Test P-384 SHA-384 cert" opensslcmd req \ -config apps.cnf -extensions ec_cert -x509 -nodes \ -nodes -keyout tecp384.pem -out tecp384.pem -newkey ec:ecp384.pem \ -days 3650 -sha384 diff --git a/demos/certs/mkcerts.sh b/demos/certs/mkcerts.sh index 2d14a95989e8..1825607fa33c 100644 --- a/demos/certs/mkcerts.sh +++ b/demos/certs/mkcerts.sh @@ -1,73 +1,78 @@ #!/bin/sh -OPENSSL=../../apps/openssl +opensslcmd() { + LD_LIBRARY_PATH=../.. ../../apps/openssl $@ +} + OPENSSL_CONF=../../apps/openssl.cnf export OPENSSL_CONF +opensslcmd version + # Root CA: create certificate directly -CN="Test Root CA" $OPENSSL req -config ca.cnf -x509 -nodes \ +CN="Test Root CA" opensslcmd req -config ca.cnf -x509 -nodes \ -keyout root.pem -out root.pem -newkey rsa:2048 -days 3650 # Intermediate CA: request first -CN="Test Intermediate CA" $OPENSSL req -config ca.cnf -nodes \ +CN="Test Intermediate CA" opensslcmd req -config ca.cnf -nodes \ -keyout intkey.pem -out intreq.pem -newkey rsa:2048 # Sign request: CA extensions -$OPENSSL x509 -req -in intreq.pem -CA root.pem -days 3600 \ +opensslcmd x509 -req -in intreq.pem -CA root.pem -days 3600 \ -extfile ca.cnf -extensions v3_ca -CAcreateserial -out intca.pem # Server certificate: create request first -CN="Test Server Cert" $OPENSSL req -config ca.cnf -nodes \ +CN="Test Server Cert" opensslcmd req -config ca.cnf -nodes \ -keyout skey.pem -out req.pem -newkey rsa:1024 # Sign request: end entity extensions -$OPENSSL x509 -req -in req.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in req.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile ca.cnf -extensions usr_cert -CAcreateserial -out server.pem # Client certificate: request first -CN="Test Client Cert" $OPENSSL req -config ca.cnf -nodes \ +CN="Test Client Cert" opensslcmd req -config ca.cnf -nodes \ -keyout ckey.pem -out creq.pem -newkey rsa:1024 # Sign using intermediate CA -$OPENSSL x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile ca.cnf -extensions usr_cert -CAcreateserial -out client.pem # Revoked certificate: request first -CN="Test Revoked Cert" $OPENSSL req -config ca.cnf -nodes \ +CN="Test Revoked Cert" opensslcmd req -config ca.cnf -nodes \ -keyout revkey.pem -out rreq.pem -newkey rsa:1024 # Sign using intermediate CA -$OPENSSL x509 -req -in rreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in rreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile ca.cnf -extensions usr_cert -CAcreateserial -out rev.pem # OCSP responder certificate: request first -CN="Test OCSP Responder Cert" $OPENSSL req -config ca.cnf -nodes \ +CN="Test OCSP Responder Cert" opensslcmd req -config ca.cnf -nodes \ -keyout respkey.pem -out respreq.pem -newkey rsa:1024 # Sign using intermediate CA and responder extensions -$OPENSSL x509 -req -in respreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ +opensslcmd x509 -req -in respreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \ -extfile ca.cnf -extensions ocsp_cert -CAcreateserial -out resp.pem # Example creating a PKCS#3 DH certificate. # First DH parameters -[ -f dhp.pem ] || $OPENSSL genpkey -genparam -algorithm DH -pkeyopt dh_paramgen_prime_len:1024 -out dhp.pem +[ -f dhp.pem ] || opensslcmd genpkey -genparam -algorithm DH -pkeyopt dh_paramgen_prime_len:1024 -out dhp.pem # Now a DH private key -$OPENSSL genpkey -paramfile dhp.pem -out dhskey.pem +opensslcmd genpkey -paramfile dhp.pem -out dhskey.pem # Create DH public key file -$OPENSSL pkey -in dhskey.pem -pubout -out dhspub.pem +opensslcmd pkey -in dhskey.pem -pubout -out dhspub.pem # Certificate request, key just reuses old one as it is ignored when the # request is signed. -CN="Test Server DH Cert" $OPENSSL req -config ca.cnf -new \ +CN="Test Server DH Cert" opensslcmd req -config ca.cnf -new \ -key skey.pem -out dhsreq.pem # Sign request: end entity DH extensions -$OPENSSL x509 -req -in dhsreq.pem -CA root.pem -days 3600 \ +opensslcmd x509 -req -in dhsreq.pem -CA root.pem -days 3600 \ -force_pubkey dhspub.pem \ -extfile ca.cnf -extensions dh_cert -CAcreateserial -out dhserver.pem # DH client certificate -$OPENSSL genpkey -paramfile dhp.pem -out dhckey.pem -$OPENSSL pkey -in dhckey.pem -pubout -out dhcpub.pem -CN="Test Client DH Cert" $OPENSSL req -config ca.cnf -new \ +opensslcmd genpkey -paramfile dhp.pem -out dhckey.pem +opensslcmd pkey -in dhckey.pem -pubout -out dhcpub.pem +CN="Test Client DH Cert" opensslcmd req -config ca.cnf -new \ -key skey.pem -out dhcreq.pem -$OPENSSL x509 -req -in dhcreq.pem -CA root.pem -days 3600 \ +opensslcmd x509 -req -in dhcreq.pem -CA root.pem -days 3600 \ -force_pubkey dhcpub.pem \ -extfile ca.cnf -extensions dh_cert -CAcreateserial -out dhclient.pem @@ -78,19 +83,19 @@ $OPENSSL x509 -req -in dhcreq.pem -CA root.pem -days 3600 \ # Create initial crl number file echo 01 >crlnum.txt # Add entries for server and client certs -$OPENSSL ca -valid server.pem -keyfile root.pem -cert root.pem \ +opensslcmd ca -valid server.pem -keyfile root.pem -cert root.pem \ -config ca.cnf -md sha1 -$OPENSSL ca -valid client.pem -keyfile root.pem -cert root.pem \ +opensslcmd ca -valid client.pem -keyfile root.pem -cert root.pem \ -config ca.cnf -md sha1 -$OPENSSL ca -valid rev.pem -keyfile root.pem -cert root.pem \ +opensslcmd ca -valid rev.pem -keyfile root.pem -cert root.pem \ -config ca.cnf -md sha1 # Generate a CRL. -$OPENSSL ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \ +opensslcmd ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \ -md sha1 -crldays 1 -out crl1.pem # Revoke a certificate openssl ca -revoke rev.pem -crl_reason superseded \ -keyfile root.pem -cert root.pem -config ca.cnf -md sha1 # Generate another CRL -$OPENSSL ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \ +opensslcmd ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \ -md sha1 -crldays 1 -out crl2.pem diff --git a/demos/certs/ocspquery.sh b/demos/certs/ocspquery.sh index f66411330569..7cb8e76423bb 100644 --- a/demos/certs/ocspquery.sh +++ b/demos/certs/ocspquery.sh @@ -1,21 +1,28 @@ +#!/bin/sh + # Example querying OpenSSL test responder. Assumes ocsprun.sh has been # called. -OPENSSL=../../apps/openssl +opensslcmd() { + LD_LIBRARY_PATH=../.. ../../apps/openssl $@ +} + OPENSSL_CONF=../../apps/openssl.cnf export OPENSSL_CONF +opensslcmd version + # Send responder queries for each certificate. echo "Requesting OCSP status for each certificate" -$OPENSSL ocsp -issuer intca.pem -cert client.pem -CAfile root.pem \ +opensslcmd ocsp -issuer intca.pem -cert client.pem -CAfile root.pem \ -url http://127.0.0.1:8888/ -$OPENSSL ocsp -issuer intca.pem -cert server.pem -CAfile root.pem \ +opensslcmd ocsp -issuer intca.pem -cert server.pem -CAfile root.pem \ -url http://127.0.0.1:8888/ -$OPENSSL ocsp -issuer intca.pem -cert rev.pem -CAfile root.pem \ +opensslcmd ocsp -issuer intca.pem -cert rev.pem -CAfile root.pem \ -url http://127.0.0.1:8888/ # One query for all three certificates. echo "Requesting OCSP status for three certificates in one request" -$OPENSSL ocsp -issuer intca.pem \ +opensslcmd ocsp -issuer intca.pem \ -cert client.pem -cert server.pem -cert rev.pem \ -CAfile root.pem -url http://127.0.0.1:8888/ diff --git a/demos/certs/ocsprun.sh b/demos/certs/ocsprun.sh index a65e5f2fd171..77fd62fcf1bb 100644 --- a/demos/certs/ocsprun.sh +++ b/demos/certs/ocsprun.sh @@ -1,14 +1,21 @@ +#!/bin/sh + +opensslcmd() { + LD_LIBRARY_PATH=../.. ../../apps/openssl $@ +} + # Example of running an querying OpenSSL test OCSP responder. # This assumes "mkcerts.sh" or similar has been run to set up the # necessary file structure. -OPENSSL=../../apps/openssl OPENSSL_CONF=../../apps/openssl.cnf export OPENSSL_CONF +opensslcmd version + # Run OCSP responder. PORT=8888 -$OPENSSL ocsp -port $PORT -index index.txt -CA intca.pem \ +opensslcmd ocsp -port $PORT -index index.txt -CA intca.pem \ -rsigner resp.pem -rkey respkey.pem -rother intca.pem $* diff --git a/demos/cipher/Makefile b/demos/cipher/Makefile index 81f526535e20..cdd7736758f9 100644 --- a/demos/cipher/Makefile +++ b/demos/cipher/Makefile @@ -1,27 +1,35 @@ -# Quick instruction: -# To build against an OpenSSL built in the source tree, do this: # -# make OPENSSL_INCS_LOCATION=-I../../include OPENSSL_LIBS_LOCATION=-L../.. -# -# To run the demos when linked with a shared library (default): +# To run the demos when linked with a shared library (default) ensure that +# libcrypto is on the library path. For example: # # LD_LIBRARY_PATH=../.. ./aesccm -# LD_LIBRARY_PATH=../.. ./aesgcm -# LD_LIBRARY_PATH=../.. ./aeskeywrap -# LD_LIBRARY_PATH=../.. ./ariacbc -CFLAGS = $(OPENSSL_INCS_LOCATION) -LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto +TESTS = aesccm \ + aesgcm \ + aeskeywrap \ + ariacbc -all: aesccm aesgcm aeskeywrap ariacbc +CFLAGS = -I../../include -g -Wall +LDFLAGS = -L../.. +LDLIBS = -lcrypto + +all: $(TESTS) aesccm: aesccm.o aesgcm: aesgcm.o aeskeywrap: aeskeywrap.o ariacbc: ariacbc.o -aesccm aesgcm aeskeywrap ariacbc: - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) +$(TESTS): + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) clean: - $(RM) aesccm aesgcm aeskeywrap ariacbc *.o + $(RM) $(TESTS) *.o + +.PHONY: test +test: all + @echo "\nCipher tests:" + @set -e; for tst in $(TESTS); do \ + echo "\n"$$tst; \ + LD_LIBRARY_PATH=../.. ./$$tst; \ + done diff --git a/demos/cipher/aesccm.c b/demos/cipher/aesccm.c index f4430e727b2f..55d2b5fe6d22 100644 --- a/demos/cipher/aesccm.c +++ b/demos/cipher/aesccm.c @@ -1,5 +1,5 @@ /* - * Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -64,11 +64,11 @@ static const unsigned char ccm_tag[] = { * algorithm implementations. If they are NULL then the default library * context and properties are used. */ -OSSL_LIB_CTX *libctx = NULL; -const char *propq = NULL; +static OSSL_LIB_CTX *libctx = NULL; +static const char *propq = NULL; -int aes_ccm_encrypt(void) +static int aes_ccm_encrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -155,7 +155,7 @@ err: return ret; } -int aes_ccm_decrypt(void) +static int aes_ccm_decrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -229,10 +229,10 @@ err: int main(int argc, char **argv) { if (!aes_ccm_encrypt()) - return 1; + return EXIT_FAILURE; if (!aes_ccm_decrypt()) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/demos/cipher/aesgcm.c b/demos/cipher/aesgcm.c index aaf4000d574f..426e0823f28a 100644 --- a/demos/cipher/aesgcm.c +++ b/demos/cipher/aesgcm.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2012-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -64,10 +64,10 @@ static const unsigned char gcm_tag[] = { * algorithm implementations. If they are NULL then the default library * context and properties are used. */ -OSSL_LIB_CTX *libctx = NULL; -const char *propq = NULL; +static OSSL_LIB_CTX *libctx = NULL; +static const char *propq = NULL; -int aes_gcm_encrypt(void) +static int aes_gcm_encrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -101,7 +101,7 @@ int aes_gcm_encrypt(void) * IV length parameter. * For demonstration purposes the IV is being set here. In a compliant * application the IV would be generated internally so the iv passed in - * would be NULL. + * would be NULL. */ if (!EVP_EncryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params)) goto err; @@ -144,7 +144,7 @@ err: return ret; } -int aes_gcm_decrypt(void) +static int aes_gcm_decrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -219,10 +219,10 @@ err: int main(int argc, char **argv) { if (!aes_gcm_encrypt()) - return 1; + return EXIT_FAILURE; if (!aes_gcm_decrypt()) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/demos/cipher/aeskeywrap.c b/demos/cipher/aeskeywrap.c index f987772e4ffe..bf036074f30c 100644 --- a/demos/cipher/aeskeywrap.c +++ b/demos/cipher/aeskeywrap.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -50,10 +50,10 @@ static const unsigned char wrap_ct[] = { * algorithm implementations. If they are NULL then the default library * context and properties are used. */ -OSSL_LIB_CTX *libctx = NULL; -const char *propq = NULL; +static OSSL_LIB_CTX *libctx = NULL; +static const char *propq = NULL; -int aes_wrap_encrypt(void) +static int aes_wrap_encrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -111,7 +111,7 @@ err: return ret; } -int aes_wrap_decrypt(void) +static int aes_wrap_decrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; @@ -171,11 +171,10 @@ err: int main(int argc, char **argv) { if (!aes_wrap_encrypt()) - return 1; + return EXIT_FAILURE; if (!aes_wrap_decrypt()) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } - diff --git a/demos/cipher/ariacbc.c b/demos/cipher/ariacbc.c index 8999fe6e701d..4238a3db899c 100644 --- a/demos/cipher/ariacbc.c +++ b/demos/cipher/ariacbc.c @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2012-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -49,18 +49,16 @@ static const unsigned char cbc_ct[] = { * algorithm implementations. If they are NULL then the default library * context and properties are used. */ -OSSL_LIB_CTX *libctx = NULL; -const char *propq = NULL; +static OSSL_LIB_CTX *libctx = NULL; +static const char *propq = NULL; -int aria_cbc_encrypt(void) +static int aria_cbc_encrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; EVP_CIPHER *cipher = NULL; int outlen, tmplen; - size_t cbc_ivlen = sizeof(cbc_iv); unsigned char outbuf[1024]; - unsigned char outtag[16]; printf("ARIA CBC Encrypt:\n"); printf("Plaintext:\n"); @@ -110,13 +108,12 @@ err: return ret; } -int aria_cbc_decrypt(void) +static int aria_cbc_decrypt(void) { int ret = 0; EVP_CIPHER_CTX *ctx; EVP_CIPHER *cipher = NULL; - int outlen, tmplen, rv; - size_t cbc_ivlen = sizeof(cbc_iv); + int outlen, tmplen; unsigned char outbuf[1024]; printf("ARIA CBC Decrypt:\n"); @@ -169,10 +166,10 @@ err: int main(int argc, char **argv) { if (!aria_cbc_encrypt()) - return 1; + return EXIT_FAILURE; if (!aria_cbc_decrypt()) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/demos/cms/cms_comp.c b/demos/cms/cms_comp.c index ee1b5a38ceef..30c5fc7fcf53 100644 --- a/demos/cms/cms_comp.c +++ b/demos/cms/cms_comp.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -16,7 +16,7 @@ int main(int argc, char **argv) { BIO *in = NULL, *out = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; /* * On OpenSSL 1.0.0+ only: @@ -48,11 +48,11 @@ int main(int argc, char **argv) if (!SMIME_write_CMS(out, cms, in, flags)) goto err; - ret = 0; + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Compressing Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_ddec.c b/demos/cms/cms_ddec.c index cb6c2694c697..d119e9722226 100644 --- a/demos/cms/cms_ddec.c +++ b/demos/cms/cms_ddec.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -21,7 +21,7 @@ int main(int argc, char **argv) X509 *rcert = NULL; EVP_PKEY *rkey = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -34,7 +34,8 @@ int main(int argc, char **argv) rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -68,11 +69,11 @@ int main(int argc, char **argv) if (!CMS_decrypt(cms, rkey, rcert, dcont, out, 0)) goto err; - ret = 0; + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Decrypting Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_dec.c b/demos/cms/cms_dec.c index f33ef1eb78f5..b15885eb18fa 100644 --- a/demos/cms/cms_dec.c +++ b/demos/cms/cms_dec.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *rcert = NULL; EVP_PKEY *rkey = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -31,7 +31,8 @@ int main(int argc, char **argv) rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -59,11 +60,12 @@ int main(int argc, char **argv) if (!CMS_decrypt(cms, rkey, rcert, NULL, out, 0)) goto err; - ret = 0; + printf("Decryption Successful\n"); + + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Decrypting Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_denc.c b/demos/cms/cms_denc.c index 60b0aa192bc0..53b680f67484 100644 --- a/demos/cms/cms_denc.c +++ b/demos/cms/cms_denc.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -21,7 +21,7 @@ int main(int argc, char **argv) X509 *rcert = NULL; STACK_OF(X509) *recips = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; int flags = CMS_STREAM | CMS_DETACHED; @@ -46,8 +46,8 @@ int main(int argc, char **argv) goto err; /* - * sk_X509_pop_free will free up recipient STACK and its contents so set - * rcert to NULL so it isn't freed up twice. + * OSSL_STACK_OF_X509_free() free up recipient STACK and its contents + * so set rcert to NULL so it isn't freed up twice. */ rcert = NULL; @@ -77,18 +77,16 @@ int main(int argc, char **argv) if (!PEM_write_bio_CMS(out, cms)) goto err; - ret = 0; - + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Encrypting Data\n"); ERR_print_errors_fp(stderr); } CMS_ContentInfo_free(cms); X509_free(rcert); - sk_X509_pop_free(recips, X509_free); + OSSL_STACK_OF_X509_free(recips); BIO_free(in); BIO_free(out); BIO_free(dout); diff --git a/demos/cms/cms_enc.c b/demos/cms/cms_enc.c index 9ef7a395583d..1f69571a17fc 100644 --- a/demos/cms/cms_enc.c +++ b/demos/cms/cms_enc.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *rcert = NULL; STACK_OF(X509) *recips = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; /* * On OpenSSL 1.0.0 and later only: @@ -47,8 +47,8 @@ int main(int argc, char **argv) goto err; /* - * sk_X509_pop_free will free up recipient STACK and its contents so set - * rcert to NULL so it isn't freed up twice. + * OSSL_STACK_OF_X509_free() will free up recipient STACK and its contents + * so set rcert to NULL so it isn't freed up twice. */ rcert = NULL; @@ -73,18 +73,18 @@ int main(int argc, char **argv) if (!SMIME_write_CMS(out, cms, in, flags)) goto err; - ret = 0; + printf("Encryption Successful\n"); + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Encrypting Data\n"); ERR_print_errors_fp(stderr); } CMS_ContentInfo_free(cms); X509_free(rcert); - sk_X509_pop_free(recips, X509_free); + OSSL_STACK_OF_X509_free(recips); BIO_free(in); BIO_free(out); BIO_free(tbio); diff --git a/demos/cms/cms_sign.c b/demos/cms/cms_sign.c index a52f5cec0fa5..31e71e8b636c 100644 --- a/demos/cms/cms_sign.c +++ b/demos/cms/cms_sign.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *scert = NULL; EVP_PKEY *skey = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; /* * For simple S/MIME signing use CMS_DETACHED. On OpenSSL 1.0.0 only: for @@ -38,7 +38,8 @@ int main(int argc, char **argv) scert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -62,18 +63,18 @@ int main(int argc, char **argv) if (!out) goto err; - if (!(flags & CMS_STREAM)) - BIO_reset(in); + if (!(flags & CMS_STREAM)) { + if (BIO_reset(in) < 0) + goto err; + } /* Write out S/MIME message */ if (!SMIME_write_CMS(out, cms, in, flags)) goto err; - ret = 0; - + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_sign2.c b/demos/cms/cms_sign2.c index beda9779a3fb..af3386eb7634 100644 --- a/demos/cms/cms_sign2.c +++ b/demos/cms/cms_sign2.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *scert = NULL, *scert2 = NULL; EVP_PKEY *skey = NULL, *skey2 = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -30,7 +30,8 @@ int main(int argc, char **argv) scert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -43,7 +44,8 @@ int main(int argc, char **argv) scert2 = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey2 = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -77,11 +79,11 @@ int main(int argc, char **argv) if (!SMIME_write_CMS(out, cms, in, CMS_STREAM)) goto err; - ret = 0; + printf("Signing Successful\n"); + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_uncomp.c b/demos/cms/cms_uncomp.c index 35e68ebcc603..13f1e756da1e 100644 --- a/demos/cms/cms_uncomp.c +++ b/demos/cms/cms_uncomp.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -16,7 +16,7 @@ int main(int argc, char **argv) { BIO *in = NULL, *out = NULL; CMS_ContentInfo *cms = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -42,11 +42,9 @@ int main(int argc, char **argv) if (!CMS_uncompress(cms, out, NULL, 0)) goto err; - ret = 0; - + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Uncompressing Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/cms/cms_ver.c b/demos/cms/cms_ver.c index 3c0a7aa19ede..43e9d0985408 100644 --- a/demos/cms/cms_ver.c +++ b/demos/cms/cms_ver.c @@ -1,5 +1,5 @@ /* - * Copyright 2008-2016 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 @@ -12,14 +12,56 @@ #include #include +/* + * print any signingTime attributes. + * signingTime is when each party purportedly signed the message. + */ +static void print_signingTime(CMS_ContentInfo *cms) +{ + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + X509_ATTRIBUTE *attr; + ASN1_TYPE *t; + ASN1_UTCTIME *utctime; + ASN1_GENERALIZEDTIME *gtime; + BIO *b; + int i, loc; + + b = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); + sis = CMS_get0_SignerInfos(cms); + for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) { + si = sk_CMS_SignerInfo_value(sis, i); + loc = CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1); + attr = CMS_signed_get_attr(si, loc); + t = X509_ATTRIBUTE_get0_type(attr, 0); + if (t == NULL) + continue; + switch (t->type) { + case V_ASN1_UTCTIME: + utctime = t->value.utctime; + ASN1_UTCTIME_print(b, utctime); + break; + case V_ASN1_GENERALIZEDTIME: + gtime = t->value.generalizedtime; + ASN1_GENERALIZEDTIME_print(b, gtime); + break; + default: + fprintf(stderr, "unrecognized signingTime type\n"); + break; + } + BIO_printf(b, ": signingTime from SignerInfo %i\n", i); + } + BIO_free(b); + return; +} + int main(int argc, char **argv) { BIO *in = NULL, *out = NULL, *tbio = NULL, *cont = NULL; X509_STORE *st = NULL; X509 *cacert = NULL; CMS_ContentInfo *cms = NULL; - - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -57,6 +99,8 @@ int main(int argc, char **argv) if (cms == NULL) goto err; + print_signingTime(cms); + /* File to output verified content to */ out = BIO_new_file("smver.txt", "w"); if (out == NULL) @@ -67,13 +111,12 @@ int main(int argc, char **argv) goto err; } - fprintf(stderr, "Verification Successful\n"); + printf("Verification Successful\n"); - ret = 0; + ret = EXIT_SUCCESS; err: - - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Verifying Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/digest/BIO_f_md.c b/demos/digest/BIO_f_md.c index 2ecc53e137ae..53b77a731553 100644 --- a/demos/digest/BIO_f_md.c +++ b/demos/digest/BIO_f_md.c @@ -1,5 +1,5 @@ /*- - * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -34,20 +34,19 @@ * The default digest is SHA3-512 */ -int main(int argc, char * argv[]) +int main(int argc, char *argv[]) { - int result = 1; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *library_context = NULL; BIO *input = NULL; - BIO *bio_digest = NULL; + BIO *bio_digest = NULL, *reading = NULL; EVP_MD *md = NULL; unsigned char buffer[512]; - size_t readct, writect; - size_t digest_size; - char *digest_value=NULL; + int digest_size; + char *digest_value = NULL; int j; - input = BIO_new_fd( fileno(stdin), 1 ); + input = BIO_new_fd(fileno(stdin), 1); if (input == NULL) { fprintf(stderr, "BIO_new_fd() for stdin returned NULL\n"); goto cleanup; @@ -60,15 +59,20 @@ int main(int argc, char * argv[]) /* * Fetch a message digest by name - * The algorithm name is case insensitive. + * The algorithm name is case insensitive. * See providers(7) for details about algorithm fetching */ - md = EVP_MD_fetch( library_context, "SHA3-512", NULL ); + md = EVP_MD_fetch(library_context, "SHA3-512", NULL); if (md == NULL) { fprintf(stderr, "EVP_MD_fetch did not find SHA3-512.\n"); goto cleanup; } digest_size = EVP_MD_get_size(md); + if (digest_size <= 0) { + fprintf(stderr, "EVP_MD_get_size returned invalid size.\n"); + goto cleanup; + } + digest_value = OPENSSL_malloc(digest_size); if (digest_value == NULL) { fprintf(stderr, "Can't allocate %lu bytes for the digest value.\n", (unsigned long)digest_size); @@ -81,7 +85,7 @@ int main(int argc, char * argv[]) goto cleanup; } /* set our bio_digest BIO to digest data */ - if (BIO_set_md(bio_digest,md) != 1) { + if (BIO_set_md(bio_digest, md) != 1) { fprintf(stderr, "BIO_set_md failed.\n"); goto cleanup; } @@ -89,9 +93,9 @@ int main(int argc, char * argv[]) * We will use BIO chaining so that as we read, the digest gets updated * See the man page for BIO_push */ - BIO *reading = BIO_push( bio_digest, input ); - - while( BIO_read(reading, buffer, sizeof(buffer)) > 0 ) + reading = BIO_push(bio_digest, input); + + while (BIO_read(reading, buffer, sizeof(buffer)) > 0) ; /*- @@ -102,14 +106,14 @@ int main(int argc, char * argv[]) fprintf(stderr, "BIO_gets(bio_digest) failed\n"); goto cleanup; } - for (j=0; jprivk); local_peer->privk = NULL; } - return rv; + return ret; } /* @@ -120,7 +120,7 @@ static int keyexch_x25519_after( PEER_DATA *local_peer, const unsigned char *remote_peer_pubk_data) { - int rv = 0; + int ret = 0; EVP_PKEY *remote_peer_pubk = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -188,21 +188,21 @@ static int keyexch_x25519_after( BIO_dump_indent_fp(stdout, local_peer->secret, local_peer->secret_len, 2); putchar('\n'); - rv = 1; + ret = 1; end: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(remote_peer_pubk); - if (rv == 0) { + if (ret == 0) { OPENSSL_clear_free(local_peer->secret, local_peer->secret_len); local_peer->secret = NULL; } - return rv; + return ret; } static int keyexch_x25519(int use_kat) { - int rv = 0; + int ret = 0; OSSL_LIB_CTX *libctx = NULL; PEER_DATA peer1 = {"peer 1"}, peer2 = {"peer 2"}; @@ -250,7 +250,7 @@ static int keyexch_x25519(int use_kat) goto end; } - rv = 1; + ret = 1; end: /* The secrets are sensitive, so ensure they are erased before freeing. */ OPENSSL_clear_free(peer1.secret, peer1.secret_len); @@ -259,7 +259,7 @@ end: EVP_PKEY_free(peer1.privk); EVP_PKEY_free(peer2.privk); OSSL_LIB_CTX_free(libctx); - return rv; + return ret; } int main(int argc, char **argv) @@ -267,12 +267,12 @@ int main(int argc, char **argv) /* Test X25519 key exchange with known result. */ printf("Key exchange using known answer (deterministic):\n"); if (keyexch_x25519(1) == 0) - return 1; + return EXIT_FAILURE; /* Test X25519 key exchange with random keys. */ printf("Key exchange using random keys:\n"); if (keyexch_x25519(0) == 0) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/demos/mac/Makefile b/demos/mac/Makefile index 00d2d8dbe64a..6c870a3d4562 100644 --- a/demos/mac/Makefile +++ b/demos/mac/Makefile @@ -1,25 +1,35 @@ -# Quick instruction: -# To build against an OpenSSL built in the source tree, do this: # -# make OPENSSL_INCS_LOCATION=-I../../include OPENSSL_LIBS_LOCATION=-L../.. -# -# To run the demos when linked with a shared library (default): +# To run the demos when linked with a shared library (default) ensure +# that libcrypto is on the library path. For example: # # LD_LIBRARY_PATH=../.. ./gmac -# LD_LIBRARY_PATH=../.. ./poly1305 -CFLAGS = $(OPENSSL_INCS_LOCATION) -Wall -LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto +TESTS = gmac \ + hmac-sha512 \ + cmac-aes256 \ + poly1305 -all: gmac hmac-sha512 cmac-aes256 poly1305 +CFLAGS = -I../../include -g -Wall +LDFLAGS = -L../.. +LDLIBS = -lcrypto + +all: $(TESTS) gmac: gmac.o hmac-sha512: hmac-sha512.o cmac-aes256: cmac-aes256.o poly1305: poly1305.o -gmac hmac-sha512 cmac-aes256 poly1305: - $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) +$(TESTS): + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) clean: - $(RM) gmac hmac-sha512 cmac-aes256 poly1305 *.o + $(RM) *.o $(TESTS) + +.PHONY: test +test: all + @echo "\nMAC tests:" + @set -e; for tst in $(TESTS); do \ + echo "\n"$$tst; \ + LD_LIBRARY_PATH=../.. ./$$tst; \ + done diff --git a/demos/mac/cmac-aes256.c b/demos/mac/cmac-aes256.c index 6f4fd78b699f..64069cf3a829 100644 --- a/demos/mac/cmac-aes256.c +++ b/demos/mac/cmac-aes256.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -65,14 +65,14 @@ static const char *propq = NULL; int main(void) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *library_context = NULL; EVP_MAC *mac = NULL; EVP_MAC_CTX *mctx = NULL; unsigned char *out = NULL; size_t out_len = 0; OSSL_PARAM params[4], *p = params; - char cipher_name[] = "aes256"; + char cipher_name[] = "AES-256-CBC"; library_context = OSSL_LIB_CTX_new(); if (library_context == NULL) { @@ -141,14 +141,14 @@ int main(void) goto end; } - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; end: - if (rv != EXIT_SUCCESS) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); /* OpenSSL free functions will ignore NULL arguments */ OPENSSL_free(out); EVP_MAC_CTX_free(mctx); EVP_MAC_free(mac); OSSL_LIB_CTX_free(library_context); - return rv; + return ret; } diff --git a/demos/mac/gmac.c b/demos/mac/gmac.c index bdaa9b1daa31..d4e350a2da65 100644 --- a/demos/mac/gmac.c +++ b/demos/mac/gmac.c @@ -1,5 +1,5 @@ /* - * Copyright 2021 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 @@ -57,7 +57,7 @@ static char *propq = NULL; int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; EVP_MAC *mac = NULL; EVP_MAC_CTX *mctx = NULL; unsigned char out[16]; @@ -85,7 +85,7 @@ int main(int argc, char **argv) goto end; } - /* GMAC requries a GCM mode cipher to be specified */ + /* GMAC requires a GCM mode cipher to be specified */ *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, "AES-128-GCM", 0); @@ -134,12 +134,12 @@ int main(int argc, char **argv) goto end; } - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; end: EVP_MAC_CTX_free(mctx); EVP_MAC_free(mac); OSSL_LIB_CTX_free(library_context); - if (rv != EXIT_SUCCESS) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); - return rv; + return ret; } diff --git a/demos/mac/hmac-sha512.c b/demos/mac/hmac-sha512.c index c258b90ee395..47b5246a19ab 100644 --- a/demos/mac/hmac-sha512.c +++ b/demos/mac/hmac-sha512.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -75,7 +75,7 @@ static const char *propq = NULL; int main(void) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *library_context = NULL; EVP_MAC *mac = NULL; EVP_MAC_CTX *mctx = NULL; @@ -152,9 +152,9 @@ int main(void) goto end; } - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; end: - if (rv != EXIT_SUCCESS) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); /* OpenSSL free functions will ignore NULL arguments */ OPENSSL_free(out); @@ -162,5 +162,5 @@ end: EVP_MAC_CTX_free(mctx); EVP_MAC_free(mac); OSSL_LIB_CTX_free(library_context); - return rv; + return ret; } diff --git a/demos/mac/poly1305.c b/demos/mac/poly1305.c index 1aa95e583dad..15c9c0097d97 100644 --- a/demos/mac/poly1305.c +++ b/demos/mac/poly1305.c @@ -1,5 +1,5 @@ /* - * 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 @@ -83,7 +83,7 @@ static char *propq = NULL; int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; EVP_CIPHER *aes = NULL; EVP_CIPHER_CTX *aesctx = NULL; EVP_MAC *mac = NULL; @@ -196,14 +196,14 @@ int main(int argc, char **argv) goto end; } - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; end: EVP_CIPHER_CTX_free(aesctx); EVP_CIPHER_free(aes); EVP_MAC_CTX_free(mctx); EVP_MAC_free(mac); OSSL_LIB_CTX_free(library_context); - if (rv != EXIT_SUCCESS) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); - return rv; + return ret; } diff --git a/demos/mac/siphash.c b/demos/mac/siphash.c index 4d36a9d4868b..2fdbfb07be5d 100644 --- a/demos/mac/siphash.c +++ b/demos/mac/siphash.c @@ -1,5 +1,5 @@ /* - * 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 @@ -44,7 +44,7 @@ static char *propq = NULL; int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; EVP_MAC *mac = NULL; EVP_MAC_CTX *mctx = NULL; unsigned char out[8]; @@ -118,12 +118,12 @@ int main(int argc, char **argv) goto end; } - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; end: EVP_MAC_CTX_free(mctx); EVP_MAC_free(mac); OSSL_LIB_CTX_free(library_context); - if (rv != EXIT_SUCCESS) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); - return rv; + return ret; } diff --git a/demos/pkcs12/pkread.c b/demos/pkcs12/pkread.c index 3b153f8edf15..7deeef9ef009 100644 --- a/demos/pkcs12/pkread.c +++ b/demos/pkcs12/pkread.c @@ -105,7 +105,7 @@ int main(int argc, char **argv) OPENSSL_free(name); X509_free(cert); EVP_PKEY_free(pkey); - sk_X509_pop_free(ca, X509_free); + OSSL_STACK_OF_X509_free(ca); return ret; } diff --git a/demos/pkcs12/pkwrite.c b/demos/pkcs12/pkwrite.c index 51afd25a260d..7bb73f35a41e 100644 --- a/demos/pkcs12/pkwrite.c +++ b/demos/pkcs12/pkwrite.c @@ -1,5 +1,5 @@ /* - * Copyright 2000-2020 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 @@ -23,13 +23,13 @@ int main(int argc, char **argv) PKCS12 *p12; if (argc != 5) { fprintf(stderr, "Usage: pkwrite infile password name p12file\n"); - exit(1); + exit(EXIT_FAILURE); } OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); if ((fp = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[1]); - exit(1); + exit(EXIT_FAILURE); } cert = PEM_read_X509(fp, NULL, NULL, NULL); rewind(fp); @@ -39,15 +39,15 @@ int main(int argc, char **argv) if (!p12) { fprintf(stderr, "Error creating PKCS#12 structure\n"); ERR_print_errors_fp(stderr); - exit(1); + exit(EXIT_FAILURE); } if ((fp = fopen(argv[4], "wb")) == NULL) { fprintf(stderr, "Error opening file %s\n", argv[4]); ERR_print_errors_fp(stderr); - exit(1); + exit(EXIT_FAILURE); } i2d_PKCS12_fp(fp, p12); PKCS12_free(p12); fclose(fp); - return 0; + return EXIT_SUCCESS; } diff --git a/demos/pkey/EVP_PKEY_DSA_keygen.c b/demos/pkey/EVP_PKEY_DSA_keygen.c index bf74a2e6230a..c335752a7fb1 100644 --- a/demos/pkey/EVP_PKEY_DSA_keygen.c +++ b/demos/pkey/EVP_PKEY_DSA_keygen.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -21,7 +21,7 @@ * See the EVP_PKEY_DSA_paramgen demo if you need to * use non default parameters. */ -EVP_PKEY *dsa_genparams(OSSL_LIB_CTX *libctx, const char *propq) +static EVP_PKEY *dsa_genparams(OSSL_LIB_CTX *libctx, const char *propq) { EVP_PKEY *dsaparamkey = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -45,7 +45,7 @@ cleanup: int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; const char *propq = NULL; EVP_PKEY *dsaparamskey = NULL; @@ -74,10 +74,10 @@ int main(int argc, char **argv) if (!dsa_print_key(dsakey, 1, libctx, propq)) goto cleanup; - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; cleanup: EVP_PKEY_free(dsakey); EVP_PKEY_free(dsaparamskey); EVP_PKEY_CTX_free(ctx); - return rv; + return ret; } diff --git a/demos/pkey/EVP_PKEY_DSA_paramfromdata.c b/demos/pkey/EVP_PKEY_DSA_paramfromdata.c index 4c9e55820e94..ec7d69d54389 100644 --- a/demos/pkey/EVP_PKEY_DSA_paramfromdata.c +++ b/demos/pkey/EVP_PKEY_DSA_paramfromdata.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -19,7 +19,7 @@ int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; const char *propq = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -61,7 +61,7 @@ int main(int argc, char **argv) if (!dsa_print_key(dsaparamkey, 0, libctx, propq)) goto cleanup; - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; cleanup: EVP_PKEY_free(dsaparamkey); EVP_PKEY_CTX_free(ctx); @@ -71,5 +71,5 @@ cleanup: BN_free(q); BN_free(p); - return rv; + return ret; } diff --git a/demos/pkey/EVP_PKEY_DSA_paramgen.c b/demos/pkey/EVP_PKEY_DSA_paramgen.c index 05dda29c9667..ad879f0d7f8c 100644 --- a/demos/pkey/EVP_PKEY_DSA_paramgen.c +++ b/demos/pkey/EVP_PKEY_DSA_paramgen.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -17,7 +17,7 @@ int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; const char *propq = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -58,9 +58,9 @@ int main(int argc, char **argv) if (!dsa_print_key(dsaparamkey, 0, libctx, propq)) goto cleanup; - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; cleanup: EVP_PKEY_free(dsaparamkey); EVP_PKEY_CTX_free(ctx); - return rv; + return ret; } diff --git a/demos/pkey/EVP_PKEY_DSA_paramvalidate.c b/demos/pkey/EVP_PKEY_DSA_paramvalidate.c index f726d30fbf7f..ac7e7905f6f9 100644 --- a/demos/pkey/EVP_PKEY_DSA_paramvalidate.c +++ b/demos/pkey/EVP_PKEY_DSA_paramvalidate.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -47,16 +47,16 @@ static const char hexseed[] = "cba30ccd905aa7675a0b81769704bf3c" "ccf2ca1892b2eaf6b9e2b38d9bf6affc" "42ada55986d8a1772b442770954d0b65"; -const int gindex = 42; -const int pcounter = 363; +static const int gindex = 42; +static const int pcounter = 363; static const char digest[] = "SHA384"; /* * Create a new dsa param key that is the combination of an existing param key * plus extra parameters. */ -EVP_PKEY_CTX *create_merged_key(EVP_PKEY *dsaparams, const OSSL_PARAM *newparams, - OSSL_LIB_CTX *libctx, const char *propq) +static EVP_PKEY_CTX *create_merged_key(EVP_PKEY *dsaparams, const OSSL_PARAM *newparams, + OSSL_LIB_CTX *libctx, const char *propq) { EVP_PKEY_CTX *out = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -102,7 +102,7 @@ cleanup: int main(int argc, char **argv) { - int rv = EXIT_FAILURE; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; const char *propq = NULL; EVP_PKEY *dsaparamskey = NULL; @@ -145,7 +145,7 @@ int main(int argc, char **argv) * a proper FIPS 186-4 key validation which requires extra parameters */ if (EVP_PKEY_param_check(ctx) <= 0) { - fprintf(stderr, "Simple EVP_PKEY_param_check() failed \n"); + fprintf(stderr, "Simple EVP_PKEY_param_check() failed\n"); goto cleanup; } @@ -191,12 +191,12 @@ int main(int argc, char **argv) if (!dsa_print_key(EVP_PKEY_CTX_get0_pkey(ctx2), 0, libctx, propq)) goto cleanup; - rv = EXIT_SUCCESS; + ret = EXIT_SUCCESS; cleanup: EVP_PKEY_free(dsaparamskey); EVP_PKEY_CTX_free(ctx2); EVP_PKEY_CTX_free(ctx1); EVP_PKEY_CTX_free(ctx); BIO_free(in); - return rv; + return ret; } diff --git a/demos/pkey/EVP_PKEY_EC_keygen.c b/demos/pkey/EVP_PKEY_EC_keygen.c index fa862bdaa07e..76c6217975e0 100644 --- a/demos/pkey/EVP_PKEY_EC_keygen.c +++ b/demos/pkey/EVP_PKEY_EC_keygen.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -84,7 +84,7 @@ cleanup: */ static int get_key_values(EVP_PKEY *pkey) { - int result = 0; + int ret = 0; char out_curvename[80]; unsigned char out_pubkey[80]; unsigned char out_privkey[80]; @@ -122,16 +122,16 @@ static int get_key_values(EVP_PKEY *pkey) fprintf(stdout, "Private Key:\n"); BIO_dump_indent_fp(stdout, out_privkey, out_privkey_len, 2); - result = 1; + ret = 1; cleanup: /* Zeroize the private key data when we free it */ BN_clear_free(out_priv); - return result; + return ret; } int main(void) { - int result = 0; + int ret = EXIT_FAILURE; EVP_PKEY *pkey; pkey = do_ec_keygen(); @@ -145,11 +145,11 @@ int main(void) * At this point we can write out the generated key using * i2d_PrivateKey() and i2d_PublicKey() if required. */ - result = 1; + ret = EXIT_SUCCESS; cleanup: - if (result != 1) + if (ret != EXIT_SUCCESS) ERR_print_errors_fp(stderr); EVP_PKEY_free(pkey); - return result == 0; + return ret; } diff --git a/demos/pkey/EVP_PKEY_RSA_keygen.c b/demos/pkey/EVP_PKEY_RSA_keygen.c index fbecfb6bdb0a..62dd8405e77b 100644 --- a/demos/pkey/EVP_PKEY_RSA_keygen.c +++ b/demos/pkey/EVP_PKEY_RSA_keygen.c @@ -1,5 +1,5 @@ /*- - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -83,7 +83,7 @@ static EVP_PKEY *generate_rsa_key_long(OSSL_LIB_CTX *libctx, unsigned int bits) * you can set a progress callback using EVP_PKEY_set_cb; see the example in * EVP_PKEY_generate(3). */ - fprintf(stderr, "Generating RSA key, this may take some time...\n"); + fprintf(stdout, "Generating RSA key, this may take some time...\n"); if (EVP_PKEY_generate(genctx, &pkey) <= 0) { fprintf(stderr, "EVP_PKEY_generate() failed\n"); goto cleanup; @@ -109,7 +109,7 @@ static EVP_PKEY *generate_rsa_key_short(OSSL_LIB_CTX *libctx, unsigned int bits) { EVP_PKEY *pkey = NULL; - fprintf(stderr, "Generating RSA key, this may take some time...\n"); + fprintf(stdout, "Generating RSA key, this may take some time...\n"); pkey = EVP_PKEY_Q_keygen(libctx, propq, "RSA", (size_t)bits); if (pkey == NULL) @@ -123,7 +123,7 @@ static EVP_PKEY *generate_rsa_key_short(OSSL_LIB_CTX *libctx, unsigned int bits) */ static int dump_key(const EVP_PKEY *pkey) { - int rv = 0; + int ret = 0; int bits = 0; BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; @@ -189,7 +189,7 @@ static int dump_key(const EVP_PKEY *pkey) /* Output hexadecimal representations of the BIGNUM objects. */ fprintf(stdout, "\nNumber of bits: %d\n\n", bits); - fprintf(stderr, "Public values:\n"); + fprintf(stdout, "Public values:\n"); fprintf(stdout, " n = 0x"); BN_print_fp(stdout, n); fprintf(stdout, "\n"); @@ -227,19 +227,19 @@ static int dump_key(const EVP_PKEY *pkey) goto cleanup; } - rv = 1; + ret = 1; cleanup: BN_free(n); /* not secret */ BN_free(e); /* not secret */ BN_clear_free(d); /* secret - scrub before freeing */ BN_clear_free(p); /* secret - scrub before freeing */ BN_clear_free(q); /* secret - scrub before freeing */ - return rv; + return ret; } int main(int argc, char **argv) { - int rv = 1; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; EVP_PKEY *pkey = NULL; unsigned int bits = 4096; @@ -256,7 +256,7 @@ int main(int argc, char **argv) bits_i = atoi(argv[1]); if (bits < 512) { fprintf(stderr, "Invalid RSA key size\n"); - return 1; + return EXIT_FAILURE; } bits = (unsigned int)bits_i; @@ -281,9 +281,9 @@ int main(int argc, char **argv) goto cleanup; } - rv = 0; + ret = EXIT_SUCCESS; cleanup: EVP_PKEY_free(pkey); OSSL_LIB_CTX_free(libctx); - return rv; + return ret; } diff --git a/demos/pkey/Makefile b/demos/pkey/Makefile index 9e7013003d61..e7859641870a 100644 --- a/demos/pkey/Makefile +++ b/demos/pkey/Makefile @@ -1,37 +1,44 @@ # -# To run the demos when linked with a shared library (default): +# To run the demos when linked with a shared library (default) ensure that +# libcrypto is on the library path. For example: # # LD_LIBRARY_PATH=../.. ./EVP_PKEY_EC_keygen -# LD_LIBRARY_PATH=../.. ./EVP_PKEY_RSA_keygen -# LD_LIBRARY_PATH=../.. ./EVP_PKEY_DSA_keygen -# LD_LIBRARY_PATH=../.. ./EVP_PKEY_DSA_paramgen -# LD_LIBRARY_PATH=../.. ./EVP_PKEY_DSA_paramvalidate -# LD_LIBRARY_PATH=../.. ./EVP_PKEY_DSA_paramfromdata -CFLAGS = -I../../include -g -Wall +TESTS = EVP_PKEY_EC_keygen \ + EVP_PKEY_RSA_keygen \ + EVP_PKEY_DSA_keygen \ + EVP_PKEY_DSA_paramgen \ + EVP_PKEY_DSA_paramvalidate \ + EVP_PKEY_DSA_paramfromdata + +CFLAGS = -I../../include -g -Wall LDFLAGS = -L../.. -LDLIBS = -lcrypto +LDLIBS = -lcrypto -all: EVP_PKEY_EC_keygen EVP_PKEY_RSA_keygen EVP_PKEY_DSA_keygen \ - EVP_PKEY_DSA_paramgen EVP_PKEY_DSA_paramvalidate EVP_PKEY_DSA_paramfromdata \ +all: $(TESTS) -%.o: %.c dsa.inc - $(CC) $(CFLAGS) -c $< +EVP_PKEY_DSA_keygen.o: EVP_PKEY_DSA_keygen.c dsa.inc +EVP_PKEY_DSA_paramgen.o: EVP_PKEY_DSA_paramgen.c dsa.inc +EVP_PKEY_DSA_paramvalidate.o: EVP_PKEY_DSA_paramvalidate.c dsa.inc +EVP_PKEY_DSA_paramfromdata.o: EVP_PKEY_DSA_paramfromdata.c dsa.inc EVP_PKEY_EC_keygen: EVP_PKEY_EC_keygen.o - EVP_PKEY_RSA_keygen: EVP_PKEY_RSA_keygen.o - EVP_PKEY_DSA_keygen: EVP_PKEY_DSA_keygen.o - EVP_PKEY_DSA_paramgen: EVP_PKEY_DSA_paramgen.o - EVP_PKEY_DSA_paramvalidate: EVP_PKEY_DSA_paramvalidate.o - EVP_PKEY_DSA_paramfromdata: EVP_PKEY_DSA_paramfromdata.o -test: ; +$(TESTS): + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) clean: - $(RM) *.o EVP_PKEY_EC_keygen EVP_PKEY_RSA_keygen EVP_PKEY_DSA_keygen \ - EVP_PKEY_DSA_paramgen EVP_PKEY_DSA_paramfromdata EVP_PKEY_DSA_paramvalidate + $(RM) *.o $(TESTS) + +.PHONY: test +test: all + @echo "\nPKEY tests:" + @set -e; for tst in $(TESTS); do \ + echo "\n"$$tst; \ + LD_LIBRARY_PATH=../.. ./$$tst; \ + done diff --git a/demos/signature/EVP_Signature_demo.c b/demos/signature/EVP_Signature_demo.c deleted file mode 100644 index 123c95c26ad8..000000000000 --- a/demos/signature/EVP_Signature_demo.c +++ /dev/null @@ -1,235 +0,0 @@ -/*- - * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * An example that uses the EVP_MD*, EVP_DigestSign* and EVP_DigestVerify* - * methods to calculate and verify a signature of two static buffers. - */ - -#include -#include -#include -#include -#include -#include "EVP_Signature_demo.h" - -/* - * This demonstration will calculate and verify a signature of data using - * the soliloquy from Hamlet scene 1 act 3 - */ - -static const char *hamlet_1 = - "To be, or not to be, that is the question,\n" - "Whether tis nobler in the minde to suffer\n" - "The slings and arrowes of outragious fortune,\n" - "Or to take Armes again in a sea of troubles,\n" -; -static const char *hamlet_2 = - "And by opposing, end them, to die to sleep;\n" - "No more, and by a sleep, to say we end\n" - "The heart-ache, and the thousand natural shocks\n" - "That flesh is heir to? tis a consumation\n" -; - -/* - * For demo_sign, load EC private key priv_key from priv_key_der[]. - * For demo_verify, load EC public key pub_key from pub_key_der[]. - */ -static EVP_PKEY *get_key(OSSL_LIB_CTX *libctx, const char *propq, int public) -{ - OSSL_DECODER_CTX *dctx = NULL; - EVP_PKEY *pkey = NULL; - int selection; - const unsigned char *data; - size_t data_len; - - if (public) { - selection = EVP_PKEY_PUBLIC_KEY; - data = pub_key_der; - data_len = sizeof(pub_key_der); - } else { - selection = EVP_PKEY_KEYPAIR; - data = priv_key_der; - data_len = sizeof(priv_key_der); - } - dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "EC", - selection, libctx, propq); - (void)OSSL_DECODER_from_data(dctx, &data, &data_len); - OSSL_DECODER_CTX_free(dctx); - if (pkey == NULL) - fprintf(stderr, "Failed to load %s key.\n", public ? "public" : "private"); - return pkey; -} - -static int demo_sign(OSSL_LIB_CTX *libctx, const char *sig_name, - size_t *sig_out_len, unsigned char **sig_out_value) -{ - int result = 0, public = 0; - size_t sig_len; - unsigned char *sig_value = NULL; - const char *propq = NULL; - EVP_MD_CTX *sign_context = NULL; - EVP_PKEY *priv_key = NULL; - - /* Get private key */ - priv_key = get_key(libctx, propq, public); - if (priv_key == NULL) { - fprintf(stderr, "Get private key failed.\n"); - goto cleanup; - } - /* - * Make a message signature context to hold temporary state - * during signature creation - */ - sign_context = EVP_MD_CTX_new(); - if (sign_context == NULL) { - fprintf(stderr, "EVP_MD_CTX_new failed.\n"); - goto cleanup; - } - /* - * Initialize the sign context to use the fetched - * sign provider. - */ - if (!EVP_DigestSignInit_ex(sign_context, NULL, sig_name, - libctx, NULL, priv_key, NULL)) { - fprintf(stderr, "EVP_DigestSignInit_ex failed.\n"); - goto cleanup; - } - /* - * EVP_DigestSignUpdate() can be called several times on the same context - * to include additional data. - */ - if (!EVP_DigestSignUpdate(sign_context, hamlet_1, strlen(hamlet_1))) { - fprintf(stderr, "EVP_DigestSignUpdate(hamlet_1) failed.\n"); - goto cleanup; - } - if (!EVP_DigestSignUpdate(sign_context, hamlet_2, strlen(hamlet_2))) { - fprintf(stderr, "EVP_DigestSignUpdate(hamlet_2) failed.\n"); - goto cleanup; - } - /* Call EVP_DigestSignFinal to get signature length sig_len */ - if (!EVP_DigestSignFinal(sign_context, NULL, &sig_len)) { - fprintf(stderr, "EVP_DigestSignFinal failed.\n"); - goto cleanup; - } - if (sig_len <= 0) { - fprintf(stderr, "EVP_DigestSignFinal returned invalid signature length.\n"); - goto cleanup; - } - sig_value = OPENSSL_malloc(sig_len); - if (sig_value == NULL) { - fprintf(stderr, "No memory.\n"); - goto cleanup; - } - if (!EVP_DigestSignFinal(sign_context, sig_value, &sig_len)) { - fprintf(stderr, "EVP_DigestSignFinal failed.\n"); - goto cleanup; - } - *sig_out_len = sig_len; - *sig_out_value = sig_value; - fprintf(stdout, "Generating signature:\n"); - BIO_dump_indent_fp(stdout, sig_value, sig_len, 2); - fprintf(stdout, "\n"); - result = 1; - -cleanup: - /* OpenSSL free functions will ignore NULL arguments */ - if (!result) - OPENSSL_free(sig_value); - EVP_PKEY_free(priv_key); - EVP_MD_CTX_free(sign_context); - return result; -} - -static int demo_verify(OSSL_LIB_CTX *libctx, const char *sig_name, - size_t sig_len, unsigned char *sig_value) -{ - int result = 0, public = 1; - const char *propq = NULL; - EVP_MD_CTX *verify_context = NULL; - EVP_PKEY *pub_key = NULL; - - /* - * Make a verify signature context to hold temporary state - * during signature verification - */ - verify_context = EVP_MD_CTX_new(); - if (verify_context == NULL) { - fprintf(stderr, "EVP_MD_CTX_new failed.\n"); - goto cleanup; - } - /* Get public key */ - pub_key = get_key(libctx, propq, public); - if (pub_key == NULL) { - fprintf(stderr, "Get public key failed.\n"); - goto cleanup; - } - /* Verify */ - if (!EVP_DigestVerifyInit_ex(verify_context, NULL, sig_name, - libctx, NULL, pub_key, NULL)) { - fprintf(stderr, "EVP_DigestVerifyInit failed.\n"); - goto cleanup; - } - /* - * EVP_DigestVerifyUpdate() can be called several times on the same context - * to include additional data. - */ - if (!EVP_DigestVerifyUpdate(verify_context, hamlet_1, strlen(hamlet_1))) { - fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_1) failed.\n"); - goto cleanup; - } - if (!EVP_DigestVerifyUpdate(verify_context, hamlet_2, strlen(hamlet_2))) { - fprintf(stderr, "EVP_DigestVerifyUpdate(hamlet_2) failed.\n"); - goto cleanup; - } - if (EVP_DigestVerifyFinal(verify_context, sig_value, sig_len) <= 0) { - fprintf(stderr, "EVP_DigestVerifyFinal failed.\n"); - goto cleanup; - } - fprintf(stdout, "Signature verified.\n"); - result = 1; - -cleanup: - /* OpenSSL free functions will ignore NULL arguments */ - EVP_PKEY_free(pub_key); - EVP_MD_CTX_free(verify_context); - return result; -} - -int main(void) -{ - OSSL_LIB_CTX *libctx = NULL; - const char *sig_name = "SHA3-512"; - size_t sig_len = 0; - unsigned char *sig_value = NULL; - int result = 0; - - libctx = OSSL_LIB_CTX_new(); - if (libctx == NULL) { - fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n"); - goto cleanup; - } - if (!demo_sign(libctx, sig_name, &sig_len, &sig_value)) { - fprintf(stderr, "demo_sign failed.\n"); - goto cleanup; - } - if (!demo_verify(libctx, sig_name, sig_len, sig_value)) { - fprintf(stderr, "demo_verify failed.\n"); - goto cleanup; - } - result = 1; - -cleanup: - if (result != 1) - ERR_print_errors_fp(stderr); - /* OpenSSL free functions will ignore NULL arguments */ - OSSL_LIB_CTX_free(libctx); - OPENSSL_free(sig_value); - return result == 0; -} diff --git a/demos/signature/EVP_Signature_demo.h b/demos/signature/EVP_Signature_demo.h deleted file mode 100644 index aef3e60783e8..000000000000 --- a/demos/signature/EVP_Signature_demo.h +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* Signers private EC key */ -static const unsigned char priv_key_der[] = { -0x30, 0x82, 0x01, 0x68, 0x02, 0x01, 0x01, 0x04, 0x20, 0x51, 0x77, 0xae, -0xf4, 0x18, 0xf4, 0x6b, 0xc4, 0xe5, 0xbb, 0xe9, 0xe6, 0x9e, 0x6d, 0xb0, -0xea, 0x12, 0xf9, 0xf3, 0xdb, 0x9d, 0x56, 0x59, 0xf7, 0x5a, 0x17, 0xd7, -0xd1, 0xe4, 0xd7, 0x47, 0x28, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02, -0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, -0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, -0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, -0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, -0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, -0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, -0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, -0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, -0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, -0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, -0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, -0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, -0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, -0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, -0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, -0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, -0x4f, 0xe7, 0x7b, 0xb6, 0xbb, 0x54, 0x42, 0x39, 0xed, 0x5d, 0xe5, 0x40, -0xc8, 0xd8, 0x71, 0xca, 0x6d, 0x83, 0x71, 0xd1, 0x88, 0x2a, 0x65, 0x00, -0x6c, 0xc6, 0x2f, 0x01, 0x31, 0x49, 0xbe, 0x76, 0x7a, 0x67, 0x6a, 0x28, -0x33, 0xc7, 0x5b, 0xb9, 0x24, 0x45, 0x24, 0x6e, 0xf0, 0x6d, 0x2f, 0x34, -0x06, 0x53, 0x73, 0x6a, 0xff, 0x90, 0x90, 0xc1, 0x6d, 0x9b, 0x94, 0x0d, -0x0e, 0x1f, 0x95, 0x65, -}; - -/* The matching public key used for verifying */ -static const unsigned char pub_key_der[] = { -0x30, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2a, 0x86, -0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, -0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, -0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, -0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x5a, -0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, -0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, -0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, -0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d, -0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, -0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, -0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, -0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, -0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, -0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, -0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, -0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, -0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xe7, 0x7b, 0xb6, 0xbb, -0x54, 0x42, 0x39, 0xed, 0x5d, 0xe5, 0x40, 0xc8, 0xd8, 0x71, 0xca, 0x6d, -0x83, 0x71, 0xd1, 0x88, 0x2a, 0x65, 0x00, 0x6c, 0xc6, 0x2f, 0x01, 0x31, -0x49, 0xbe, 0x76, 0x7a, 0x67, 0x6a, 0x28, 0x33, 0xc7, 0x5b, 0xb9, 0x24, -0x45, 0x24, 0x6e, 0xf0, 0x6d, 0x2f, 0x34, 0x06, 0x53, 0x73, 0x6a, 0xff, -0x90, 0x90, 0xc1, 0x6d, 0x9b, 0x94, 0x0d, 0x0e, 0x1f, 0x95, 0x65, -}; - diff --git a/demos/signature/Makefile b/demos/signature/Makefile index 563ec7799fb8..4f02b07d7379 100644 --- a/demos/signature/Makefile +++ b/demos/signature/Makefile @@ -1,22 +1,37 @@ # -# To run the demos when linked with a shared library (default): +# To run the demos when linked with a shared library (default) ensure +# that libcrypto is on the library path. For example: # -# LD_LIBRARY_PATH=../.. ./EVP_Signature_demo +# LD_LIBRARY_PATH=../.. ./EVP_EC_Signature_demo -CFLAGS = -I../../include -g -Wall +TESTS = EVP_EC_Signature_demo \ + EVP_DSA_Signature_demo \ + EVP_ED_Signature_demo \ + rsa_pss_direct \ + rsa_pss_hash + +CFLAGS = -I../../include -g -Wall LDFLAGS = -L../.. -LDLIBS = -lcrypto +LDLIBS = -lcrypto -all: EVP_Signature_demo rsa_pss_direct rsa_pss_hash +all: $(TESTS) -%.o: %.c - $(CC) $(CFLAGS) -c $< - -EVP_Signature_demo: EVP_Signature_demo.o +EVP_EC_Signature_demo: EVP_EC_Signature_demo.o +EVP_DSA_Signature_demo: EVP_DSA_Signature_demo.o +EVP_ED_Signature_demo: EVP_ED_Signature_demo.o rsa_pss_direct: rsa_pss_direct.o rsa_pss_hash: rsa_pss_hash.o -test: ; +$(TESTS): + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) clean: - $(RM) *.o EVP_Signature_demo rsa_pss_direct rsa_pss_hash + $(RM) *.o $(TESTS) + +.PHONY: test +test: all + @echo "\nSignature tests:" + @set -e; for tst in $(TESTS); do \ + echo "\n"$$tst; \ + LD_LIBRARY_PATH=../.. ./$$tst; \ + done diff --git a/demos/signature/rsa_pss_direct.c b/demos/signature/rsa_pss_direct.c index 1ecfa9d89747..097ad69f24b6 100644 --- a/demos/signature/rsa_pss_direct.c +++ b/demos/signature/rsa_pss_direct.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -37,7 +37,7 @@ static const char *propq = NULL; */ static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len) { - int rv = 0; + int ret = 0; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_MD *md = NULL; @@ -105,16 +105,16 @@ static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len) goto end; } - rv = 1; + ret = 1; end: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); EVP_MD_free(md); - if (rv == 0) + if (ret == 0) OPENSSL_free(*sig); - return rv; + return ret; } /* @@ -123,7 +123,7 @@ end: */ static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len) { - int rv = 0; + int ret = 0; const unsigned char *ppub_key = NULL; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; @@ -175,17 +175,17 @@ static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len goto end; } - rv = 1; + ret = 1; end: EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); EVP_MD_free(md); - return rv; + return ret; } int main(int argc, char **argv) { - int rv = 1; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; unsigned char *sig = NULL; size_t sig_len = 0; @@ -196,9 +196,11 @@ int main(int argc, char **argv) if (verify(libctx, sig, sig_len) == 0) goto end; - rv = 0; + printf("Success\n"); + + ret = EXIT_SUCCESS; end: OPENSSL_free(sig); OSSL_LIB_CTX_free(libctx); - return rv; + return ret; } diff --git a/demos/signature/rsa_pss_hash.c b/demos/signature/rsa_pss_hash.c index e1d4e7cc9d0b..57d5c5ae195c 100644 --- a/demos/signature/rsa_pss_hash.c +++ b/demos/signature/rsa_pss_hash.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2022-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 @@ -32,7 +32,7 @@ static const char *propq = NULL; */ static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len) { - int rv = 0; + int ret = 0; EVP_PKEY *pkey = NULL; EVP_MD_CTX *mctx = NULL; OSSL_PARAM params[2], *p = params; @@ -95,15 +95,15 @@ static int sign(OSSL_LIB_CTX *libctx, unsigned char **sig, size_t *sig_len) goto end; } - rv = 1; + ret = 1; end: EVP_MD_CTX_free(mctx); EVP_PKEY_free(pkey); - if (rv == 0) + if (ret == 0) OPENSSL_free(*sig); - return rv; + return ret; } /* @@ -113,7 +113,7 @@ end: */ static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len) { - int rv = 0; + int ret = 0; EVP_PKEY *pkey = NULL; EVP_MD_CTX *mctx = NULL; OSSL_PARAM params[2], *p = params; @@ -161,16 +161,16 @@ static int verify(OSSL_LIB_CTX *libctx, const unsigned char *sig, size_t sig_len goto end; } - rv = 1; + ret = 1; end: EVP_MD_CTX_free(mctx); EVP_PKEY_free(pkey); - return rv; + return ret; } int main(int argc, char **argv) { - int rv = 1; + int ret = EXIT_FAILURE; OSSL_LIB_CTX *libctx = NULL; unsigned char *sig = NULL; size_t sig_len = 0; @@ -181,9 +181,11 @@ int main(int argc, char **argv) if (verify(libctx, sig, sig_len) == 0) goto end; - rv = 0; + printf("Success\n"); + + ret = EXIT_SUCCESS; end: OPENSSL_free(sig); OSSL_LIB_CTX_free(libctx); - return rv; + return ret; } diff --git a/demos/smime/smdec.c b/demos/smime/smdec.c index debcedd5e866..f27c353f4046 100644 --- a/demos/smime/smdec.c +++ b/demos/smime/smdec.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2016 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 @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *rcert = NULL; EVP_PKEY *rkey = NULL; PKCS7 *p7 = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -31,7 +31,8 @@ int main(int argc, char **argv) rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -59,10 +60,11 @@ int main(int argc, char **argv) if (!PKCS7_decrypt(p7, rkey, rcert, out, 0)) goto err; - ret = 0; + printf("Success\n"); + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } @@ -74,5 +76,4 @@ int main(int argc, char **argv) BIO_free(tbio); return ret; - } diff --git a/demos/smime/smenc.c b/demos/smime/smenc.c index 0714dddfd2c9..2113e12d1cda 100644 --- a/demos/smime/smenc.c +++ b/demos/smime/smenc.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2016 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 @@ -18,10 +18,9 @@ int main(int argc, char **argv) X509 *rcert = NULL; STACK_OF(X509) *recips = NULL; PKCS7 *p7 = NULL; - int ret = 1; + int ret = EXIT_FAILURE; /* - * On OpenSSL 0.9.9 only: * for streaming set PKCS7_STREAM */ int flags = PKCS7_STREAM; @@ -47,8 +46,8 @@ int main(int argc, char **argv) goto err; /* - * sk_X509_pop_free will free up recipient STACK and its contents so set - * rcert to NULL so it isn't freed up twice. + * OSSL_STACK_OF_X509_free() will free up recipient STACK and its contents + * so set rcert to NULL so it isn't freed up twice. */ rcert = NULL; @@ -73,19 +72,19 @@ int main(int argc, char **argv) if (!SMIME_write_PKCS7(out, p7, in, flags)) goto err; - ret = 0; + printf("Success\n"); + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Encrypting Data\n"); ERR_print_errors_fp(stderr); } PKCS7_free(p7); X509_free(rcert); - sk_X509_pop_free(recips, X509_free); + OSSL_STACK_OF_X509_free(recips); BIO_free(in); BIO_free(out); BIO_free(tbio); return ret; - } diff --git a/demos/smime/smsign.c b/demos/smime/smsign.c index ac2c27b52591..3e27c931f6be 100644 --- a/demos/smime/smsign.c +++ b/demos/smime/smsign.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2016 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 @@ -18,10 +18,10 @@ int main(int argc, char **argv) X509 *scert = NULL; EVP_PKEY *skey = NULL; PKCS7 *p7 = NULL; - int ret = 1; + int ret = EXIT_FAILURE; /* - * For simple S/MIME signing use PKCS7_DETACHED. On OpenSSL 0.9.9 only: + * For simple S/MIME signing use PKCS7_DETACHED. * for streaming detached set PKCS7_DETACHED|PKCS7_STREAM for streaming * non-detached set PKCS7_STREAM */ @@ -38,7 +38,8 @@ int main(int argc, char **argv) scert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -62,17 +63,20 @@ int main(int argc, char **argv) if (!out) goto err; - if (!(flags & PKCS7_STREAM)) - BIO_reset(in); + if (!(flags & PKCS7_STREAM)) { + if (BIO_reset(in) < 0) + goto err; + } /* Write out S/MIME message */ if (!SMIME_write_PKCS7(out, p7, in, flags)) goto err; - ret = 0; + printf("Success\n"); + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } @@ -84,5 +88,4 @@ int main(int argc, char **argv) BIO_free(tbio); return ret; - } diff --git a/demos/smime/smsign2.c b/demos/smime/smsign2.c index a9e70257481b..5ad86f15f86e 100644 --- a/demos/smime/smsign2.c +++ b/demos/smime/smsign2.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2016 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 @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -/* S/MIME signing example: 2 signers. OpenSSL 0.9.9 only */ +/* S/MIME signing example: 2 signers */ #include #include #include @@ -18,7 +18,7 @@ int main(int argc, char **argv) X509 *scert = NULL, *scert2 = NULL; EVP_PKEY *skey = NULL, *skey2 = NULL; PKCS7 *p7 = NULL; - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -30,7 +30,8 @@ int main(int argc, char **argv) scert = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -43,7 +44,8 @@ int main(int argc, char **argv) scert2 = PEM_read_bio_X509(tbio, NULL, 0, NULL); - BIO_reset(tbio); + if (BIO_reset(tbio) < 0) + goto err; skey2 = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL); @@ -77,10 +79,11 @@ int main(int argc, char **argv) if (!SMIME_write_PKCS7(out, p7, in, PKCS7_STREAM)) goto err; - ret = 0; + printf("Success\n"); + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Signing Data\n"); ERR_print_errors_fp(stderr); } diff --git a/demos/smime/smver.c b/demos/smime/smver.c index 5d552b18082a..caa9ed304ff0 100644 --- a/demos/smime/smver.c +++ b/demos/smime/smver.c @@ -1,5 +1,5 @@ /* - * Copyright 2007-2016 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 @@ -18,8 +18,7 @@ int main(int argc, char **argv) X509_STORE *st = NULL; X509 *cacert = NULL; PKCS7 *p7 = NULL; - - int ret = 1; + int ret = EXIT_FAILURE; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -67,12 +66,11 @@ int main(int argc, char **argv) goto err; } - fprintf(stderr, "Verification Successful\n"); - - ret = 0; + printf("Verification Successful\n"); + ret = EXIT_SUCCESS; err: - if (ret) { + if (ret != EXIT_SUCCESS) { fprintf(stderr, "Error Verifying Data\n"); ERR_print_errors_fp(stderr); } diff --git a/doc/HOWTO/certificates.txt b/doc/HOWTO/certificates.txt index 82ce502a1d3d..49ff96cbaf45 100644 --- a/doc/HOWTO/certificates.txt +++ b/doc/HOWTO/certificates.txt @@ -48,7 +48,7 @@ give you the result back, thus making it authentic according to their policies). A certificate request is sent to a certificate authority to get it signed into a certificate. You can also sign the certificate yourself if you have your own certificate authority or create a -self-signed certificate (typically for testing purpose). +self-signed certificate (typically for testing purposes). The certificate request is created like this: diff --git a/doc/HOWTO/keys.txt b/doc/HOWTO/keys.txt index c4a74c54fcb8..1132fe7507ba 100644 --- a/doc/HOWTO/keys.txt +++ b/doc/HOWTO/keys.txt @@ -90,16 +90,41 @@ or openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 +5. To generate an ML-DSA key -5. NOTE +An ML-DSA key can be used for signing (and verification via the public key) +only. + +Generating a key for the ML-DSA algorithm is a one-step process. + + openssl genpkey -algorithm ML-DSA-44 -out key.pem + openssl genpkey -algorithm ML-DSA-65 -out key.pem + openssl genpkey -algorithm ML-DSA-87 -out key.pem + +See L for more detail. + +6. To generate an ML-KEM key + +An ML-KEM key can be used for decapsulation (and encapsulation via the public +key) only. + +Generating a key for the ML-KEM algorithm is a one-step process. + + openssl genpkey -algorithm ML-KEM-512 -out key.pem + openssl genpkey -algorithm ML-KEM-768 -out key.pem + openssl genpkey -algorithm ML-KEM-1024 -out key.pem + +See L for more detail. + +7. NOTE If you intend to use the key together with a server certificate, it may be reasonable to avoid protecting it with a password, since otherwise someone would have to type in the password every time the server needs to access the key. -For X25519 and X448, it's treated as a distinct algorithm but not as one of -the curves listed with 'ecparam -list_curves' option. You can use -the following command to generate an X25519 key: +X25519, X448, Ed25519 and Ed448 are treated as distinct algorithms and not as +one of the EC curves listed with 'ecparam -list_curves' option. You can use the +following command to generate an X25519 key: openssl genpkey -algorithm X25519 -out xkey.pem diff --git a/doc/README.md b/doc/README.md index 12bb37ddb8fc..d999b0262b76 100644 --- a/doc/README.md +++ b/doc/README.md @@ -6,10 +6,6 @@ README.md This file [fingerprints.txt](fingerprints.txt) PGP fingerprints of authorised release signers -standards.txt -standards.txt - Moved to the web, - [HOWTO/](HOWTO/) A few how-to documents; not necessarily up-to-date @@ -27,4 +23,4 @@ standards.txt Algorithm specific EVP_PKEY documentation. Formatted versions of the manpages (apps,ssl,crypto) can be found at - + diff --git a/doc/build.info b/doc/build.info index 0279e2390a32..bff57d5d50fb 100644 --- a/doc/build.info +++ b/doc/build.info @@ -280,6 +280,12 @@ 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-skeyutl.html]=man1/openssl-skeyutl.pod +GENERATE[html/man1/openssl-skeyutl.html]=man1/openssl-skeyutl.pod +DEPEND[man/man1/openssl-skeyutl.1]=man1/openssl-skeyutl.pod +GENERATE[man/man1/openssl-skeyutl.1]=man1/openssl-skeyutl.pod +DEPEND[man1/openssl-skeyutl.pod]{pod}=man1/openssl-skeyutl.pod.in +GENERATE[man1/openssl-skeyutl.pod]=man1/openssl-skeyutl.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 @@ -395,6 +401,7 @@ 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-skeyutl.html \ html/man1/openssl-smime.html \ html/man1/openssl-speed.html \ html/man1/openssl-spkac.html \ @@ -455,6 +462,7 @@ 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-skeyutl.1 \ man/man1/openssl-smime.1 \ man/man1/openssl-speed.1 \ man/man1/openssl-spkac.1 \ @@ -607,6 +615,10 @@ 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_get_rpoll_descriptor.html]=man3/BIO_get_rpoll_descriptor.pod +GENERATE[html/man3/BIO_get_rpoll_descriptor.html]=man3/BIO_get_rpoll_descriptor.pod +DEPEND[man/man3/BIO_get_rpoll_descriptor.3]=man3/BIO_get_rpoll_descriptor.pod +GENERATE[man/man3/BIO_get_rpoll_descriptor.3]=man3/BIO_get_rpoll_descriptor.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 @@ -655,6 +667,10 @@ 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_dgram_pair.html]=man3/BIO_s_dgram_pair.pod +GENERATE[html/man3/BIO_s_dgram_pair.html]=man3/BIO_s_dgram_pair.pod +DEPEND[man/man3/BIO_s_dgram_pair.3]=man3/BIO_s_dgram_pair.pod +GENERATE[man/man3/BIO_s_dgram_pair.3]=man3/BIO_s_dgram_pair.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 @@ -675,6 +691,10 @@ 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_sendmmsg.html]=man3/BIO_sendmmsg.pod +GENERATE[html/man3/BIO_sendmmsg.html]=man3/BIO_sendmmsg.pod +DEPEND[man/man3/BIO_sendmmsg.3]=man3/BIO_sendmmsg.pod +GENERATE[man/man3/BIO_sendmmsg.3]=man3/BIO_sendmmsg.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 @@ -771,6 +791,10 @@ 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/CMAC_CTX.html]=man3/CMAC_CTX.pod +GENERATE[html/man3/CMAC_CTX.html]=man3/CMAC_CTX.pod +DEPEND[man/man3/CMAC_CTX.3]=man3/CMAC_CTX.pod +GENERATE[man/man3/CMAC_CTX.3]=man3/CMAC_CTX.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 @@ -859,6 +883,10 @@ 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/COMP_CTX_new.html]=man3/COMP_CTX_new.pod +GENERATE[html/man3/COMP_CTX_new.html]=man3/COMP_CTX_new.pod +DEPEND[man/man3/COMP_CTX_new.3]=man3/COMP_CTX_new.pod +GENERATE[man/man3/COMP_CTX_new.3]=man3/COMP_CTX_new.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 @@ -991,6 +1019,14 @@ 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_get_timeout.html]=man3/DTLSv1_get_timeout.pod +GENERATE[html/man3/DTLSv1_get_timeout.html]=man3/DTLSv1_get_timeout.pod +DEPEND[man/man3/DTLSv1_get_timeout.3]=man3/DTLSv1_get_timeout.pod +GENERATE[man/man3/DTLSv1_get_timeout.3]=man3/DTLSv1_get_timeout.pod +DEPEND[html/man3/DTLSv1_handle_timeout.html]=man3/DTLSv1_handle_timeout.pod +GENERATE[html/man3/DTLSv1_handle_timeout.html]=man3/DTLSv1_handle_timeout.pod +DEPEND[man/man3/DTLSv1_handle_timeout.3]=man3/DTLSv1_handle_timeout.pod +GENERATE[man/man3/DTLSv1_handle_timeout.3]=man3/DTLSv1_handle_timeout.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 @@ -1175,6 +1211,10 @@ 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_get_algor.html]=man3/EVP_PKEY_CTX_get_algor.pod +GENERATE[html/man3/EVP_PKEY_CTX_get_algor.html]=man3/EVP_PKEY_CTX_get_algor.pod +DEPEND[man/man3/EVP_PKEY_CTX_get_algor.3]=man3/EVP_PKEY_CTX_get_algor.pod +GENERATE[man/man3/EVP_PKEY_CTX_get_algor.3]=man3/EVP_PKEY_CTX_get_algor.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 @@ -1331,6 +1371,14 @@ 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_SKEY.html]=man3/EVP_SKEY.pod +GENERATE[html/man3/EVP_SKEY.html]=man3/EVP_SKEY.pod +DEPEND[man/man3/EVP_SKEY.3]=man3/EVP_SKEY.pod +GENERATE[man/man3/EVP_SKEY.3]=man3/EVP_SKEY.pod +DEPEND[html/man3/EVP_SKEYMGMT.html]=man3/EVP_SKEYMGMT.pod +GENERATE[html/man3/EVP_SKEYMGMT.html]=man3/EVP_SKEYMGMT.pod +DEPEND[man/man3/EVP_SKEYMGMT.3]=man3/EVP_SKEYMGMT.pod +GENERATE[man/man3/EVP_SKEYMGMT.3]=man3/EVP_SKEYMGMT.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 @@ -1447,6 +1495,10 @@ 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/GENERAL_NAME.html]=man3/GENERAL_NAME.pod +GENERATE[html/man3/GENERAL_NAME.html]=man3/GENERAL_NAME.pod +DEPEND[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.pod +GENERATE[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.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 @@ -1543,10 +1595,18 @@ DEPEND[html/man3/OPENSSL_load_builtin_modules.html]=man3/OPENSSL_load_builtin_mo 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_load_u16_le.html]=man3/OPENSSL_load_u16_le.pod +GENERATE[html/man3/OPENSSL_load_u16_le.html]=man3/OPENSSL_load_u16_le.pod +DEPEND[man/man3/OPENSSL_load_u16_le.3]=man3/OPENSSL_load_u16_le.pod +GENERATE[man/man3/OPENSSL_load_u16_le.3]=man3/OPENSSL_load_u16_le.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_riscvcap.html]=man3/OPENSSL_riscvcap.pod +GENERATE[html/man3/OPENSSL_riscvcap.html]=man3/OPENSSL_riscvcap.pod +DEPEND[man/man3/OPENSSL_riscvcap.3]=man3/OPENSSL_riscvcap.pod +GENERATE[man/man3/OPENSSL_riscvcap.3]=man3/OPENSSL_riscvcap.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 @@ -1567,6 +1627,10 @@ 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_ATAV_set0.html]=man3/OSSL_CMP_ATAV_set0.pod +GENERATE[html/man3/OSSL_CMP_ATAV_set0.html]=man3/OSSL_CMP_ATAV_set0.pod +DEPEND[man/man3/OSSL_CMP_ATAV_set0.3]=man3/OSSL_CMP_ATAV_set0.pod +GENERATE[man/man3/OSSL_CMP_ATAV_set0.3]=man3/OSSL_CMP_ATAV_set0.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 @@ -1575,6 +1639,10 @@ DEPEND[html/man3/OSSL_CMP_HDR_get0_transactionID.html]=man3/OSSL_CMP_HDR_get0_tr 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_new_caCerts.html]=man3/OSSL_CMP_ITAV_new_caCerts.pod +GENERATE[html/man3/OSSL_CMP_ITAV_new_caCerts.html]=man3/OSSL_CMP_ITAV_new_caCerts.pod +DEPEND[man/man3/OSSL_CMP_ITAV_new_caCerts.3]=man3/OSSL_CMP_ITAV_new_caCerts.pod +GENERATE[man/man3/OSSL_CMP_ITAV_new_caCerts.3]=man3/OSSL_CMP_ITAV_new_caCerts.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 @@ -1667,10 +1735,22 @@ 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_ERR_STATE_save.html]=man3/OSSL_ERR_STATE_save.pod +GENERATE[html/man3/OSSL_ERR_STATE_save.html]=man3/OSSL_ERR_STATE_save.pod +DEPEND[man/man3/OSSL_ERR_STATE_save.3]=man3/OSSL_ERR_STATE_save.pod +GENERATE[man/man3/OSSL_ERR_STATE_save.3]=man3/OSSL_ERR_STATE_save.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_GENERAL_NAMES_print.html]=man3/OSSL_GENERAL_NAMES_print.pod +GENERATE[html/man3/OSSL_GENERAL_NAMES_print.html]=man3/OSSL_GENERAL_NAMES_print.pod +DEPEND[man/man3/OSSL_GENERAL_NAMES_print.3]=man3/OSSL_GENERAL_NAMES_print.pod +GENERATE[man/man3/OSSL_GENERAL_NAMES_print.3]=man3/OSSL_GENERAL_NAMES_print.pod +DEPEND[html/man3/OSSL_HPKE_CTX_new.html]=man3/OSSL_HPKE_CTX_new.pod +GENERATE[html/man3/OSSL_HPKE_CTX_new.html]=man3/OSSL_HPKE_CTX_new.pod +DEPEND[man/man3/OSSL_HPKE_CTX_new.3]=man3/OSSL_HPKE_CTX_new.pod +GENERATE[man/man3/OSSL_HPKE_CTX_new.3]=man3/OSSL_HPKE_CTX_new.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 @@ -1683,6 +1763,18 @@ 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_IETF_ATTR_SYNTAX.html]=man3/OSSL_IETF_ATTR_SYNTAX.pod +GENERATE[html/man3/OSSL_IETF_ATTR_SYNTAX.html]=man3/OSSL_IETF_ATTR_SYNTAX.pod +DEPEND[man/man3/OSSL_IETF_ATTR_SYNTAX.3]=man3/OSSL_IETF_ATTR_SYNTAX.pod +GENERATE[man/man3/OSSL_IETF_ATTR_SYNTAX.3]=man3/OSSL_IETF_ATTR_SYNTAX.pod +DEPEND[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +GENERATE[html/man3/OSSL_IETF_ATTR_SYNTAX_print.html]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +DEPEND[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +GENERATE[man/man3/OSSL_IETF_ATTR_SYNTAX_print.3]=man3/OSSL_IETF_ATTR_SYNTAX_print.pod +DEPEND[html/man3/OSSL_INDICATOR_set_callback.html]=man3/OSSL_INDICATOR_set_callback.pod +GENERATE[html/man3/OSSL_INDICATOR_set_callback.html]=man3/OSSL_INDICATOR_set_callback.pod +DEPEND[man/man3/OSSL_INDICATOR_set_callback.3]=man3/OSSL_INDICATOR_set_callback.pod +GENERATE[man/man3/OSSL_INDICATOR_set_callback.3]=man3/OSSL_INDICATOR_set_callback.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 @@ -1691,6 +1783,10 @@ 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_LIB_CTX_set_conf_diagnostics.html]=man3/OSSL_LIB_CTX_set_conf_diagnostics.pod +GENERATE[html/man3/OSSL_LIB_CTX_set_conf_diagnostics.html]=man3/OSSL_LIB_CTX_set_conf_diagnostics.pod +DEPEND[man/man3/OSSL_LIB_CTX_set_conf_diagnostics.3]=man3/OSSL_LIB_CTX_set_conf_diagnostics.pod +GENERATE[man/man3/OSSL_LIB_CTX_set_conf_diagnostics.3]=man3/OSSL_LIB_CTX_set_conf_diagnostics.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 @@ -1711,10 +1807,18 @@ 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_PARAM_print_to_bio.html]=man3/OSSL_PARAM_print_to_bio.pod +GENERATE[html/man3/OSSL_PARAM_print_to_bio.html]=man3/OSSL_PARAM_print_to_bio.pod +DEPEND[man/man3/OSSL_PARAM_print_to_bio.3]=man3/OSSL_PARAM_print_to_bio.pod +GENERATE[man/man3/OSSL_PARAM_print_to_bio.3]=man3/OSSL_PARAM_print_to_bio.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_QUIC_client_method.html]=man3/OSSL_QUIC_client_method.pod +GENERATE[html/man3/OSSL_QUIC_client_method.html]=man3/OSSL_QUIC_client_method.pod +DEPEND[man/man3/OSSL_QUIC_client_method.3]=man3/OSSL_QUIC_client_method.pod +GENERATE[man/man3/OSSL_QUIC_client_method.3]=man3/OSSL_QUIC_client_method.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 @@ -1747,6 +1851,10 @@ 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_sleep.html]=man3/OSSL_sleep.pod +GENERATE[html/man3/OSSL_sleep.html]=man3/OSSL_sleep.pod +DEPEND[man/man3/OSSL_sleep.3]=man3/OSSL_sleep.pod +GENERATE[man/man3/OSSL_sleep.3]=man3/OSSL_sleep.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 @@ -1767,6 +1875,10 @@ 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/PBMAC1_get1_pbkdf2_param.html]=man3/PBMAC1_get1_pbkdf2_param.pod +GENERATE[html/man3/PBMAC1_get1_pbkdf2_param.html]=man3/PBMAC1_get1_pbkdf2_param.pod +DEPEND[man/man3/PBMAC1_get1_pbkdf2_param.3]=man3/PBMAC1_get1_pbkdf2_param.pod +GENERATE[man/man3/PBMAC1_get1_pbkdf2_param.3]=man3/PBMAC1_get1_pbkdf2_param.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 @@ -1815,6 +1927,10 @@ DEPEND[html/man3/PKCS12_SAFEBAG_get1_cert.html]=man3/PKCS12_SAFEBAG_get1_cert.po 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_SAFEBAG_set0_attrs.html]=man3/PKCS12_SAFEBAG_set0_attrs.pod +GENERATE[html/man3/PKCS12_SAFEBAG_set0_attrs.html]=man3/PKCS12_SAFEBAG_set0_attrs.pod +DEPEND[man/man3/PKCS12_SAFEBAG_set0_attrs.3]=man3/PKCS12_SAFEBAG_set0_attrs.pod +GENERATE[man/man3/PKCS12_SAFEBAG_set0_attrs.3]=man3/PKCS12_SAFEBAG_set0_attrs.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 @@ -2179,6 +2295,10 @@ 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_cert_comp_preference.html]=man3/SSL_CTX_set1_cert_comp_preference.pod +GENERATE[html/man3/SSL_CTX_set1_cert_comp_preference.html]=man3/SSL_CTX_set1_cert_comp_preference.pod +DEPEND[man/man3/SSL_CTX_set1_cert_comp_preference.3]=man3/SSL_CTX_set1_cert_comp_preference.pod +GENERATE[man/man3/SSL_CTX_set1_cert_comp_preference.3]=man3/SSL_CTX_set1_cert_comp_preference.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 @@ -2231,6 +2351,10 @@ DEPEND[html/man3/SSL_CTX_set_default_passwd_cb.html]=man3/SSL_CTX_set_default_pa 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_domain_flags.html]=man3/SSL_CTX_set_domain_flags.pod +GENERATE[html/man3/SSL_CTX_set_domain_flags.html]=man3/SSL_CTX_set_domain_flags.pod +DEPEND[man/man3/SSL_CTX_set_domain_flags.3]=man3/SSL_CTX_set_domain_flags.pod +GENERATE[man/man3/SSL_CTX_set_domain_flags.3]=man3/SSL_CTX_set_domain_flags.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 @@ -2259,6 +2383,10 @@ DEPEND[html/man3/SSL_CTX_set_msg_callback.html]=man3/SSL_CTX_set_msg_callback.po 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_new_pending_conn_cb.html]=man3/SSL_CTX_set_new_pending_conn_cb.pod +GENERATE[html/man3/SSL_CTX_set_new_pending_conn_cb.html]=man3/SSL_CTX_set_new_pending_conn_cb.pod +DEPEND[man/man3/SSL_CTX_set_new_pending_conn_cb.3]=man3/SSL_CTX_set_new_pending_conn_cb.pod +GENERATE[man/man3/SSL_CTX_set_new_pending_conn_cb.3]=man3/SSL_CTX_set_new_pending_conn_cb.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 @@ -2411,6 +2539,10 @@ 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_accept_stream.html]=man3/SSL_accept_stream.pod +GENERATE[html/man3/SSL_accept_stream.html]=man3/SSL_accept_stream.pod +DEPEND[man/man3/SSL_accept_stream.3]=man3/SSL_accept_stream.pod +GENERATE[man/man3/SSL_accept_stream.3]=man3/SSL_accept_stream.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 @@ -2447,10 +2579,26 @@ 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_connection.html]=man3/SSL_get0_connection.pod +GENERATE[html/man3/SSL_get0_connection.html]=man3/SSL_get0_connection.pod +DEPEND[man/man3/SSL_get0_connection.3]=man3/SSL_get0_connection.pod +GENERATE[man/man3/SSL_get0_connection.3]=man3/SSL_get0_connection.pod +DEPEND[html/man3/SSL_get0_group_name.html]=man3/SSL_get0_group_name.pod +GENERATE[html/man3/SSL_get0_group_name.html]=man3/SSL_get0_group_name.pod +DEPEND[man/man3/SSL_get0_group_name.3]=man3/SSL_get0_group_name.pod +GENERATE[man/man3/SSL_get0_group_name.3]=man3/SSL_get0_group_name.pod +DEPEND[html/man3/SSL_get0_peer_rpk.html]=man3/SSL_get0_peer_rpk.pod +GENERATE[html/man3/SSL_get0_peer_rpk.html]=man3/SSL_get0_peer_rpk.pod +DEPEND[man/man3/SSL_get0_peer_rpk.3]=man3/SSL_get0_peer_rpk.pod +GENERATE[man/man3/SSL_get0_peer_rpk.3]=man3/SSL_get0_peer_rpk.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_get1_builtin_sigalgs.html]=man3/SSL_get1_builtin_sigalgs.pod +GENERATE[html/man3/SSL_get1_builtin_sigalgs.html]=man3/SSL_get1_builtin_sigalgs.pod +DEPEND[man/man3/SSL_get1_builtin_sigalgs.3]=man3/SSL_get1_builtin_sigalgs.pod +GENERATE[man/man3/SSL_get1_builtin_sigalgs.3]=man3/SSL_get1_builtin_sigalgs.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 @@ -2471,6 +2619,10 @@ 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_conn_close_info.html]=man3/SSL_get_conn_close_info.pod +GENERATE[html/man3/SSL_get_conn_close_info.html]=man3/SSL_get_conn_close_info.pod +DEPEND[man/man3/SSL_get_conn_close_info.3]=man3/SSL_get_conn_close_info.pod +GENERATE[man/man3/SSL_get_conn_close_info.3]=man3/SSL_get_conn_close_info.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 @@ -2483,6 +2635,10 @@ 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_event_timeout.html]=man3/SSL_get_event_timeout.pod +GENERATE[html/man3/SSL_get_event_timeout.html]=man3/SSL_get_event_timeout.pod +DEPEND[man/man3/SSL_get_event_timeout.3]=man3/SSL_get_event_timeout.pod +GENERATE[man/man3/SSL_get_event_timeout.3]=man3/SSL_get_event_timeout.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 @@ -2491,6 +2647,10 @@ 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_handshake_rtt.html]=man3/SSL_get_handshake_rtt.pod +GENERATE[html/man3/SSL_get_handshake_rtt.html]=man3/SSL_get_handshake_rtt.pod +DEPEND[man/man3/SSL_get_handshake_rtt.3]=man3/SSL_get_handshake_rtt.pod +GENERATE[man/man3/SSL_get_handshake_rtt.3]=man3/SSL_get_handshake_rtt.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 @@ -2515,6 +2675,10 @@ 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_rpoll_descriptor.html]=man3/SSL_get_rpoll_descriptor.pod +GENERATE[html/man3/SSL_get_rpoll_descriptor.html]=man3/SSL_get_rpoll_descriptor.pod +DEPEND[man/man3/SSL_get_rpoll_descriptor.3]=man3/SSL_get_rpoll_descriptor.pod +GENERATE[man/man3/SSL_get_rpoll_descriptor.3]=man3/SSL_get_rpoll_descriptor.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 @@ -2523,6 +2687,18 @@ 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_stream_id.html]=man3/SSL_get_stream_id.pod +GENERATE[html/man3/SSL_get_stream_id.html]=man3/SSL_get_stream_id.pod +DEPEND[man/man3/SSL_get_stream_id.3]=man3/SSL_get_stream_id.pod +GENERATE[man/man3/SSL_get_stream_id.3]=man3/SSL_get_stream_id.pod +DEPEND[html/man3/SSL_get_stream_read_state.html]=man3/SSL_get_stream_read_state.pod +GENERATE[html/man3/SSL_get_stream_read_state.html]=man3/SSL_get_stream_read_state.pod +DEPEND[man/man3/SSL_get_stream_read_state.3]=man3/SSL_get_stream_read_state.pod +GENERATE[man/man3/SSL_get_stream_read_state.3]=man3/SSL_get_stream_read_state.pod +DEPEND[html/man3/SSL_get_value_uint.html]=man3/SSL_get_value_uint.pod +GENERATE[html/man3/SSL_get_value_uint.html]=man3/SSL_get_value_uint.pod +DEPEND[man/man3/SSL_get_value_uint.3]=man3/SSL_get_value_uint.pod +GENERATE[man/man3/SSL_get_value_uint.3]=man3/SSL_get_value_uint.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 @@ -2535,10 +2711,18 @@ 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_handle_events.html]=man3/SSL_handle_events.pod +GENERATE[html/man3/SSL_handle_events.html]=man3/SSL_handle_events.pod +DEPEND[man/man3/SSL_handle_events.3]=man3/SSL_handle_events.pod +GENERATE[man/man3/SSL_handle_events.3]=man3/SSL_handle_events.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_inject_net_dgram.html]=man3/SSL_inject_net_dgram.pod +GENERATE[html/man3/SSL_inject_net_dgram.html]=man3/SSL_inject_net_dgram.pod +DEPEND[man/man3/SSL_inject_net_dgram.3]=man3/SSL_inject_net_dgram.pod +GENERATE[man/man3/SSL_inject_net_dgram.3]=man3/SSL_inject_net_dgram.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 @@ -2555,10 +2739,26 @@ 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_new_domain.html]=man3/SSL_new_domain.pod +GENERATE[html/man3/SSL_new_domain.html]=man3/SSL_new_domain.pod +DEPEND[man/man3/SSL_new_domain.3]=man3/SSL_new_domain.pod +GENERATE[man/man3/SSL_new_domain.3]=man3/SSL_new_domain.pod +DEPEND[html/man3/SSL_new_listener.html]=man3/SSL_new_listener.pod +GENERATE[html/man3/SSL_new_listener.html]=man3/SSL_new_listener.pod +DEPEND[man/man3/SSL_new_listener.3]=man3/SSL_new_listener.pod +GENERATE[man/man3/SSL_new_listener.3]=man3/SSL_new_listener.pod +DEPEND[html/man3/SSL_new_stream.html]=man3/SSL_new_stream.pod +GENERATE[html/man3/SSL_new_stream.html]=man3/SSL_new_stream.pod +DEPEND[man/man3/SSL_new_stream.3]=man3/SSL_new_stream.pod +GENERATE[man/man3/SSL_new_stream.3]=man3/SSL_new_stream.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_poll.html]=man3/SSL_poll.pod +GENERATE[html/man3/SSL_poll.html]=man3/SSL_poll.pod +DEPEND[man/man3/SSL_poll.3]=man3/SSL_poll.pod +GENERATE[man/man3/SSL_poll.3]=man3/SSL_poll.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 @@ -2579,6 +2779,14 @@ 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_set1_initial_peer_addr.html]=man3/SSL_set1_initial_peer_addr.pod +GENERATE[html/man3/SSL_set1_initial_peer_addr.html]=man3/SSL_set1_initial_peer_addr.pod +DEPEND[man/man3/SSL_set1_initial_peer_addr.3]=man3/SSL_set1_initial_peer_addr.pod +GENERATE[man/man3/SSL_set1_initial_peer_addr.3]=man3/SSL_set1_initial_peer_addr.pod +DEPEND[html/man3/SSL_set1_server_cert_type.html]=man3/SSL_set1_server_cert_type.pod +GENERATE[html/man3/SSL_set1_server_cert_type.html]=man3/SSL_set1_server_cert_type.pod +DEPEND[man/man3/SSL_set1_server_cert_type.3]=man3/SSL_set1_server_cert_type.pod +GENERATE[man/man3/SSL_set1_server_cert_type.3]=man3/SSL_set1_server_cert_type.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 @@ -2587,14 +2795,30 @@ 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_blocking_mode.html]=man3/SSL_set_blocking_mode.pod +GENERATE[html/man3/SSL_set_blocking_mode.html]=man3/SSL_set_blocking_mode.pod +DEPEND[man/man3/SSL_set_blocking_mode.3]=man3/SSL_set_blocking_mode.pod +GENERATE[man/man3/SSL_set_blocking_mode.3]=man3/SSL_set_blocking_mode.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_default_stream_mode.html]=man3/SSL_set_default_stream_mode.pod +GENERATE[html/man3/SSL_set_default_stream_mode.html]=man3/SSL_set_default_stream_mode.pod +DEPEND[man/man3/SSL_set_default_stream_mode.3]=man3/SSL_set_default_stream_mode.pod +GENERATE[man/man3/SSL_set_default_stream_mode.3]=man3/SSL_set_default_stream_mode.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_incoming_stream_policy.html]=man3/SSL_set_incoming_stream_policy.pod +GENERATE[html/man3/SSL_set_incoming_stream_policy.html]=man3/SSL_set_incoming_stream_policy.pod +DEPEND[man/man3/SSL_set_incoming_stream_policy.3]=man3/SSL_set_incoming_stream_policy.pod +GENERATE[man/man3/SSL_set_incoming_stream_policy.3]=man3/SSL_set_incoming_stream_policy.pod +DEPEND[html/man3/SSL_set_quic_tls_cbs.html]=man3/SSL_set_quic_tls_cbs.pod +GENERATE[html/man3/SSL_set_quic_tls_cbs.html]=man3/SSL_set_quic_tls_cbs.pod +DEPEND[man/man3/SSL_set_quic_tls_cbs.3]=man3/SSL_set_quic_tls_cbs.pod +GENERATE[man/man3/SSL_set_quic_tls_cbs.3]=man3/SSL_set_quic_tls_cbs.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 @@ -2603,6 +2827,10 @@ 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_session_secret_cb.html]=man3/SSL_set_session_secret_cb.pod +GENERATE[html/man3/SSL_set_session_secret_cb.html]=man3/SSL_set_session_secret_cb.pod +DEPEND[man/man3/SSL_set_session_secret_cb.3]=man3/SSL_set_session_secret_cb.pod +GENERATE[man/man3/SSL_set_session_secret_cb.3]=man3/SSL_set_session_secret_cb.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 @@ -2619,6 +2847,14 @@ 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_stream_conclude.html]=man3/SSL_stream_conclude.pod +GENERATE[html/man3/SSL_stream_conclude.html]=man3/SSL_stream_conclude.pod +DEPEND[man/man3/SSL_stream_conclude.3]=man3/SSL_stream_conclude.pod +GENERATE[man/man3/SSL_stream_conclude.3]=man3/SSL_stream_conclude.pod +DEPEND[html/man3/SSL_stream_reset.html]=man3/SSL_stream_reset.pod +GENERATE[html/man3/SSL_stream_reset.html]=man3/SSL_stream_reset.pod +DEPEND[man/man3/SSL_stream_reset.3]=man3/SSL_stream_reset.pod +GENERATE[man/man3/SSL_stream_reset.3]=man3/SSL_stream_reset.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 @@ -2631,10 +2867,10 @@ 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/TS_VERIFY_CTX.html]=man3/TS_VERIFY_CTX.pod +GENERATE[html/man3/TS_VERIFY_CTX.html]=man3/TS_VERIFY_CTX.pod +DEPEND[man/man3/TS_VERIFY_CTX.3]=man3/TS_VERIFY_CTX.pod +GENERATE[man/man3/TS_VERIFY_CTX.3]=man3/TS_VERIFY_CTX.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 @@ -2659,6 +2895,26 @@ 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_ACERT_add1_attr.html]=man3/X509_ACERT_add1_attr.pod +GENERATE[html/man3/X509_ACERT_add1_attr.html]=man3/X509_ACERT_add1_attr.pod +DEPEND[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod +GENERATE[man/man3/X509_ACERT_add1_attr.3]=man3/X509_ACERT_add1_attr.pod +DEPEND[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod +GENERATE[html/man3/X509_ACERT_add_attr_nconf.html]=man3/X509_ACERT_add_attr_nconf.pod +DEPEND[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.pod +GENERATE[man/man3/X509_ACERT_add_attr_nconf.3]=man3/X509_ACERT_add_attr_nconf.pod +DEPEND[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod +GENERATE[html/man3/X509_ACERT_get0_holder_baseCertId.html]=man3/X509_ACERT_get0_holder_baseCertId.pod +DEPEND[man/man3/X509_ACERT_get0_holder_baseCertId.3]=man3/X509_ACERT_get0_holder_baseCertId.pod +GENERATE[man/man3/X509_ACERT_get0_holder_baseCertId.3]=man3/X509_ACERT_get0_holder_baseCertId.pod +DEPEND[html/man3/X509_ACERT_get_attr.html]=man3/X509_ACERT_get_attr.pod +GENERATE[html/man3/X509_ACERT_get_attr.html]=man3/X509_ACERT_get_attr.pod +DEPEND[man/man3/X509_ACERT_get_attr.3]=man3/X509_ACERT_get_attr.pod +GENERATE[man/man3/X509_ACERT_get_attr.3]=man3/X509_ACERT_get_attr.pod +DEPEND[html/man3/X509_ACERT_print_ex.html]=man3/X509_ACERT_print_ex.pod +GENERATE[html/man3/X509_ACERT_print_ex.html]=man3/X509_ACERT_print_ex.pod +DEPEND[man/man3/X509_ACERT_print_ex.3]=man3/X509_ACERT_print_ex.pod +GENERATE[man/man3/X509_ACERT_print_ex.3]=man3/X509_ACERT_print_ex.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 @@ -2723,6 +2979,10 @@ 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_by_subject.html]=man3/X509_STORE_CTX_get_by_subject.pod +GENERATE[html/man3/X509_STORE_CTX_get_by_subject.html]=man3/X509_STORE_CTX_get_by_subject.pod +DEPEND[man/man3/X509_STORE_CTX_get_by_subject.3]=man3/X509_STORE_CTX_get_by_subject.pod +GENERATE[man/man3/X509_STORE_CTX_get_by_subject.3]=man3/X509_STORE_CTX_get_by_subject.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 @@ -2811,6 +3071,10 @@ 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_default_cert_file.html]=man3/X509_get_default_cert_file.pod +GENERATE[html/man3/X509_get_default_cert_file.html]=man3/X509_get_default_cert_file.pod +DEPEND[man/man3/X509_get_default_cert_file.3]=man3/X509_get_default_cert_file.pod +GENERATE[man/man3/X509_get_default_cert_file.3]=man3/X509_get_default_cert_file.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 @@ -2935,6 +3199,7 @@ 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_get_rpoll_descriptor.html \ html/man3/BIO_meth_new.html \ html/man3/BIO_new.html \ html/man3/BIO_new_CMS.html \ @@ -2947,11 +3212,13 @@ 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_dgram_pair.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_sendmmsg.html \ html/man3/BIO_set_callback.html \ html/man3/BIO_should_retry.html \ html/man3/BIO_socket_wait.html \ @@ -2976,6 +3243,7 @@ html/man3/BN_set_bit.html \ html/man3/BN_swap.html \ html/man3/BN_zero.html \ html/man3/BUF_MEM_new.html \ +html/man3/CMAC_CTX.html \ html/man3/CMS_EncryptedData_decrypt.html \ html/man3/CMS_EncryptedData_encrypt.html \ html/man3/CMS_EnvelopedData_create.html \ @@ -2998,6 +3266,7 @@ html/man3/CMS_signed_get_attr.html \ html/man3/CMS_uncompress.html \ html/man3/CMS_verify.html \ html/man3/CMS_verify_receipt.html \ +html/man3/COMP_CTX_new.html \ html/man3/CONF_modules_free.html \ html/man3/CONF_modules_load_file.html \ html/man3/CRYPTO_THREAD_run_once.html \ @@ -3031,6 +3300,8 @@ 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_get_timeout.html \ +html/man3/DTLSv1_handle_timeout.html \ html/man3/DTLSv1_listen.html \ html/man3/ECDSA_SIG_new.html \ html/man3/ECDSA_sign.html \ @@ -3077,6 +3348,7 @@ 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_get_algor.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 \ @@ -3116,6 +3388,8 @@ 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_SKEY.html \ +html/man3/EVP_SKEYMGMT.html \ html/man3/EVP_SealInit.html \ html/man3/EVP_SignInit.html \ html/man3/EVP_VerifyInit.html \ @@ -3145,6 +3419,7 @@ html/man3/EVP_sha3_224.html \ html/man3/EVP_sm3.html \ html/man3/EVP_sm4_cbc.html \ html/man3/EVP_whirlpool.html \ +html/man3/GENERAL_NAME.html \ html/man3/HMAC.html \ html/man3/MD5.html \ html/man3/MDC2_Init.html \ @@ -3169,14 +3444,18 @@ 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_load_u16_le.html \ html/man3/OPENSSL_malloc.html \ +html/man3/OPENSSL_riscvcap.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_ATAV_set0.html \ html/man3/OSSL_CMP_CTX_new.html \ html/man3/OSSL_CMP_HDR_get0_transactionID.html \ +html/man3/OSSL_CMP_ITAV_new_caCerts.html \ html/man3/OSSL_CMP_ITAV_set0.html \ html/man3/OSSL_CMP_MSG_get0_header.html \ html/man3/OSSL_CMP_MSG_http_perform.html \ @@ -3200,18 +3479,27 @@ 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_ERR_STATE_save.html \ html/man3/OSSL_ESS_check_signing_certs.html \ +html/man3/OSSL_GENERAL_NAMES_print.html \ +html/man3/OSSL_HPKE_CTX_new.html \ html/man3/OSSL_HTTP_REQ_CTX.html \ html/man3/OSSL_HTTP_parse_url.html \ html/man3/OSSL_HTTP_transfer.html \ +html/man3/OSSL_IETF_ATTR_SYNTAX.html \ +html/man3/OSSL_IETF_ATTR_SYNTAX_print.html \ +html/man3/OSSL_INDICATOR_set_callback.html \ html/man3/OSSL_ITEM.html \ html/man3/OSSL_LIB_CTX.html \ +html/man3/OSSL_LIB_CTX_set_conf_diagnostics.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_PARAM_print_to_bio.html \ html/man3/OSSL_PROVIDER.html \ +html/man3/OSSL_QUIC_client_method.html \ html/man3/OSSL_SELF_TEST_new.html \ html/man3/OSSL_SELF_TEST_set_callback.html \ html/man3/OSSL_STORE_INFO.html \ @@ -3220,11 +3508,13 @@ 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_sleep.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/PBMAC1_get1_pbkdf2_param.html \ html/man3/PEM_X509_INFO_read_bio_ex.html \ html/man3/PEM_bytes_read_bio.html \ html/man3/PEM_read.html \ @@ -3237,6 +3527,7 @@ 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_SAFEBAG_set0_attrs.html \ html/man3/PKCS12_add1_attr_by_NID.html \ html/man3/PKCS12_add_CSPName_asc.html \ html/man3/PKCS12_add_cert.html \ @@ -3328,6 +3619,7 @@ 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_cert_comp_preference.html \ html/man3/SSL_CTX_set1_curves.html \ html/man3/SSL_CTX_set1_sigalgs.html \ html/man3/SSL_CTX_set1_verify_cert_store.html \ @@ -3341,6 +3633,7 @@ 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_domain_flags.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 \ @@ -3348,6 +3641,7 @@ 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_new_pending_conn_cb.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 \ @@ -3386,6 +3680,7 @@ 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_accept_stream.html \ html/man3/SSL_alert_type_string.html \ html/man3/SSL_alloc_buffers.html \ html/man3/SSL_check_chain.html \ @@ -3395,59 +3690,90 @@ 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_connection.html \ +html/man3/SSL_get0_group_name.html \ +html/man3/SSL_get0_peer_rpk.html \ html/man3/SSL_get0_peer_scts.html \ +html/man3/SSL_get1_builtin_sigalgs.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_conn_close_info.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_event_timeout.html \ html/man3/SSL_get_extms_support.html \ html/man3/SSL_get_fd.html \ +html/man3/SSL_get_handshake_rtt.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_rpoll_descriptor.html \ html/man3/SSL_get_session.html \ html/man3/SSL_get_shared_sigalgs.html \ +html/man3/SSL_get_stream_id.html \ +html/man3/SSL_get_stream_read_state.html \ +html/man3/SSL_get_value_uint.html \ html/man3/SSL_get_verify_result.html \ html/man3/SSL_get_version.html \ html/man3/SSL_group_to_name.html \ +html/man3/SSL_handle_events.html \ html/man3/SSL_in_init.html \ +html/man3/SSL_inject_net_dgram.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_new_domain.html \ +html/man3/SSL_new_listener.html \ +html/man3/SSL_new_stream.html \ html/man3/SSL_pending.html \ +html/man3/SSL_poll.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_set1_initial_peer_addr.html \ +html/man3/SSL_set1_server_cert_type.html \ html/man3/SSL_set_async_callback.html \ html/man3/SSL_set_bio.html \ +html/man3/SSL_set_blocking_mode.html \ html/man3/SSL_set_connect_state.html \ +html/man3/SSL_set_default_stream_mode.html \ html/man3/SSL_set_fd.html \ +html/man3/SSL_set_incoming_stream_policy.html \ +html/man3/SSL_set_quic_tls_cbs.html \ html/man3/SSL_set_retry_verify.html \ html/man3/SSL_set_session.html \ +html/man3/SSL_set_session_secret_cb.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_stream_conclude.html \ +html/man3/SSL_stream_reset.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/TS_VERIFY_CTX.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_ACERT_add1_attr.html \ +html/man3/X509_ACERT_add_attr_nconf.html \ +html/man3/X509_ACERT_get0_holder_baseCertId.html \ +html/man3/X509_ACERT_get_attr.html \ +html/man3/X509_ACERT_print_ex.html \ html/man3/X509_ALGOR_dup.html \ html/man3/X509_ATTRIBUTE.html \ html/man3/X509_CRL_get0_by_serial.html \ @@ -3464,6 +3790,7 @@ html/man3/X509_PUBKEY_new.html \ html/man3/X509_REQ_get_attr.html \ html/man3/X509_REQ_get_extensions.html \ html/man3/X509_SIG_get0.html \ +html/man3/X509_STORE_CTX_get_by_subject.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 \ @@ -3486,6 +3813,7 @@ 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_default_cert_file.html \ html/man3/X509_get_extension_flags.html \ html/man3/X509_get_pubkey.html \ html/man3/X509_get_serialNumber.html \ @@ -3543,6 +3871,7 @@ 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_get_rpoll_descriptor.3 \ man/man3/BIO_meth_new.3 \ man/man3/BIO_new.3 \ man/man3/BIO_new_CMS.3 \ @@ -3555,11 +3884,13 @@ 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_dgram_pair.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_sendmmsg.3 \ man/man3/BIO_set_callback.3 \ man/man3/BIO_should_retry.3 \ man/man3/BIO_socket_wait.3 \ @@ -3584,6 +3915,7 @@ man/man3/BN_set_bit.3 \ man/man3/BN_swap.3 \ man/man3/BN_zero.3 \ man/man3/BUF_MEM_new.3 \ +man/man3/CMAC_CTX.3 \ man/man3/CMS_EncryptedData_decrypt.3 \ man/man3/CMS_EncryptedData_encrypt.3 \ man/man3/CMS_EnvelopedData_create.3 \ @@ -3606,6 +3938,7 @@ man/man3/CMS_signed_get_attr.3 \ man/man3/CMS_uncompress.3 \ man/man3/CMS_verify.3 \ man/man3/CMS_verify_receipt.3 \ +man/man3/COMP_CTX_new.3 \ man/man3/CONF_modules_free.3 \ man/man3/CONF_modules_load_file.3 \ man/man3/CRYPTO_THREAD_run_once.3 \ @@ -3639,6 +3972,8 @@ 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_get_timeout.3 \ +man/man3/DTLSv1_handle_timeout.3 \ man/man3/DTLSv1_listen.3 \ man/man3/ECDSA_SIG_new.3 \ man/man3/ECDSA_sign.3 \ @@ -3685,6 +4020,7 @@ 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_get_algor.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 \ @@ -3724,6 +4060,8 @@ 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_SKEY.3 \ +man/man3/EVP_SKEYMGMT.3 \ man/man3/EVP_SealInit.3 \ man/man3/EVP_SignInit.3 \ man/man3/EVP_VerifyInit.3 \ @@ -3753,6 +4091,7 @@ man/man3/EVP_sha3_224.3 \ man/man3/EVP_sm3.3 \ man/man3/EVP_sm4_cbc.3 \ man/man3/EVP_whirlpool.3 \ +man/man3/GENERAL_NAME.3 \ man/man3/HMAC.3 \ man/man3/MD5.3 \ man/man3/MDC2_Init.3 \ @@ -3777,14 +4116,18 @@ 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_load_u16_le.3 \ man/man3/OPENSSL_malloc.3 \ +man/man3/OPENSSL_riscvcap.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_ATAV_set0.3 \ man/man3/OSSL_CMP_CTX_new.3 \ man/man3/OSSL_CMP_HDR_get0_transactionID.3 \ +man/man3/OSSL_CMP_ITAV_new_caCerts.3 \ man/man3/OSSL_CMP_ITAV_set0.3 \ man/man3/OSSL_CMP_MSG_get0_header.3 \ man/man3/OSSL_CMP_MSG_http_perform.3 \ @@ -3808,18 +4151,27 @@ 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_ERR_STATE_save.3 \ man/man3/OSSL_ESS_check_signing_certs.3 \ +man/man3/OSSL_GENERAL_NAMES_print.3 \ +man/man3/OSSL_HPKE_CTX_new.3 \ man/man3/OSSL_HTTP_REQ_CTX.3 \ man/man3/OSSL_HTTP_parse_url.3 \ man/man3/OSSL_HTTP_transfer.3 \ +man/man3/OSSL_IETF_ATTR_SYNTAX.3 \ +man/man3/OSSL_IETF_ATTR_SYNTAX_print.3 \ +man/man3/OSSL_INDICATOR_set_callback.3 \ man/man3/OSSL_ITEM.3 \ man/man3/OSSL_LIB_CTX.3 \ +man/man3/OSSL_LIB_CTX_set_conf_diagnostics.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_PARAM_print_to_bio.3 \ man/man3/OSSL_PROVIDER.3 \ +man/man3/OSSL_QUIC_client_method.3 \ man/man3/OSSL_SELF_TEST_new.3 \ man/man3/OSSL_SELF_TEST_set_callback.3 \ man/man3/OSSL_STORE_INFO.3 \ @@ -3828,11 +4180,13 @@ 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_sleep.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/PBMAC1_get1_pbkdf2_param.3 \ man/man3/PEM_X509_INFO_read_bio_ex.3 \ man/man3/PEM_bytes_read_bio.3 \ man/man3/PEM_read.3 \ @@ -3845,6 +4199,7 @@ 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_SAFEBAG_set0_attrs.3 \ man/man3/PKCS12_add1_attr_by_NID.3 \ man/man3/PKCS12_add_CSPName_asc.3 \ man/man3/PKCS12_add_cert.3 \ @@ -3936,6 +4291,7 @@ 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_cert_comp_preference.3 \ man/man3/SSL_CTX_set1_curves.3 \ man/man3/SSL_CTX_set1_sigalgs.3 \ man/man3/SSL_CTX_set1_verify_cert_store.3 \ @@ -3949,6 +4305,7 @@ 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_domain_flags.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 \ @@ -3956,6 +4313,7 @@ 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_new_pending_conn_cb.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 \ @@ -3994,6 +4352,7 @@ 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_accept_stream.3 \ man/man3/SSL_alert_type_string.3 \ man/man3/SSL_alloc_buffers.3 \ man/man3/SSL_check_chain.3 \ @@ -4003,59 +4362,90 @@ 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_connection.3 \ +man/man3/SSL_get0_group_name.3 \ +man/man3/SSL_get0_peer_rpk.3 \ man/man3/SSL_get0_peer_scts.3 \ +man/man3/SSL_get1_builtin_sigalgs.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_conn_close_info.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_event_timeout.3 \ man/man3/SSL_get_extms_support.3 \ man/man3/SSL_get_fd.3 \ +man/man3/SSL_get_handshake_rtt.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_rpoll_descriptor.3 \ man/man3/SSL_get_session.3 \ man/man3/SSL_get_shared_sigalgs.3 \ +man/man3/SSL_get_stream_id.3 \ +man/man3/SSL_get_stream_read_state.3 \ +man/man3/SSL_get_value_uint.3 \ man/man3/SSL_get_verify_result.3 \ man/man3/SSL_get_version.3 \ man/man3/SSL_group_to_name.3 \ +man/man3/SSL_handle_events.3 \ man/man3/SSL_in_init.3 \ +man/man3/SSL_inject_net_dgram.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_new_domain.3 \ +man/man3/SSL_new_listener.3 \ +man/man3/SSL_new_stream.3 \ man/man3/SSL_pending.3 \ +man/man3/SSL_poll.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_set1_initial_peer_addr.3 \ +man/man3/SSL_set1_server_cert_type.3 \ man/man3/SSL_set_async_callback.3 \ man/man3/SSL_set_bio.3 \ +man/man3/SSL_set_blocking_mode.3 \ man/man3/SSL_set_connect_state.3 \ +man/man3/SSL_set_default_stream_mode.3 \ man/man3/SSL_set_fd.3 \ +man/man3/SSL_set_incoming_stream_policy.3 \ +man/man3/SSL_set_quic_tls_cbs.3 \ man/man3/SSL_set_retry_verify.3 \ man/man3/SSL_set_session.3 \ +man/man3/SSL_set_session_secret_cb.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_stream_conclude.3 \ +man/man3/SSL_stream_reset.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/TS_VERIFY_CTX.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_ACERT_add1_attr.3 \ +man/man3/X509_ACERT_add_attr_nconf.3 \ +man/man3/X509_ACERT_get0_holder_baseCertId.3 \ +man/man3/X509_ACERT_get_attr.3 \ +man/man3/X509_ACERT_print_ex.3 \ man/man3/X509_ALGOR_dup.3 \ man/man3/X509_ATTRIBUTE.3 \ man/man3/X509_CRL_get0_by_serial.3 \ @@ -4072,6 +4462,7 @@ man/man3/X509_PUBKEY_new.3 \ man/man3/X509_REQ_get_attr.3 \ man/man3/X509_REQ_get_extensions.3 \ man/man3/X509_SIG_get0.3 \ +man/man3/X509_STORE_CTX_get_by_subject.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 \ @@ -4094,6 +4485,7 @@ 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_default_cert_file.3 \ man/man3/X509_get_extension_flags.3 \ man/man3/X509_get_pubkey.3 \ man/man3/X509_get_serialNumber.3 \ @@ -4199,10 +4591,18 @@ 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-ARGON2.html]=man7/EVP_KDF-ARGON2.pod +GENERATE[html/man7/EVP_KDF-ARGON2.html]=man7/EVP_KDF-ARGON2.pod +DEPEND[man/man7/EVP_KDF-ARGON2.7]=man7/EVP_KDF-ARGON2.pod +GENERATE[man/man7/EVP_KDF-ARGON2.7]=man7/EVP_KDF-ARGON2.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-HMAC-DRBG.html]=man7/EVP_KDF-HMAC-DRBG.pod +GENERATE[html/man7/EVP_KDF-HMAC-DRBG.html]=man7/EVP_KDF-HMAC-DRBG.pod +DEPEND[man/man7/EVP_KDF-HMAC-DRBG.7]=man7/EVP_KDF-HMAC-DRBG.pod +GENERATE[man/man7/EVP_KDF-HMAC-DRBG.7]=man7/EVP_KDF-HMAC-DRBG.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 @@ -4223,6 +4623,10 @@ 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-PVKKDF.html]=man7/EVP_KDF-PVKKDF.pod +GENERATE[html/man7/EVP_KDF-PVKKDF.html]=man7/EVP_KDF-PVKKDF.pod +DEPEND[man/man7/EVP_KDF-PVKKDF.7]=man7/EVP_KDF-PVKKDF.pod +GENERATE[man/man7/EVP_KDF-PVKKDF.7]=man7/EVP_KDF-PVKKDF.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 @@ -4255,10 +4659,22 @@ 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-EC.html]=man7/EVP_KEM-EC.pod +GENERATE[html/man7/EVP_KEM-EC.html]=man7/EVP_KEM-EC.pod +DEPEND[man/man7/EVP_KEM-EC.7]=man7/EVP_KEM-EC.pod +GENERATE[man/man7/EVP_KEM-EC.7]=man7/EVP_KEM-EC.pod +DEPEND[html/man7/EVP_KEM-ML-KEM.html]=man7/EVP_KEM-ML-KEM.pod +GENERATE[html/man7/EVP_KEM-ML-KEM.html]=man7/EVP_KEM-ML-KEM.pod +DEPEND[man/man7/EVP_KEM-ML-KEM.7]=man7/EVP_KEM-ML-KEM.pod +GENERATE[man/man7/EVP_KEM-ML-KEM.7]=man7/EVP_KEM-ML-KEM.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_KEM-X25519.html]=man7/EVP_KEM-X25519.pod +GENERATE[html/man7/EVP_KEM-X25519.html]=man7/EVP_KEM-X25519.pod +DEPEND[man/man7/EVP_KEM-X25519.7]=man7/EVP_KEM-X25519.pod +GENERATE[man/man7/EVP_KEM-X25519.7]=man7/EVP_KEM-X25519.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 @@ -4303,6 +4719,10 @@ 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-KECCAK.html]=man7/EVP_MD-KECCAK.pod +GENERATE[html/man7/EVP_MD-KECCAK.html]=man7/EVP_MD-KECCAK.pod +DEPEND[man/man7/EVP_MD-KECCAK.7]=man7/EVP_MD-KECCAK.pod +GENERATE[man/man7/EVP_MD-KECCAK.7]=man7/EVP_MD-KECCAK.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 @@ -4379,10 +4799,22 @@ 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-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod +GENERATE[html/man7/EVP_PKEY-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod +DEPEND[man/man7/EVP_PKEY-ML-DSA.7]=man7/EVP_PKEY-ML-DSA.pod +GENERATE[man/man7/EVP_PKEY-ML-DSA.7]=man7/EVP_PKEY-ML-DSA.pod +DEPEND[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod +GENERATE[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod +DEPEND[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.pod +GENERATE[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.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-SLH-DSA.html]=man7/EVP_PKEY-SLH-DSA.pod +GENERATE[html/man7/EVP_PKEY-SLH-DSA.html]=man7/EVP_PKEY-SLH-DSA.pod +DEPEND[man/man7/EVP_PKEY-SLH-DSA.7]=man7/EVP_PKEY-SLH-DSA.pod +GENERATE[man/man7/EVP_PKEY-SLH-DSA.7]=man7/EVP_PKEY-SLH-DSA.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 @@ -4391,6 +4823,10 @@ 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-CRNG-TEST.html]=man7/EVP_RAND-CRNG-TEST.pod +GENERATE[html/man7/EVP_RAND-CRNG-TEST.html]=man7/EVP_RAND-CRNG-TEST.pod +DEPEND[man/man7/EVP_RAND-CRNG-TEST.7]=man7/EVP_RAND-CRNG-TEST.pod +GENERATE[man/man7/EVP_RAND-CRNG-TEST.7]=man7/EVP_RAND-CRNG-TEST.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 @@ -4403,6 +4839,10 @@ 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-JITTER.html]=man7/EVP_RAND-JITTER.pod +GENERATE[html/man7/EVP_RAND-JITTER.html]=man7/EVP_RAND-JITTER.pod +DEPEND[man/man7/EVP_RAND-JITTER.7]=man7/EVP_RAND-JITTER.pod +GENERATE[man/man7/EVP_RAND-JITTER.7]=man7/EVP_RAND-JITTER.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 @@ -4431,10 +4871,18 @@ 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-ML-DSA.html]=man7/EVP_SIGNATURE-ML-DSA.pod +GENERATE[html/man7/EVP_SIGNATURE-ML-DSA.html]=man7/EVP_SIGNATURE-ML-DSA.pod +DEPEND[man/man7/EVP_SIGNATURE-ML-DSA.7]=man7/EVP_SIGNATURE-ML-DSA.pod +GENERATE[man/man7/EVP_SIGNATURE-ML-DSA.7]=man7/EVP_SIGNATURE-ML-DSA.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/EVP_SIGNATURE-SLH-DSA.html]=man7/EVP_SIGNATURE-SLH-DSA.pod +GENERATE[html/man7/EVP_SIGNATURE-SLH-DSA.html]=man7/EVP_SIGNATURE-SLH-DSA.pod +DEPEND[man/man7/EVP_SIGNATURE-SLH-DSA.7]=man7/EVP_SIGNATURE-SLH-DSA.pod +GENERATE[man/man7/EVP_SIGNATURE-SLH-DSA.7]=man7/EVP_SIGNATURE-SLH-DSA.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 @@ -4455,6 +4903,10 @@ 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/OSSL_STORE-winstore.html]=man7/OSSL_STORE-winstore.pod +GENERATE[html/man7/OSSL_STORE-winstore.html]=man7/OSSL_STORE-winstore.pod +DEPEND[man/man7/OSSL_STORE-winstore.7]=man7/OSSL_STORE-winstore.pod +GENERATE[man/man7/OSSL_STORE-winstore.7]=man7/OSSL_STORE-winstore.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 @@ -4471,10 +4923,6 @@ 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 @@ -4515,10 +4963,6 @@ 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 @@ -4539,6 +4983,18 @@ 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-qlog.html]=man7/openssl-qlog.pod +GENERATE[html/man7/openssl-qlog.html]=man7/openssl-qlog.pod +DEPEND[man/man7/openssl-qlog.7]=man7/openssl-qlog.pod +GENERATE[man/man7/openssl-qlog.7]=man7/openssl-qlog.pod +DEPEND[html/man7/openssl-quic-concurrency.html]=man7/openssl-quic-concurrency.pod +GENERATE[html/man7/openssl-quic-concurrency.html]=man7/openssl-quic-concurrency.pod +DEPEND[man/man7/openssl-quic-concurrency.7]=man7/openssl-quic-concurrency.pod +GENERATE[man/man7/openssl-quic-concurrency.7]=man7/openssl-quic-concurrency.pod +DEPEND[html/man7/openssl-quic.html]=man7/openssl-quic.pod +GENERATE[html/man7/openssl-quic.html]=man7/openssl-quic.pod +DEPEND[man/man7/openssl-quic.7]=man7/openssl-quic.pod +GENERATE[man/man7/openssl-quic.7]=man7/openssl-quic.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 @@ -4549,6 +5005,66 @@ 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-guide-introduction.html]=man7/ossl-guide-introduction.pod +GENERATE[html/man7/ossl-guide-introduction.html]=man7/ossl-guide-introduction.pod +DEPEND[man/man7/ossl-guide-introduction.7]=man7/ossl-guide-introduction.pod +GENERATE[man/man7/ossl-guide-introduction.7]=man7/ossl-guide-introduction.pod +DEPEND[html/man7/ossl-guide-libcrypto-introduction.html]=man7/ossl-guide-libcrypto-introduction.pod +GENERATE[html/man7/ossl-guide-libcrypto-introduction.html]=man7/ossl-guide-libcrypto-introduction.pod +DEPEND[man/man7/ossl-guide-libcrypto-introduction.7]=man7/ossl-guide-libcrypto-introduction.pod +GENERATE[man/man7/ossl-guide-libcrypto-introduction.7]=man7/ossl-guide-libcrypto-introduction.pod +DEPEND[html/man7/ossl-guide-libraries-introduction.html]=man7/ossl-guide-libraries-introduction.pod +GENERATE[html/man7/ossl-guide-libraries-introduction.html]=man7/ossl-guide-libraries-introduction.pod +DEPEND[man/man7/ossl-guide-libraries-introduction.7]=man7/ossl-guide-libraries-introduction.pod +GENERATE[man/man7/ossl-guide-libraries-introduction.7]=man7/ossl-guide-libraries-introduction.pod +DEPEND[html/man7/ossl-guide-libssl-introduction.html]=man7/ossl-guide-libssl-introduction.pod +GENERATE[html/man7/ossl-guide-libssl-introduction.html]=man7/ossl-guide-libssl-introduction.pod +DEPEND[man/man7/ossl-guide-libssl-introduction.7]=man7/ossl-guide-libssl-introduction.pod +GENERATE[man/man7/ossl-guide-libssl-introduction.7]=man7/ossl-guide-libssl-introduction.pod +DEPEND[html/man7/ossl-guide-migration.html]=man7/ossl-guide-migration.pod +GENERATE[html/man7/ossl-guide-migration.html]=man7/ossl-guide-migration.pod +DEPEND[man/man7/ossl-guide-migration.7]=man7/ossl-guide-migration.pod +GENERATE[man/man7/ossl-guide-migration.7]=man7/ossl-guide-migration.pod +DEPEND[html/man7/ossl-guide-quic-client-block.html]=man7/ossl-guide-quic-client-block.pod +GENERATE[html/man7/ossl-guide-quic-client-block.html]=man7/ossl-guide-quic-client-block.pod +DEPEND[man/man7/ossl-guide-quic-client-block.7]=man7/ossl-guide-quic-client-block.pod +GENERATE[man/man7/ossl-guide-quic-client-block.7]=man7/ossl-guide-quic-client-block.pod +DEPEND[html/man7/ossl-guide-quic-client-non-block.html]=man7/ossl-guide-quic-client-non-block.pod +GENERATE[html/man7/ossl-guide-quic-client-non-block.html]=man7/ossl-guide-quic-client-non-block.pod +DEPEND[man/man7/ossl-guide-quic-client-non-block.7]=man7/ossl-guide-quic-client-non-block.pod +GENERATE[man/man7/ossl-guide-quic-client-non-block.7]=man7/ossl-guide-quic-client-non-block.pod +DEPEND[html/man7/ossl-guide-quic-introduction.html]=man7/ossl-guide-quic-introduction.pod +GENERATE[html/man7/ossl-guide-quic-introduction.html]=man7/ossl-guide-quic-introduction.pod +DEPEND[man/man7/ossl-guide-quic-introduction.7]=man7/ossl-guide-quic-introduction.pod +GENERATE[man/man7/ossl-guide-quic-introduction.7]=man7/ossl-guide-quic-introduction.pod +DEPEND[html/man7/ossl-guide-quic-multi-stream.html]=man7/ossl-guide-quic-multi-stream.pod +GENERATE[html/man7/ossl-guide-quic-multi-stream.html]=man7/ossl-guide-quic-multi-stream.pod +DEPEND[man/man7/ossl-guide-quic-multi-stream.7]=man7/ossl-guide-quic-multi-stream.pod +GENERATE[man/man7/ossl-guide-quic-multi-stream.7]=man7/ossl-guide-quic-multi-stream.pod +DEPEND[html/man7/ossl-guide-quic-server-block.html]=man7/ossl-guide-quic-server-block.pod +GENERATE[html/man7/ossl-guide-quic-server-block.html]=man7/ossl-guide-quic-server-block.pod +DEPEND[man/man7/ossl-guide-quic-server-block.7]=man7/ossl-guide-quic-server-block.pod +GENERATE[man/man7/ossl-guide-quic-server-block.7]=man7/ossl-guide-quic-server-block.pod +DEPEND[html/man7/ossl-guide-quic-server-non-block.html]=man7/ossl-guide-quic-server-non-block.pod +GENERATE[html/man7/ossl-guide-quic-server-non-block.html]=man7/ossl-guide-quic-server-non-block.pod +DEPEND[man/man7/ossl-guide-quic-server-non-block.7]=man7/ossl-guide-quic-server-non-block.pod +GENERATE[man/man7/ossl-guide-quic-server-non-block.7]=man7/ossl-guide-quic-server-non-block.pod +DEPEND[html/man7/ossl-guide-tls-client-block.html]=man7/ossl-guide-tls-client-block.pod +GENERATE[html/man7/ossl-guide-tls-client-block.html]=man7/ossl-guide-tls-client-block.pod +DEPEND[man/man7/ossl-guide-tls-client-block.7]=man7/ossl-guide-tls-client-block.pod +GENERATE[man/man7/ossl-guide-tls-client-block.7]=man7/ossl-guide-tls-client-block.pod +DEPEND[html/man7/ossl-guide-tls-client-non-block.html]=man7/ossl-guide-tls-client-non-block.pod +GENERATE[html/man7/ossl-guide-tls-client-non-block.html]=man7/ossl-guide-tls-client-non-block.pod +DEPEND[man/man7/ossl-guide-tls-client-non-block.7]=man7/ossl-guide-tls-client-non-block.pod +GENERATE[man/man7/ossl-guide-tls-client-non-block.7]=man7/ossl-guide-tls-client-non-block.pod +DEPEND[html/man7/ossl-guide-tls-introduction.html]=man7/ossl-guide-tls-introduction.pod +GENERATE[html/man7/ossl-guide-tls-introduction.html]=man7/ossl-guide-tls-introduction.pod +DEPEND[man/man7/ossl-guide-tls-introduction.7]=man7/ossl-guide-tls-introduction.pod +GENERATE[man/man7/ossl-guide-tls-introduction.7]=man7/ossl-guide-tls-introduction.pod +DEPEND[html/man7/ossl-guide-tls-server-block.html]=man7/ossl-guide-tls-server-block.pod +GENERATE[html/man7/ossl-guide-tls-server-block.html]=man7/ossl-guide-tls-server-block.pod +DEPEND[man/man7/ossl-guide-tls-server-block.7]=man7/ossl-guide-tls-server-block.pod +GENERATE[man/man7/ossl-guide-tls-server-block.7]=man7/ossl-guide-tls-server-block.pod 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 @@ -4621,6 +5137,10 @@ 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-skeymgmt.html]=man7/provider-skeymgmt.pod +GENERATE[html/man7/provider-skeymgmt.html]=man7/provider-skeymgmt.pod +DEPEND[man/man7/provider-skeymgmt.7]=man7/provider-skeymgmt.pod +GENERATE[man/man7/provider-skeymgmt.7]=man7/provider-skeymgmt.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 @@ -4633,10 +5153,6 @@ 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 @@ -4663,12 +5179,15 @@ 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-ARGON2.html \ html/man7/EVP_KDF-HKDF.html \ +html/man7/EVP_KDF-HMAC-DRBG.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-PVKKDF.html \ html/man7/EVP_KDF-SCRYPT.html \ html/man7/EVP_KDF-SS.html \ html/man7/EVP_KDF-SSHKDF.html \ @@ -4677,7 +5196,10 @@ 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-EC.html \ +html/man7/EVP_KEM-ML-KEM.html \ html/man7/EVP_KEM-RSA.html \ +html/man7/EVP_KEM-X25519.html \ html/man7/EVP_KEYEXCH-DH.html \ html/man7/EVP_KEYEXCH-ECDH.html \ html/man7/EVP_KEYEXCH-X25519.html \ @@ -4689,6 +5211,7 @@ 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-KECCAK.html \ html/man7/EVP_MD-MD2.html \ html/man7/EVP_MD-MD4.html \ html/man7/EVP_MD-MD5-SHA1.html \ @@ -4708,12 +5231,17 @@ 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-ML-DSA.html \ +html/man7/EVP_PKEY-ML-KEM.html \ html/man7/EVP_PKEY-RSA.html \ +html/man7/EVP_PKEY-SLH-DSA.html \ html/man7/EVP_PKEY-SM2.html \ html/man7/EVP_PKEY-X25519.html \ +html/man7/EVP_RAND-CRNG-TEST.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-JITTER.html \ html/man7/EVP_RAND-SEED-SRC.html \ html/man7/EVP_RAND-TEST-RAND.html \ html/man7/EVP_RAND.html \ @@ -4721,17 +5249,19 @@ 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-ML-DSA.html \ html/man7/EVP_SIGNATURE-RSA.html \ +html/man7/EVP_SIGNATURE-SLH-DSA.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/OSSL_STORE-winstore.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 \ @@ -4742,14 +5272,31 @@ 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-qlog.html \ +html/man7/openssl-quic-concurrency.html \ +html/man7/openssl-quic.html \ html/man7/openssl-threads.html \ html/man7/openssl_user_macros.html \ +html/man7/ossl-guide-introduction.html \ +html/man7/ossl-guide-libcrypto-introduction.html \ +html/man7/ossl-guide-libraries-introduction.html \ +html/man7/ossl-guide-libssl-introduction.html \ +html/man7/ossl-guide-migration.html \ +html/man7/ossl-guide-quic-client-block.html \ +html/man7/ossl-guide-quic-client-non-block.html \ +html/man7/ossl-guide-quic-introduction.html \ +html/man7/ossl-guide-quic-multi-stream.html \ +html/man7/ossl-guide-quic-server-block.html \ +html/man7/ossl-guide-quic-server-non-block.html \ +html/man7/ossl-guide-tls-client-block.html \ +html/man7/ossl-guide-tls-client-non-block.html \ +html/man7/ossl-guide-tls-introduction.html \ +html/man7/ossl-guide-tls-server-block.html \ html/man7/ossl_store-file.html \ html/man7/ossl_store.html \ html/man7/passphrase-encoding.html \ @@ -4768,10 +5315,10 @@ html/man7/provider-mac.html \ html/man7/provider-object.html \ html/man7/provider-rand.html \ html/man7/provider-signature.html \ +html/man7/provider-skeymgmt.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 \ @@ -4789,12 +5336,15 @@ 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-ARGON2.7 \ man/man7/EVP_KDF-HKDF.7 \ +man/man7/EVP_KDF-HMAC-DRBG.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-PVKKDF.7 \ man/man7/EVP_KDF-SCRYPT.7 \ man/man7/EVP_KDF-SS.7 \ man/man7/EVP_KDF-SSHKDF.7 \ @@ -4803,7 +5353,10 @@ 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-EC.7 \ +man/man7/EVP_KEM-ML-KEM.7 \ man/man7/EVP_KEM-RSA.7 \ +man/man7/EVP_KEM-X25519.7 \ man/man7/EVP_KEYEXCH-DH.7 \ man/man7/EVP_KEYEXCH-ECDH.7 \ man/man7/EVP_KEYEXCH-X25519.7 \ @@ -4815,6 +5368,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-KECCAK.7 \ man/man7/EVP_MD-MD2.7 \ man/man7/EVP_MD-MD4.7 \ man/man7/EVP_MD-MD5-SHA1.7 \ @@ -4834,12 +5388,17 @@ 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-ML-DSA.7 \ +man/man7/EVP_PKEY-ML-KEM.7 \ man/man7/EVP_PKEY-RSA.7 \ +man/man7/EVP_PKEY-SLH-DSA.7 \ man/man7/EVP_PKEY-SM2.7 \ man/man7/EVP_PKEY-X25519.7 \ +man/man7/EVP_RAND-CRNG-TEST.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-JITTER.7 \ man/man7/EVP_RAND-SEED-SRC.7 \ man/man7/EVP_RAND-TEST-RAND.7 \ man/man7/EVP_RAND.7 \ @@ -4847,17 +5406,19 @@ 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-ML-DSA.7 \ man/man7/EVP_SIGNATURE-RSA.7 \ +man/man7/EVP_SIGNATURE-SLH-DSA.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/OSSL_STORE-winstore.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 \ @@ -4868,14 +5429,31 @@ 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-qlog.7 \ +man/man7/openssl-quic-concurrency.7 \ +man/man7/openssl-quic.7 \ man/man7/openssl-threads.7 \ man/man7/openssl_user_macros.7 \ +man/man7/ossl-guide-introduction.7 \ +man/man7/ossl-guide-libcrypto-introduction.7 \ +man/man7/ossl-guide-libraries-introduction.7 \ +man/man7/ossl-guide-libssl-introduction.7 \ +man/man7/ossl-guide-migration.7 \ +man/man7/ossl-guide-quic-client-block.7 \ +man/man7/ossl-guide-quic-client-non-block.7 \ +man/man7/ossl-guide-quic-introduction.7 \ +man/man7/ossl-guide-quic-multi-stream.7 \ +man/man7/ossl-guide-quic-server-block.7 \ +man/man7/ossl-guide-quic-server-non-block.7 \ +man/man7/ossl-guide-tls-client-block.7 \ +man/man7/ossl-guide-tls-client-non-block.7 \ +man/man7/ossl-guide-tls-introduction.7 \ +man/man7/ossl-guide-tls-server-block.7 \ man/man7/ossl_store-file.7 \ man/man7/ossl_store.7 \ man/man7/passphrase-encoding.7 \ @@ -4894,9 +5472,9 @@ man/man7/provider-mac.7 \ man/man7/provider-object.7 \ man/man7/provider-rand.7 \ man/man7/provider-signature.7 \ +man/man7/provider-skeymgmt.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/images/openssl-square-nontransparent.png b/doc/images/openssl-square-nontransparent.png deleted file mode 100644 index 5e6b747ce087..000000000000 Binary files a/doc/images/openssl-square-nontransparent.png and /dev/null differ diff --git a/doc/images/openssl-square.svg b/doc/images/openssl-square.svg deleted file mode 100644 index bb1ddc0490f3..000000000000 --- a/doc/images/openssl-square.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/images/openssl.svg b/doc/images/openssl.svg index 988d3a0e91be..218eb8528ad5 100644 --- a/doc/images/openssl.svg +++ b/doc/images/openssl.svg @@ -1,49 +1,29 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/doc/internal/man3/OPTIONS.pod b/doc/internal/man3/OPTIONS.pod index dbdd39a2ee64..acd7a44038da 100644 --- a/doc/internal/man3/OPTIONS.pod +++ b/doc/internal/man3/OPTIONS.pod @@ -333,7 +333,7 @@ things very differently. =head1 COPYRIGHT -Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file diff --git a/doc/internal/man3/OSSL_METHOD_STORE.pod b/doc/internal/man3/OSSL_METHOD_STORE.pod index 70f6eb520ff3..1b5c3aaf633b 100644 --- a/doc/internal/man3/OSSL_METHOD_STORE.pod +++ b/doc/internal/man3/OSSL_METHOD_STORE.pod @@ -5,7 +5,7 @@ OSSL_METHOD_STORE, ossl_method_store_new, ossl_method_store_free, ossl_method_store_init, ossl_method_store_cleanup, ossl_method_store_add, ossl_method_store_fetch, -ossl_method_store_remove, ossl_method_store_remove_all_provided, +ossl_method_store_remove, ossl_method_store_remove_all_provided, ossl_method_store_cache_get, ossl_method_store_cache_set, ossl_method_store_cache_flush_all - implementation method store and query diff --git a/doc/internal/man3/cms_add1_signing_cert.pod b/doc/internal/man3/cms_add1_signing_cert.pod index cc2747dcde6e..1f5f681c6434 100644 --- a/doc/internal/man3/cms_add1_signing_cert.pod +++ b/doc/internal/man3/cms_add1_signing_cert.pod @@ -36,7 +36,7 @@ is added or 0 if an error occurred. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man3/evp_generic_fetch.pod b/doc/internal/man3/evp_generic_fetch.pod index b23d2ec0eaa2..016494239e04 100644 --- a/doc/internal/man3/evp_generic_fetch.pod +++ b/doc/internal/man3/evp_generic_fetch.pod @@ -2,7 +2,7 @@ =head1 NAME -evp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov +evp_generic_fetch, evp_generic_fetch_from_prov - generic algorithm fetchers and method creators for EVP =head1 SYNOPSIS @@ -20,15 +20,6 @@ evp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov int (*up_ref_method)(void *), void (*free_method)(void *)); - void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id, - int name_id, const char *properties, - void *(*new_method)(int name_id, - const OSSL_DISPATCH *fns, - OSSL_PROVIDER *prov, - void *method_data), - void *method_data, - int (*up_ref_method)(void *), - void (*free_method)(void *)); void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id, int name_id, const char *properties, void *(*new_method)(int name_id, @@ -46,14 +37,6 @@ I, I, I, and I and uses it to create an EVP method with the help of the functions I, I, and I. -evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(), -but takes a numeric I instead of a name. -I must always be nonzero; as a matter of fact, it being zero -is considered a programming error. -This is meant to be used when one method needs to fetch an associated -method, and is typically called from inside the given function -I. - evp_generic_fetch_from_prov() does the same thing as evp_generic_fetch(), but limits the search of methods to the provider given with I. This is meant to be used when one method needs to fetch an associated @@ -138,6 +121,9 @@ And here's the implementation of the FOO method fetcher: if ((foo = OPENSSL_zalloc(sizeof(*foo))) == NULL) return NULL; + if (!CRYPTO_NEW_REF(&foo->refcnt, 1)) + goto err; + foo->name_id = name_id; for (; fns->function_id != 0; fns++) { @@ -159,18 +145,32 @@ And here's the implementation of the FOO method fetcher: break; } } + if (prov != NULL && !ossl_provider_up_ref(prov)) + goto err; + foo->prov = prov; - if (prov) - ossl_provider_up_ref(prov); return foo; + + err: + if (foo != NULL) + CRYPTO_FREE_REF(&foo->refcnt); + OPENSSL_free(foo); + return NULL } EVP_FOO_meth_free(EVP_FOO *foo) { + int i; + if (foo != NULL) { OSSL_PROVIDER *prov = foo->prov; + CRYPTO_DOWN_REF(&foo->refcnt, &i); + if (i > 0) + return; + + CRYPTO_FREE_REF(&foo->refcnt); OPENSSL_free(foo); ossl_provider_free(prov); } @@ -187,7 +187,7 @@ And here's the implementation of the FOO method fetcher: EVP_FOO *foo = vfoo; int ref = 0; - CRYPTO_UP_REF(&foo->refcnt, &ref, foo_lock); + CRYPTO_UP_REF(&foo->refcnt, &ref); return 1; } @@ -275,7 +275,7 @@ The functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod index 7099e4496473..1008d2113149 100644 --- a/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod +++ b/doc/internal/man3/evp_keymgmt_util_export_to_provider.pod @@ -25,7 +25,7 @@ OP_CACHE_ELEM OP_CACHE_ELEM *evp_keymgmt_util_find_operation_cache(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt, int selection); - int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk, int locking); + int evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk); int evp_keymgmt_util_cache_keydata(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt, void *keydata, int selection); void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk); @@ -52,9 +52,8 @@ I in I's cache of provided keys for operations. It should only be called while holding I's lock (read or write). evp_keymgmt_util_clear_operation_cache() can be used to explicitly -clear the cache of operation key references. If I is set to 1 then -then I's lock will be obtained while doing the clear. Otherwise it will be -assumed that the lock has already been obtained or is not required. +clear the cache of operation key references. If required the lock must already +have been obtained. evp_keymgmt_util_cache_keydata() can be used to add a provider key object to a B. @@ -96,7 +95,7 @@ L, L =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 diff --git a/doc/internal/man3/ossl_DER_w_bn.pod b/doc/internal/man3/ossl_DER_w_bn.pod index 49644ffd058f..3d67067a9e8b 100644 --- a/doc/internal/man3/ossl_DER_w_bn.pod +++ b/doc/internal/man3/ossl_DER_w_bn.pod @@ -56,7 +56,7 @@ L =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man3/ossl_cmp_mock_srv_new.pod b/doc/internal/man3/ossl_cmp_mock_srv_new.pod index 7bc449a84352..6f4f4fe86ba0 100644 --- a/doc/internal/man3/ossl_cmp_mock_srv_new.pod +++ b/doc/internal/man3/ossl_cmp_mock_srv_new.pod @@ -4,9 +4,13 @@ ossl_cmp_mock_srv_new, ossl_cmp_mock_srv_free, +ossl_cmp_mock_srv_set1_refCert, ossl_cmp_mock_srv_set1_certOut, ossl_cmp_mock_srv_set1_chainOut, ossl_cmp_mock_srv_set1_caPubsOut, +ossl_cmp_mock_srv_set1_newWithNew, +ossl_cmp_mock_srv_set1_newWithOld, +ossl_cmp_mock_srv_set1_oldWithNew, ossl_cmp_mock_srv_set_statusInfo, ossl_cmp_mock_srv_set_sendError, ossl_cmp_mock_srv_set_pollCount, @@ -20,11 +24,15 @@ ossl_cmp_mock_srv_set_checkAfterTime 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_refCert(OSSL_CMP_SRV_CTX *ctx, const X509 *cert); + int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *ctx, const X509 *cert); int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx, - STACK_OF(X509) *chain); + const STACK_OF(X509) *chain); int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx, - STACK_OF(X509) *caPubs); + const STACK_OF(X509) *caPubs); + int ossl_cmp_mock_srv_set1_newWithNew(OSSL_CMP_SRV_CTX *ctx, const X509 *cert); + int ossl_cmp_mock_srv_set1_newWithOld(OSSL_CMP_SRV_CTX *ctx, const X509 *cert); + int ossl_cmp_mock_srv_set1_oldWithNew(OSSL_CMP_SRV_CTX *ctx, const X509 *cert); 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_sendError(OSSL_CMP_SRV_CTX *srv_ctx, int bodytype); @@ -39,15 +47,30 @@ I, 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_mock_srv_set1_certOut() sets the certificate to be returned in -cp/ip/kup. +ossl_cmp_mock_srv_set1_refCert() sets the reference certificate (or NULL) +to be expected for rr messages and for any oldCertID included in kur messages. -ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain to be added to -the extraCerts in a cp/ip/kup. +ossl_cmp_mock_srv_set1_certOut() sets the certificate (or NULL) +to be returned in cp/ip/kup messages. +Note that on each certificate request the mock server does not produce +a fresh certificate but just returns the same pre-existing certificate. + +ossl_cmp_mock_srv_set1_chainOut() sets the certificate chain (or NULL) +to be added to the extraCerts in a cp/ip/kup message. It should be useful for the validation of the certificate given via ossl_cmp_mock_srv_set1_certOut(). -ossl_cmp_mock_srv_set1_caPubsOut() sets the caPubs to be returned in an ip. +ossl_cmp_mock_srv_set1_caPubsOut() sets list of certificates (or NULL) to be +returned in the caPubs field an ip message and in a genp of infoType caCerts. + +ossl_cmp_mock_srv_set1_newWithNew() sets the value (which may be NULL) +of the newWithNew field to be returned in a genp of infoType rootCaKeyUpdate. + +ossl_cmp_mock_srv_set1_newWithOld() sets the value (which may be NULL) +of the newWithOld field to be returned in a genp of infoType rootCaKeyUpdate. + +ossl_cmp_mock_srv_set1_oldWithNew() sets the value (which may be NULL) +of the oldWithNew field to be returned in a genp of infoType rootCaKeyUpdate. ossl_cmp_mock_srv_set_statusInfo() sets the status info to be returned. diff --git a/doc/internal/man3/ossl_cmp_msg_check_update.pod b/doc/internal/man3/ossl_cmp_msg_check_update.pod index 4e7a9224afdd..d1513bf34f0c 100644 --- a/doc/internal/man3/ossl_cmp_msg_check_update.pod +++ b/doc/internal/man3/ossl_cmp_msg_check_update.pod @@ -33,7 +33,7 @@ The B is checked for the following: =item its protection is present and valid (or a callback function B is present and indicates that a missing or invalid protection is acceptable), -=item its CMP protocol version is acceptable, namely B, +=item its CMP protocol version is acceptable, =item its body type is valid, @@ -66,7 +66,7 @@ and learns the transaction ID if none is currently present in B. Moreover, according to RFC 4210 section 5.3.2, if the message protection is PBM-based then any certificates in the caPubs field are added to the list of -trusted certificates (if set via L). +trusted certificates (if set via L). This way these certs are available for validating subsequent messages in the same context and could apply to any Polling Response (pollRep), error, or PKI Confirmation (PKIConf) messages following in the same or future transactions. diff --git a/doc/internal/man3/ossl_cmp_msg_protect.pod b/doc/internal/man3/ossl_cmp_msg_protect.pod index 744fbce576ca..7e14274f584a 100644 --- a/doc/internal/man3/ossl_cmp_msg_protect.pod +++ b/doc/internal/man3/ossl_cmp_msg_protect.pod @@ -21,6 +21,9 @@ ossl_cmp_msg_add_extraCerts ossl_cmp_calc_protection() calculates the protection for the given I according to the algorithm and parameters in the message header's protectionAlg using the credentials, library context, and property criteria in the I. +Unless Iheader->protectionAlg> is B, +its value is completed according to Ipkey> and Idigest>, +where the latter irrelevant in the case of Edwards curves. ossl_cmp_msg_protect() (re-)protects the given message I using an algorithm depending on the available context information given in the I. diff --git a/doc/internal/man3/ossl_lib_ctx_get_data.pod b/doc/internal/man3/ossl_lib_ctx_get_data.pod index faedf7275f08..2780c7b91706 100644 --- a/doc/internal/man3/ossl_lib_ctx_get_data.pod +++ b/doc/internal/man3/ossl_lib_ctx_get_data.pod @@ -11,14 +11,7 @@ ossl_lib_ctx_is_child #include #include "internal/cryptlib.h" - typedef struct ossl_lib_ctx_method { - int priority; - void *(*new_func)(OSSL_LIB_CTX *ctx); - void (*free_func)(void *); - } OSSL_LIB_CTX_METHOD; - - void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index, - const OSSL_LIB_CTX_METHOD *meth); + void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index); int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx, ossl_lib_ctx_run_once_fn run_once_fn); @@ -28,38 +21,24 @@ ossl_lib_ctx_is_child =head1 DESCRIPTION -Internally, the OpenSSL library context B is implemented -as a B, which allows data from diverse parts of the -library to be added and removed dynamically. -Each such data item must have a corresponding CRYPTO_EX_DATA index -associated with it. Unlike normal CRYPTO_EX_DATA objects we use static indexes -to identify data items. These are mapped transparently to CRYPTO_EX_DATA dynamic -indexes internally to the implementation. -See the example further down to see how that's done. - -ossl_lib_ctx_get_data() is used to retrieve a pointer to the data in -the library context I associated with the given I. An -OSSL_LIB_CTX_METHOD must be defined and given in the I parameter. The index -for it should be defined in cryptlib.h. The functions through the method are -used to create or free items that are stored at that index whenever a library -context is created or freed, meaning that the code that use a data item of that -index doesn't have to worry about that, just use the data available. - -Deallocation of an index happens automatically when the library -context is freed. - -ossl_lib_ctx_run_once is used to run some initialisation routine I +ossl_lib_ctx_run_once() is used to run some initialisation routine I exactly once per library context I object. Each initialisation routine should be allocate a unique run once index in cryptlib.h. Any resources allocated via a run once initialisation routine can be cleaned up -using ossl_lib_ctx_onfree. This associates an "on free" routine I with +using ossl_lib_ctx_onfree(). This associates an "on free" routine I with the library context I. When I is freed all associated "on free" routines are called. ossl_lib_ctx_is_child() returns 1 if this library context is a child and 0 otherwise. +ossl_lib_ctx_get_data() allows different parts of the library to retrieve +pointers to structures used in diverse parts of the library. The lifetime of +these structures is managed by B. The different objects which can +be retrieved are specified with the given argument I. The valid values of +I are specified in cryptlib.h. + =head1 RETURN VALUES ossl_lib_ctx_get_data() returns a pointer on success, or NULL on @@ -67,51 +46,15 @@ failure. =head1 EXAMPLES -=head2 Initialization - -For a type C that should end up in the OpenSSL library context, a -small bit of initialization is needed, i.e. to associate a constructor -and a destructor to an index. - - typedef struct foo_st { - int i; - void *data; - } FOO; - - static void *foo_new(OSSL_LIB_CTX *ctx) - { - FOO *ptr = OPENSSL_zalloc(sizeof(*foo)); - if (ptr != NULL) - ptr->i = 42; - return ptr; - } - static void foo_free(void *ptr) - { - OPENSSL_free(ptr); - } - - /* - * Include a reference to this in the methods table in context.c - * OSSL_LIB_CTX_FOO_INDEX should be added to internal/cryptlib.h - * Priorities can be OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - * OSSL_LIB_CTX_METHOD_PRIORITY_1, OSSL_LIB_CTX_METHOD_PRIORITY_2, etc. - * Default priority is low (0). The higher the priority the earlier the - * method's destructor will be called when the library context is cleaned up. - */ - const OSSL_LIB_CTX_METHOD foo_method = { - OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, - foo_new, - foo_free - }; - =head2 Usage -To get and use the data stored in the library context, simply do this: +To obtain a pointer for an object managed by the library context, simply do +this: /* * ctx is received from a caller, */ - FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX, &foo_method); + FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX); =head2 Run Once @@ -144,7 +87,7 @@ L =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man3/ossl_method_construct.pod b/doc/internal/man3/ossl_method_construct.pod index 422d7a5b6850..603930dc1f69 100644 --- a/doc/internal/man3/ossl_method_construct.pod +++ b/doc/internal/man3/ossl_method_construct.pod @@ -148,7 +148,7 @@ This functionality was added to OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod index ff247e87b03c..7f4940fc9341 100644 --- a/doc/internal/man3/ossl_namemap_new.pod +++ b/doc/internal/man3/ossl_namemap_new.pod @@ -3,7 +3,7 @@ =head1 NAME ossl_namemap_new, ossl_namemap_free, ossl_namemap_stored, ossl_namemap_empty, -ossl_namemap_add_name, ossl_namemap_add_name_n, ossl_namemap_add_names, +ossl_namemap_add_name, ossl_namemap_add_names, ossl_namemap_name2num, ossl_namemap_name2num_n, ossl_namemap_doall_names - internal number E-E name map @@ -19,8 +19,6 @@ ossl_namemap_doall_names int ossl_namemap_empty(OSSL_NAMEMAP *namemap); int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name); - int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number, - const char *name, size_t name_len); int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name); int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap, @@ -62,10 +60,9 @@ names already associated with that number. ossl_namemap_name2num() finds the number corresponding to the given I. -ossl_namemap_add_name_n() and ossl_namemap_name2num_n() do the same thing -as ossl_namemap_add_name() and ossl_namemap_name2num(), but take a string -length I as well, allowing the caller to use a fragment of -a string as a name. +ossl_namemap_name2num_n() does the same thing as +ossl_namemap_name2num(), but takes a string length I as well, +allowing the caller to use a fragment of a string as a name. ossl_namemap_doall_names() walks through all names associated with I in the given I and calls the function I for @@ -88,8 +85,8 @@ ossl_namemap_empty() returns 1 if the B is NULL or empty, 0 if it's not empty, or -1 on internal error (such as inability to lock). -ossl_namemap_add_name() and ossl_namemap_add_name_n() return the number -associated with the added string, or zero on error. +ossl_namemap_add_name() returns the number associated with the added +string, or zero on error. ossl_namemap_num2names() returns a pointer to a NULL-terminated list of pointers to the names corresponding to the given number, or NULL if diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod index 193472462b38..3e3694b79cae 100644 --- a/doc/internal/man3/ossl_provider_new.pod +++ b/doc/internal/man3/ossl_provider_new.pod @@ -3,9 +3,8 @@ =head1 NAME ossl_provider_find, ossl_provider_new, ossl_provider_up_ref, -ossl_provider_free, -ossl_provider_set_fallback, ossl_provider_set_module_path, -ossl_provider_add_parameter, ossl_provider_set_child, ossl_provider_get_parent, +ossl_provider_free, ossl_provider_set_module_path, +ossl_provider_set_child, ossl_provider_get_parent, ossl_provider_up_ref_parent, ossl_provider_free_parent, ossl_provider_default_props_update, ossl_provider_get0_dispatch, ossl_provider_init_as_child, ossl_provider_deinit_child, @@ -18,6 +17,7 @@ ossl_provider_libctx, ossl_provider_teardown, ossl_provider_gettable_params, ossl_provider_get_params, ossl_provider_query_operation, ossl_provider_unquery_operation, +ossl_provider_random_bytes, ossl_provider_set_operation_bit, ossl_provider_test_operation_bit, ossl_provider_get_capabilities - internal provider routines @@ -35,10 +35,7 @@ ossl_provider_get_capabilities void ossl_provider_free(OSSL_PROVIDER *prov); /* Setters */ - int ossl_provider_set_fallback(OSSL_PROVIDER *prov); int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *path); - int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name, - const char *value); /* Child Providers */ int ossl_provider_set_child(OSSL_PROVIDER *prov, @@ -90,6 +87,8 @@ ossl_provider_get_capabilities void ossl_provider_unquery_operation(const OSSL_PROVIDER *prov, int operation_id, const OSSL_ALGORITHM *algs); + int ossl_provider_random_bytes(const OSSL_PROVIDER *prov, int which, + void *buf, size_t n, unsigned int strength); int ossl_provider_set_operation_bit(OSSL_PROVIDER *provider, size_t bitnum); int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum, @@ -159,11 +158,6 @@ to have fallen out of use and will be deinitialized (its I function is called), and the associated module will be unloaded if one was loaded, and I itself will be freed. -ossl_provider_set_fallback() marks an available provider I as -fallback. -Note that after this call, the provider object pointer that was -used can simply be dropped, but not freed. - ossl_provider_set_module_path() sets the module path to load the provider module given the provider object I. This will be used in preference to automatically trying to figure out @@ -173,13 +167,6 @@ on this in L). ossl_provider_libctx() returns the library context the given provider I is registered in. -ossl_provider_add_parameter() adds a global parameter for the provider -to retrieve as it sees fit. -The parameters are a combination of I and I, and the -provider will use the name to find the value it wants. -Only text parameters can be given, and it's up to the provider to -interpret them. - ossl_provider_set_child() marks this provider as a child of a provider in the parent library context. I is the B object passed to the provider's B function. @@ -292,6 +279,26 @@ ossl_provider_unquery_operation() informs the provider that the result of ossl_provider_query_operation() is no longer going to be directly accessed and that all relevant information has been copied. +ossl_provider_random_bytes() queries the provider, I, randomness +source for I bytes of entropy which are returned in the buffer +I, the returned entropy will have a number of bits of I. +The entropy is drawn from the source, I, which can be: + +=over 4 + +=item * + +OSSL_PROV_RANDOM_PUBLIC for a source equivalent to L or + +=item * + +.OSSL_PROV_RANDOM_PRIVATE for a source equivalent to L. + +=back + +Specifying other values for I will result in an unspecified source but will +not result in an error. + ossl_provider_set_operation_bit() registers a 1 for operation I in a bitstring that's internal to I. @@ -350,7 +357,7 @@ ossl_provider_doall_activated() returns 1 if the callback was called for all activated providers. A return value of 0 means that the callback was not called for any activated providers. -ossl_provider_set_module_path(), ossl_provider_set_fallback(), +ossl_provider_set_module_path(), ossl_provider_activate(), ossl_provider_activate_leave_fallbacks() and ossl_provider_deactivate(), ossl_provider_add_to_store(), ossl_provider_default_props_update() return 1 on success, or 0 on error. @@ -380,6 +387,9 @@ ossl_provider_get_capabilities() returns 1 on success, or 0 on error. If this function isn't available in the provider or the provider does not support the requested capability then 0 is returned. +ossl_provider_random_bytes() returns 1 on success or 0 or -1 on error as per +L. + =head1 SEE ALSO L, L, L @@ -390,7 +400,7 @@ The functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man3/ossl_punycode_decode.pod b/doc/internal/man3/ossl_punycode_decode.pod index 652626159e3a..64fe670ac6ae 100644 --- a/doc/internal/man3/ossl_punycode_decode.pod +++ b/doc/internal/man3/ossl_punycode_decode.pod @@ -2,7 +2,7 @@ =head1 NAME -ossl_punycode_decode, ossl_a2ulabel, ossl_a2ucompare +ossl_punycode_decode, ossl_a2ulabel - internal punycode-related functions =head1 SYNOPSIS @@ -12,33 +12,24 @@ ossl_punycode_decode, ossl_a2ulabel, ossl_a2ucompare int ossl_punycode_decode(const char *pEncoded, const size_t enc_len, unsigned int *pDecoded, unsigned int *pout_length); - int ossl_a2ulabel(const char *in, char *out, size_t *outlen); - - int ossl_a2ucompare(const char *a, const char *u); + int ossl_a2ulabel(const char *in, char *out, size_t outlen); =head1 DESCRIPTION PUNYCODE encoding introduced in RFCs 3490-3492 is widely used for -representation of host names in ASCII-only format. Some specifications, -such as RFC 8398, require comparison of host names encoded in UTF-8 charset. +representation of hostnames in ASCII-only format. Some specifications, +such as RFC 8398, require comparison of hostnames encoded in UTF-8 charset. ossl_a2ulabel() decodes NUL-terminated hostname from PUNYCODE to UTF-8, -using a provided buffer for output. - -ossl_a2ucompare() accepts two NUL-terminated hostnames, decodes the 1st -from PUNYCODE to UTF-8 and compares it with the 2nd one as is. +using a provided buffer for output. The output buffer is NUL-terminated. ossl_punycode_decode() decodes one label (one dot-separated part) from a hostname, with stripped PUNYCODE marker I. =head1 RETURN VALUES -ossl_a2ulabel() returns 1 on success, 0 on not enough buf passed, --1 on invalid PUNYCODE string passed. When valid string is provided, it sets the -I<*outlen> to the length of required buffer to perform correct decoding. - -ossl_a2ucompare() returns 1 on non-equal strings, 0 on equal strings, --1 when invalid PUNYCODE string passed. +ossl_a2ulabel() returns 1 on success, 0 if the output buffer is too small and +-1 if an invalid PUNYCODE string is passed or another error occurs. ossl_punycode_decode() returns 1 on success, 0 on error. On success, *pout_length contains the number of codepoints decoded. @@ -49,7 +40,7 @@ The functions described here were all added 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 diff --git a/doc/internal/man3/ossl_rand_get_entropy.pod b/doc/internal/man3/ossl_rand_get_entropy.pod index 4da3f1f4d9db..be39369f2b70 100644 --- a/doc/internal/man3/ossl_rand_get_entropy.pod +++ b/doc/internal/man3/ossl_rand_get_entropy.pod @@ -2,8 +2,10 @@ =head1 NAME -ossl_rand_get_entropy, ossl_rand_cleanup_entropy, -ossl_rand_get_nonce, ossl_rand_cleanup_nonce +ossl_rand_get_entropy, ossl_rand_get_user_entropy, +ossl_rand_cleanup_entropy, ossl_rand_cleanup_user_entropy, +ossl_rand_get_nonce, ossl_rand_get_user_nonce, +ossl_rand_cleanup_nonce, ossl_rand_cleanup_user_nonce - get seed material from the operating system =head1 SYNOPSIS @@ -13,13 +15,23 @@ ossl_rand_get_nonce, ossl_rand_cleanup_nonce size_t ossl_rand_get_entropy(OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t ossl_rand_get_user_entropy(OSSL_CORE_HANDLE *handle, + unsigned char **pout, int entropy, + size_t min_len, size_t max_len); void ossl_rand_cleanup_entropy(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); + void ossl_rand_cleanup_user_entropy(OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len); size_t ossl_rand_get_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, size_t min_len, size_t max_len, const void *salt, size_t salt_len); + size_t ossl_rand_get_user_nonce(OSSL_CORE_HANDLE *handle, unsigned char **pout, + size_t min_len, size_t max_len, + const void *salt, size_t salt_len); void ossl_rand_cleanup_nonce(OSSL_CORE_HANDLE *handle, unsigned char *buf, size_t len); + void ossl_rand_cleanup_user_nonce(OSSL_CORE_HANDLE *handle, + unsigned char *buf, size_t len); =head1 DESCRIPTION @@ -29,9 +41,18 @@ stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. +ossl_rand_get_user_entropy() is the same as ossl_rand_get_entropy() +except that it retrieves the seeding material from the library context's +DRBG seed source. By default this is the operating system but it can +be changed by calling L. + ossl_rand_cleanup_entropy() cleanses and frees any storage allocated by -ossl_rand_get_entropy(). The seeding buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_entropy(). The entropy buffer is pointed to by I +and is of length I bytes. + +ossl_rand_cleanup_user_entropy() cleanses and frees any storage allocated by +ossl_rand_get_user_entropy(). The entropy buffer is pointed to by I +and is of length I bytes. ossl_rand_get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -41,22 +62,39 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. +ossl_rand_get_user_nonce() is the same as ossl_rand_get_nonce() except +that it retrieves the seeding material from the library context's DRBG +seed source. By default this is the operating system but it can be +changed by calling L. + ossl_rand_cleanup_nonce() cleanses and frees any storage allocated by -ossl_rand_get_nonce(). The nonce buffer is pointed to by I and is -of length I bytes. +ossl_rand_get_nonce() or ossl_rand_get_user_nonce(). The nonce buffer +is pointed to by I and is of length I bytes. + +=head1 NOTES + +FIPS providers 3.0.0, 3.0.8 and 3.0.9 incorrectly pass a provider +internal pointer to ossl_rand_get_entropy(), ossl_rand_cleanup_entropy(), +ossl_rand_get_nonce() and ossl_rand_cleanup_nonce(). This pointer cannot +be safely dereferenced. =head1 RETURN VALUES -ossl_rand_get_entropy() and ossl_rand_get_nonce() return the number of bytes -in I<*pout> or 0 on error. +ossl_rand_get_entropy(), ossl_rand_get_user_entropy(), +ossl_rand_get_nonce() and ossl_rand_get_user_nonce() return the number +of bytes in I<*pout> or 0 on error. =head1 HISTORY -The functions described here were all added in OpenSSL 3.0. +The functions ossl_rand_get_user_entropy(), ossl_rand_get_user_nonce(), +ossl_rand_cleanup_user_entropy(), and ossl_rand_cleanup_user_nonce() +were added in OpenSSL 3.1.4 and 3.2.0. + +The remaining functions described here were all added in OpenSSL 3.0. =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 diff --git a/doc/internal/man3/ossl_random_add_conf_module.pod b/doc/internal/man3/ossl_random_add_conf_module.pod index a3c1285fe01b..f1fd22be10fa 100644 --- a/doc/internal/man3/ossl_random_add_conf_module.pod +++ b/doc/internal/man3/ossl_random_add_conf_module.pod @@ -32,7 +32,7 @@ The functions described here were all added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man7/DERlib.pod b/doc/internal/man7/DERlib.pod index 24280b976b34..f4f3abab51a4 100644 --- a/doc/internal/man7/DERlib.pod +++ b/doc/internal/man7/DERlib.pod @@ -139,7 +139,7 @@ L =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man7/EVP_PKEY.pod b/doc/internal/man7/EVP_PKEY.pod index 3dc10fa4104c..fd3c27c2db71 100644 --- a/doc/internal/man7/EVP_PKEY.pod +++ b/doc/internal/man7/EVP_PKEY.pod @@ -77,9 +77,9 @@ OpenSSL providers allow it for the following: =over 4 -=item DH, EC, X25519, X448: +=item DH, EC, X25519, X448, ML-KEM (512, 768 and 1024): -It's possible to set the encoded public key. This is supported in +It is possible to set the encoded public key. This is supported in particular through L. =item EC: @@ -198,11 +198,16 @@ reflected back in the provider key. =head1 SEE ALSO -L +L, +L, +L, +L, +L, +L. =head1 COPYRIGHT -Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/internal/man7/build.info.pod b/doc/internal/man7/build.info.pod index 080c9e444eea..6f67aca7a55a 100644 --- a/doc/internal/man7/build.info.pod +++ b/doc/internal/man7/build.info.pod @@ -461,18 +461,15 @@ C is strong, while the dependency between C and C and C is weak. See the description of B in L for more information. +B is a bit more involving when used with Is that are +generated with B. This is described more in depth below. + =item BIB<]> B<=> I I ... This specifies that the I is generated using the I with the Is as arguments, plus the name of the output file as last argument. -For Is where this is applicable, any B statement -for the same I will be given to the I as its -inclusion directories. Likewise, any B statement for the same -I will be given to the I as an extra file or module -to load, where this is applicable. - The build file generators must be able to recognise the I. Currently, they at least recognise files ending in C<.pl>, and will execute them to generate the I, and files ending in C<.in>, @@ -480,6 +477,42 @@ which will be used as input for L to generate I (in other words, we use the exact same style of L mechanism that is used to read F files). +For Is where this is applicable, any B statement +for the same I will be given to the I as its +inclusion directories. + +Likewise, For Is where this is applicable, any B +statement for the same I will be given to the I as an +extra file or module to load, where this is applicable. + +=over 4 + +=item The B statement may be problematic: + +Depending on what generator is used, a B statement also acts +as an B statement for the directory where the I is +located. In some cases, that's not quite feasible, because a module +isn't meant to be loaded by filename only and may require a nondefault +separation between the implied inclusion directory and the intended module +name. + +=item ... but there is a solution: + +To enable that sort of separation, B can use a slightly +different I syntax, that looks like this: + +BIB<]> B<=> I|I + +The I must be specified in a way that makes sense for the generator. +For example, when the generator implies perl (ends with C<.in>) and depends +on the module F - a.k.a. F - which lives in +F, it feasible to have something like this: + + GENERATE[something.c]=something.c.in + DEPEND[something.c]=util/perl|OpenSSL/foo.pm + +=back + =item BIB<]> B<=> I ... Collects filenames that will be used as source files for I. @@ -634,7 +667,7 @@ L =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 diff --git a/doc/internal/man7/deprecation.pod b/doc/internal/man7/deprecation.pod index 13a4b059a04c..de34c30fa22f 100644 --- a/doc/internal/man7/deprecation.pod +++ b/doc/internal/man7/deprecation.pod @@ -2,6 +2,7 @@ =head1 NAME +OPENSSL_NO_DEPRECATED_3_1, OSSL_DEPRECATEDIN_3_1, OPENSSL_NO_DEPRECATED_3_0, OSSL_DEPRECATEDIN_3_0, OPENSSL_NO_DEPRECATED_1_1_1, OSSL_DEPRECATEDIN_1_1_1, OPENSSL_NO_DEPRECATED_1_1_0, OSSL_DEPRECATEDIN_1_1_0, diff --git a/doc/life-cycles/digest.dot b/doc/life-cycles/digest.dot index 8d4d72480c9a..2f22a0d5e695 100644 --- a/doc/life-cycles/digest.dot +++ b/doc/life-cycles/digest.dot @@ -6,28 +6,30 @@ digraph digest { initialised [label=initialised, fontcolor="#c94c4c"]; updated [label=updated, fontcolor="#c94c4c"]; finaled [label="finaled", fontcolor="#c94c4c"]; + squeezed [label="squeezed", fontcolor="#c94c4c"]; end [label="freed", color="#deeaee", style="filled"]; begin -> newed [label="EVP_MD_CTX_new"]; - newed -> initialised [label="EVP_DigestInit"]; - initialised -> updated [label="EVP_DigestUpdate", weight=3]; + newed -> initialised [label="EVP_DigestInit", weight=100]; + initialised -> updated [label="EVP_DigestUpdate", weight=100]; updated -> updated [label="EVP_DigestUpdate"]; - updated -> finaled [label="EVP_DigestFinal"]; + updated -> finaled [label="EVP_DigestFinal", weight=2]; updated -> finaled [label="EVP_DigestFinalXOF", fontcolor="#808080", color="#808080"]; - /* Once this works it should go back in: - finaled -> finaled [taillabel="EVP_DigestFinalXOF", - labeldistance=9, labelangle=345, - labelfontcolor="#808080", color="#808080"]; - */ + updated -> squeezed [label="EVP_DigestSqueeze", weight=3]; finaled -> end [label="EVP_MD_CTX_free"]; - finaled -> newed [label="EVP_MD_CTX_reset", style=dashed, weight=2, + finaled -> newed [label="EVP_MD_CTX_reset", style=dashed, color="#034f84", fontcolor="#034f84"]; updated -> newed [label="EVP_MD_CTX_reset", style=dashed, color="#034f84", fontcolor="#034f84"]; - updated -> initialised [label="EVP_DigestInit", weight=0, style=dashed, + updated -> initialised [label="EVP_DigestInit", style=dashed, color="#034f84", fontcolor="#034f84"]; finaled -> initialised [label="EVP_DigestInit", style=dashed, color="#034f84", fontcolor="#034f84"]; + squeezed -> squeezed [label="EVP_DigestSqueeze"]; + squeezed -> end [label="EVP_MD_CTX_free", weight=1]; + squeezed -> newed [label="EVP_MD_CTX_reset", style=dashed, + color="#034f84", fontcolor="#034f84"]; + squeezed -> initialised [label="EVP_DigestInit", style=dashed, + color="#034f84", fontcolor="#034f84"]; } - diff --git a/doc/man1/CA.pl.pod b/doc/man1/CA.pl.pod index e05775cdca66..184382ee8335 100644 --- a/doc/man1/CA.pl.pod +++ b/doc/man1/CA.pl.pod @@ -6,6 +6,8 @@ CA.pl - friendlier interface for OpenSSL certificate programs =head1 SYNOPSIS +=for openssl duplicate options + B B<-?> | B<-h> | @@ -189,7 +191,7 @@ L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/build.info b/doc/man1/build.info index b796fce42fdd..ee6f243e20b3 100644 --- a/doc/man1/build.info +++ b/doc/man1/build.info @@ -44,6 +44,7 @@ DEPEND[openssl-rsa.pod]=../perlvars.pm DEPEND[openssl-rsautl.pod]=../perlvars.pm DEPEND[openssl-s_client.pod]=../perlvars.pm DEPEND[openssl-sess_id.pod]=../perlvars.pm +DEPEND[openssl-skeyutl.pod]=../perlvars.pm DEPEND[openssl-smime.pod]=../perlvars.pm DEPEND[openssl-speed.pod]=../perlvars.pm DEPEND[openssl-spkac.pod]=../perlvars.pm diff --git a/doc/man1/openssl-asn1parse.pod.in b/doc/man1/openssl-asn1parse.pod.in index f098c89c3382..6fd5ed692d95 100644 --- a/doc/man1/openssl-asn1parse.pod.in +++ b/doc/man1/openssl-asn1parse.pod.in @@ -9,7 +9,7 @@ openssl-asn1parse - ASN.1 parsing command B B [B<-help>] -[B<-inform> B|B] +[B<-inform> B|B|B] [B<-in> I] [B<-out> I] [B<-noout>] @@ -38,7 +38,7 @@ It can also be used to extract data from ASN.1 formatted data. Print out a usage message. -=item B<-inform> B|B +=item B<-inform> B|B|B The input format; the default is B. See L for details. @@ -210,7 +210,7 @@ L =head1 COPYRIGHT -Copyright 2000-2020 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 diff --git a/doc/man1/openssl-ca.pod.in b/doc/man1/openssl-ca.pod.in index 1c07db3c8ef1..05fe63d4e39c 100644 --- a/doc/man1/openssl-ca.pod.in +++ b/doc/man1/openssl-ca.pod.in @@ -10,6 +10,7 @@ openssl-ca - sample minimal CA application B B [B<-help>] [B<-verbose>] +[B<-quiet>] [B<-config> I] [B<-name> I
] [B<-section> I
] @@ -29,7 +30,9 @@ B B [B<-crlsec> I] [B<-crlexts> I
] [B<-startdate> I] +[B<-not_before> I] [B<-enddate> I] +[B<-not_after> I] [B<-days> I] [B<-md> I] [B<-policy> I] @@ -70,6 +73,11 @@ B B This command emulates a CA application. See the B especially when considering to use it productively. + +It generates certificates bearing X.509 version 3. +Unless specified otherwise, +key identifier extensions are included as described in L. + It can be used to sign certificate requests (CSRs) in a variety of forms and generate certificate revocation lists (CRLs). It also maintains a text database of issued certificates and their status. @@ -95,6 +103,11 @@ Print out a usage message. This prints extra details about the operations being performed. +=item B<-quiet> + +This prints fewer details about the operations being performed, which may +be handy during batch scripts or pipelines. + =item B<-config> I Specifies the configuration file to use. @@ -113,8 +126,8 @@ signed by the CA. =item B<-inform> B|B -The format of the data in certificate request input files; -unspecified by default. +The format to use when loading certificate request (CSR) input files; +by default PEM is tried first. See L for details. =item B<-ss_cert> I @@ -166,7 +179,8 @@ See L for details. =item B<-sigopt> I:I Pass options to the signature algorithm during sign operations. -Names and values of these options are algorithm-specific. +Names and values of these options are algorithm-specific and +documented in L. =item B<-vfyopt> I:I @@ -215,23 +229,32 @@ Don't output the text form of a certificate to the output file. Specify the date output format. Values are: rfc_822 and iso_8601. Defaults to rfc_822. -=item B<-startdate> I +=item B<-startdate> I, B<-not_before> I This allows the start date to be explicitly set. The format of the date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In both formats, seconds SS and timezone Z must be present. +Alternatively, you can also use "today". -=item B<-enddate> I +=item B<-enddate> I, B<-not_after> I This allows the expiry date to be explicitly set. The format of the date is YYMMDDHHMMSSZ (the same as an ASN1 UTCTime structure), or YYYYMMDDHHMMSSZ (the same as an ASN1 GeneralizedTime structure). In both formats, seconds SS and timezone Z must be present. +Alternatively, you can also use "today". + +This overrides the B<-days> option. =item B<-days> I -The number of days to certify the certificate for. +The number of days from today to certify the certificate for. + +Regardless of the option B<-not_before>, the days are always counted from +today. +When used together with the option B<-not_after>/B<-startdate>, the explicit +expiry date takes precedence. =item B<-md> I @@ -281,8 +304,7 @@ and all certificates will be certified automatically. The section of the configuration file containing certificate extensions to be added when a certificate is issued (defaults to B unless the B<-extfile> option is used). -If no X.509 extensions are specified then a V1 certificate is created, -else a V3 certificate is created. + See the L manual page for details of the extension section format. @@ -492,7 +514,7 @@ not necessary anymore, see the L section. =item B -The same as the B<-days> option. The number of days to certify +The same as the B<-days> option. The number of days from today to certify a certificate for. =item B @@ -780,7 +802,7 @@ properly secure the private key(s) used for signing certificates. It is advisable to keep them in a secure HW storage such as a smart card or HSM and access them via a suitable engine or crypto provider. -This command command is effectively a single user command: no locking +This command is effectively a single user command: no locking is done on the various files and attempts to run more than one B command on the same database can have unpredictable results. @@ -827,6 +849,9 @@ has no effect. The B<-engine> option was deprecated in OpenSSL 3.0. +Since OpenSSL 3.2, generated certificates bear X.509 version 3, +and key identifier extensions are included by default. + =head1 SEE ALSO L, @@ -839,7 +864,7 @@ L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-ciphers.pod.in b/doc/man1/openssl-ciphers.pod.in index 658730ec5382..69195bcdcbd0 100644 --- a/doc/man1/openssl-ciphers.pod.in +++ b/doc/man1/openssl-ciphers.pod.in @@ -17,7 +17,6 @@ B B [B<-tls1_1>] [B<-tls1_2>] [B<-tls1_3>] -[B<-s>] [B<-psk>] [B<-srp>] [B<-stdname>] @@ -115,6 +114,10 @@ used. The format is described below. The cipher list consists of one or more I separated by colons. Commas or spaces are also acceptable separators but colons are normally used. +The cipher string may reference a cipher using its standard name from +the IANA TLS Cipher Suites Registry +(L). + The actual cipher string can take several different forms. It can consist of a single cipher suite such as B. @@ -413,10 +416,13 @@ B, B, B, B, B is only available if OpenSSL is built with tracing enabled The B<-convert> option was added in OpenSSL 1.1.1. +Support for standard IANA names in cipher lists was added in +OpenSSL 3.2.0. + +The support for TLS v1.3 integrity-only cipher suites was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-cmds.pod.in b/doc/man1/openssl-cmds.pod.in index a8b158123239..4cfb7ce4ee05 100644 --- a/doc/man1/openssl-cmds.pod.in +++ b/doc/man1/openssl-cmds.pod.in @@ -152,7 +152,7 @@ deprecated in OpenSSL 3.0 and will be removed in OpenSSL 4.0. =head1 COPYRIGHT -Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 889a59cd497e..f44615d1fc18 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -17,14 +17,18 @@ Generic message options: [B<-cmd> I] [B<-infotype> I] -[B<-geninfo> I] +[B<-profile> I] +[B<-geninfo> I] +[B<-template> I] +[B<-keyspec> I] Certificate enrollment options: [B<-newkey> I|I] [B<-newkeypass> I] +[B<-centralkeygen> +[B<-newkeyout> I] [B<-subject> I] -[B<-issuer> I] [B<-days> I] [B<-reqexts> I] [B<-sans> I] @@ -43,6 +47,8 @@ Certificate enrollment options: Certificate enrollment and revocation options: [B<-oldcert> I|I] +[B<-issuer> I] +[B<-serial> I] [B<-revreason> I] Message transfer options: @@ -64,8 +70,17 @@ Server authentication options: [B<-expect_sender> I] [B<-ignore_keyusage>] [B<-unprotected_errors>] +[B<-no_cache_extracerts>] +[B<-srvcertout> I] [B<-extracertsout> I] [B<-cacertsout> I] +[B<-oldwithold> I] +[B<-newwithnew> I] +[B<-newwithold> I] +[B<-oldwithnew> I] +[B<-crlcert> I] +[B<-oldcrl> I] +[B<-crlout> I] Client authentication and protection options: @@ -83,6 +98,7 @@ Client authentication and protection options: Credentials format options: [B<-certform> I] +[B<-crlform> I] [B<-keyform> I] [B<-otherpass> I] {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -108,6 +124,7 @@ Client-side debugging options: [B<-reqin> I] [B<-reqin_new_tid>] [B<-reqout> I] +[B<-reqout_only> I] [B<-rspin> I] [B<-rspout> I] [B<-use_mock_srv>] @@ -123,9 +140,16 @@ Mock server options: [B<-srv_keypass> I] [B<-srv_trusted> I|I] [B<-srv_untrusted> I|I] +[B<-ref_cert> I|I] [B<-rsp_cert> I|I] +[B<-rsp_key> I|I] +[B<-rsp_keypass> I|I] +[B<-rsp_crl> I|I] [B<-rsp_extracerts> I|I] [B<-rsp_capubs> I|I] +[B<-rsp_newwithnew> I|I] +[B<-rsp_newwithold> I|I] +[B<-rsp_oldwithnew> I|I] [B<-poll_count> I] [B<-check_after> I] [B<-grant_implicitconf>] @@ -234,11 +258,33 @@ ITAV Bs is printed to stdout. Set InfoType name to use for requesting specific info in B, e.g., C. +There is specific support for C, C, +C, and C (CRL update retrieval). -=item B<-geninfo> I +=item B<-profile> I -generalInfo integer values to place in request PKIHeader with given OID, -e.g., C<1.2.3.4:int:56789>. +Name of a certificate profile to place in +the PKIHeader generalInfo field of request messages. + +=item B<-geninfo> I + +A comma-separated list of InfoTypeAndValue to place in +the generalInfo field of the PKIHeader of requests messages. +Each InfoTypeAndValue gives an OID and an integer or string value +of the form I:int:I or I:str:I, +e.g., C<'1.2.3.4:int:56789, id-kp:str:name'>. + +=item B<-template> I + +The file to save any CRMF certTemplate in DER format +received in a genp message with id-it-certReqTemplate. + +=item B<-keyspec> I + +It is optional and used to specify the file to save any keySpec if +present in a genp message with id-it-keyGenParameters. + +Note: any keySpec field contents received are logged as INFO. =back @@ -266,17 +312,26 @@ If not given here, the password will be prompted for if needed. For more information about the format of I see L. +=item B<-centralkeygen> + +Request central key generation for certificate enrollment. +This applies to B<-cmd> I. + +=item B<-newkeyout> I + +File to save centrally generated private key, in PEM format. + =item B<-subject> I -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. +X.509 Distinguished Name (DN) to use as subject field +in the requested certificate template in IR/CR/KUR messages. +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, +If provided and neither of B<-cert>, B<-oldcert>, or B<-csr> is given, the subject DN is used as fallback sender of outgoing CMP messages. The argument must be formatted as I. @@ -289,18 +344,6 @@ Example: C -=item B<-issuer> I - -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. -For details see the description of the B<-subject> option. - =item B<-days> I Number of days the new certificate is requested to be valid for, counting from @@ -316,7 +359,8 @@ contained the given PKCS#10 CSR, overriding any extensions with same OIDs. =item B<-sans> I -One or more IP addresses, DNS names, or URIs separated by commas or whitespace +One or more IP addresses, email 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. @@ -349,7 +393,8 @@ Flag the policies given with B<-policy_oids> as critical. =item B<-popo> I 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. +C<-1> = NONE, which implies central key generation, +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. @@ -369,6 +414,8 @@ and the respective public key is placed in the certification request PKCS#10 CSR input may also be used with B<-cmd> I to specify the certificate to be revoked via the included subject name and public key. +Its subject is used as fallback sender in CMP message headers +if B<-cert> and B<-oldcert> are not given. =item B<-out_trusted> I|I @@ -396,11 +443,17 @@ B This leads to behavior violating RFC 4210. =item B<-certout> I -The file where the newly enrolled certificate should be saved. +The file where any newly enrolled certificate should be saved. =item B<-chainout> I -The file where the chain of the newly enrolled certificate should be saved. +The file where the chain of any newly enrolled certificate should be saved. +This chain excludes the leaf certificate, i.e., the newly enrolled certificate. +Also the trust anchor (the root certificate) is not included. + +If the B<-certout> option is given, too, with equal I argument, +then the file produced contains both outputs concatenated: +the newly enrolled certificate followed by its chain. =back @@ -415,6 +468,7 @@ The certificate to be updated (i.e., renewed or re-keyed) in Key Update Request For KUR the certificate to be updated defaults to B<-cert>, and the resulting certificate is called I. For RR the certificate to be revoked can also be specified using B<-csr>. +B<-oldcert> and B<-csr> is ignored if B<-issuer> and B<-serial> is provided. The reference certificate, if any, is also used for deriving default subject DN and Subject Alternative Names and the @@ -424,6 +478,23 @@ 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<-issuer> I + +X.509 Distinguished Name (DN) to place as the issuer field +in the requested certificate template in IR/CR/KUR/RR messages. +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. +For details see the description of the B<-subject> option. + +=item B<-serial> I + +Specify the Serial number of certificate to be revoked in revocation request. +The serial number can be decimal or hex (if preceded by C<0x>) + =item B<-revreason> I Set CRLReason to be included in revocation request (RR); values: C<0>..C<10> @@ -461,8 +532,8 @@ If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>. This option excludes I<-port> and I<-use_mock_srv>. It is ignored if I<-rspin> is given with enough filename arguments. -The scheme C may be given only if the B<-tls_used> option is used. -In this case the default port is 443, else 80. +If the scheme C is given, the B<-tls_used> option is implied. +When TLS is used, the default port is 443, otherwise 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. @@ -473,9 +544,9 @@ The HTTP(S) proxy server to use for reaching the CMP server unless B<-no_proxy> applies, see below. If the host string is an IPv6 address, it must be enclosed in C<[> and C<]>. The proxy port defaults to 80 or 443 if the scheme is C; apart from that -the optional C or C prefix is ignored (note that TLS may be -selected by B<-tls_used>), as well as any path, userinfo, and query, and fragment -components. +the optional C or C prefix is ignored (note that using TLS +may be required by B<-tls_used> or B<-server> with the prefix C), +as well as any path, userinfo, and query, and fragment components. Defaults to the environment variable C if set, else C in case no TLS is used, otherwise C if set, else C. This option is ignored if I<-server> is not given. @@ -511,11 +582,13 @@ Defaults to any path given with B<-server>, else C<"/">. =item B<-keep_alive> I -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. +If the given value is 0 then HTTP connections are closed after each response +(which would be the default behavior of HTTP 1.0) +even if a CMP transaction needs more than one round trip. +If the value is 1 or 2 +then for each transaction a persistent connection is requested. +If the value is 2 then a persistent connection is required, +i.e., an error occurs if the server does not grant it. The default value is 1, which means preferring to keep the connection open. =item B<-msg_timeout> I @@ -564,12 +637,13 @@ Non-trusted intermediate CA certificate(s). Any extra certificates given with the B<-cert> option are appended to it. All these certificates may be useful for cert path construction for the own CMP signer certificate (to include in the extraCerts field of -request messages) and for the TLS client certificate (if TLS is enabled) +request messages) and for the TLS client certificate (if TLS is used) as well as for chain building when validating server certificates (checking signature-based CMP message protection) and when validating newly enrolled certificates. -Multiple filenames or URLs may be given, separated by commas and/or whitespace. +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<-srvcert> I|I @@ -602,6 +676,7 @@ For details see the description of the B<-subject> option. Ignore key usage restrictions in CMP signer certificates when validating signature-based protection of incoming CMP messages. By default, C must be allowed by CMP signer certificates. +This option applies to both CMP clients and the mock server. =item B<-unprotected_errors> @@ -639,15 +714,85 @@ with a signature key." =back +=item B<-no_cache_extracerts> + +Do not cache certificates in the extraCerts field of CMP messages received. +By default, they are kept as they may be helful for validating further messages. +This option applies to both CMP clients and the mock server. + +=item B<-srvcertout> I + +The file where to save the successfully validated certificate, if any, +that the CMP server used for signature-based response message protection. +If there is no such certificate, typically because the protection was MAC-based, +this is indicated by deleting the file (if it existed). + =item B<-extracertsout> I -The file where to save all certificates contained in the extraCerts field -of the last received response message (except for pollRep and PKIConf). +The file where to save the list of certificates contained in the extraCerts +field of the last received response message that is not a pollRep nor PKIConf. =item B<-cacertsout> I -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. +The file where to save the list of CA certificates contained in the caPubs field +if a positive certificate response (i.e., IP, CP, or KUP) message was received +or contained in a general response (genp) message with infoType C. + +=item B<-oldwithold> I + +The root CA certificate to include in a genm request of infoType C. +If present and the optional oldWithNew certificate is received, +it is verified using the newWithNew certificate as the (only) trust anchor. + +=item B<-newwithnew> I + +This option must be provided when B<-infotype> I is given. +It specifies the file to save the newWithNew certificate +received in a genp message of type C. +If on success no such cert was received, this file (if present) is deleted +to indicate that the requested root CA certificate update is not available. + +Any received newWithNew certificate is verified +using any received newWithOld certificate as untrusted intermediate certificate +and the certificate provided with B<-oldwithold> as the (only) trust anchor, +or if not provided, using the certificates given with the B<-trusted> option. + +B +The newWithNew certificate is meant to be a certificate that will be trusted. +The trust placed in it cannot be stronger than the trust placed in +the B<-oldwithold> certificate if present, otherwise it cannot be stronger than +the weakest trust placed in any of the B<-trusted> certificates. + +=item B<-newwithold> I + +The file to save any newWithOld certificate +received in a genp message of infoType C. +If on success no such cert was received, this is indicated by deleting the file. + +=item B<-oldwithnew> I + +The file to save any oldWithNew certificate +received in a genp message of infoType C. +If on success no such cert was received, this is indicated by deleting the file. + +=item B<-crlcert> I + +Certificate to derive CRL issuer data for the source field +when obtaining a CRL in a genm request with infoType C. +Any available distribution point name is preferred over issuer names. + +=item B<-oldcrl> I + +The CRL to obtain an update for in a genm request with infoType C. +Unless the B<-crlcert> option is provided as well, +the given CRL is used for deriving CRL issuer data for the source field. +Any available distribution point name is preferred over issuer names. +If the CRL contains a thisUpdate field, its value is copied to the request. + +=item B<-crlout> I + +The file to save any CRL received in a genp message of infoType C. +If on success no such CRL was received, this is indicated by deleting the file. =back @@ -774,6 +919,13 @@ Send request messages without CMP-level protection. File format to use when saving a certificate to a file. Default value is PEM. +=item B<-crlform> I + +File format to use when saving a CRL to a file. +Default value is DER. +DER format is preferred because it enables more efficient storage +of large CRLs. + =item B<-keyform> I The format of the key input; unspecified by default. @@ -782,8 +934,10 @@ See L for details. =item B<-otherpass> I 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<-own_trusted>, B<-srvcert>, B<-crlcert>, B<-out_trusted>, B<-extracerts>, +B<-srv_trusted>, B<-srv_untrusted>, B<-ref_cert>, +B<-rsp_extracerts>, B<-rsp_capubs>, +B<-rsp_newwithnew>, B<-rsp_newwithold>, B<-rsp_oldwithnew>, B<-tls_extra>, and B<-tls_trusted> options. If not given here, the password will be prompted for if needed. @@ -830,18 +984,18 @@ B<-tls_key>. =item B<-tls_used> -Enable using TLS (even when other TLS-related options are not set) -for message exchange with CMP server via HTTP. +Make the CMP client use TLS (regardless if other TLS-related options are set) +for message exchange with the 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. +It is implied if the B<-server> option is given with the scheme C. +It is ignored if the B<-server> option is not given or B<-use_mock_srv> is given +or B<-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. +The following TLS-related options are ignored if TLS is not used. =item B<-tls_cert> I|I -Client's TLS certificate. +Client's TLS certificate to use for authenticating to the TLS server. 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. @@ -860,7 +1014,7 @@ L. =item B<-tls_extra> I|I -Extra certificates to provide to TLS server during TLS handshake +Extra certificates to provide to the TLS server during handshake. =item B<-tls_trusted> I|I @@ -883,7 +1037,7 @@ If not given it defaults to the B<-server> address. =back -=head2 Client-side debugging options +=head2 Client-side options for debugging and offline scenarios =over 4 @@ -902,9 +1056,29 @@ Default is one invocation. 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 useful for supporting offline scenarios where the certificate +request (or any other CMP request) is produced beforehand and sent out later. + This option is ignored if the B<-rspin> option is given because in the latter case no requests are actually sent. +Note that in any case the client produces internally its sequence +of CMP request messages. Thus, all options required for doing this +(such as B<-cmd> and all options providing the required parameters) +need to be given also when the B<-reqin> option is present. + +If the B<-reqin> option is given for a certificate request +and no B<-newkey>, B<-key>, B<-oldcert>, or B<-csr> option is given, +a fallback public key is taken from the request message file +(if it is included in the certificate template). + +Hint: In case the B<-reqin> option is given for a certificate request, there are +situations where the client has access to the public key to be certified but +not to the private key that by default will be needed for proof of possession. +In this case the POPO is not actually needed (because the internally produced +certificate request message will not be sent), and its generation +can be disabled using the options B<-popo> I<-1> or B<-popo> I<0>. + Multiple filenames may be given, separated by commas and/or whitespace (where in the latter case the whole argument must be enclosed in "..."). @@ -935,6 +1109,14 @@ 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<-reqout_only> I + +Save the first CMP requests created by the client to the given file and exit. +Any options related to CMP servers and their responses are ignored. + +This option is useful for supporting offline scenarios where the certificate +request (or any other CMP request) is produced beforehand and sent out later. + =item B<-rspin> I Process the sequence of CMP responses provided in the given file(s), @@ -1019,10 +1201,26 @@ have no effect on the certificate verification enabled via this option. Intermediate CA certs that may be useful when validating client certificates. +=item B<-ref_cert> I|I + +Certificate to be expected for RR messages and any oldCertID in KUR messages. + =item B<-rsp_cert> I|I Certificate to be returned as mock enrollment result. +=item B<-rsp_key> I|I + +Private key to be returned as central key generation result. + +=item B<-rsp_keypass> I + +Pass phrase source for B and B. + +=item B<-rsp_crl> I|I + +CRL to be returned in genp of type C. + =item B<-rsp_extracerts> I|I Extra certificates to be included in mock certification responses. @@ -1031,6 +1229,18 @@ Extra certificates to be included in mock certification responses. CA certificates to be included in mock Initialization Response (IP) message. +=item B<-rsp_newwithnew> I|I + +Certificate to be returned in newWithNew field of genp of type rootCaKeyUpdate. + +=item B<-rsp_newwithold> I|I + +Certificate to be returned in newWithOld field of genp of type rootCaKeyUpdate. + +=item B<-rsp_oldwithnew> I|I + +Certificate to be returned in oldWithNew field of genp of type rootCaKeyUpdate. + =item B<-poll_count> I Number of times the client must poll before receiving a certificate. @@ -1104,12 +1314,16 @@ only affect the certificate verification enabled via the B<-out_trusted> option. =head1 NOTES -When a client obtains from a CMP server CA certificates that it is going to -trust, for instance via the C field of a certificate response, +When a client obtains, from a CMP server, CA certificates that it is going to +trust, for instance via the C field of a certificate response +or using general messages with infoType C or C, authentication of the CMP server is particularly critical. So special care must be taken setting up server authentication using B<-trusted> and related options for certificate-based authentication or B<-secret> for MAC-based protection. +If authentication is certificate-based, the B<-srvcertout> option +should be used to obtain the validated server certificate +and perform an authorization check based on it. When setting up CMP configurations and experimenting with enrollment options typically various errors occur until the configuration is correct and complete. @@ -1121,6 +1335,10 @@ 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. +If OpenSSL was built with trace support enabled (e.g., C<./config enable-trace>) +and the environment variable B includes B, +the requests and the response headers transferred via HTTP are printed. + =head1 EXAMPLES =head2 Simple examples using the default OpenSSL configuration file @@ -1178,13 +1396,10 @@ or by referencing in addition the B<[cr]> section of the example configuration: In order to update the enrolled certificate one may call - openssl cmp -section insta,kur - -using MAC-based protection with PBM or - openssl cmp -section insta,kur,signature -using signature-based protection. +using signature-based protection with the certificate that is to be updated. +For certificate updates, MAC-based protection should generally not be used. In a similar way any previously enrolled certificate may be revoked by @@ -1298,11 +1513,25 @@ L, L, L The B application was added in OpenSSL 3.0. -The B<-engine option> was deprecated in OpenSSL 3.0. +The B<-engine> option was deprecated in OpenSSL 3.0. + +The B<-oldwithold>, B<-newwithnew>, B<-newwithold>, B<-oldwithnew>, +The B<-srvcertout>, and B<-serial> option were added in OpenSSL 3.2, as well +as an extension of B<-cacertsout> to use when getting CA certificates. +Since then, the B<-issuer> may be used also for certificates to be revoked. + +The B<-profile> and B<-no_cache_extracerts> options were added in OpenSSL 3.3, +as well as support for delayed delivery of all types of response messages. + +The B<-template>, B<-crlcert>, B<-oldcrl>, B<-crlout>, B<-crlform> +and B<-rsp_crl> options were added in OpenSSL 3.4. + +B<-centralkeygen>, b<-newkeyout>, B<-rsp_key> and +B<-rsp_keypass> were added in OpenSSL 3.5. =head1 COPYRIGHT -Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in index f4d12312b7cb..36f1b3e4a82c 100644 --- a/doc/man1/openssl-cms.pod.in +++ b/doc/man1/openssl-cms.pod.in @@ -7,6 +7,8 @@ openssl-cms - CMS command =head1 SYNOPSIS +=for openssl duplicate options + B B [B<-help>] @@ -25,6 +27,7 @@ Operation options: [B<-resign>] [B<-sign_receipt>] [B<-verify_receipt> I] +[B<-digest> I] [B<-digest_create>] [B<-digest_verify>] [B<-compress>] @@ -82,6 +85,7 @@ Signing options: [B<-nocerts>] [B<-noattr>] [B<-nosmimecap>] +[B<-no_signing_time>] [B<-receipt_request_all>] [B<-receipt_request_first>] [B<-receipt_request_from> I] @@ -211,6 +215,16 @@ Verify a signed receipt in filename B. The input message B contain the original receipt request. Functionality is otherwise similar to the B<-verify> operation. +=item B<-digest> I + +When used with B<-sign>, provides the digest in hexadecimal form instead of +computing it from the original message content. Cannot be combined with B<-in> +or B<-nodetach>. + +This operation is the CMS equivalent of L signing. +When signing a pre-computed digest, the security relies on the digest and its +computation from the original message being trusted. + =item B<-digest_create> Create a CMS B type. @@ -400,16 +414,16 @@ One or more certificate filenames may be given. =item B<-I> -The encryption algorithm to use. For example triple DES (168 bits) - B<-des3> -or 256 bit AES - B<-aes256>. Any standard algorithm name (as used by the +The encryption algorithm to use. For example, AES (256 bits) - B<-aes256> +or triple DES (168 bits) - B<-des3>. Any standard algorithm name (as used by the EVP_get_cipherbyname() function) can also be used preceded by a dash, for example B<-aes-128-cbc>. See L for a list of ciphers supported by your version of OpenSSL. -Currently the AES variants with GCM mode are the only supported AEAD +Currently, the AES variants with GCM mode are the only supported AEAD algorithms. -If not specified triple DES is used. Only used with B<-encrypt> and +If not specified, AES-256-CBC is used as the default. Only used with B<-encrypt> and B<-EncryptedData_create> commands. =item B<-wrap> I @@ -447,8 +461,9 @@ used multiple times if more than one signer is required. =item B<-certfile> I Allows additional certificates to be specified. When signing these will -be included with the message. When verifying these will be searched for -the signers certificates. +be included with the message. When verifying, these will be searched for +signer certificates and will be used for chain building. + The input can be in PEM, DER, or PKCS#12 format. =item B<-cades> @@ -481,7 +496,12 @@ option they are not included. =item B<-nosmimecap> Exclude the list of supported algorithms from signed attributes, other options -such as signing time and content type are still included. +such as content type and (optionally) signing time are still included. + +=item B<-no_signing_time> + +Exclude the signing time from signed attributes, other options +such as content type are still included. =item B<-receipt_request_all>, B<-receipt_request_first> @@ -889,6 +909,8 @@ L =head1 HISTORY +The default encryption cipher was changed from 3DES to AES-256 in OpenSSL 3.5. + The use of multiple B<-signer> options and the B<-resign> command were first added in OpenSSL 1.0.0. @@ -905,6 +927,8 @@ The B<-nameopt> option was added in OpenSSL 3.0.0. The B<-engine> option was deprecated in OpenSSL 3.0. +The B<-digest> option was added in OpenSSL 3.2. + =head1 COPYRIGHT Copyright 2008-2025 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man1/openssl-crl.pod.in b/doc/man1/openssl-crl.pod.in index 5ace18f5807f..4327b6157b15 100644 --- a/doc/man1/openssl-crl.pod.in +++ b/doc/man1/openssl-crl.pod.in @@ -93,7 +93,9 @@ Print out the CRL in text form. =item B<-verify> -Verify the signature in the CRL. +Verify the signature in the CRL. If the verification fails, +the program will immediately exit, i.e. further option processing +(e.g. B<-gendelta>) is skipped. This option is implicitly enabled if any of B<-CApath>, B<-CAfile> or B<-CAstore> is specified. @@ -163,6 +165,10 @@ L, L, L +=head1 HISTORY + +Since OpenSSL 3.3, the B<-verify> option will exit with 1 on failure. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man1/openssl-dgst.pod.in b/doc/man1/openssl-dgst.pod.in index 5dcdbe548e69..fb15c1e2a2a9 100644 --- a/doc/man1/openssl-dgst.pod.in +++ b/doc/man1/openssl-dgst.pod.in @@ -89,17 +89,19 @@ Output the digest or signature in binary form. Set the output length for XOF algorithms, such as B and B. This option is not supported for signing operations. -For OpenSSL providers it is recommended to set this value for shake algorithms, -since the default values are set to only supply half of the maximum security -strength. +For OpenSSL providers it is required to set this value for shake algorithms, +since the previous default values were only set to supply half of the maximum +security strength. -For backwards compatibility reasons the default xoflen length for B is -16 (bytes) which results in a security strength of only 64 bits. To ensure the -maximum security strength of 128 bits, the xoflen should be set to at least 32. +To ensure the maximum security strength of 128 bits, the xoflen for B +should be set to at least 32 (bytes). For compatibility with previous versions +of OpenSSL, it may be set to 16, resulting in a security strength of only 64 +bits. -For backwards compatibility reasons the default xoflen length for B is -32 (bytes) which results in a security strength of only 128 bits. To ensure the -maximum security strength of 256 bits, the xoflen should be set to at least 64. +To ensure the maximum security strength of 256 bits, the xoflen for B +should be set to at least 64 (bytes). For compatibility with previous versions +of OpenSSL, it may be set to 32, resulting in a security strength of only 128 +bits. =item B<-r> @@ -114,9 +116,13 @@ Filename to output to, or standard output by default. =item B<-sign> I|I -Digitally sign the digest using the given private key. Note this option -does not support Ed25519 or Ed448 private keys. Use the L -command instead for this. +Digitally sign the digest using the given private key. + +Note that for algorithms that only support one-shot signing +(such as Ed25519, ED448, ML-DSA-44, ML-DSA-65 andML-DSA-87) the digest must not +be set. For these algorithms the input is buffered (and not digested) before +signing. For these algorithms, if the input is larger than 16MB an error +will occur. =item B<-keyform> B|B|B|B @@ -126,7 +132,8 @@ See L for details. =item B<-sigopt> I:I Pass options to the signature algorithm during sign or verify operations. -Names and values of these options are algorithm-specific. +Names and values of these options are algorithm-specific and documented +in L. =item B<-passin> I @@ -278,7 +285,7 @@ The B<-engine> and B<-engine_impl> options were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-dhparam.pod.in b/doc/man1/openssl-dhparam.pod.in index 7865e3b25b9d..62ea9d2a43da 100644 --- a/doc/man1/openssl-dhparam.pod.in +++ b/doc/man1/openssl-dhparam.pod.in @@ -17,6 +17,8 @@ B [B<-check>] [B<-noout>] [B<-text>] +[B<-verbose>] +[B<-quiet>] [B<-2>] [B<-3>] [B<-5>] @@ -48,26 +50,27 @@ See L for details. =item B<-in> I -This specifies the input filename to read parameters from or standard input if +This specifies the input file to read parameters from or standard input if this option is not specified. =item B<-out> I -This specifies the output filename parameters to. Standard output is used -if this option is not present. The output filename should B be the same -as the input filename. +This specifies the output file to write parameters to. +Standard output is used if this option is not present. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. =item B<-dsaparam> If this option is used, DSA rather than DH parameters are read or created; -they are converted to DH format. Otherwise, "strong" primes (such +they are converted to DH format. Otherwise, safe primes (such that (p-1)/2 is also prime) will be used for DH parameter generation. -DH parameter generation with the B<-dsaparam> option is much faster, -and the recommended exponent length is shorter, which makes DH key -exchange more efficient. Beware that with such DSA-style DH -parameters, a fresh DH key should be created for each use to -avoid small-subgroup attacks that may be possible otherwise. +DH parameter generation with the B<-dsaparam> option is much faster. +Beware that with such DSA-style DH parameters, a fresh DH key should be +created for each use to avoid small-subgroup attacks that may be possible +otherwise. =item B<-check> @@ -104,6 +107,16 @@ This option prints out the DH parameters in human readable form. {- $OpenSSL::safe::opt_provider_item -} +=item B<-verbose> + +This option enables the output of progress messages, which is handy when +running commands interactively that may take a long time to execute. + +=item B<-quiet> + +This option suppresses the output of progress messages, which may be +undesirable in batch scripts or pipelines. + =back =head1 NOTES diff --git a/doc/man1/openssl-dsa.pod.in b/doc/man1/openssl-dsa.pod.in index 6d15e950b935..116cafd71e72 100644 --- a/doc/man1/openssl-dsa.pod.in +++ b/doc/man1/openssl-dsa.pod.in @@ -115,8 +115,9 @@ This option prints out the value of the public key component of the key. =item B<-pubin> -By default, a private key is read from the input file. With this option a -public key is read instead. +By default, a private key is read from the input. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =item B<-pubout> @@ -185,7 +186,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0. =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 diff --git a/doc/man1/openssl-dsaparam.pod.in b/doc/man1/openssl-dsaparam.pod.in index c88e11f3cf5a..d2e8973ee0e7 100644 --- a/doc/man1/openssl-dsaparam.pod.in +++ b/doc/man1/openssl-dsaparam.pod.in @@ -17,9 +17,11 @@ B [B<-text>] [B<-genkey>] [B<-verbose>] +[B<-quiet>] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} [I] +[I] =head1 DESCRIPTION @@ -51,15 +53,17 @@ This is compatible with RFC 2459 B structure. =item B<-in> I -This specifies the input filename to read parameters from or standard input if +This specifies the input file to read parameters from or standard input if this option is not specified. If the I parameter is included then this option will be ignored. =item B<-out> I -This specifies the output filename parameters to. Standard output is used -if this option is not present. The output filename should B be the same -as the input filename. +This specifies the output file to write parameters to. Standard output is used +if this option is not present. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. =item B<-noout> @@ -79,15 +83,26 @@ parameters. Print extra details about the operations being performed. +=item B<-quiet> + +Print fewer details about the operations being performed, which may +be handy during batch scripts and pipelines. + {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_engine_item -} =item I -This option specifies that a parameter set should be generated of size -I. It must be the last option. If this option is included then -the input file (if any) is ignored. +This optional argument specifies that a parameter set should be generated of +size I. If this argument is included then the input file (if any) is +ignored. + +=item I + +This optional argument specifies that a parameter set should be generated with +a subprime parameter q of size I. It must be the last argument. If +this argument is included then the input file (if any) is ignored. {- $OpenSSL::safe::opt_provider_item -} @@ -110,7 +125,7 @@ The B<-C> option was removed in OpenSSL 3.0. =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 diff --git a/doc/man1/openssl-ec.pod.in b/doc/man1/openssl-ec.pod.in index 27de8ebaf6de..51200076a89b 100644 --- a/doc/man1/openssl-ec.pod.in +++ b/doc/man1/openssl-ec.pod.in @@ -106,8 +106,9 @@ Print the elliptic curve parameters. =item B<-pubin> -By default, a private key is read from the input file. With this option a -public key is read instead. +By default a private key is read from the input. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =item B<-pubout> @@ -198,7 +199,7 @@ with keys loaded from an engine in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2003-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2003-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 diff --git a/doc/man1/openssl-ecparam.pod.in b/doc/man1/openssl-ecparam.pod.in index 458505051493..27ce10490fe2 100644 --- a/doc/man1/openssl-ecparam.pod.in +++ b/doc/man1/openssl-ecparam.pod.in @@ -55,14 +55,16 @@ Parameters are encoded as B as specified in IETF RFC 3279. =item B<-in> I -This specifies the input filename to read parameters from or standard input if +This specifies the input file to read parameters from or standard input if this option is not specified. =item B<-out> I This specifies the output filename parameters to. Standard output is used -if this option is not present. The output filename should B be the same -as the input filename. +if this option is not present. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. =item B<-noout> diff --git a/doc/man1/openssl-enc.pod.in b/doc/man1/openssl-enc.pod.in index a47e783e2d63..4d7ff3dc77e7 100644 --- a/doc/man1/openssl-enc.pod.in +++ b/doc/man1/openssl-enc.pod.in @@ -31,6 +31,7 @@ B B|I [B<-md> I] [B<-iter> I] [B<-pbkdf2>] +[B<-saltlen> I] [B<-p>] [B<-P>] [B<-bufsize> I] @@ -38,6 +39,8 @@ B B|I [B<-v>] [B<-debug>] [B<-none>] +[B<-skeymgmt> I] +[B<-skeyopt> I:I] {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_provider_synopsis -} @@ -138,6 +141,15 @@ This option enables the use of PBKDF2 algorithm to derive the key. Use PBKDF2 algorithm with a default iteration count of 10000 unless otherwise specified by the B<-iter> command line option. +=item B<-saltlen> + +Set the salt length to use when using the B<-pbkdf2> option. +For compatibility reasons, the default is 8 bytes. +The maximum value is currently 16 bytes. +If the B<-pbkdf2> option is not used, then this option is ignored +and a fixed salt length of 8 is used. The salt length used when +encrypting must also be used when decrypting. + =item B<-nosalt> Don't use a salt in the key derivation routines. This option B be @@ -153,7 +165,8 @@ encrypting, this is the default. 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. +again during decryption. This salt may be truncated or zero padded to +match the salt length (See B<-saltlen>). =item B<-K> I @@ -206,6 +219,21 @@ or zlib-dynamic option. Use NULL cipher (no encryption or decryption of input). +=item B<-skeymgmt> I + +Some providers may support opaque symmetric keys objects. To use them, we need +to know the name of the B to be used. If not specified, the name +of the cipher will be used. + +To find out the name of the suitable symmetric key management, +please refer to the output of the C command. + +=item B<-skeyopt> I:I + +To obtain an existing opaque symmetric key or generate a new one, key +options are specified as opt:value. These options can't be used together with +any options implying raw key directly or indirectly. + {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_provider_item -} @@ -294,7 +322,7 @@ 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 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 +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. @@ -302,6 +330,15 @@ For bulk encryption of data, whether using authenticated encryption modes or other modes, L is recommended, as it provides a standard data format and performs the needed key/iv/nonce management. +When enc is used with key wrapping modes the input data cannot be streamed, +meaning it must be processed in a single pass. +Consequently, the input data size must be less than +the buffer size (-bufsize arg, default to 8*1024 bytes). +The '*-wrap' ciphers require the input to be a multiple of 8 bytes long, +because no padding is involved. +The '*-wrap-pad' ciphers allow any input length. +In both cases, no IV is needed. See example below. + base64 Base 64 @@ -389,6 +426,9 @@ standard data format and performs the needed key/iv/nonce management. 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 + aes-[128|192|256]-wrap key wrapping using 128/192/256 bit AES + aes-[128|192|256]-wrap-pad key wrapping with padding using 128/192/256 bit AES + 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 @@ -437,6 +477,12 @@ 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: +AES key wrapping: + + openssl enc -e -a -id-aes128-wrap-pad -K 000102030405060708090A0B0C0D0E0F -in file.bin +or + openssl aes128-wrap-pad -e -a -K 000102030405060708090A0B0C0D0E0F -in file.bin + =head1 BUGS The B<-A> option when used with large files doesn't work properly. @@ -448,6 +494,10 @@ The B 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 SEE ALSO + +L, L + =head1 HISTORY The default digest was changed from MD5 to SHA256 in OpenSSL 1.1.0. @@ -456,9 +506,13 @@ The B<-list> option was added in OpenSSL 1.1.1e. The B<-ciphers> and B<-engine> options were deprecated in OpenSSL 3.0. +The B<-saltlen> option was added in OpenSSL 3.2. + +The B<-skeymgmt> and B<-skeyopt> options were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-fipsinstall.pod.in b/doc/man1/openssl-fipsinstall.pod.in index 57758597cdae..9dd4f5a49ffe 100644 --- a/doc/man1/openssl-fipsinstall.pod.in +++ b/doc/man1/openssl-fipsinstall.pod.in @@ -19,9 +19,38 @@ B [B<-macopt> I:I] [B<-noout>] [B<-quiet>] +[B<-pedantic>] [B<-no_conditional_errors>] [B<-no_security_checks>] +[B<-hmac_key_check>] +[B<-kmac_key_check>] +[B<-ems_check>] +[B<-no_drbg_truncated_digests>] +[B<-signature_digest_check>] +[B<-hkdf_digest_check>] +[B<-tls13_kdf_digest_check>] +[B<-tls1_prf_digest_check>] +[B<-sshkdf_digest_check>] +[B<-sskdf_digest_check>] +[B<-x963kdf_digest_check>] +[B<-dsa_sign_disabled>] +[B<-no_pbkdf2_lower_bound_check>] +[B<-no_short_mac>] +[B<-tdes_encrypt_disabled>] +[B<-rsa_pkcs15_padding_disabled>] +[B<-rsa_pss_saltlen_check>] +[B<-rsa_sign_x931_disabled>] +[B<-hkdf_key_check>] +[B<-kbkdf_key_check>] +[B<-tls13_kdf_key_check>] +[B<-tls1_prf_key_check>] +[B<-sshkdf_key_check>] +[B<-sskdf_key_check>] +[B<-x963kdf_key_check>] +[B<-x942kdf_key_check>] +[B<-ecdh_cofactor_check>] [B<-self_test_onload>] +[B<-self_test_oninstall>] [B<-corrupt_desc> I] [B<-corrupt_type> I] [B<-config> I] @@ -155,6 +184,14 @@ The default digest is SHA-256. Disable logging of the self tests. +=item B<-pedantic> + +Configure the module so that it is strictly FIPS compliant rather +than being backwards compatible. This enables conditional errors, +security checks etc. Note that any previous configuration options will +be overwritten and any subsequent configuration options that violate +FIPS compliance will result in an error. + =item B<-no_conditional_errors> Configure the module to not enter an error state if a conditional self test @@ -164,6 +201,163 @@ fails as described above. Configure the module to not perform run-time security checks as described above. +Enabling the configuration option "no-fips-securitychecks" provides another way to +turn off the check at compile time. + +=item B<-ems_check> + +Configure the module to enable a run-time Extended Master Secret (EMS) check +when using the TLS1_PRF KDF algorithm. This check is disabled by default. +See RFC 7627 for information related to EMS. + +=item B<-no_short_mac> + +Configure the module to not allow short MAC outputs. +See SP 800-185 8.4.2 and FIPS 140-3 ID C.D for details. + +=item B<-hmac_key_check> + +Configure the module to not allow small keys sizes when using HMAC. +See SP 800-131Ar2 for details. + +=item B<-kmac_key_check> + +Configure the module to not allow small keys sizes when using KMAC. +See SP 800-131Ar2 for details. + +=item B<-no_drbg_truncated_digests> + +Configure the module to not allow truncated digests to be used with Hash and +HMAC DRBGs. See FIPS 140-3 IG D.R for details. + +=item B<-signature_digest_check> + +Configure the module to enforce signature algorithms to use digests that are +explicitly permitted by the various standards. + +=item B<-hkdf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +HKDF. +See NIST SP 800-56Cr2 for details. + +=item B<-tls13_kdf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +TLS13 KDF. +See RFC 8446 for details. + +=item B<-tls1_prf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +TLS_PRF. +See NIST SP 800-135r1 for details. + +=item B<-sshkdf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +SSHKDF. +See NIST SP 800-135r1 for details. + +=item B<-sskdf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +SSKDF. +See NIST SP 800-56Cr2 for details. + +=item B<-x963kdf_digest_check> + +Configure the module to enable a run-time digest check when deriving a key by +X963KDF. +See NIST SP 800-131Ar2 for details. + +=item B<-dsa_sign_disabled> + +Configure the module to not allow DSA signing (DSA signature verification is +still allowed). See FIPS 140-3 IG C.K for details. + +=item B<-tdes_encrypt_disabled> + +Configure the module to not allow Triple-DES encryption. +Triple-DES decryption is still allowed for legacy purposes. +See SP800-131Ar2 for details. + +=item B<-rsa_pkcs15_padding_disabled> + +Configure the module to not allow PKCS#1 version 1.5 padding to be used with +RSA for key transport and key agreement. See NIST's SP 800-131A Revision 2 +for details. + +=item B<-rsa_pss_saltlen_check> + +Configure the module to enable a run-time salt length check when generating or +verifying a RSA-PSS signature. +See FIPS 186-5 5.4 (g) for details. + +=item B<-rsa_sign_x931_disabled> + +Configure the module to not allow X9.31 padding to be used when signing with +RSA. See FIPS 140-3 IG C.K for details. + +=item B<-hkdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by HKDF. +See NIST SP 800-131Ar2 for details. + +=item B<-kbkdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by KBKDF. +See NIST SP 800-131Ar2 for details. + +=item B<-tls13_kdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by TLS13 KDF. +See NIST SP 800-131Ar2 for details. + +=item B<-tls1_prf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by TLS_PRF. +See NIST SP 800-131Ar2 for details. + +=item B<-sshkdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by SSHKDF. +See NIST SP 800-131Ar2 for details. + +=item B<-sskdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by SSKDF. +See NIST SP 800-131Ar2 for details. + +=item B<-x963kdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by X963KDF. +See NIST SP 800-131Ar2 for details. + +=item B<-x942kdf_key_check> + +Configure the module to enable a run-time short key-derivation key check when +deriving a key by X942KDF. +See NIST SP 800-131Ar2 for details. + +=item B<-no_pbkdf2_lower_bound_check> + +Configure the module to not perform run-time lower bound check for PBKDF2. +See NIST SP 800-132 for details. + +=item B<-ecdh_cofactor_check> + +Configure the module to enable a run-time check that ECDH uses the EC curves +cofactor value when deriving a key. This only affects the 'B' and 'K' curves. +See SP 800-56A r3 Section 5.7.1.2 for details. + =item B<-self_test_onload> Do not write the two fields related to the "test status indicator" and @@ -173,6 +367,17 @@ used for cross compiling, since the self tests need to run at least once on each target machine. Once the self tests have run on the target machine the user could possibly then add the 2 fields into the configuration using some other mechanism. +This option defaults to 0 for any OpenSSL FIPS 140-2 provider (OpenSSL 3.0.X). +and is not relevant for an OpenSSL FIPS 140-3 provider, since this is no +longer allowed. + +=item B<-self_test_oninstall> + +The converse of B<-self_test_oninstall>. The two fields related to the +"test status indicator" and "MAC status indicator" are written to the +output configuration file. +This field is not relevant for an OpenSSL FIPS 140-3 provider, since this is no +longer allowed. =item B<-quiet> @@ -209,6 +414,11 @@ test output and the options B<-corrupt_desc> and B<-corrupt_type> will be ignore For normal usage the base configuration file should use the default provider when generating the fips configuration file. +The B<-self_test_oninstall> option was added and the +B<-self_test_onload> option was made the default in OpenSSL 3.1. + +The command and all remaining options were added in OpenSSL 3.0. + =head1 EXAMPLES Calculate the mac of a FIPS module F and run a FIPS self test @@ -243,9 +453,47 @@ L The B application was added in OpenSSL 3.0. +The following options were added in OpenSSL 3.1: + +B<-ems_check>, +B<-self_test_oninstall> + +The following options were added in OpenSSL 3.2: + +B<-pedantic>, +B<-no_drbg_truncated_digests> + +The following options were added in OpenSSL 3.4: + +B<-hmac_key_check>, +B<-kmac_key_check>, +B<-signature_digest_check>, +B<-hkdf_digest_check>, +B<-tls13_kdf_digest_check>, +B<-tls1_prf_digest_check>, +B<-sshkdf_digest_check>, +B<-sskdf_digest_check>, +B<-x963kdf_digest_check>, +B<-dsa_sign_disabled>, +B<-no_pbkdf2_lower_bound_check>, +B<-no_short_mac>, +B<-tdes_encrypt_disabled>, +B<-rsa_pkcs15_padding_disabled>, +B<-rsa_pss_saltlen_check>, +B<-rsa_sign_x931_disabled>, +B<-hkdf_key_check>, +B<-kbkdf_key_check>, +B<-tls13_kdf_key_check>, +B<-tls1_prf_key_check>, +B<-sshkdf_key_check>, +B<-sskdf_key_check>, +B<-x963kdf_key_check>, +B<-x942kdf_key_check>, +B<-ecdh_cofactor_check> + =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-gendsa.pod.in b/doc/man1/openssl-gendsa.pod.in index b6d37c576d3a..cfbb305eb3e3 100644 --- a/doc/man1/openssl-gendsa.pod.in +++ b/doc/man1/openssl-gendsa.pod.in @@ -24,6 +24,7 @@ B B [B<-des3>] [B<-idea>] [B<-verbose>] +[B<-quiet>] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} [I] @@ -58,12 +59,16 @@ cipher before outputting it. A pass phrase is prompted for. If none of these options is specified no encryption is used. Note that all options must be given before the I argument. -Otherwise they are ignored. =item B<-verbose> Print extra details about the operations being performed. +=item B<-quiet> + +Print fewer details about the operations being performed, which may +be handy during batch scripts and pipelines. + {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_engine_item -} diff --git a/doc/man1/openssl-genpkey.pod.in b/doc/man1/openssl-genpkey.pod.in index 8f139d147f92..1daa55df05b9 100644 --- a/doc/man1/openssl-genpkey.pod.in +++ b/doc/man1/openssl-genpkey.pod.in @@ -7,14 +7,16 @@ =head1 NAME -openssl-genpkey - generate a private key +openssl-genpkey - generate a private key or key pair =head1 SYNOPSIS B B [B<-help>] [B<-out> I] +[B<-outpubkey> I] [B<-outform> B|B] +[B<-verbose>] [B<-quiet>] [B<-pass> I] [B<-I>] @@ -23,12 +25,14 @@ B B [B<-pkeyopt> I:I] [B<-genparam>] [B<-text>] -{- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} +{- $OpenSSL::safe::opt_r_synopsis -} +{- $OpenSSL::safe::opt_engine_synopsis -} +{- $OpenSSL::safe::opt_provider_synopsis -} {- $OpenSSL::safe::opt_config_synopsis -} =head1 DESCRIPTION -This command generates a private key. +This command generates a private key or key pair. =head1 OPTIONS @@ -40,8 +44,13 @@ Print out a usage message. =item B<-out> I -Output the key to the specified file. If this argument is not specified then -standard output is used. +Output the private key to the specified file. If this argument is not +specified then standard output is used. + +=item B<-outpubkey> I + +Output the public key to the specified file. If this argument is not +specified then the public key is not output. =item B<-outform> B|B @@ -50,6 +59,10 @@ See L for details. When B<-genparam> is given, B<-outform> is ignored. +=item B<-verbose> + +Output "status dots" while generating keys. + =item B<-quiet> Do not output "status dots" while generating keys. @@ -68,11 +81,11 @@ name accepted by EVP_get_cipherbyname() is acceptable such as B. Public key algorithm to use such as RSA, DSA, DH or DHX. If used this option must precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm> -are mutually exclusive. Engines may add algorithms in addition to the standard -built-in ones. +are mutually exclusive. Engines or providers may add algorithms in addition to +the standard built-in ones. Valid built-in algorithm names for private key generation are RSA, RSA-PSS, EC, -X25519, X448, ED25519 and ED448. +X25519, X448, ED25519, ED448, ML-DSA and ML-KEM. Valid built-in algorithm names for parameter generation (see the B<-genparam> option) are DH, DSA and EC. @@ -87,6 +100,9 @@ options supported depends on the public key algorithm used and its implementation. See L and L below for more details. +To list the possible I values for an algorithm use: +B B -algorithm XXX -help + =item B<-genparam> Generate a set of parameters instead of a private key. If used this option must @@ -105,6 +121,8 @@ are mutually exclusive. Print an (unencrypted) text representation of private and public keys and parameters along with the PEM or DER structure. +{- $OpenSSL::safe::opt_r_item -} + {- $OpenSSL::safe::opt_engine_item -} {- $OpenSSL::safe::opt_provider_item -} @@ -182,6 +200,40 @@ B or B. The default value is B. =back +=head2 ML-DSA Key Generation Options + +=over 4 + +=item B:I + +This specifies the optional ML-DSA I in hexadecimal form. The seed is 32 +bytes, giving 64 hexadecimal digits. +When generated from an explicit seed the key is completely determined by the +seed value. +If other users can see the command-line arguments of the running process, this +option may compromise the secret key, it is best avoided, tests-aside. + +See L for more detail. + +=back + +=head2 ML-KEM Key Generation Options + +=over 4 + +=item B:I + +This specifies the optional ML-KEM I in hexadecimal form. The seed is 64 +bytes, giving 128 hexadecimal digits. +When generated from an explicit seed the key is completely determined by the +seed value. +If other users can see the command-line arguments of the running process, this +option may compromise the secret key, it is best avoided, tests-aside. + +See L for more detail. + +=back + =head2 DH Key Generation Options =over 4 @@ -483,6 +535,14 @@ Generate an ED448 private key: openssl genpkey -algorithm ED448 -out xkey.pem +Generate an ML-DSA-65 private key: + + openssl genpkey -algorithm ML-DSA-65 -out ml-dsa-key.pem + +Generate an ML-KEM-768 private key: + + openssl genpkey -algorithm ML-KEM-768 -out ml-kem-key.pem + =head1 HISTORY The ability to use NIST curve names, and to generate an EC key directly, @@ -492,9 +552,11 @@ The ability to generate X448, ED25519 and ED448 keys was added in OpenSSL 1.1.1. The B<-engine> option was deprecated in OpenSSL 3.0. +Support for B and B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-genrsa.pod.in b/doc/man1/openssl-genrsa.pod.in index db1cab6e41a3..c75d52ceae78 100644 --- a/doc/man1/openssl-genrsa.pod.in +++ b/doc/man1/openssl-genrsa.pod.in @@ -28,6 +28,7 @@ B B [B<-3>] [B<-primes> I] [B<-verbose>] +[B<-quiet>] [B<-traditional>] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -78,6 +79,11 @@ RSA key, which is defined in RFC 8017. Print extra details about the operations being performed. +=item B<-quiet> + +Print fewer details about the operations being performed, which may +be handy during batch scripts and pipelines. + =item B<-traditional> Write the key using the traditional PKCS#1 format instead of the PKCS#8 format. diff --git a/doc/man1/openssl-info.pod.in b/doc/man1/openssl-info.pod.in index 0e91bb28ee10..ac3a36d54c7e 100644 --- a/doc/man1/openssl-info.pod.in +++ b/doc/man1/openssl-info.pod.in @@ -17,6 +17,7 @@ B [B<-listsep>] [B<-seeds>] [B<-cpusettings>] +[B<-windowscontext>] =head1 DESCRIPTION @@ -73,12 +74,18 @@ Outputs the randomness seed sources. Outputs the OpenSSL CPU settings info. +=item B<-windowscontext> + +Outputs the Windows install context. + =back =head1 HISTORY This command was added in OpenSSL 3.0. +The B<-windowscontext> option was added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man1/openssl-list.pod.in b/doc/man1/openssl-list.pod.in index 784dcb89b11d..dce292a3f54c 100644 --- a/doc/man1/openssl-list.pod.in +++ b/doc/man1/openssl-list.pod.in @@ -12,6 +12,7 @@ B [B<-verbose>] [B<-select> I] [B<-1>] +[B<-all-algorithms>] [B<-commands>] [B<-standard-commands>] [B<-digest-algorithms>] @@ -29,9 +30,15 @@ B -}[B<-encoders>] [B<-decoders>] [B<-key-managers>] +[B<-skey-managers>] [B<-key-exchange-algorithms>] [B<-kem-algorithms>] +[B<-tls-groups>] +[B<-all-tls-groups>] +[B<-tls1_2>] +[B<-tls1_3>] [B<-signature-algorithms>] +[B<-tls-signature-algorithms>] [B<-asymcipher-algorithms>] [B<-public-key-algorithms>] [B<-public-key-methods>] @@ -72,6 +79,42 @@ Only list algorithms that match this name. List the commands, digest-commands, or cipher-commands in a single column. If used, this option must be given first. +=item B<-all-algorithms> + +Display lists of all algorithms. These include: + +=over 4 + +=item Asymmetric ciphers + +=item Decoders + +=item Digests + +=item Encoders + +=item Key derivation algorithms (KDF) + +=item Key encapsulation methods (KEM) + +=item Key exchange algorithms (KEX) + +=item Key managers + +=item Symmetric key managers + +=item Message authentication code algorithms (MAC) + +=item Random number generators (RNG, DRBG) + +=item Signature algorithms + +=item Store loaders + +=item Symmetric ciphers + +=back + =item B<-commands> Display a list of standard commands. @@ -147,6 +190,10 @@ Display a list of public key methods. Display a list of key managers. +=item B<-skey-managers> + +Display a list of symmetric key managers. + =item B<-key-exchange-algorithms> Display a list of key exchange algorithms. @@ -155,10 +202,40 @@ Display a list of key exchange algorithms. Display a list of key encapsulation algorithms. +=item B<-tls-groups> + +Display a list of the IANA names of all available (implemented) TLS groups. +By default the listed groups are those compatible with TLS 1.3. + +=item B<-all-tls-groups> + +Display a list of the names of all available (implemented) TLS groups, +including any aliases. +Some groups are known under multiple names, for example, B is also +known as B. +By default the listed groups are those compatible with TLS 1.3. + +=item B<-tls1_2> + +When listing TLS groups, list those compatible with TLS 1.2 + +=item B<-tls1_3> + +When listing TLS groups, output those compatible with TLS 1.3. +TLS 1.3 is the current default protocol version, but the default version is +subject to change, so best to specify the version explicitly. + =item B<-signature-algorithms> Display a list of signature algorithms. +=item B<-tls-signature-algorithms> + +Display the list of signature algorithms available for TLS handshakes +made available by all currently active providers. +The output format is colon delimited in a form directly usable in +L specifying SignatureAlgorithms. + =item B<-asymcipher-algorithms> Display a list of asymmetric cipher algorithms. @@ -235,9 +312,11 @@ In both cases, C is the name of the provider. The B<-engines>, B<-digest-commands>, and B<-cipher-commands> options were deprecated in OpenSSL 3.0. +The B<-skey-managers> option was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-mac.pod.in b/doc/man1/openssl-mac.pod.in index 5ed979697381..5d6008f002b3 100644 --- a/doc/man1/openssl-mac.pod.in +++ b/doc/man1/openssl-mac.pod.in @@ -48,8 +48,7 @@ Output the MAC in binary form. Uses hexadecimal text format if not specified. =item B<-cipher> I Used by CMAC and GMAC to specify the cipher algorithm. -For CMAC it must be one of AES-128-CBC, AES-192-CBC, AES-256-CBC or -DES-EDE3-CBC. +For CMAC it should be a CBC mode cipher e.g. AES-128-CBC. For GMAC it should be a GCM mode cipher e.g. AES-128-GCM. =item B<-digest> I diff --git a/doc/man1/openssl-namedisplay-options.pod b/doc/man1/openssl-namedisplay-options.pod index ff6ed1f4b470..b7772ac946e5 100644 --- a/doc/man1/openssl-namedisplay-options.pod +++ b/doc/man1/openssl-namedisplay-options.pod @@ -18,8 +18,10 @@ displayed. This is specified by using the B<-nameopt> option, which takes a comma-separated list of options from the following set. An option may be preceded by a minus sign, C<->, to turn it off. -The default value is C. -The first four are the most commonly used. +The first four option arguments are the most commonly used. + +The default value is +C. =head1 OPTIONS @@ -169,7 +171,7 @@ name. =head1 COPYRIGHT -Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-ocsp.pod.in b/doc/man1/openssl-ocsp.pod.in index fd23a44df063..1d43bc985b7c 100644 --- a/doc/man1/openssl-ocsp.pod.in +++ b/doc/man1/openssl-ocsp.pod.in @@ -24,10 +24,10 @@ B B [B<-req_text>] [B<-resp_text>] [B<-text>] -[B<-reqout> I] -[B<-respout> I] -[B<-reqin> I] -[B<-respin> I] +[B<-reqout> I] +[B<-respout> I] +[B<-reqin> I] +[B<-respin> I] [B<-url> I] [B<-host> I:I] [B<-path> I] @@ -102,15 +102,20 @@ specify output filename, default is standard output. =item B<-issuer> I -This specifies the current issuer certificate. This option can be used -multiple times. +This specifies the current issuer certificate. +The input can be in PEM, DER, or PKCS#12 format. + +This option can be used multiple times. This option B come before any B<-cert> options. =item B<-cert> I -Add the certificate I to the request. The issuer certificate -is taken from the previous B<-issuer> option, or an error occurs if no -issuer certificate is specified. +Add the certificate I to the request. +The input can be in PEM, DER, or PKCS#12 format. + +This option can be used multiple times. +The issuer certificate is taken from the previous B<-issuer> option, +or an error occurs if no issuer certificate is specified. =item B<-no_certs> @@ -126,8 +131,10 @@ be specified by preceding the value by a C<-> sign. =item B<-signer> I, B<-signkey> I Sign the OCSP request using the certificate specified in the B<-signer> -option and the private key specified by the B<-signkey> option. If -the B<-signkey> option is not present then the private key is read +option and the private key specified by the B<-signkey> option. +The input can be in PEM, DER, or PKCS#12 format. + +If the B<-signkey> option is not present then the private key is read from the same file as the certificate. If neither option is specified then the OCSP request is not signed. @@ -148,11 +155,14 @@ a nonce is automatically added specifying B<-no_nonce> overrides this. Print out the text form of the OCSP request, response or both respectively. -=item B<-reqout> I, B<-respout> I +=item B<-reqout> I, B<-respout> I -Write out the DER encoded certificate request or response to I. +Write out the DER-encoded OCSP request or response to I. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. -=item B<-reqin> I, B<-respin> I +=item B<-reqin> I, B<-respin> I Read OCSP request or response file from I. These option are ignored if OCSP request or response creation is implied by other options (for example @@ -329,13 +339,14 @@ must also be present. =item B<-CA> I -CA certificate corresponding to the revocation information in the index +CA certificates corresponding to the revocation information in the index file given with B<-index>. The input can be in PEM, DER, or PKCS#12 format. =item B<-rsigner> I The certificate to sign OCSP responses with. +The input can be in PEM, DER, or PKCS#12 format. =item B<-rkey> I @@ -515,7 +526,7 @@ The -no_alt_chains option was added in OpenSSL 1.1.0. =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 diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in index 929bf60fd2c8..5859d3aded57 100644 --- a/doc/man1/openssl-pkcs12.pod.in +++ b/doc/man1/openssl-pkcs12.pod.in @@ -7,6 +7,8 @@ openssl-pkcs12 - PKCS#12 file command =head1 SYNOPSIS +=for openssl duplicate options + B B [B<-help>] [B<-passin> I] @@ -62,11 +64,15 @@ PKCS#12 output (export) options: [B<-certpbe> I] [B<-descert>] [B<-macalg> I] +[B<-pbmac1_pbkdf2>] +[B<-pbmac1_pbkdf2_md> I] [B<-iter> I] [B<-noiter>] [B<-nomaciter>] [B<-maciter>] +[B<-macsaltlen>] [B<-nomac>] +[B<-jdktrust> I] =head1 DESCRIPTION @@ -170,7 +176,7 @@ see the L section. =item B<-out> I The filename to write certificates and private keys to, standard output by -default. They are all written in PEM format. +default. They are all written in PEM format. =item B<-info> @@ -343,6 +349,15 @@ then both, the private key and the certificates are encrypted using triple DES. Specify the MAC digest algorithm. If not included SHA256 will be used. +=item B<-pbmac1_pbkdf2> + +Use PBMAC1 with PBKDF2 for MAC protection of the PKCS#12 file. + +=item B<-pbmac1_pbkdf2_md> I + +Specify the PBKDF2 KDF digest algorithm. If not specified, SHA256 will be used. +Unless C<-pbmac1_pbkdf2> is specified, this parameter is ignored. + =item B<-iter> I This option specifies the iteration count for the encryption key and MAC. The @@ -368,12 +383,27 @@ option. This option is included for compatibility with previous versions, it used to be needed to use MAC iterations counts but they are now used by default. +=item B<-macsaltlen> + +This option specifies the salt length in bytes for the MAC. The salt length +should be at least 16 bytes as per NIST SP 800-132. The default value +is 8 bytes for backwards compatibility. + =item B<-nomac> Do not attempt to provide the MAC integrity. This can be useful with the FIPS provider as the PKCS12 MAC requires PKCS12KDF which is not an approved FIPS algorithm and cannot be supported by the FIPS provider. +=item B<-jdktrust> + +Export pkcs12 file in a format compatible with Java keystore usage. This option +accepts a string parameter indicating the trust oid name to be granted to the +certificate it is associated with. Currently only "anyExtendedKeyUsage" is +defined. Note that, as Java keystores do not accept PKCS12 files with both +trusted certificates and keypairs, use of this option implies the setting of the +B<-nokeys> option + =back =head1 NOTES @@ -460,7 +490,7 @@ The B<-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead. =head1 COPYRIGHT -Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-pkcs7.pod.in b/doc/man1/openssl-pkcs7.pod.in index efd772d1d438..412c7592d9bc 100644 --- a/doc/man1/openssl-pkcs7.pod.in +++ b/doc/man1/openssl-pkcs7.pod.in @@ -19,6 +19,7 @@ B B [B<-out> I] [B<-print>] [B<-print_certs>] +[B<-quiet>] [B<-text>] [B<-noout>] {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -63,6 +64,11 @@ Print out the full PKCS7 object. Prints out any certificates or CRLs contained in the file. They are preceded by their subject and issuer names in one line format. +=item B<-quiet> + +When used with -print_certs, prints out just the PEM-encoded +certificates without any other output. + =item B<-text> Prints out certificate details in full rather than just subject and @@ -100,7 +106,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-pkcs8.pod.in b/doc/man1/openssl-pkcs8.pod.in index 2af61203e9a7..db089d6777d7 100644 --- a/doc/man1/openssl-pkcs8.pod.in +++ b/doc/man1/openssl-pkcs8.pod.in @@ -27,6 +27,7 @@ B B [B<-scrypt_N> I] [B<-scrypt_r> I] [B<-scrypt_p> I

] +[B<-saltlen> I] {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -78,9 +79,9 @@ key is written. =item B<-in> I -This specifies the input filename to read a key from or standard input if this +This specifies the input file to read a key from or standard input if this option is not specified. If the key is encrypted a pass phrase will be -prompted for. +prompted for unless B<-passin> is given. =item B<-passin> I, B<-passout> I @@ -90,10 +91,14 @@ see L. =item B<-out> I -This specifies the output filename to write a key to or standard output by -default. If any encryption options are set then a pass phrase will be -prompted for. The output filename should B be the same as the input -filename. +This specifies the output file to write a key to or standard output by default. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. + +If any encryption options are set and B<-passout> is not given +then a pass phrase will be prompted for. +When password input is interrupted, the output file is not touched. =item B<-iter> I @@ -148,6 +153,12 @@ B<-scrypt_p> and B<-v2> options. Sets the scrypt I, I or I

parameters. +=item B<-saltlen> + +Sets the length (in bytes) of the salt to use for the PBE algorithm. +If this value is not specified, the default for PBES2 is 16 (128 bits) +and 8 (64 bits) for PBES1. + {- $OpenSSL::safe::opt_r_item -} {- $OpenSSL::safe::opt_engine_item -} @@ -278,7 +289,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0. =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 diff --git a/doc/man1/openssl-pkey.pod.in b/doc/man1/openssl-pkey.pod.in index 34d57f7d1422..64e28bcadabb 100644 --- a/doc/man1/openssl-pkey.pod.in +++ b/doc/man1/openssl-pkey.pod.in @@ -69,8 +69,9 @@ or the public component of a key pair. =item B<-in> I|I -This specifies the input to read a key from +This specifies the input file to read a key from or standard input if this option is not specified. + If the key input is encrypted and B<-passin> is not given a pass phrase will be prompted for. @@ -89,7 +90,8 @@ see L. =item B<-pubin> By default a private key is read from the input. -With this option only the public components are read. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =back @@ -99,11 +101,15 @@ With this option only the public components are read. =item B<-out> I -This specifies the output filename to save the encoded and/or text output of key +This specifies the output file to save the encoded and/or text output of key or standard output if this option is not specified. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. + If any cipher option is set but no B<-passout> is given then a pass phrase will be prompted for. -The output filename should B be the same as the input filename. +When password input is interrupted, the output file is not touched. =item B<-outform> B|B @@ -228,7 +234,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2021 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 diff --git a/doc/man1/openssl-pkeyparam.pod.in b/doc/man1/openssl-pkeyparam.pod.in index 5053316c6880..b8b1792f2894 100644 --- a/doc/man1/openssl-pkeyparam.pod.in +++ b/doc/man1/openssl-pkeyparam.pod.in @@ -35,13 +35,16 @@ Print out a usage message. =item B<-in> I -This specifies the input filename to read parameters from or standard input if +This specifies the input file to read parameters from or standard input if this option is not specified. =item B<-out> I This specifies the output filename to write parameters to or standard output if this option is not specified. +The output filename can be the same as the input filename, +which leads to replacing the file contents. +Note that file I/O is not atomic. The output file is truncated and then written. =item B<-text> diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in index 2f6ef0021d14..3c59957b8d8a 100644 --- a/doc/man1/openssl-pkeyutl.pod.in +++ b/doc/man1/openssl-pkeyutl.pod.in @@ -3,7 +3,7 @@ =head1 NAME -openssl-pkeyutl - public key algorithm command +openssl-pkeyutl - asymmetric key command =head1 SYNOPSIS @@ -13,12 +13,11 @@ B B [B<-rawin>] [B<-digest> I] [B<-out> I] +[B<-secret> I] [B<-sigfile> I] [B<-inkey> I|I] [B<-keyform> B|B|B|B] [B<-passin> I] -[B<-peerkey> I] -[B<-peerform> B|B|B|B] [B<-pubin>] [B<-certin>] [B<-rev>] @@ -28,8 +27,13 @@ B B [B<-encrypt>] [B<-decrypt>] [B<-derive>] +[B<-peerkey> I] +[B<-peerform> B|B|B|B] +[B<-encap>] +[B<-decap>] [B<-kdf> I] [B<-kdflen> I] +[B<-kemop> I] [B<-pkeyopt> I:I] [B<-pkeyopt_passin> I[:I]] [B<-hexdump>] @@ -41,8 +45,8 @@ B B =head1 DESCRIPTION -This command can be used to perform low-level public key -operations using any supported algorithm. +This command can be used to perform low-level operations +on asymmetric (public or private) keys using any supported algorithm. By default the signing operation (see B<-sign> option) is assumed. @@ -66,10 +70,13 @@ which is not hashed by any message digest algorithm. Except with EdDSA, the user can specify a digest algorithm by using the B<-digest> option. For signature algorithms like RSA, DSA and ECDSA, -the default digest algorithm is SHA-256. For SM2, it is SM3. +the default digest algorithm is SHA256. For SM2, it is SM3. This option can only be used with B<-sign> and B<-verify>. -For EdDSA (the Ed25519 and Ed448 algorithms) this option is required. +For EdDSA (the Ed25519 and Ed448 algorithms) this option +is implied since OpenSSL 3.5, and required in earlier versions. + +The B<-digest> option implies B<-rawin> since OpenSSL 3.5. =item B<-digest> I @@ -80,19 +87,27 @@ if the signature algorithm does not require preprocessing the input through a pluggable hash function before signing (for instance, EdDSA). If this option is omitted but the signature algorithm requires one and the B<-rawin> option is given, a default value will be used (see B<-rawin> for details). -If this option is present, then the B<-rawin> option is required. +If this option is present, then the B<-rawin> option +is implied since OpenSSL 3.5, and required in earlier versions. At this time, HashEdDSA (the ph or "prehash" variant of EdDSA) is not supported, so the B<-digest> option cannot be used with EdDSA. =item B<-out> I -Specifies the output filename to write to or standard output by -default. +Specifies the output filename to write to or standard output by default. + +=item B<-secret> I + +Specifies the shared-secret output filename for when performing encapsulation +via the B<-encap> option or decapsulation via the B<-decap> option. +The B<-encap> option also produces a separate (public) ciphertext output which +is by default written to standard output, but being I non-text data, +is typically also redirected to a file selected via the I<-out> option. =item B<-sigfile> I -Signature file, required and allowed for B<-verify> operations only +Signature file, required and allowed for B<-verify> operations only. =item B<-inkey> I|I @@ -108,18 +123,11 @@ See L for details. The input key password source. For more information about the format of I see L. -=item B<-peerkey> I - -The peer key file, used by key derivation (agreement) operations. - -=item B<-peerform> B|B|B|B - -The peer key format; unspecified by default. -See L for details. - =item B<-pubin> -The input file is a public key. +By default a private key is read from the key input. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =item B<-certin> @@ -175,7 +183,71 @@ Decrypt the input data using a private key. =item B<-derive> -Derive a shared secret using the peer key. +Derive a shared secret using own private (EC)DH key and peer key. + +=item B<-peerkey> I + +File containing the peer public or private (EC)DH key +to use with the key derivation (agreement) operation. +Its type must match the type of the own private key given with B<-inkey>. + +=item B<-peerform> B|B|B|B + +The peer key format; unspecified by default. +See L for details. + +=item B<-encap> + +Use a Key Encapsulation Mechanism (B) to B a shared-secret to +a peer's B key. +The encapsulated result (or ciphertext, non-text binary data) is written to +standard output by default, or else to the file specified with I<-out>. +The I<-secret> option must also be provided to specify the output file for the +derived shared-secret value generated in the encapsulation process. +Encapsulation is supported with a number of public key algorithms, currently: +L, +L, +L, +and +L. +The ECX and EC algorithms use the +L DHKEM construction. +Encapsulation is also supported with L keys via the +B construction. + +At the API level, encapsulation and decapsulation are also supported for a few +hybrid ECDHE (no DHKEM) plus B algorithms, but these are intended +primarily for use with TLS and should not be used standalone. +There are in any case no standard public and private key formats for the hybrid +algorithms, so it is not possible to provide the required key material. + +=item B<-decap> + +Decode an encapsulated secret, with the use of a B<-private> key, to derive the +same shared-secret as that obtained when the secret was encapsulated to the +corresponding public key. +The encapsulated secret is by default read from the standard input, or else +from the file specified with B<-in>. +The derived shared-secret is written to the file specified with the B<-secret> +option, which I also be provided. +Decapsulation is supported with a number of public key algorithms, currently: +L, +L, +L, +and +L. +The ECX and EC algorithms use the +L DHKEM construction. +Decapsulation is also supported with L keys via the +B construction. + +=item B<-kemop> I + +This option is used with the I<-encap>/I<-decap> commands and specifies the KEM +I specific for the key algorithm when there is no default way to +encapsulate and decapsulate shared secrets with the chosen key type. +All the supported algorithms presently support only their default I, and +this option, though available, is not required. =item B<-kdf> I @@ -208,8 +280,9 @@ hex dump the output data. =item B<-asn1parse> Parse the ASN.1 output data to check its DER encoding and print any errors. -When combined with the B<-verifyrecover> option, this may be useful only in case -an ASN.1 DER-encoded structure had been signed directly (without hashing it). +When combined with the B<-verifyrecover> option, this may be useful in case +an ASN.1 DER-encoded structure had been signed directly (without hashing it) +and when checking a signature in PKCS#1 v1.5 format, which has a DER encoding. {- $OpenSSL::safe::opt_engine_item -} @@ -233,25 +306,28 @@ engine I for crypto operations. The operations and options supported vary according to the key algorithm and its implementation. The OpenSSL operations and options are indicated below. -Unless otherwise mentioned, all algorithms support the BI option, +Unless otherwise mentioned, the B<-pkeyopt> option supports +for all public-key types the CI argument, which specifies the digest in use for the signing and verification operations. The value I should represent a digest name as used in the -EVP_get_digestbyname() function for example B. This value is not used to +EVP_get_digestbyname() function for example B. This value is not used to hash the input data. It is used (by some algorithms) for sanity-checking the lengths of data passed in and for creating the structures that make up the -signature (e.g. B in RSASSA PKCS#1 v1.5 signatures). +signature (e.g., B in RSASSA PKCS#1 v1.5 signatures). -This command does not hash the input data (except where -rawin is used) but -rather it will use the data directly as input to the signature algorithm. +For instance, +if the value of the B<-pkeyopt> option C argument is B, +the signature or verification input should be the 32 bytes long binary value +of the SHA256 hash function output. + +Unless B<-rawin> is used or implied, this command does not hash the input data +but rather it will use the data directly as input to the signature algorithm. Depending on the key type, signature type, and mode of padding, the maximum -acceptable lengths of input data differ. The signed data can't be longer than -the key modulus with RSA. In case of ECDSA and DSA the data shouldn't be longer +sensible lengths of input data differ. With RSA the signed data cannot be longer +than the key modulus. In case of ECDSA and DSA the data should not be longer than the field size, otherwise it will be silently truncated to the field size. In any event the input size must not be larger than the largest supported digest -size. - -In other words, if the value of digest is B the input should be the 20 -bytes long binary encoding of the SHA-1 hash function output. +output size B, which currently is 64 bytes. =head1 RSA ALGORITHM @@ -273,6 +349,11 @@ signed or verified directly instead of using a B structure. If a digest is set, then the B structure is used and its length must correspond to the digest type. +Note, for B padding, as a protection against the Bleichenbacher attack, +the decryption will not fail in case of padding check failures. Use B +and manual inspection of the decrypted message to verify if the decrypted +value has correct PKCS#1 v1.5 padding. + For B mode only encryption and decryption is supported. For B if the digest type is set it is used to format the block data @@ -298,7 +379,17 @@ explicitly set in PSS mode then the signing digest is used. =item BI Sets the digest used for the OAEP hash function. If not explicitly set then -SHA1 is used. +SHA256 is used. + +=item BI + +Disables (when set to 0) or enables (when set to 1) the use of implicit +rejection with PKCS#1 v1.5 decryption. When enabled (the default), as a +protection against Bleichenbacher attack, the library will generate a +deterministic random plaintext that it will return to the caller in case +of padding check failure. +When disabled, it's the callers' responsibility to handle the returned +errors in a side-channel free manner. =back @@ -317,7 +408,7 @@ These have the same meaning as the B algorithm with some additional restrictions. The padding mode can only be set to B which is the default value. -If the key has parameter restrictions than the digest, MGF1 +If the key has parameter restrictions then the digest, MGF1 digest and salt length are set to the values specified in the parameters. The digest and MG cannot be changed and the salt length cannot be set to a value less than the minimum restriction. @@ -327,7 +418,7 @@ value less than the minimum restriction. =head1 DSA ALGORITHM The DSA algorithm supports signing and verification operations only. Currently -there are no additional B<-pkeyopt> options other than B. The SHA1 +there are no additional B<-pkeyopt> options other than B. The SHA256 digest is assumed by default. =head1 DH ALGORITHM @@ -338,20 +429,44 @@ B<-pkeyopt> options. =head1 EC ALGORITHM The EC algorithm supports sign, verify and derive operations. The sign and -verify operations use ECDSA and derive uses ECDH. SHA1 is assumed by default for -the B<-pkeyopt> B option. +verify operations use ECDSA and derive uses ECDH. SHA256 is assumed by default +for the B<-pkeyopt> B option. =head1 X25519 AND X448 ALGORITHMS The X25519 and X448 algorithms support key derivation only. Currently there are no additional options. +=head1 ML-DSA-44, ML-DSA-65 AND ML-DSA-87 ALGORITHMS + +The B algorithms support signing and verification of "raw" messages. +No preliminary hashing is performed. + +The signing operation supports a B:I option, +with I set to C<1> if a deterministic signature is to be generated +with a fixed all zero random input. +By default, or if the I is C<0> a random entropy value is used. +A deterministic result can also be obtained by specifying an explicit +entropy value via the B:I parameter. +Deterministic B signing should only be used in tests. + +See L for additional options and detail. + +=head1 ML-KEM-512, ML-KEM-768 AND ML-KEM-1024 ALGORITHMS + +The ML-KEM algorithms support encapsulation and decapsulation only. +The encapsulation operation supports a B:I option, +with I the 64 hexadecimal digit encoding of a 32-byte value. +This should only be used in tests, known or leaked values of the option may +compromise the generated shared secret. + +See L for additional detail. + =head1 ED25519 AND ED448 ALGORITHMS These algorithms only support signing and verifying. OpenSSL only implements the "pure" variants of these algorithms so raw data can be passed directly to them -without hashing them first. The option B<-rawin> must be used with these -algorithms with no B<-digest> specified. Additionally OpenSSL only supports +without hashing them first. OpenSSL only supports "oneshot" operation with these algorithms. This means that the entire file to be signed/verified must be read into memory before processing it. Signing or Verifying very large files should be avoided. Additionally the size of the file @@ -449,11 +564,18 @@ L, =head1 HISTORY +Since OpenSSL 3.5, +the B<-digest> option implies B<-rawin>, and these two options are +no longer required when signing or verifying with an Ed25519 or Ed448 key. + +Also since OpenSSL 3.5, the B<-kemop> option is no longer required for any of +the supported algorithms, the only supported B is now the default. + The B<-engine> option was deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-rand.pod.in b/doc/man1/openssl-rand.pod.in index af2c24ae4b0f..7c07df3f147b 100644 --- a/doc/man1/openssl-rand.pod.in +++ b/doc/man1/openssl-rand.pod.in @@ -14,12 +14,20 @@ B [B<-hex>] {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_provider_synopsis -} -I +I[K|M|G|T] =head1 DESCRIPTION This command generates I random bytes using a cryptographically -secure pseudo random number generator (CSPRNG). +secure pseudo random number generator (CSPRNG). A suffix [K|M|G|T] may be +appended to the num value to indicate the requested value be scaled as a +multiple of KiB/MiB/GiB/TiB respectively. Note that suffixes are case +sensitive, and that the suffixes represent binary multiples +(K = 1024 bytes, M = 1024*1024 bytes, etc). + +The string 'max' may be substituted for a numerical value in num, to request the +maximum number of bytes the CSPRNG can produce per instantiation. Currently, +this is restricted to 2^61 bytes as per NIST SP 800-90C. The random bytes are generated using the L function, which provides a security level of 256 bits, provided it managed to diff --git a/doc/man1/openssl-rehash.pod.in b/doc/man1/openssl-rehash.pod.in index 380ad6dd2a46..06a34f6910fa 100644 --- a/doc/man1/openssl-rehash.pod.in +++ b/doc/man1/openssl-rehash.pod.in @@ -10,6 +10,7 @@ openssl-rehash, c_rehash - Create symbolic links to files named by the hash values =head1 SYNOPSIS +=for openssl duplicate options B B @@ -147,7 +148,7 @@ L =head1 COPYRIGHT -Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man1/openssl-req.pod.in b/doc/man1/openssl-req.pod.in index 7ba599b54a06..4d386ec423cb 100644 --- a/doc/man1/openssl-req.pod.in +++ b/doc/man1/openssl-req.pod.in @@ -9,6 +9,7 @@ openssl-req - PKCS#10 certificate request and certificate generating command B B [B<-help>] +[B<-cipher>] [B<-inform> B|B] [B<-outform> B|B] [B<-in> I] @@ -33,15 +34,18 @@ B B [B<-config> I] [B<-section> I] [B<-x509>] +[B<-x509v1>] [B<-CA> I|I] [B<-CAkey> I|I] +[B<-not_before> I] +[B<-not_after> I] [B<-days> I] [B<-set_serial> I] [B<-newhdr>] [B<-copy_extensions> I] -[B<-addext> I] [B<-extensions> I

] [B<-reqexts> I
] +[B<-addext> I] [B<-precert>] [B<-utf8>] [B<-reqopt>] @@ -52,6 +56,7 @@ B B [B<-vfyopt> I:I] [B<-batch>] [B<-verbose>] +[B<-quiet>] {- $OpenSSL::safe::opt_name_synopsis -} {- $OpenSSL::safe::opt_r_synopsis -} {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -} @@ -70,13 +75,24 @@ for use as root CAs for example. Print out a usage message. -=item B<-inform> B|B, B<-outform> B|B +=item B<-inform> B|B -The input and output formats; unspecified by default. +The CSR input file format to use; by default PEM is tried first. +See L for details. + +=item B<-outform> B|B + +The output format; unspecified by default. See L for details. The data is a PKCS#10 object. +=item B<-cipher> I + +Specify the cipher to be used for encrypting the private key. +If no cipher is specified, AES-256-CBC will be used by default. +You can override this by providing any valid OpenSSL cipher name. + =item B<-in> I This specifies the input filename to read a request from. @@ -141,7 +157,9 @@ Prints out the value of the modulus of the public key contained in the request. =item B<-verify> -Verifies the self-signature on the request. +Verifies the self-signature on the request. If the verification fails, +the program will immediately exit, i.e. further option processing +(e.g. B<-text>) is skipped. =item B<-new> @@ -161,7 +179,7 @@ This option is used to generate a new private key unless B<-key> is given. It is subsequently used as if it was given using the B<-key> option. This option implies the B<-new> flag to create a new certificate request -or a new certificate in case B<-x509> is given. +or a new certificate in case B<-x509> is used. The argument takes one of several forms. @@ -290,8 +308,19 @@ a large random number will be used for the serial number. Unless the B<-copy_extensions> option is used, X.509 extensions are not copied from any provided request input file. -X.509 extensions to be added can be specified in the configuration file -or using the B<-addext> option. +X.509 extensions to be added can be specified in the configuration file, +possibly using the B<-config> and B<-extensions> options, +and/or using the B<-addext> option. + +Unless B<-x509v1> is given, generated certificates bear X.509 version 3. +Unless specified otherwise, +key identifier extensions are included as described in L. + +=item B<-x509v1> + +Request generation of certificates with X.509 version 1. +This implies B<-x509>. +If X.509 extensions are given, anyway X.509 version 3 is set. =item B<-CA> I|I @@ -307,12 +336,37 @@ Sets the "CA" private key to sign a certificate with. The private key must match the public key of the certificate given with B<-CA>. If this option is not provided then the key must be present in the B<-CA> input. +=item B<-not_before> I + +When B<-x509> is in use this allows the start date to be explicitly set, +otherwise it is ignored. The format of I is YYMMDDHHMMSSZ (the +same as an ASN1 UTCTime structure), or YYYYMMDDHHMMSSZ (the same as an +ASN1 GeneralizedTime structure). In both formats, seconds SS and +timezone Z must be present. +Alternatively, you can also use "today". + +=item B<-not_after> I + +When B<-x509> is in use this allows the expiry date to be explicitly +set, otherwise it is ignored. The format of I is YYMMDDHHMMSSZ +(the same as an ASN1 UTCTime structure), or YYYYMMDDHHMMSSZ (the same as +an ASN1 GeneralizedTime structure). In both formats, seconds SS and +timezone Z must be present. +Alternatively, you can also use "today". + +This overrides the B<-days> option. + =item B<-days> I -When B<-x509> is in use this specifies the number of -days to certify the certificate for, otherwise it is ignored. I should +When B<-x509> is in use this specifies the number of days from today to +certify the certificate for, otherwise it is ignored. I should be a positive integer. The default is 30 days. +Regardless of the option B<-not_before>, the days are always counted from +today. +When used together with the option B<-not_after>, the explicit expiry +date takes precedence. + =item B<-set_serial> I Serial number to use when outputting a self-signed certificate. @@ -330,23 +384,26 @@ all extensions in the request are copied to the certificate. The main use of this option is to allow a certificate request to supply values for certain extensions such as subjectAltName. +=item B<-extensions> I
, +B<-reqexts> I
+ +Can be used to override the name of the configuration file section +from which X.509 extensions are included +in the certificate (when B<-x509> is in use) or certificate request. +This allows several different sections to be used in the same configuration +file to specify requests for a variety of purposes. + =item B<-addext> I Add a specific extension to the certificate (if B<-x509> is in use) or certificate request. The argument must have the form of -a key=value pair as it would appear in a config file. +a C pair as it would appear in a config file. + +If an extension is added using this option that has the same OID as one +defined in the extension section of the config file, it overrides that one. This option can be given multiple times. - -=item B<-extensions> I
- -=item B<-reqexts> I
- -These options specify alternative sections to include certificate -extensions (if B<-x509> is in use) or certificate request extensions. -This allows several different sections to -be used in the same configuration file to specify requests for -a variety of purposes. +Doing so, the same key most not be given more than once. =item B<-precert> @@ -386,6 +443,12 @@ Non-interactive mode. Print extra details about the operations being performed. +=item B<-quiet> + +Print fewer details about the operations being performed, which may be +handy during batch scripts or pipelines (specifically "progress dots" +during key generation are suppressed). + =item B<-keygen_engine> I Specifies an engine (by its unique I string) which would be used @@ -500,7 +563,7 @@ BMPStrings and UTF8Strings. This specifies the configuration file section containing a list of extensions to add to the certificate request. It can be overridden -by the B<-reqexts> command line switch. See the +by the B<-reqexts> (or B<-extensions>) command line switch. See the L manual page for details of the extension section format. @@ -596,6 +659,10 @@ Examine and verify certificate request: openssl req -in req.pem -text -verify -noout +Specify the cipher to be used for encrypting the private key: + + openssl req -newkey rsa:2048 -keyout privatekey.pem -out request.csr -cipher aes-256-cbc + Create a private key and then generate a certificate request from it: openssl genrsa -out key.pem 2048 @@ -768,6 +835,8 @@ L =head1 HISTORY +The default encryption cipher was changed from 3DES to AES-256 in OpenSSL 3.5. + The B<-section> option was added in OpenSSL 3.0.0. The B<-multivalue-rdn> option has become obsolete in OpenSSL 3.0.0 and @@ -776,6 +845,14 @@ has no effect. The B<-engine> option was deprecated in OpenSSL 3.0. The <-nodes> option was deprecated in OpenSSL 3.0, too; use B<-noenc> instead. +The B<-reqexts> option has been made an alias of B<-extensions> in OpenSSL 3.2. + +Since OpenSSL 3.2, +generated certificates bear X.509 version 3 unless B<-x509v1> is given, +and key identifier extensions are included by default. + +Since OpenSSL 3.3, the B<-verify> option will exit with 1 on failure. + =head1 COPYRIGHT Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man1/openssl-rsa.pod.in b/doc/man1/openssl-rsa.pod.in index 35bd30042907..faa4872e19e6 100644 --- a/doc/man1/openssl-rsa.pod.in +++ b/doc/man1/openssl-rsa.pod.in @@ -121,8 +121,9 @@ This option checks the consistency of an RSA private key. =item B<-pubin> -By default a private key is read from the input file: with this -option a public key is read instead. +By default a private key is read from the input. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =item B<-pubout> @@ -206,7 +207,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0. =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 diff --git a/doc/man1/openssl-rsautl.pod.in b/doc/man1/openssl-rsautl.pod.in index 0a32fd965bf1..41d0d309dd2e 100644 --- a/doc/man1/openssl-rsautl.pod.in +++ b/doc/man1/openssl-rsautl.pod.in @@ -76,7 +76,9 @@ See L for details. =item B<-pubin> -The input file is an RSA public key. +By default a private key is read from the key input. +With this option a public key is read instead. +If the input contains no public key but a private key, its public part is used. =item B<-certin> @@ -105,6 +107,11 @@ The padding to use: PKCS#1 v1.5 (the default), PKCS#1 OAEP, ANSI X9.31, or no padding, respectively. For signatures, only B<-pkcs> and B<-raw> can be used. +Note: because of protection against Bleichenbacher attacks, decryption +using PKCS#1 v1.5 mode will not return errors in case padding check failed. +Use B<-raw> and inspect the returned value manually to check if the +padding is correct. + =item B<-hexdump> Hex dump the output data. diff --git a/doc/man1/openssl-s_client.pod.in b/doc/man1/openssl-s_client.pod.in index caebe10bffb8..d089bc60d80d 100644 --- a/doc/man1/openssl-s_client.pod.in +++ b/doc/man1/openssl-s_client.pod.in @@ -20,6 +20,7 @@ B B [B<-unix> I] [B<-4>] [B<-6>] +[B<-quic>] [B<-servername> I] [B<-noservername>] [B<-verify> I] @@ -48,15 +49,17 @@ B B [B<-reconnect>] [B<-showcerts>] [B<-prexit>] +[B<-no-interactive>] [B<-debug>] [B<-trace>] [B<-nocommands>] +[B<-adv>] [B<-security_debug>] [B<-security_debug_verbose>] [B<-msg>] [B<-timeout>] [B<-mtu> I] -[B<-no_etm>] +[B<-no_ems>] [B<-keymatexport> I into big-endian form and stores it at B. B must point to BN_num_bytes(B) bytes of -memory. +memory. B and B B be NULL. BN_bn2binpad() also converts the absolute value of B into big-endian form and stores it at B. B indicates the length of the output buffer B. The result is padded with zeros if necessary. If B is less than BN_num_bytes(B) an error is returned. +BN_signed_bn2bin() converts the value of B into big-endian signed 2's +complements form and stores it at B. B indicates the length of +the output buffer B. The result is signed extended (padded with 0x00 +for positive numbers or with 0xff for negative numbers) if necessary. +If B is smaller than the necessary size (which may be +C<) + 1>>), an error is returned. + BN_bin2bn() converts the positive integer in big-endian form of length B at B into a B and places it in B. If B is -NULL, a new B is created. +NULL, a new B is created. B B be NULL. -BN_bn2lebinpad() and BN_lebin2bn() are identical to BN_bn2binpad() and -BN_bin2bn() except the buffer is in little-endian format. +BN_signed_bin2bn() converts the integer in big-endian signed 2's complement +form of length B at B into a B and places it in B. If +B is NULL, a new B is created. -BN_bn2nativepad() and BN_native2bn() are identical to BN_bn2binpad() and -BN_bin2bn() except the buffer is in native format, i.e. most significant -byte first on big-endian platforms, and least significant byte first on -little-endian platforms. +BN_bn2lebinpad(), BN_signed_bn2lebin() and BN_lebin2bn() are identical to +BN_bn2binpad(), BN_signed_bn2bin() and BN_bin2bn() except the buffer is in +little-endian format. + +BN_bn2nativepad(), BN_signed_bn2native() and BN_native2bn() are identical +to BN_bn2binpad(), BN_signed_bn2bin() and BN_bin2bn() except the buffer is +in native format, i.e. most significant byte first on big-endian platforms, +and least significant byte first on little-endian platforms. BN_bn2hex() and BN_bn2dec() return printable strings containing the hexadecimal and decimal encoding of B respectively. For negative @@ -91,8 +110,9 @@ if B is NULL. BN_bn2bin() returns the length of the big-endian number placed at B. BN_bin2bn() returns the B, NULL on error. -BN_bn2binpad(), BN_bn2lebinpad(), and BN_bn2nativepad() return the number of bytes written or -1 if the supplied -buffer is too small. +BN_bn2binpad(), BN_signed_bn2bin(), BN_bn2lebinpad(), BN_signed_bn2lebin(), +BN_bn2nativepad(), and_signed BN_bn2native() return the number of bytes +written or -1 if the supplied buffer is too small. BN_bn2hex() and BN_bn2dec() return a NUL-terminated string, or NULL on error. BN_hex2bn() and BN_dec2bn() return the number of characters @@ -112,9 +132,15 @@ L, L, L, L +=head1 HISTORY + +The functions BN_signed_bin2bn(), BN_signed_bn2bin(), BN_signed_lebin2bn(), +BN_signed_bn2lebin(), BN_signed_native2bn(), BN_signed_bn2native() +were added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/BN_cmp.pod b/doc/man3/BN_cmp.pod index f302818f215e..e9ddf8fa2d4d 100644 --- a/doc/man3/BN_cmp.pod +++ b/doc/man3/BN_cmp.pod @@ -2,7 +2,8 @@ =head1 NAME -BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd - BIGNUM comparison and test functions +BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd, BN_are_coprime +- BIGNUM comparison and test functions =head1 SYNOPSIS @@ -17,6 +18,8 @@ BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd - int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); int BN_is_odd(const BIGNUM *a); + int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + =head1 DESCRIPTION BN_cmp() compares the numbers I and I. BN_ucmp() compares their @@ -26,6 +29,10 @@ BN_is_zero(), BN_is_one(), BN_is_word() and BN_abs_is_word() test if I equals 0, 1, I, or EIE respectively. BN_is_odd() tests if I is odd. +BN_are_coprime() determines if B and B are coprime. +B is used internally for storing temporary variables. +The values of B and B and B must not be NULL. + =head1 RETURN VALUES BN_cmp() returns -1 if I E I, 0 if I == I and 1 if @@ -35,11 +42,16 @@ of I and I. BN_is_zero(), BN_is_one() BN_is_word(), BN_abs_is_word() and BN_is_odd() return 1 if the condition is true, 0 otherwise. +BN_are_coprime() returns 1 if the B's are coprime, otherwise it +returns 0. + =head1 HISTORY Prior to OpenSSL 1.1.0, BN_is_zero(), BN_is_one(), BN_is_word(), BN_abs_is_word() and BN_is_odd() were macros. +The function BN_are_coprime() was added in OpenSSL 3.1. + =head1 COPYRIGHT Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/BN_mod_mul_reciprocal.pod b/doc/man3/BN_mod_mul_reciprocal.pod index 28d5f1131d73..a2f4ebc79dcc 100644 --- a/doc/man3/BN_mod_mul_reciprocal.pod +++ b/doc/man3/BN_mod_mul_reciprocal.pod @@ -66,7 +66,7 @@ BN_RECP_CTX_init() was removed in OpenSSL 1.1.0 =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/BN_rand.pod b/doc/man3/BN_rand.pod index 0ad76d6af7e7..4ce4a0ee6cd0 100644 --- a/doc/man3/BN_rand.pod +++ b/doc/man3/BN_rand.pod @@ -119,7 +119,7 @@ BN_priv_rand_range_ex() functions were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index 3aa3f474fc5a..fe77701fe017 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -2,8 +2,8 @@ =head1 NAME -CMS_EncryptedData_decrypt -- Decrypt CMS EncryptedData +CMS_EncryptedData_decrypt, CMS_EnvelopedData_decrypt +- Decrypt CMS EncryptedData or EnvelopedData =head1 SYNOPSIS @@ -13,6 +13,11 @@ CMS_EncryptedData_decrypt const unsigned char *key, size_t keylen, BIO *dcont, BIO *out, unsigned int flags); + BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data, + EVP_PKEY *pkey, X509 *cert, + ASN1_OCTET_STRING *secret, unsigned int flags, + OSSL_LIB_CTX *libctx, const char *propq); + =head1 DESCRIPTION CMS_EncryptedData_decrypt() decrypts a I EncryptedData object using the @@ -27,19 +32,33 @@ If the B flag is set MIME headers for type C are deleted from the content. If the content is not of type C then an error is returned. +CMS_EnvelopedData_decrypt() decrypts, similarly to CMS_decrypt(3), +a CMS EnvelopedData object I using the symmetric key I if it +is not NULL, otherwise the private key of the recipient I. +If I is given, it is recommended to provide also the associated +certificate in I - see L and the NOTES on I there. +The optional parameters I and I are used as described above. +The optional parameters library context I and property query I +are used when retrieving algorithms from providers. + =head1 RETURN VALUES -CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise it -returns 1. +CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise returns 1. + +CMS_EnvelopedData_decrypt() returns NULL if an error occurred, +otherwise a BIO containing the decypted content. =head1 SEE ALSO -L, L +L, L, L +=head1 HISTORY + +CMS_EnvelopedData_decrypt() was added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_EnvelopedData_create.pod b/doc/man3/CMS_EnvelopedData_create.pod index e5ff269e47be..5026db545f24 100644 --- a/doc/man3/CMS_EnvelopedData_create.pod +++ b/doc/man3/CMS_EnvelopedData_create.pod @@ -42,35 +42,42 @@ L. The B structure needs to be finalized using L and then freed using L. -CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create are similar to -CMS_EnvelopedData_create_ex() and -CMS_AuthEnvelopedData_create_ex() but use default values of NULL for +CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create() are similar to +CMS_EnvelopedData_create_ex() and CMS_AuthEnvelopedData_create_ex() +but use default values of NULL for the library context I and the property query I. =head1 NOTES -Although CMS_EnvelopedData_create() and CMS_AuthEnvelopedData_create() allocate +Although CMS_EnvelopedData_create_ex(), and CMS_EnvelopedData_create(), +CMS_AuthEnvelopedData_create_ex(), and CMS_AuthEnvelopedData_create() allocate a new B structure, they are not usually used in applications. The wrappers L and L are often used instead. =head1 RETURN VALUES -If the allocation fails, CMS_EnvelopedData_create() and -CMS_AuthEnvelopedData_create() return NULL and set an error code that can be -obtained by L. Otherwise they return a pointer to the newly -allocated structure. +If the allocation fails, CMS_EnvelopedData_create_ex(), +CMS_EnvelopedData_create(), CMS_AuthEnvelopedData_create_ex(), +CMS_AuthEnvelopedData_create(), CMS_AuthEnvelopedData_create(), +and CMS_AuthEnvelopedData_create_ex() return NULL and set an +error code that can be obtained by L. +Otherwise, they return a pointer to the newly allocated structure. =head1 SEE ALSO -L, L, L, L +L, L, L, L, +L, L =head1 HISTORY The CMS_EnvelopedData_create_ex() method was added in OpenSSL 3.0. +CMS_AuthEnvelopedData_create() and CMS_AuthEnvelopedData_create_ex() +were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_add0_cert.pod b/doc/man3/CMS_add0_cert.pod index 8908ff2f1fc0..8f7e0e9e42f5 100644 --- a/doc/man3/CMS_add0_cert.pod +++ b/doc/man3/CMS_add0_cert.pod @@ -2,7 +2,8 @@ =head1 NAME -CMS_add0_cert, CMS_add1_cert, CMS_get1_certs, CMS_add0_crl, CMS_add1_crl, CMS_get1_crls +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 @@ -19,9 +20,13 @@ CMS_add0_cert, CMS_add1_cert, CMS_get1_certs, CMS_add0_crl, CMS_add1_crl, CMS_ge =head1 DESCRIPTION -CMS_add0_cert() and CMS_add1_cert() add certificate I to I. +CMS_add0_cert() and CMS_add1_cert() add certificate I to I +unless it is already present. This is used by L and L and may be used before calling L to help chain building in certificate validation. +As the 0 implies, CMS_add0_cert() adds I internally to I +and on success it must not be freed up by the caller. +In contrast, the caller of CMS_add1_cert() must free I. I 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 @@ -41,17 +46,11 @@ CMS_get1_crls() returns all CRLs in I. =head1 NOTES The CMS_ContentInfo structure I must be of type signed data or enveloped -data or an error will be returned. +data or authenticated enveloped data or an error will be returned. -For signed data certificates and CRLs are added to the I and -I fields of SignedData structure. For enveloped data they are added to -B. - -As the I<0> implies CMS_add0_cert() adds I internally to I and it -must not be freed up after the call as opposed to CMS_add1_cert() where I -must be freed up. - -The same certificate must not be added to the same cms structure more than once. +For signed data, certificates and CRLs are added to the I and +I fields of SignedData structure. +For enveloped data they are added to B. =head1 RETURN VALUES @@ -59,7 +58,8 @@ 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 +or NULL if there are none or an error occurs. +Besides out-of-memory, the only error which will occur in practice is if the I type is invalid. =head1 SEE ALSO @@ -68,9 +68,14 @@ L, L, L, L, L +=head1 HISTORY + +CMS_add0_cert() and CMS_add1_cert() have been changed in OpenSSL 3.2 +not to throw an error if a certificate to be added is already present. + =head1 COPYRIGHT -Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_add1_recipient_cert.pod b/doc/man3/CMS_add1_recipient_cert.pod index e1fc34303be0..0855d5321b06 100644 --- a/doc/man3/CMS_add1_recipient_cert.pod +++ b/doc/man3/CMS_add1_recipient_cert.pod @@ -76,7 +76,7 @@ OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_add1_signer.pod b/doc/man3/CMS_add1_signer.pod index d606a02cc1fd..3d994889aaab 100644 --- a/doc/man3/CMS_add1_signer.pod +++ b/doc/man3/CMS_add1_signer.pod @@ -67,7 +67,8 @@ previously signed message. The SignedData structure includes several CMS signedAttributes including the signing time, the CMS content type and the supported list of ciphers in an SMIMECapabilities attribute. If B is set then no signedAttributes -will be used. If B is set then just the SMIMECapabilities are +will be used at all. If B is set then the SMIMECapabilities +will be omitted. If B is set then the signing time will be omitted. OpenSSL will by default identify signing certificates using issuer name @@ -99,7 +100,7 @@ L, =head1 COPYRIGHT -Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_decrypt.pod b/doc/man3/CMS_decrypt.pod index 75c33a91d176..121b74a30a10 100644 --- a/doc/man3/CMS_decrypt.pod +++ b/doc/man3/CMS_decrypt.pod @@ -24,8 +24,8 @@ 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 if I is not NULL. -In this case, it is recommended to provide the associated certificate -in I - see the NOTES below. +In this case, the associated certificate is recommended to provide in I - +see the NOTES below. I is a BIO to write the content to and I is an optional set of flags. If I is NULL the function assumes that decryption was already done @@ -36,9 +36,8 @@ is detached. It will normally be set to NULL. CMS_decrypt_set1_pkey_and_peer() decrypts the CMS_ContentInfo structure I using the private key I, the corresponding certificate I, which is -recommended to be supplied but may be NULL, -and the (optional) originator certificate I. -On success, it also records in I the decryption key I, and this +recommended but may be NULL, and the (optional) originator certificate I. +On success, it also records in I the decryption key I, and then should be followed by C. This call deallocates any decryption key stored in I. @@ -47,7 +46,7 @@ CMS_decrypt_set1_pkey_and_peer() with I being NULL. CMS_decrypt_set1_password() decrypts the CMS_ContentInfo structure I using the secret I of length I. -On success, it also records in I the decryption key used, and this +On success, it also records in I the decryption key used, and then should be followed by C. This call deallocates any decryption key stored in I. @@ -113,7 +112,7 @@ were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_final.pod b/doc/man3/CMS_final.pod index 8270d53bc712..eec4cf31616b 100644 --- a/doc/man3/CMS_final.pod +++ b/doc/man3/CMS_final.pod @@ -2,13 +2,15 @@ =head1 NAME -CMS_final - finalise a CMS_ContentInfo structure +CMS_final, CMS_final_digest - finalise a CMS_ContentInfo structure =head1 SYNOPSIS #include int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags); + int CMS_final_digest(CMS_ContentInfo *cms, const unsigned char *md, + unsigned int mdlen, BIO *dcont, unsigned int flags); =head1 DESCRIPTION @@ -19,24 +21,37 @@ processed. The B parameter contains a BIO to write content to after processing: this is only used with detached data and will usually be set to NULL. +CMS_final_digest() finalises the structure B using a pre-computed digest, +rather than computing the digest from the original data. + =head1 NOTES -This function will normally be called when the B flag is used. It +These functions will normally be called when the B flag is used. It should only be used when streaming is not performed because the streaming I/O functions perform finalisation operations internally. +To sign a pre-computed digest, L or CMS_sign_ex() is called +with the B parameter set to NULL before the CMS structure is finalised +with the digest provided to CMS_final_digest() in binary form. +When signing a pre-computed digest, the security relies on the digest and its +computation from the original message being trusted. + =head1 RETURN VALUES -CMS_final() returns 1 for success or 0 for failure. +CMS_final() and CMS_final_digest() return 1 for success or 0 for failure. =head1 SEE ALSO L, L, L +=head1 HISTORY + +CMS_final_digest() was added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_get0_RecipientInfos.pod b/doc/man3/CMS_get0_RecipientInfos.pod index 8f4593538d19..eb755f524310 100644 --- a/doc/man3/CMS_get0_RecipientInfos.pod +++ b/doc/man3/CMS_get0_RecipientInfos.pod @@ -145,7 +145,7 @@ were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CMS_sign.pod b/doc/man3/CMS_sign.pod index 03bfc6fce16a..3380b1a1dd95 100644 --- a/doc/man3/CMS_sign.pod +++ b/doc/man3/CMS_sign.pod @@ -60,7 +60,8 @@ otherwise the translation will corrupt it. The SignedData structure includes several CMS signedAttributes including the signing time, the CMS content type and the supported list of ciphers in an SMIMECapabilities attribute. If B is set then no signedAttributes -will be used. If B is set then just the SMIMECapabilities are +will be used at all. If B is set then the SMIMECapabilities +will be omitted. If B is set then the signing time will be omitted. If present the SMIMECapabilities attribute indicates support for the following @@ -130,6 +131,9 @@ it is supported for embedded data in OpenSSL 1.0.0 and later. The CMS_sign_ex() method was added in OpenSSL 3.0. +Since OpenSSL 3.2, CMS_sign_ex() and CMS_sign() ignore any duplicate +certificates in their I argument and no longer throw an error for them. + =head1 COPYRIGHT Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/CMS_verify.pod b/doc/man3/CMS_verify.pod index 70c8eb212d6b..9cc0d11818b1 100644 --- a/doc/man3/CMS_verify.pod +++ b/doc/man3/CMS_verify.pod @@ -2,14 +2,20 @@ =head1 NAME -CMS_verify, CMS_get0_signers - verify a CMS SignedData structure +CMS_verify, CMS_SignedData_verify, +CMS_get0_signers - verify a CMS SignedData structure =head1 SYNOPSIS #include int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, X509_STORE *store, - BIO *indata, BIO *out, unsigned int flags); + BIO *detached_data, BIO *out, unsigned int flags); + BIO *CMS_SignedData_verify(CMS_SignedData *sd, BIO *detached_data, + STACK_OF(X509) *scerts, X509_STORE *store, + STACK_OF(X509) *extra, STACK_OF(X509_CRL) *crls, + unsigned int flags, + OSSL_LIB_CTX *libctx, const char *propq); STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); @@ -20,17 +26,31 @@ B structure contained in a structure of type B. I points to the B structure to verify. The optional I parameter refers to a set of certificates in which to search for signing certificates. +It is also used +as a source of untrusted intermediate CA certificates for chain building. I may contain extra untrusted CA certificates that may be used for chain building as well as CRLs that may be used for certificate validation. I may be NULL or point to the trusted certificate store to use for chain verification. -I refers to the signed data if the content is detached from I. -Otherwise I should be NULL and the signed data must be in I. +I refers to the signed data if the content is detached from I. +Otherwise I should be NULL and the signed data must be in I. The content is written to the BIO I unless it is NULL. I is an optional set of flags, which can be used to modify the operation. -CMS_get0_signers() retrieves the signing certificate(s) from I, it may only -be called after a successful CMS_verify() operation. +CMS_SignedData_verify() is like CMS_verify() except that +it operates on B input in the I argument, +it has some additional parameters described next, +and on success it returns the verified content as a memory BIO. +The optional I parameter may be used to provide untrusted CA +certificates that may be helpful for chain building in certificate validation. +This list of certificates must not contain duplicates. +The optional I parameter may be used to provide extra CRLs. +Also the list of CRLs must not contain duplicates. +The optional parameters library context I and property query I +are used when retrieving algorithms from providers. + +CMS_get0_signers() retrieves the signing certificate(s) from I; it may only +be called after a successful CMS_verify() or CMS_SignedData_verify() operation. =head1 VERIFY PROCESS @@ -38,7 +58,7 @@ Normally the verify process proceeds as follows. Initially some sanity checks are performed on I. The type of I must be SignedData. There must be at least one signature on the data and if -the content is detached I cannot be NULL. +the content is detached I cannot be NULL. An attempt is made to locate all the signing certificate(s), first looking in the I parameter (if it is not NULL) and then looking in any @@ -67,10 +87,10 @@ searched when locating the signing certificate(s). This means that all the signing certificates must be in the I parameter. If B is set and CRL checking is enabled in I then any -CRLs in the message itself are ignored. +CRLs in the message itself and provided via the I parameter are ignored. -If the B flag is set MIME headers for type B are deleted -from the content. If the content is not of type B then an error is +If the B flag is set MIME headers for type C are deleted +from the content. If the content is not of type C then an error is returned. If B is set the signing certificates are not @@ -114,9 +134,12 @@ timestamp). CMS_verify() returns 1 for a successful verification and 0 if an error occurred. +CMS_SignedData_verify() returns a memory BIO containing the verified content, +or NULL on error. + CMS_get0_signers() returns all signers or NULL if an error occurred. -The error can be obtained from L +The error can be obtained from L. =head1 BUGS @@ -133,9 +156,13 @@ L, L, L, L, L, L +=head1 HISTORY + +CMS_SignedData_verify() was added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2008-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CONF_modules_free.pod b/doc/man3/CONF_modules_free.pod index 81b10ebc3bbe..fd22d828994d 100644 --- a/doc/man3/CONF_modules_free.pod +++ b/doc/man3/CONF_modules_free.pod @@ -48,7 +48,7 @@ For more information see L. =head1 COPYRIGHT -Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CONF_modules_load_file.pod b/doc/man3/CONF_modules_load_file.pod index 620bbfd89861..ce9aa9cf9443 100644 --- a/doc/man3/CONF_modules_load_file.pod +++ b/doc/man3/CONF_modules_load_file.pod @@ -154,7 +154,7 @@ L =head1 COPYRIGHT -Copyright 2004-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2004-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/CRYPTO_THREAD_run_once.pod b/doc/man3/CRYPTO_THREAD_run_once.pod index 420ff7278b26..e977b91e862e 100644 --- a/doc/man3/CRYPTO_THREAD_run_once.pod +++ b/doc/man3/CRYPTO_THREAD_run_once.pod @@ -5,7 +5,11 @@ CRYPTO_THREAD_run_once, CRYPTO_THREAD_lock_new, CRYPTO_THREAD_read_lock, CRYPTO_THREAD_write_lock, CRYPTO_THREAD_unlock, CRYPTO_THREAD_lock_free, -CRYPTO_atomic_add, CRYPTO_atomic_or, CRYPTO_atomic_load - OpenSSL thread support +CRYPTO_atomic_add, CRYPTO_atomic_add64, CRYPTO_atomic_and, CRYPTO_atomic_or, +CRYPTO_atomic_load, CRYPTO_atomic_store, CRYPTO_atomic_load_int, +OSSL_set_max_threads, OSSL_get_max_threads, +OSSL_get_thread_support_flags, OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL, +OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN - OpenSSL thread support =head1 SYNOPSIS @@ -21,9 +25,22 @@ CRYPTO_atomic_add, CRYPTO_atomic_or, CRYPTO_atomic_load - OpenSSL thread support void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock); int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); + int CRYPTO_atomic_add64(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock); + int CRYPTO_atomic_and(uint64_t *val, uint64_t op, uint64_t *ret, + CRYPTO_RWLOCK *lock); int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock); int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock); + int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock); + int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock); + + int OSSL_set_max_threads(OSSL_LIB_CTX *ctx, uint64_t max_threads); + uint64_t OSSL_get_max_threads(OSSL_LIB_CTX *ctx); + uint32_t OSSL_get_thread_support_flags(void); + + #define OSSL_THREAD_SUPPORT_FLAG_THREAD_POOL + #define OSSL_THREAD_SUPPORT_FLAG_DEFAULT_SPAWN =head1 DESCRIPTION @@ -82,6 +99,25 @@ supported and I is NULL, then the function will fail. =item * +CRYPTO_atomic_add64() atomically adds I to I<*val> and returns the +result of the operation in I<*ret>. I will be locked, unless atomic +operations are supported on the specific platform. Because of this, if a +variable is modified by CRYPTO_atomic_add64() then CRYPTO_atomic_add64() must +be the only way that the variable is modified. If atomic operations are not +supported and I is NULL, then the function will fail. + +=item * + +CRYPTO_atomic_and() performs an atomic bitwise and of I and I<*val> and stores +the result back in I<*val>. It also returns the result of the operation in +I<*ret>. I will be locked, unless atomic operations are supported on the +specific platform. Because of this, if a variable is modified by +CRYPTO_atomic_and() or read by CRYPTO_atomic_load() then CRYPTO_atomic_and() must +be the only way that the variable is modified. If atomic operations are not +supported and I is NULL, then the function will fail. + +=item * + CRYPTO_atomic_or() performs an atomic bitwise or of I and I<*val> and stores the result back in I<*val>. It also returns the result of the operation in I<*ret>. I will be locked, unless atomic operations are supported on the @@ -99,6 +135,38 @@ read by CRYPTO_atomic_load() then CRYPTO_atomic_load() must be the only way that the variable is read. If atomic operations are not supported and I is NULL, then the function will fail. +=item * + +CRYPTO_atomic_store() atomically stores the contents of I into I<*dst>. +I will be locked, unless atomic operations are supported on the specific +platform. + +=item * + +CRYPTO_atomic_load_int() works identically to CRYPTO_atomic_load() but operates +on an I value instead of a I value. + +=item * + +OSSL_set_max_threads() sets the maximum number of threads to be used by the +thread pool. If the argument is 0, thread pooling is disabled. OpenSSL will +not create any threads and existing threads in the thread pool will be torn +down. The maximum thread count is a limit, not a target. Threads will not be +spawned unless (and until) there is demand. Thread polling is disabled by +default. To enable threading you must call OSSL_set_max_threads() explicitly. +Under no circumstances is this done for you. + +=item * + +OSSL_get_thread_support_flags() determines what thread pool functionality +OpenSSL is compiled with and is able to support in the current run time +environment. B indicates that the base +thread pool functionality is available, and +B indicates that the default thread pool +model is available. The default thread pool model is currently the only model +available, therefore both of these flags must be set for thread pool +functionality to be used. + =back =head1 RETURN VALUES @@ -109,6 +177,18 @@ CRYPTO_THREAD_lock_new() returns the allocated lock, or NULL on error. CRYPTO_THREAD_lock_free() returns no value. +OSSL_set_max_threads() returns 1 on success and 0 on failure. Returns failure +if OpenSSL-managed thread pooling is not supported (for example, if it is not +supported on the current platform, or because OpenSSL is not built with the +necessary support). + +OSSL_get_max_threads() returns the maximum number of threads currently allowed +to be used by the thread pool. If thread pooling is disabled or not available, +returns 0. + +OSSL_get_thread_support_flags() returns zero or more B +values. + The other functions return 1 on success, or 0 on error. =head1 NOTES @@ -185,6 +265,14 @@ repeatedly load/unload shared libraries that allocate locks. L, L. +=head1 HISTORY + +CRYPTO_atomic_load_int(), OSSL_set_max_threads(), OSSL_get_max_threads(), +OSSL_get_thread_support_flags() were added in OpenSSL 3.2. + +CRYPTO_atomic_store(), CRYPTO_atomic_add64(), CRYPTO_atomic_and() +were added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/DEFINE_STACK_OF.pod b/doc/man3/DEFINE_STACK_OF.pod index 3ebd473afcb2..ff2074820f68 100644 --- a/doc/man3/DEFINE_STACK_OF.pod +++ b/doc/man3/DEFINE_STACK_OF.pod @@ -178,10 +178,7 @@ where a comparison function has been specified, I is sorted and B_find>() returns the index of a matching element or B<-1> if there is no match. Note that, in this case the comparison function will usually compare the values pointed to rather than the pointers themselves and -the order of elements in I can change. Note that because the stack may be -sorted as the result of a B_find>() call, if a lock is being used to -synchronise access to the stack across multiple threads, then that lock must be -a "write" lock. +the order of elements in I can change. B_find_ex>() operates like B_find>() except when a comparison function has been specified and no matching element is found. @@ -273,7 +270,6 @@ on error. B_insert>(), B_push>() and B_unshift>() return the total number of elements in the stack and 0 if an error occurred. -B_push>() further returns -1 if I is NULL. B_set>() returns a pointer to the replacement element or NULL on error. @@ -295,6 +291,14 @@ and was not a public API. B_reserve>() and B_new_reserve>() were added in OpenSSL 1.1.1. +From OpenSSL 3.2.0, the B_find>(), B_find_ex>() +and B_find_all>() calls are read-only and do not sort the +stack. To avoid any performance implications this change introduces, +B_sort>() should be called before these find operations. + +Before OpenSSL 3.3.0 B_push>() returned -1 if I was NULL. It +was changed to return 0 in this condition as for other errors. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/DES_random_key.pod b/doc/man3/DES_random_key.pod index ff16961ea92a..48fd3d023156 100644 --- a/doc/man3/DES_random_key.pod +++ b/doc/man3/DES_random_key.pod @@ -323,7 +323,7 @@ on some platforms. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DH_generate_parameters.pod b/doc/man3/DH_generate_parameters.pod index 9c1dff7aedd9..e677885597ae 100644 --- a/doc/man3/DH_generate_parameters.pod +++ b/doc/man3/DH_generate_parameters.pod @@ -164,7 +164,7 @@ DH_generate_parameters_ex() instead. =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DH_get0_pqg.pod b/doc/man3/DH_get0_pqg.pod index 6e5b301f6c6e..ae8da4865b69 100644 --- a/doc/man3/DH_get0_pqg.pod +++ b/doc/man3/DH_get0_pqg.pod @@ -141,7 +141,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DH_new.pod b/doc/man3/DH_new.pod index 5c8bcdce5c36..dc073b4e3f95 100644 --- a/doc/man3/DH_new.pod +++ b/doc/man3/DH_new.pod @@ -47,7 +47,7 @@ For replacement see EVP_PKEY-DH(7). =head1 COPYRIGHT -Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DH_new_by_nid.pod b/doc/man3/DH_new_by_nid.pod index 5703440e9201..ac2285b148f4 100644 --- a/doc/man3/DH_new_by_nid.pod +++ b/doc/man3/DH_new_by_nid.pod @@ -42,7 +42,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DH_set_method.pod b/doc/man3/DH_set_method.pod index 88dffab26c0c..d6da38100190 100644 --- a/doc/man3/DH_set_method.pod +++ b/doc/man3/DH_set_method.pod @@ -89,7 +89,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DSA_dup_DH.pod b/doc/man3/DSA_dup_DH.pod index b2a1529ac867..f8a4815cd597 100644 --- a/doc/man3/DSA_dup_DH.pod +++ b/doc/man3/DSA_dup_DH.pod @@ -43,7 +43,7 @@ This function was deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DSA_generate_parameters.pod b/doc/man3/DSA_generate_parameters.pod index a10dc9ba2759..32eecb6891fa 100644 --- a/doc/man3/DSA_generate_parameters.pod +++ b/doc/man3/DSA_generate_parameters.pod @@ -126,7 +126,7 @@ DSA_generate_parameters_ex() instead. =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DSA_get0_pqg.pod b/doc/man3/DSA_get0_pqg.pod index 7b2f132a99b2..fc2a967cfa94 100644 --- a/doc/man3/DSA_get0_pqg.pod +++ b/doc/man3/DSA_get0_pqg.pod @@ -113,7 +113,7 @@ OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DSA_new.pod b/doc/man3/DSA_new.pod index 60b3d50dfa01..01be4e842d71 100644 --- a/doc/man3/DSA_new.pod +++ b/doc/man3/DSA_new.pod @@ -50,7 +50,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DSA_sign.pod b/doc/man3/DSA_sign.pod index 0d20f0f6809c..dadd6d5cbf55 100644 --- a/doc/man3/DSA_sign.pod +++ b/doc/man3/DSA_sign.pod @@ -73,7 +73,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/DTLSv1_listen.pod b/doc/man3/DTLSv1_listen.pod index 26f34e33acf5..eda8aaf22a27 100644 --- a/doc/man3/DTLSv1_listen.pod +++ b/doc/man3/DTLSv1_listen.pod @@ -103,6 +103,9 @@ TLSv1.3 is used. Both SSL_stateless() and DTLSv1_listen() will clear the error queue when they start. +SSL_stateless() cannot be used with QUIC SSL objects and returns an error if +called on such an object. + =head1 RETURN VALUES For SSL_stateless() a return value of 1 indicates success and the B object diff --git a/doc/man3/EC_GFp_simple_method.pod b/doc/man3/EC_GFp_simple_method.pod index 8c4acd28e0b0..6e3e9b708ae6 100644 --- a/doc/man3/EC_GFp_simple_method.pod +++ b/doc/man3/EC_GFp_simple_method.pod @@ -73,7 +73,7 @@ were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2013-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EC_GROUP_new.pod b/doc/man3/EC_GROUP_new.pod index b6d67b617642..6c6b61af8aa3 100644 --- a/doc/man3/EC_GROUP_new.pod +++ b/doc/man3/EC_GROUP_new.pod @@ -5,6 +5,7 @@ EC_GROUP_get_ecparameters, EC_GROUP_get_ecpkparameters, EC_GROUP_new_from_params, +EC_GROUP_to_params, EC_GROUP_new_from_ecparameters, EC_GROUP_new_from_ecpkparameters, EC_GROUP_new, @@ -30,6 +31,8 @@ Functions for creating and destroying EC_GROUP objects EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[], OSSL_LIB_CTX *libctx, const char *propq); + OSSL_PARAM *EC_GROUP_to_params(const EC_GROUP *group, OSSL_LIB_CTX *libctx, + const char *propq, BN_CTX *bnctx); EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params); EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params); void EC_GROUP_free(EC_GROUP *group); @@ -107,6 +110,16 @@ The values for I and I may be NULL. The I that can be used are described in L(7)|EVP_PKEY-EC(7)/Common EC parameters>. +EC_GROUP_to_params creates an OSSL_PARAM array with the corresponding parameters +describing the given EC_GROUP. The resulting parameters may contain parameters +describing a named or explicit curve depending on the EC_GROUP. +The library context I (see L) and property query string +I are used to fetch algorithms from providers. +I is an optional preallocated BN_CTX (to save the overhead of allocating +and freeing the structure in a loop). +The values for I, I and I may be NULL. +The caller is responsible for freeing the OSSL_PARAM pointer returned. + EC_GROUP_new_from_ecparameters() will create a group from the specified I and EC_GROUP_new_from_ecpkparameters() will create a group from the specific PK @@ -199,6 +212,8 @@ L, L =head1 HISTORY +EC_GROUP_to_params() was added in OpenSSL 3.2. + =over 2 =item * @@ -223,7 +238,7 @@ instead. =head1 COPYRIGHT -Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/ERR_error_string.pod b/doc/man3/ERR_error_string.pod index 42b192178a0a..31a069887806 100644 --- a/doc/man3/ERR_error_string.pod +++ b/doc/man3/ERR_error_string.pod @@ -32,7 +32,7 @@ of the buffer; use ERR_error_string_n() instead. ERR_error_string_n() is a variant of ERR_error_string() that writes at most I characters (including the terminating 0) and truncates the string if necessary. -For ERR_error_string_n(), I may not be B. +For ERR_error_string_n(), I B be NULL. The string will have the following format: diff --git a/doc/man3/ERR_load_crypto_strings.pod b/doc/man3/ERR_load_crypto_strings.pod index ef871896494c..dc3b5292b1a4 100644 --- a/doc/man3/ERR_load_crypto_strings.pod +++ b/doc/man3/ERR_load_crypto_strings.pod @@ -46,7 +46,7 @@ OPENSSL_init_crypto() and OPENSSL_init_ssl() and should not be used. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/ERR_load_strings.pod b/doc/man3/ERR_load_strings.pod index f291644bb361..55f4cb244ec9 100644 --- a/doc/man3/ERR_load_strings.pod +++ b/doc/man3/ERR_load_strings.pod @@ -48,7 +48,7 @@ L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/ERR_put_error.pod b/doc/man3/ERR_put_error.pod index 1078c31b636a..56c73c13eff7 100644 --- a/doc/man3/ERR_put_error.pod +++ b/doc/man3/ERR_put_error.pod @@ -179,7 +179,7 @@ were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/ERR_remove_state.pod b/doc/man3/ERR_remove_state.pod index f5f6ffbb49bb..2ef34c7c34c8 100644 --- a/doc/man3/ERR_remove_state.pod +++ b/doc/man3/ERR_remove_state.pod @@ -41,7 +41,7 @@ and should not be used. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/ERR_set_mark.pod b/doc/man3/ERR_set_mark.pod index e61d5c61edd4..a067d6db7004 100644 --- a/doc/man3/ERR_set_mark.pod +++ b/doc/man3/ERR_set_mark.pod @@ -2,8 +2,8 @@ =head1 NAME -ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark -- set mark, clear mark and pop errors until mark +ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark, ERR_count_to_mark, ERR_pop - +set mark, clear mark, pop errors until mark and pop last error =head1 SYNOPSIS @@ -12,6 +12,8 @@ ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark int ERR_set_mark(void); int ERR_pop_to_mark(void); int ERR_clear_last_mark(void); + int ERR_count_to_mark(void); + int ERR_pop(void); =head1 DESCRIPTION @@ -23,6 +25,13 @@ The mark is then removed. If there is no mark, the whole stack is removed. ERR_clear_last_mark() removes the last mark added if there is one. +ERR_count_to_mark() returns the number of entries on the error stack above the +most recently marked entry, not including that entry. If there is no mark in the +error stack, the number of entries in the error stack is returned. + +ERR_pop() unconditionally pops a single error entry from the top of the error +stack (which is the entry obtainable via L). + =head1 RETURN VALUES ERR_set_mark() returns 0 if the error stack is empty, otherwise 1. @@ -30,9 +39,19 @@ ERR_set_mark() returns 0 if the error stack is empty, otherwise 1. ERR_clear_last_mark() and ERR_pop_to_mark() return 0 if there was no mark in the error stack, which implies that the stack became empty, otherwise 1. +ERR_count_to_mark() returns the number of error stack entries found above the +most recent mark, if any, or the total number of error stack entries. + +ERR_pop() returns 1 if an error was popped or 0 if the error stack was empty. + +=head1 HISTORY + +ERR_count_to_mark() was added in OpenSSL 3.2. +ERR_pop() was added in OpenSSL 3.3. + =head1 COPYRIGHT -Copyright 2003-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2003-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index de30191b61ac..ddad2f8f8831 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -4,26 +4,28 @@ EVP_MD_fetch, EVP_MD_up_ref, EVP_MD_free, EVP_MD_get_params, EVP_MD_gettable_params, -EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_copy, -EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, +EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_dup, +EVP_MD_CTX_copy, EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, EVP_MD_CTX_set_params, EVP_MD_CTX_get_params, EVP_MD_settable_ctx_params, EVP_MD_gettable_ctx_params, EVP_MD_CTX_settable_params, EVP_MD_CTX_gettable_params, EVP_MD_CTX_set_flags, EVP_MD_CTX_clear_flags, EVP_MD_CTX_test_flags, EVP_Q_digest, EVP_Digest, EVP_DigestInit_ex2, EVP_DigestInit_ex, EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal, +EVP_DigestSqueeze, EVP_MD_is_a, EVP_MD_get0_name, EVP_MD_get0_description, EVP_MD_names_do_all, EVP_MD_get0_provider, EVP_MD_get_type, EVP_MD_get_pkey_type, EVP_MD_get_size, EVP_MD_get_block_size, EVP_MD_get_flags, EVP_MD_CTX_get0_name, EVP_MD_CTX_md, EVP_MD_CTX_get0_md, EVP_MD_CTX_get1_md, -EVP_MD_CTX_get_type, EVP_MD_CTX_get_size, EVP_MD_CTX_get_block_size, +EVP_MD_CTX_get_type, EVP_MD_CTX_get_size_ex, EVP_MD_CTX_get_block_size, EVP_MD_CTX_get0_md_data, EVP_MD_CTX_update_fn, EVP_MD_CTX_set_update_fn, EVP_md_null, EVP_get_digestbyname, EVP_get_digestbynid, EVP_get_digestbyobj, EVP_MD_CTX_get_pkey_ctx, EVP_MD_CTX_set_pkey_ctx, EVP_MD_do_all_provided, EVP_MD_type, EVP_MD_nid, EVP_MD_name, EVP_MD_pkey_type, EVP_MD_size, -EVP_MD_block_size, EVP_MD_flags, EVP_MD_CTX_size, EVP_MD_CTX_block_size, +EVP_MD_block_size, EVP_MD_flags, EVP_MD_xof, +EVP_MD_CTX_size, EVP_MD_CTX_get_size, EVP_MD_CTX_block_size, EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data - EVP digest routines @@ -61,8 +63,10 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); - int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); + int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); + int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); + EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in); int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); @@ -82,11 +86,12 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data int EVP_MD_get_size(const EVP_MD *md); int EVP_MD_get_block_size(const EVP_MD *md); unsigned long EVP_MD_get_flags(const EVP_MD *md); + int EVP_MD_xof(const EVP_MD *md); const EVP_MD *EVP_MD_CTX_get0_md(const EVP_MD_CTX *ctx); EVP_MD *EVP_MD_CTX_get1_md(EVP_MD_CTX *ctx); const char *EVP_MD_CTX_get0_name(const EVP_MD_CTX *ctx); - int EVP_MD_CTX_get_size(const EVP_MD_CTX *ctx); + int EVP_MD_CTX_get_size_ex(const EVP_MD_CTX *ctx); int EVP_MD_CTX_get_block_size(const EVP_MD_CTX *ctx); int EVP_MD_CTX_get_type(const EVP_MD_CTX *ctx); void *EVP_MD_CTX_get0_md_data(const EVP_MD_CTX *ctx); @@ -111,7 +116,8 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data #define EVP_MD_size EVP_MD_get_size #define EVP_MD_block_size EVP_MD_get_block_size #define EVP_MD_flags EVP_MD_get_flags - #define EVP_MD_CTX_size EVP_MD_CTX_get_size + #define EVP_MD_CTX_get_size EVP_MD_CTX_get_size_ex + #define EVP_MD_CTX_size EVP_MD_CTX_get_size_ex #define EVP_MD_CTX_block_size EVP_MD_CTX_get_block_size #define EVP_MD_CTX_type EVP_MD_CTX_get_type #define EVP_MD_CTX_pkey_ctx EVP_MD_CTX_get_pkey_ctx @@ -132,11 +138,20 @@ see L: =head1 DESCRIPTION -The EVP digest routines are a high-level interface to message digests, -and should be used instead of the digest-specific functions. +The EVP digest routines are a high-level interface to message digests, and +Extendable Output Functions (XOF). The B type is a structure for digest method implementation. +Each Message digest algorithm (such as SHA256) produces a fixed size output +length which is returned when EVP_DigestFinal_ex() is called. +Extendable Output Functions (XOF) such as SHAKE256 have a variable sized output +length I which can be used with either EVP_DigestFinalXOF() or +EVP_DigestSqueeze(). EVP_DigestFinal_ex() may also be used for an XOF, but the +"xoflen" must be set beforehand (See L). +Note that EVP_MD_get_size() and EVP_MD_CTX_get_size_ex() behave differently for +an XOF. + =over 4 =item EVP_MD_fetch() @@ -251,7 +266,7 @@ If I is NULL the default implementation of digest I is used. Sets up digest context I to use a digest I. I is typically supplied by a function such as EVP_sha1(), or a -value explicitly fetched with EVP_MD_fetch(). +value explicitly fetched with EVP_MD_fetch(). I B be NULL. The parameters B are set on the context after initialisation. @@ -283,16 +298,31 @@ data. Retrieves the digest value from I and places it in I. If the I parameter is not NULL then the number of bytes of data written (i.e. the length of the digest) will be written to the integer at I, at most -B bytes will be written. After calling EVP_DigestFinal_ex() -no additional calls to EVP_DigestUpdate() can be made, but -EVP_DigestInit_ex2() can be called to initialize a new digest operation. +B bytes will be written unless the digest implementation +allows changing the digest size and it is set to a larger value by the +application. After calling EVP_DigestFinal_ex() no additional calls to +EVP_DigestUpdate() can be made, but EVP_DigestInit_ex2() can be called to +initialize a new digest operation. I B be NULL. =item EVP_DigestFinalXOF() Interfaces to extendable-output functions, XOFs, such as SHAKE128 and SHAKE256. -It retrieves the digest value from I and places it in I-sized I. +It retrieves the digest value from I and places it in I-sized I. After calling this function no additional calls to EVP_DigestUpdate() can be made, but EVP_DigestInit_ex2() can be called to initialize a new operation. +EVP_DigestFinalXOF() may only be called once + +=item EVP_DigestSqueeze() + +Similar to EVP_DigestFinalXOF() but allows multiple calls to be made to +squeeze variable length output data. +EVP_DigestFinalXOF() should not be called after this. + +=item EVP_MD_CTX_dup() + +Can be used to duplicate the message digest state from I. This is useful +to avoid multiple EVP_MD_fetch() calls or if large amounts of data are to be +hashed which only differ in the last few bytes. =item EVP_MD_CTX_copy_ex() @@ -326,6 +356,12 @@ EVP_sha256() rather than the result of an EVP_MD_fetch()), only cipher names registered with the default library context (see L) will be considered. +=item EVP_MD_xof() + +Returns 1 if I is an Extendable-output Function (XOF) otherwise it returns +0. SHAKE128 and SHAKE256 are XOF functions. +It returns 0 for BLAKE2B algorithms. + =item EVP_MD_get0_name(), EVP_MD_CTX_get0_name() @@ -348,11 +384,16 @@ The description is at the discretion of the digest implementation. Returns an B pointer to the provider that implements the given B. -=item EVP_MD_get_size(), -EVP_MD_CTX_get_size() +=item EVP_MD_get_size() -Return the size of the message digest when passed an B or an -B structure, i.e. the size of the hash. +Return the size of the message digest when passed an B, i.e. the size of +the hash. A negative value or 0 can occur for invalid size. +For an XOF with no default size this returns 0. + +=item EVP_MD_CTX_get_size_ex(), EVP_MD_CTX_get_size() + +For a normal digest this is the same as EVP_MD_get_size(). +For an XOF this returns the "xoflen" if it has been set, otherwise it returns 0. =item EVP_MD_get_block_size(), EVP_MD_CTX_get_block_size() @@ -464,15 +505,30 @@ I as argument. See L for information about passing parameters. -EVP_MD_CTX_set_params() can be used with the following OSSL_PARAM keys: +EVP_MD_CTX_set_params() and EVP_MD_CTX_get_params() can be used with the +following OSSL_PARAM keys: =over 4 =item "xoflen" (B) -Sets the digest length for extendable output functions. -It is used by the SHAKE algorithm and should not exceed what can be given -using a B. +Sets or gets the digest length for extendable output functions. +The value should not exceed what can be given using a B. +It may be used by SHAKE-128 and SHAKE-256 to set the +output length used by EVP_DigestFinal_ex() and EVP_DigestFinal(). + +=item "size" (B) + +Sets or gets a fixed digest length. +The value should not exceed what can be given using a B. +It may be used by BLAKE2B-512 to set the output length used by +EVP_DigestFinal_ex() and EVP_DigestFinal(). + +=back + +EVP_MD_CTX_set_params() can be used with the following OSSL_PARAM keys: + +=over 4 =item "pad-type" (B) @@ -513,7 +569,7 @@ an L item with the key "micalg" (B). This control sets the digest length for extendable output functions to I. Sending this control directly should not be necessary, the use of EVP_DigestFinalXOF() is preferred. -Currently used by SHAKE. +Currently used by SHAKE algorithms. When used with a fetched B, EVP_MD_CTX_get_params() gets called with an L item with the key "xoflen" (B). @@ -596,6 +652,10 @@ EVP_MD_CTX_gettable_params() Return an array of constant Ls, or NULL if there is none to get. +=item EVP_MD_CTX_dup() + +Returns a new EVP_MD_CTX if successful or NULL on failure. + =item EVP_MD_CTX_copy_ex() Returns 1 if successful or 0 for failure. @@ -701,6 +761,10 @@ digest name passed on the command line. } mdctx = EVP_MD_CTX_new(); + if (mdctx == NULL) { + printf("Message digest create failed.\n"); + exit(1); + } if (!EVP_DigestInit_ex2(mdctx, md, NULL)) { printf("Message digest initialization failed.\n"); EVP_MD_CTX_free(mdctx); @@ -788,6 +852,16 @@ EVP_MD_CTX_get0_md() instead. EVP_MD_CTX_update_fn() and EVP_MD_CTX_set_update_fn() were deprecated in OpenSSL 3.0. +The EVP_MD_CTX_dup() function was added in OpenSSL 3.1. + +The EVP_DigestSqueeze() function was added in OpenSSL 3.3. + +The EVP_MD_CTX_get_size_ex() and EVP_xof() functions were added in OpenSSL 3.4. +The macros EVP_MD_CTX_get_size() and EVP_MD_CTX_size were changed in OpenSSL 3.4 +to be aliases for EVP_MD_CTX_get_size_ex(), previously they were aliases for +EVP_MD_get_size which returned a constant value. This is required for XOF +digests since they do not have a fixed size. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/EVP_DigestSignInit.pod b/doc/man3/EVP_DigestSignInit.pod index 7232e9786026..68baac639f22 100644 --- a/doc/man3/EVP_DigestSignInit.pod +++ b/doc/man3/EVP_DigestSignInit.pod @@ -18,7 +18,7 @@ EVP_DigestSignFinal, EVP_DigestSign - EVP signing functions int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen); - int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, + int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); @@ -118,7 +118,7 @@ be used for the signing and digest algorithm implementations. I may be NULL. EVP_DigestSignUpdate() hashes I bytes of data at I into the signature context I. This function can be called several times on the -same I to include additional data. +same I to include additional data. I B be NULL. Unless I is NULL EVP_DigestSignFinal() signs the data in I and places the signature in I. @@ -128,13 +128,12 @@ I parameter should contain the length of the I buffer. If the call is successful the signature is written to I and the amount of data written to I. -EVP_DigestSign() signs I bytes of data at I and places the -signature in I and its length in I in a similar way to -EVP_DigestSignFinal(). In the event of a failure EVP_DigestSign() cannot be -called again without reinitialising the EVP_MD_CTX. If I is NULL before the -call then I will be populated with the required size for the I -buffer. If I is non-NULL before the call then I should contain the -length of the I buffer. +EVP_DigestSign() is similar to a single call to EVP_DigestSignUpdate() and +EVP_DigestSignFinal(). +Unless I is NULL, EVP_DigestSign() signs the data I of length I +bytes and places the signature in a buffer I of size I. +If I is NULL, the maximum necessary size of the signature buffer is written +to the I parameter. =head1 RETURN VALUES @@ -166,12 +165,23 @@ external circumstances (see L), the operation will fail. The call to EVP_DigestSignFinal() internally finalizes a copy of the digest context. This means that calls to EVP_DigestSignUpdate() and EVP_DigestSignFinal() can be called later to digest and sign additional data. +Applications may disable this behavior by setting the EVP_MD_CTX_FLAG_FINALISE +context flag via L. + +Note that not all providers support continuation, in case the selected +provider does not allow to duplicate contexts EVP_DigestSignFinal() will +finalize the digest context and attempting to process additional data via +EVP_DigestSignUpdate() will result in an error. EVP_DigestSignInit() and EVP_DigestSignInit_ex() functions can be called multiple times on a context and the parameters set by previous calls should be preserved if the I parameter is NULL. The call then just resets the state of the I. +EVP_DigestSign() can not be called again, once a signature is generated (by +passing I as non NULL), unless the B is reinitialised by +calling EVP_DigestSignInit_ex(). + Ignoring failure returns of EVP_DigestSignInit() and EVP_DigestSignInit_ex() functions can lead to subsequent undefined behavior when calling EVP_DigestSignUpdate(), EVP_DigestSignFinal(), or EVP_DigestSign(). @@ -201,7 +211,7 @@ EVP_DigestSignUpdate() was converted from a macro to a function in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod index 55826fe16bd5..dc694308f975 100644 --- a/doc/man3/EVP_DigestVerifyInit.pod +++ b/doc/man3/EVP_DigestVerifyInit.pod @@ -18,7 +18,7 @@ EVP_DigestVerifyFinal, EVP_DigestVerify - EVP signature verification functions int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen); - int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); =head1 DESCRIPTION @@ -154,13 +154,23 @@ external circumstances (see L), the operation will fail. The call to EVP_DigestVerifyFinal() internally finalizes a copy of the digest context. This means that EVP_VerifyUpdate() and EVP_VerifyFinal() can -be called later to digest and verify additional data. +be called later to digest and verify additional data. Applications may disable +this behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via +L. + +Note that not all providers support continuation, in case the selected +provider does not allow to duplicate contexts EVP_DigestVerifyFinal() will +finalize the digest context and attempting to process additional data via +EVP_DigestVerifyUpdate() will result in an error. EVP_DigestVerifyInit() and EVP_DigestVerifyInit_ex() functions can be called multiple times on a context and the parameters set by previous calls should be preserved if the I parameter is NULL. The call then just resets the state of the I. +EVP_DigestVerify() can only be called once, and cannot be used again without +reinitialising the B by calling EVP_DigestVerifyInit_ex(). + Ignoring failure returns of EVP_DigestVerifyInit() and EVP_DigestVerifyInit_ex() functions can lead to subsequent undefined behavior when calling EVP_DigestVerifyUpdate(), EVP_DigestVerifyFinal(), or EVP_DigestVerify(). @@ -186,7 +196,7 @@ EVP_DigestVerifyUpdate() was converted from a macro to a function in OpenSSL =head1 COPYRIGHT -Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_EncodeInit.pod b/doc/man3/EVP_EncodeInit.pod index 03c6f4e60579..ab6b07bcdba8 100644 --- a/doc/man3/EVP_EncodeInit.pod +++ b/doc/man3/EVP_EncodeInit.pod @@ -5,7 +5,7 @@ EVP_ENCODE_CTX_new, EVP_ENCODE_CTX_free, EVP_ENCODE_CTX_copy, EVP_ENCODE_CTX_num, EVP_EncodeInit, EVP_EncodeUpdate, EVP_EncodeFinal, EVP_EncodeBlock, EVP_DecodeInit, EVP_DecodeUpdate, EVP_DecodeFinal, -EVP_DecodeBlock - EVP base 64 encode/decode routines +EVP_DecodeBlock - EVP base64 encode/decode routines =head1 SYNOPSIS @@ -29,10 +29,11 @@ EVP_DecodeBlock - EVP base 64 encode/decode routines =head1 DESCRIPTION -The EVP encode routines provide a high-level interface to base 64 encoding and -decoding. Base 64 encoding converts binary data into a printable form that uses +The EVP encode routines provide a high-level interface to base64 encoding and +decoding. +Base64 encoding converts binary data into a printable form that uses the characters A-Z, a-z, 0-9, "+" and "/" to represent the data. For every 3 -bytes of binary data provided 4 bytes of base 64 encoded data will be produced +bytes of binary data provided 4 bytes of base64 encoded data will be produced plus some occasional newlines (see below). If the input data length is not a multiple of 3 then the output data will be padded at the end using the "=" character. @@ -44,7 +45,8 @@ EVP_ENCODE_CTX_free() cleans up an encode/decode context B and frees up the space allocated to it. If the argument is NULL, nothing is done. Encoding of binary data is performed in blocks of 48 input bytes (or less for -the final block). For each 48 byte input block encoded 64 bytes of base 64 data +the final block). +For each 48 byte input block encoded 64 bytes of base64 data is output plus an additional newline character (i.e. 65 bytes in total). The final block (which may be less than 48 bytes) will output 4 bytes for every 3 bytes of input. If the data length is not divisible by 3 then a full 4 bytes is @@ -93,37 +95,62 @@ the data generated I the NUL terminator is returned from the function. EVP_DecodeInit() initialises B for the start of a new decoding operation. -EVP_DecodeUpdate() decodes B characters of data found in the buffer pointed -to by B. The output is stored in the buffer B and the number of bytes -output is stored in B<*outl>. It is the caller's responsibility to ensure that -the buffer at B is sufficiently large to accommodate the output data. This -function will attempt to decode as much data as possible in 4 byte chunks. Any -whitespace, newline or carriage return characters are ignored. Any partial chunk -of unprocessed data (1, 2 or 3 bytes) that remains at the end will be held in -the B object and processed by a subsequent call to EVP_DecodeUpdate(). If -any illegal base 64 characters are encountered or if the base 64 padding -character "=" is encountered in the middle of the data then the function returns --1 to indicate an error. A return value of 0 or 1 indicates successful -processing of the data. A return value of 0 additionally indicates that the last -input data characters processed included the base 64 padding character "=" and -therefore no more non-padding character data is expected to be processed. For -every 4 valid base 64 bytes processed (ignoring whitespace, carriage returns and -line feeds), 3 bytes of binary output data will be produced (or less at the end -of the data where the padding character "=" has been used). +EVP_DecodeUpdate() decodes B characters of data found in the buffer +pointed to by B. +The output is stored in the buffer B and the number of bytes output is +stored in B<*outl>. +It is the caller's responsibility to ensure that the buffer at B is +sufficiently large to accommodate the output data. +This function will attempt to decode as much data as possible in chunks of up +to 80 base64 characters at a time. +Residual input shorter than the internal chunk size will be buffered in B +if its length is not a multiple of 4 (including any padding), to be processed +in future calls to EVP_DecodeUpdate() or EVP_DecodeFinal(). +If the final chunk length is a multiple of 4, it is decoded immediately and +not buffered. -EVP_DecodeFinal() must be called at the end of a decoding operation. If there -is any unprocessed data still in B then the input data must not have been -a multiple of 4 and therefore an error has occurred. The function will return -1 -in this case. Otherwise the function returns 1 on success. +Any whitespace, newline or carriage return characters are ignored. +For compatibility with B, the B<-> (hyphen) character is treated as a soft +end-of-input, subsequent bytes are not buffered, and the return value will be +0 to indicate that the end of the base64 input has been detected. +The soft end-of-input, if present, MUST occur after a multiple of 4 valid base64 +input bytes. +The soft end-of-input condition is not remembered in B, it is up to the +caller to avoid further calls to EVP_DecodeUpdate() after a 0 or negative +(error) return. -EVP_DecodeBlock() will decode the block of B characters of base 64 data -contained in B and store the result in B. Any leading whitespace will be -trimmed as will any trailing whitespace, newlines, carriage returns or EOF -characters. After such trimming the length of the data in B must be divisible -by 4. For every 4 input bytes exactly 3 output bytes will be produced. The -output will be padded with 0 bits if necessary to ensure that the output is -always 3 bytes for every 4 input bytes. This function will return the length of -the data decoded or -1 on error. +If any invalid base64 characters are encountered or if the base64 padding +character (B<=>) is encountered in the middle of the data then +EVP_DecodeUpdate() returns -1 to indicate an error. +A return value of 0 or 1 indicates successful processing of the data. +A return value of 0 additionally indicates that the last 4 bytes processed +ended with base64 padding (B<=>), or that the next 4 byte group starts with the +soft end-of-input (B<->) character, and therefore no more input data is +expected to be processed. + +For every 4 valid base64 bytes processed (ignoring whitespace, carriage returns +and line feeds), 3 bytes of binary output data will be produced (except at the +end of data terminated with one or two padding characters). + +EVP_DecodeFinal() should be called at the end of a decoding operation, +but it will never decode additional data. If there is no residual data +it will return 1 to indicate success. If there is residual data, its +length is not a multiple of 4, i.e. it was not properly padded, -1 is +is returned in that case to indicate an error. + +EVP_DecodeBlock() will decode the block of B characters of base64 data +contained in B and store the result in B. +Any leading whitespace will be trimmed as will any trailing whitespace, +newlines, carriage returns or EOF characters. +Internal whitespace MUST NOT be present. +After trimming the data in B MUST consist entirely of valid base64 +characters or padding (only at the tail of the input) and its length MUST be +divisible by 4. +For every 4 input bytes exactly 3 output bytes will be produced. +Padding bytes (B<=>) (even if internal) are decoded to 6 zero bits, the caller +is responsible for taking trailing padding into account, by ignoring as many +bytes at the tail of the returned output. +EVP_DecodeBlock() will return the length of the data decoded or -1 on error. =head1 RETURN VALUES @@ -139,7 +166,7 @@ EVP_EncodeBlock() returns the number of bytes encoded excluding the NUL terminator. EVP_DecodeUpdate() returns -1 on error and 0 or 1 on success. If 0 is returned -then no more non-padding base 64 characters are expected. +then no more non-padding base64 characters are expected. EVP_DecodeFinal() returns -1 on error or 1 on success. @@ -149,9 +176,15 @@ EVP_DecodeBlock() returns the length of the data decoded or -1 on error. L +=head1 HISTORY + +The EVP_DecodeUpdate() function was fixed in OpenSSL 3.5, +so now it produces the number of bytes specified in B +and does not decode padding bytes (B<=>) to 6 zero bits. + =head1 COPYRIGHT -Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod index a4635f994c2f..2c42e3969e03 100644 --- a/doc/man3/EVP_EncryptInit.pod +++ b/doc/man3/EVP_EncryptInit.pod @@ -8,6 +8,8 @@ EVP_CIPHER_free, EVP_CIPHER_CTX_new, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX_free, +EVP_CIPHER_CTX_dup, +EVP_CIPHER_CTX_copy, EVP_EncryptInit_ex, EVP_EncryptInit_ex2, EVP_EncryptUpdate, @@ -18,6 +20,7 @@ EVP_DecryptUpdate, EVP_DecryptFinal_ex, EVP_CipherInit_ex, EVP_CipherInit_ex2, +EVP_CipherInit_SKEY, EVP_CipherUpdate, EVP_CipherFinal_ex, EVP_CIPHER_CTX_set_key_length, @@ -29,6 +32,11 @@ EVP_DecryptFinal, EVP_CipherInit, EVP_CipherFinal, EVP_Cipher, +EVP_CIPHER_can_pipeline, +EVP_CipherPipelineEncryptInit, +EVP_CipherPipelineDecryptInit, +EVP_CipherPipelineUpdate, +EVP_CipherPipelineFinal, EVP_get_cipherbyname, EVP_get_cipherbynid, EVP_get_cipherbyobj, @@ -109,6 +117,8 @@ EVP_CIPHER_CTX_mode 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); + EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in); + int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv); @@ -133,6 +143,9 @@ EVP_CIPHER_CTX_mode 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_CipherInit_SKEY(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + EVP_SKEY *skey, const unsigned char *iv, size_t iv_len, + 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); @@ -152,6 +165,25 @@ EVP_CIPHER_CTX_mode int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl); + int EVP_CIPHER_can_pipeline(const EVP_CIPHER *cipher, int enc); + int EVP_CipherPipelineEncryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + size_t numpipes, + const unsigned char **iv, size_t ivlen); + int EVP_CipherPipelineDecryptInit(EVP_CIPHER_CTX *ctx, + const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, + size_t numpipes, + const unsigned char **iv, size_t ivlen); + int EVP_CipherPipelineUpdate(EVP_CIPHER_CTX *ctx, + unsigned char **out, size_t *outl, + const size_t *outsize, + const unsigned char **in, const size_t *inl); + int EVP_CipherPipelineFinal(EVP_CIPHER_CTX *ctx, + unsigned char **outm, size_t *outl, + const size_t *outsize); + 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); @@ -281,6 +313,16 @@ associated with it, including I itself. This function should be called after all operations using a cipher are complete so sensitive information does not remain in memory. If the argument is NULL, nothing is done. +=item EVP_CIPHER_CTX_dup() + +Can be used to duplicate the cipher state from I. This is useful +to avoid multiple EVP_CIPHER_fetch() calls or if large amounts of data are to be +fed which only differ in the last few bytes. + +=item EVP_CIPHER_CTX_copy() + +Can be used to copy the cipher state from I to I. + =item EVP_CIPHER_CTX_ctrl() I EVP_CIPHER_CTX_set_params() and @@ -338,8 +380,8 @@ can be set in the context's current state. =item EVP_EncryptInit_ex2() -Sets up cipher context I for encryption with cipher I. I is -typically supplied by calling EVP_CIPHER_fetch(). I may also be set +Sets up cipher context I for encryption with cipher I. I B be NULL. +I is typically supplied by calling EVP_CIPHER_fetch(). I may also be set using legacy functions such as EVP_aes_256_cbc(), but this is not recommended for new applications. I is the symmetric key to use and I is the IV to use (if necessary), the actual number of bytes used for the key and IV depends @@ -364,7 +406,7 @@ I. The pointers I and I may point to the same location, in which case the encryption will be done in-place. However, in-place encryption is guaranteed to work only if the encryption context (I) has processed data in multiples of the block size. If the context contains an incomplete data block -from previous operations, in-place encryption will fail. +from previous operations, in-place encryption will fail. I B be NULL. If I and I point to different locations, the two buffers must be disjoint, otherwise the operation might fail or the outcome might be undefined. @@ -401,10 +443,7 @@ 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 passed to EVP_DecryptUpdate() should have -sufficient room for (I + cipher_block_size) bytes unless the cipher block -size is 1 in which case I bytes is sufficient. +identical to the encryption operations. I B be NULL. =item EVP_CipherInit_ex2(), EVP_CipherInit_ex(), EVP_CipherUpdate() and EVP_CipherFinal_ex() @@ -414,6 +453,11 @@ performed depends on the value of the I 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_CipherInit_SKEY() + +This function is similar to EVP_CipherInit_ex2() but accepts a +symmetric key object of type I as a key. + =item EVP_CIPHER_CTX_reset() Clears all information from a cipher context and free up any allocated memory @@ -448,6 +492,51 @@ 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_CIPHER_can_pipeline() + +This function checks if a B fetched using EVP_CIPHER_fetch() supports +cipher pipelining. If the cipher supports pipelining, it returns 1, otherwise 0. +This function will return 0 for non-fetched ciphers such as EVP_aes_128_gcm(). +There are currently no built-in ciphers that support pipelining. + +Cipher pipelining support allows an application to submit multiple chunks of +data in one set of EVP_CipherUpdate()/EVP_CipherFinal calls, thereby allowing +the provided implementation to take advantage of parallel computing. This is +beneficial for hardware accelerators as pipeline amortizes the latency over +multiple chunks. + +For non-fetched ciphers, EVP_CipherPipelineEncryptInit() or +EVP_CipherPipelineDecryptInit() may be directly called, which will perform a +fetch and return an error if a pipeline supported implementation is not found. + +=item EVP_CipherPipelineEncryptInit(), EVP_CipherPipelineDecryptInit(), EVP_CipherPipelineUpdate() and EVP_CipherPipelineFinal() + +These functions can be used to perform multiple encryption or decryption +operations in parallel. EVP_CIPHER_can_pipeline() may be called to check if the +cipher supports pipelining. These functions are analogous to +EVP_EncryptInit_ex2(), EVP_DecryptInit_ex2(), EVP_CipherUpdate() and +EVP_CipherFinal() but take an array of pointers for iv, input and output buffers. + +The I, of length I, is the symmetric key to use. The I +parameter specifies the number of parallel operations to perform. The +I cannot exceed B. The I parameter is an array of +buffer pointers, containing IVs. The array size must be equal to I. +The size of each IV buffer must be equal to I. When IV is not provided, +I must be NULL, rather than an array of NULL pointers. The I +parameters takes an array of buffer pointers, each pointing to a buffer +containing the input data. The buffers can be of different sizes. The I +parameter is an array of size_t, each specifying the size of the corresponding +input buffer. The I and I parameters are arrays of buffer pointers, +each pointing to a buffer where the output data will be written. The I +parameter is an array of size_t, each specifying the size of the corresponding +output buffer. The I parameter is an array of size_t which will be updated +with the size of the output data written to the corresponding output buffer. +For size requirement of the output buffers, see the description of EVP_CipherUpdate(). + +The EVP_CipherPipelineUpdate() function can be called multiple times to encrypt +successive blocks of data. For AAD data, the I, and I parameter +should be NULL, rather than an array of NULL pointers. + =item EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj() Returns an B structure when passed a cipher name, a cipher B or @@ -479,7 +568,9 @@ EVP_CIPHER_free(). Return the NID of a cipher when passed an B or B structure. The actual NID value is an internal value which may not have a -corresponding OBJECT IDENTIFIER. +corresponding OBJECT IDENTIFIER. NID_undef is returned in the event that the +nid is unknown or if the cipher has not been properly initialized via a call to +B. =item EVP_CIPHER_CTX_set_flags(), EVP_CIPHER_CTX_clear_flags() and EVP_CIPHER_CTX_test_flags() @@ -493,11 +584,12 @@ L instead. 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 parameter is zero then no padding is -performed, the total amount of data encrypted or decrypted must then -be a multiple of the block size or an error will occur. +EVP_DecryptInit_ex2(), EVP_CipherInit_ex2(), or EVP_CipherInit_SKEY(). By +default encryption operations are padded using standard block padding and the +padding is checked and removed when decrypting. If the I 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. I B be NULL. =item EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() @@ -516,8 +608,10 @@ 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 or -B. It will return zero if the cipher does not use an IV. -The constant B is the maximum IV length for all ciphers. +B. It will return zero if the cipher does not use an IV, if +the cipher has not yet been initialized within the B, or if the +passed cipher is NULL. The constant B is the maximum IV +length for all ciphers. =item EVP_CIPHER_CTX_get_tag_length() @@ -530,6 +624,10 @@ the tag length has not been set. Return the block size of a cipher when passed an B or B structure. The constant B is also the maximum block length for all ciphers. +A value of 0 is returned if, with B, the cipher +I is NULL, or, with B, the context +I is NULL or has not been properly initialized with a call to +B. =item EVP_CIPHER_get_type() and EVP_CIPHER_CTX_get_type() @@ -551,6 +649,7 @@ context (see L) will be considered. 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(). +I B be NULL. =item EVP_CIPHER_names_do_all() @@ -571,7 +670,7 @@ B. Returns the B structure when passed an B structure. EVP_CIPHER_CTX_get1_cipher() is the same except the ownership is passed to -the caller. +the caller. Both functions return NULL on error. =item EVP_CIPHER_get_mode() and EVP_CIPHER_CTX_get_mode() @@ -607,7 +706,8 @@ 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. +This function may fail if the cipher does not have any ASN1 support, or if an +uninitialized cipher is passed to it. =item EVP_CIPHER_asn1_to_param() @@ -713,6 +813,12 @@ Gets 1 if the cipher algorithm I supports the gettable EVP_CIPHER_CTX parameter B. Only DES and 3DES set this to 1, all other OpenSSL ciphers return 0. +=item "decrypt-only" (B + +Gets 1 if the cipher algorithm I implementation supports only +the decryption operation such as the 3DES ciphers in the fips provider. +Otherwise gets 0 or the parameter might not be present at all. + =back =head2 Gettable and Settable EVP_CIPHER_CTX parameters @@ -746,6 +852,13 @@ See also EVP_CIPHER_CTX_get_key_length() and EVP_CIPHER_CTX_set_key_length(). Gets or sets the AEAD tag for the associated cipher context I. See L. +=item "pipeline-tag" (B) + +Gets or sets the AEAD tag when using cipher pipelining. The pointer must +point to an array of buffers, where the aead tag will be read from or written to. +The array size must be equal to I used in +EVP_CipherPipelineEncryptInit() or EVP_CipherPipelineDecryptInit(). + =item "keybits" (B) Gets or sets the effective keybits used for a RC2 cipher. @@ -756,12 +869,23 @@ The length of the "keybits" parameter should not exceed that of a B. 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) +=item "algorithm-id" (B) + +Used to get the DER encoded AlgorithmIdentifier from the cipher +implementation. Functions like L use this +parameter. + +=item "algorithm-id-params" (B) Used to pass the DER encoded AlgorithmIdentifier parameter to or from -the cipher implementation. Functions like L -and L use this parameter for any implementation -that has the flag B set. +the cipher implementation. +Functions like L and +L use this parameter. + +=item "alg_id_params" (B) + +An deprecated alias for "algorithm-id-params", only used by +L and L. =item "cts_mode" (B) @@ -873,6 +997,24 @@ Gets the result of running the "tls1multi_aad" operation. Used to pass the TLS MAC data. +=item "fips-indicator" (B) + +This option is used by the OpenSSL FIPS provider. + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling a cipher final operation such as +EVP_EncryptFinal_ex(). It may return 0 if the "encrypt-check" option is set to 0. + +=item "iv-generated" (B) + +An indicator that returns 1 if an IV was generated internally during encryption, +or O otherwise. +This may be used by GCM ciphers after calling a cipher final operation such +as EVP_EncryptFinal_ex(). +GCM should generate an IV internally if the IV is not specified during a +cipher initialisation call such as EVP_CipherInit_ex(). +See FIPS 140-3 IG C.H for information related to IV requirements. + =back =head2 Settable EVP_CIPHER_CTX parameters @@ -985,6 +1127,52 @@ Byte 11-12: Input length (Always 0) "tls1multi_interleave" must also be set for this operation. +=item "xts_standard" (B) + +Sets the XTS standard to use with SM4-XTS algorithm. XTS mode has two +implementations, one is standardized in IEEE Std. 1619-2007 and has +been widely used (e.g., XTS AES), the other is proposed recently +(GB/T 17964-2021 implemented in May 2022) and is currently only used +in SM4. + +The main difference between them is the multiplication by the +primitive element E to calculate the tweak values. The IEEE +Std 1619-2007 noted that the multiplication "is a left shift of each +byte by one bit with carry propagating from one byte to the next +one", which means that in each byte, the leftmost bit is the most +significant bit. But in GB/T 17964-2021, the rightmost bit is the +most significant bit, thus the multiplication becomes a right shift +of each byte by one bit with carry propagating from one byte to the +next one. + +Valid values for the mode are: + +=over 4 + +=item "GB" + +The GB/T 17964-2021 variant of SM4-XTS algorithm. + +=item "IEEE" + +The IEEE Std. 1619-2007 variant of SM4-XTS algorithm. + +=back + +The default value is "GB". + +=item "encrypt-check" (B) + +This option is used by the OpenSSL FIPS provider. + +If required this parameter should be set early via an cipher encrypt init +function such as EVP_EncryptInit_ex2(). +The default value of 1 causes an error when an encryption operation is triggered. +Setting this to 0 will ignore the error and set the approved "fips-indicator" to +0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + =back =head1 CONTROLS @@ -1185,12 +1373,16 @@ flags. =head1 RETURN VALUES EVP_CIPHER_fetch() returns a pointer to a B for success -and B for failure. +and 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 for success and B for failure. +B for success and NULL for failure. + +EVP_CIPHER_CTX_dup() returns a new EVP_CIPHER_CTX if successful or NULL on failure. + +EVP_CIPHER_CTX_copy() returns 1 if successful or 0 for failure. EVP_EncryptInit_ex2(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex() return 1 for success and 0 for failure. @@ -1198,14 +1390,26 @@ 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_CipherInit_ex2(), EVP_CipherInit_SKEY() and EVP_CipherUpdate() return 1 for +success and 0 for failure. +EVP_CipherFinal_ex() returns 0 for an encryption/decryption failure or 1 for +success. -EVP_Cipher() returns 1 on success or 0 on failure, if the flag -B is not set for the cipher. -EVP_Cipher() returns the number of bytes written to I for encryption / decryption, or -the number of bytes authenticated in a call specifying AAD for an AEAD cipher, if the flag -B is set for the cipher. +EVP_Cipher() returns 1 on success and <= 0 on failure, if the flag +B is not set for the cipher, or if the cipher has +not been initialized via a call to B. +EVP_Cipher() returns the number of bytes written to I for +encryption/decryption, or the number of bytes authenticated in a call specifying +AAD for an AEAD cipher, if the flag B is set for +the cipher. + +EVP_CIPHER_can_pipeline() returns 1 if the cipher can be used in a pipeline, 0 otherwise. + +EVP_CipherPipelineEncryptInit() and EVP_CipherPipelineDecryptInit() +return 1 for success and 0 for failure. + +EVP_CipherPipelineUpdate() and EVP_CipherPipelineFinal() +return 1 for success and 0 for failure. EVP_CIPHER_CTX_reset() returns 1 for success and 0 for failure. @@ -1215,7 +1419,7 @@ return an B 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. +block size, or 0 on error. EVP_CIPHER_get_key_length() and EVP_CIPHER_CTX_get_key_length() return the key length. @@ -1223,7 +1427,7 @@ 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. +length, zero if the cipher does not use an IV and a negative value on error. EVP_CIPHER_CTX_get_tag_length() return the tag length or zero if the cipher does not use a tag. @@ -1276,7 +1480,7 @@ 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 set to B. In this case, on success, the parameter +parameter I set to NULL. In this case, on success, the parameter I is set to the number of bytes authenticated. When decrypting, the return value of EVP_DecryptFinal() or EVP_CipherFinal() @@ -1344,7 +1548,7 @@ few additional requirements and different I values. For CCM mode, the total plaintext or ciphertext length B be passed to EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() with the output -and input parameters (I and I) set to B and the length passed in +and input parameters (I and I) set to NULL and the length passed in the I parameter. The following Is are supported in CCM mode. @@ -1374,12 +1578,14 @@ AES. =head2 SIV Mode +Both the AES-SIV and AES-GCM-SIV ciphers fall under this 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 set to B. +with the output parameter I set to 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 @@ -1390,7 +1596,7 @@ indicates if the operation was successful. If it does not indicate success the authentication operation has failed and any output data B be used as it is corrupted. -The API does not store the the SIV (Synthetic Initialization Vector) in +The API does not store 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. @@ -1422,7 +1628,7 @@ calls). For SIV mode the taglen must be 16. 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 set to a non-B value. A call to EVP_DecryptFinal() or +with I set to a non-NULL value. A call to EVP_DecryptFinal() or EVP_CipherFinal() is not required, but will indicate if the update operation succeeded. @@ -1744,9 +1950,17 @@ non-deprecated alias macro. The EVP_CIPHER_CTX_flags() macro was deprecated in OpenSSL 1.1.0. +EVP_CIPHER_CTX_dup() was added in OpenSSL 3.2. + +EVP_CipherInit_SKEY() was added in OpenSSL 3.5. + +Prior to OpenSSL 3.5, passing a NULL I to +B would result in a NULL pointer dereference, +rather than a 0 return value indicating an error. + =head1 COPYRIGHT -Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_KDF.pod b/doc/man3/EVP_KDF.pod index 9447651a340e..1a5bbb1fcc37 100644 --- a/doc/man3/EVP_KDF.pod +++ b/doc/man3/EVP_KDF.pod @@ -283,9 +283,7 @@ EVP_KDF_get0_name() returns the name of the KDF, or NULL on error. EVP_KDF_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. -The remaining functions return 1 for success and 0 or a negative value for -failure. In particular, a return value of -2 indicates the operation is not -supported by the KDF algorithm. +The remaining functions return 1 for success and 0 for failure. =head1 NOTES diff --git a/doc/man3/EVP_KEYMGMT.pod b/doc/man3/EVP_KEYMGMT.pod index 4c0c3b776c64..eedf7b021953 100644 --- a/doc/man3/EVP_KEYMGMT.pod +++ b/doc/man3/EVP_KEYMGMT.pod @@ -14,6 +14,7 @@ EVP_KEYMGMT_do_all_provided, EVP_KEYMGMT_names_do_all, EVP_KEYMGMT_gettable_params, EVP_KEYMGMT_settable_params, +EVP_KEYMGMT_gen_gettable_params, EVP_KEYMGMT_gen_settable_params - EVP key management routines @@ -41,6 +42,7 @@ EVP_KEYMGMT_gen_settable_params const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt); const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt); const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt); + const OSSL_PARAM *EVP_KEYMGMT_gen_gettable_params(const EVP_KEYMGMT *keymgmt); =head1 DESCRIPTION @@ -93,9 +95,10 @@ constant L array that describes the names and types of key parameters that can be retrieved or set. EVP_KEYMGMT_gettable_params() is used by L. -EVP_KEYMGMT_gen_settable_params() returns a constant L array that -describes the names and types of key generation parameters that can be set via -L. +EVP_KEYMGMT_gen_gettable_params() and EVP_KEYMGMT_gen_settable_params() return a +constant L array that describes the names and types of key +generation parameters that can be retrieved or set via +L or L respectively. =head1 NOTES @@ -127,9 +130,9 @@ EVP_KEYMGMT_get0_name() returns the algorithm name, or NULL on error. EVP_KEYMGMT_get0_description() returns a pointer to a description, or NULL if there isn't one. -EVP_KEYMGMT_gettable_params(), EVP_KEYMGMT_settable_params() and -EVP_KEYMGMT_gen_settable_params() return a constant L array or -NULL on error. +EVP_KEYMGMT_gettable_params(), EVP_KEYMGMT_settable_params(), +EVP_KEYMGMT_gen_gettable_params() and EVP_KEYMGMT_gen_settable_params() +return a constant L array or NULL on error. =head1 SEE ALSO @@ -137,7 +140,8 @@ L, L =head1 HISTORY -The functions described here were added in OpenSSL 3.0. +The function EVP_KEYMGMT_gen_gettable_params() was added in OpenSSL 3.4.0 +All other functions described here were added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod index d1281dfcbd03..e766a5d234fd 100644 --- a/doc/man3/EVP_MAC.pod +++ b/doc/man3/EVP_MAC.pod @@ -8,7 +8,7 @@ EVP_MAC_get0_provider, EVP_MAC_get_params, EVP_MAC_gettable_params, EVP_MAC_CTX, EVP_MAC_CTX_new, EVP_MAC_CTX_free, EVP_MAC_CTX_dup, EVP_MAC_CTX_get0_mac, EVP_MAC_CTX_get_params, EVP_MAC_CTX_set_params, EVP_MAC_CTX_get_mac_size, EVP_MAC_CTX_get_block_size, EVP_Q_mac, -EVP_MAC_init, EVP_MAC_update, EVP_MAC_final, EVP_MAC_finalXOF, +EVP_MAC_init, EVP_MAC_init_SKEY, EVP_MAC_update, EVP_MAC_final, EVP_MAC_finalXOF, EVP_MAC_gettable_ctx_params, EVP_MAC_settable_ctx_params, EVP_MAC_CTX_gettable_params, EVP_MAC_CTX_settable_params, EVP_MAC_do_all_provided - EVP MAC routines @@ -49,6 +49,7 @@ EVP_MAC_do_all_provided - EVP MAC routines unsigned char *out, size_t outsize, size_t *outlen); int EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen, const OSSL_PARAM params[]); + int EVP_MAC_init_SKEY(EVP_MAC_CTX *ctx, EVP_SKEY *skey, const OSSL_PARAM params[]); int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen); int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *outl, size_t outsize); @@ -151,6 +152,9 @@ has been called on the same object). See the NOTES section below. EVP_MAC_init() should be called before EVP_MAC_update() and EVP_MAC_final(). +EVP_MAC_init_SKEY() is similar to EVP_MAC_init() but it accepts an opaque +B object as a key. + EVP_MAC_update() adds I bytes from I to the MAC input. EVP_MAC_final() does the final computation and stores the result in @@ -282,14 +286,16 @@ This option is used by KMAC. A simple flag to set the MAC digest to not initialise the implementation specific data. The value 0 or 1 is expected. -This option is used by HMAC. +This option is deprecated and will be removed in a future release. +The option may be set, but is ignored. =item "digest-oneshot" (B) A simple flag to set the MAC digest to be a oneshot operation. The value 0 or 1 is expected. -This option is used by HMAC. +This option is deprecated and will be removed in a future release. +The option may be set, but is ignored. =item "properties" (B) @@ -382,8 +388,8 @@ success, 0 on error. EVP_Q_mac() returns a pointer to the computed MAC value, or NULL on error. -EVP_MAC_init(), EVP_MAC_update(), EVP_MAC_final(), and EVP_MAC_finalXOF() -return 1 on success, 0 on error. +EVP_MAC_init(), EVP_MAC_init_SKEY(), EVP_MAC_update(), EVP_MAC_final(), and +EVP_MAC_finalXOF() return 1 on success, 0 on error. EVP_MAC_CTX_get_mac_size() returns the expected output size, or 0 if it isn't set. If it isn't set, a call to EVP_MAC_init() will set it. @@ -489,9 +495,11 @@ L These functions were added in OpenSSL 3.0. +The EVP_MAC_init_SKEY() function was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PBE_CipherInit.pod b/doc/man3/EVP_PBE_CipherInit.pod index c6191a945347..c3b551e602d7 100644 --- a/doc/man3/EVP_PBE_CipherInit.pod +++ b/doc/man3/EVP_PBE_CipherInit.pod @@ -101,7 +101,7 @@ EVP_PBE_CipherInit_ex() and EVP_PBE_find_ex() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY2PKCS8.pod b/doc/man3/EVP_PKEY2PKCS8.pod index 1129a5c75c4b..fda8683817d5 100644 --- a/doc/man3/EVP_PKEY2PKCS8.pod +++ b/doc/man3/EVP_PKEY2PKCS8.pod @@ -37,7 +37,7 @@ L, =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod index 3075eaafd677..d6cf9e79ad11 100644 --- a/doc/man3/EVP_PKEY_CTX_ctrl.pod +++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod @@ -270,8 +270,8 @@ EVP_PKEY_CTX_get_rsa_padding() gets the RSA padding mode for I. EVP_PKEY_CTX_set_rsa_pss_saltlen() sets the RSA PSS salt length to I. As its name implies it is only supported for PSS padding. If this function is -not called then the maximum salt length is used when signing and auto detection -when verifying. Three special values are supported: +not called then the salt length is maximized up to the digest length when +signing and auto detection when verifying. Four special values are supported: =over 4 @@ -289,6 +289,13 @@ causes the salt length to be automatically determined based on the B block structure when verifying. When signing, it has the same meaning as B. +=item B + +causes the salt length to be automatically determined based on the B block +structure when verifying, like B. When signing, the salt +length is maximized up to a maximum of the digest length to comply with FIPS +186-4 section 5.5. + =back EVP_PKEY_CTX_get_rsa_pss_saltlen() gets the RSA PSS salt length for I. @@ -386,6 +393,16 @@ this behaviour should be tolerated then OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION should be set to the actual negotiated protocol version. Otherwise it should be left unset. +Similarly to the B above, since OpenSSL version +3.2.0, the use of B will return a randomly generated message +instead of padding errors in case padding checks fail. Applications that +want to remain secure while using earlier versions of OpenSSL, or a provider +that doesn't implement the implicit rejection mechanism, still need to +handle both the error code from the RSA decryption operation and the +returned message in a side channel secure manner. +This protection against Bleichenbacher attacks can be disabled by setting +B (an unsigned integer) to 0. + =head2 DSA parameters EVP_PKEY_CTX_set_dsa_paramgen_bits() sets the number of bits used for DSA @@ -634,10 +651,14 @@ returns the previously set ID value to caller in I. The caller should allocate adequate memory space for the I before calling EVP_PKEY_CTX_get1_id(). EVP_PKEY_CTX_set_kem_op() sets the KEM operation to run. This can be set after -EVP_PKEY_encapsulate_init() or EVP_PKEY_decapsulate_init() to select the -kem operation. RSA is the only key type that supports encapsulation currently, -and as there is no default operation for the RSA type, this function must be -called before EVP_PKEY_encapsulate() or EVP_PKEY_decapsulate(). +EVP_PKEY_encapsulate_init() or EVP_PKEY_decapsulate_init() to select the kem +operation. For the key types that support encapsulation and don't have the +default operation, e.g. RSA, this function must be called before +EVP_PKEY_encapsulate() or EVP_PKEY_decapsulate(). + +The supported parameters for the built-in algorithms are documented in +L, L, L, +L, and L. =head1 RETURN VALUES @@ -680,7 +701,7 @@ and EVP_PKEY_CTX_get0_ecdh_kdf_ukm() were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod index 66fe3dc8fa27..81ee5c485b5c 100644 --- a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod +++ b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod @@ -159,7 +159,7 @@ OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_CTX_set_params.pod b/doc/man3/EVP_PKEY_CTX_set_params.pod index 8947648ccbe6..5faae0540cc0 100644 --- a/doc/man3/EVP_PKEY_CTX_set_params.pod +++ b/doc/man3/EVP_PKEY_CTX_set_params.pod @@ -57,6 +57,8 @@ L L L L +L +L =head1 RETURN VALUES @@ -84,9 +86,11 @@ L All functions were added in OpenSSL 3.0. +Support for B> and B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_decapsulate.pod b/doc/man3/EVP_PKEY_decapsulate.pod index cd6f5f0221a2..156d9afcecbe 100644 --- a/doc/man3/EVP_PKEY_decapsulate.pod +++ b/doc/man3/EVP_PKEY_decapsulate.pod @@ -2,7 +2,7 @@ =head1 NAME -EVP_PKEY_decapsulate_init, EVP_PKEY_decapsulate +EVP_PKEY_decapsulate_init, EVP_PKEY_auth_decapsulate_init, EVP_PKEY_decapsulate - Key decapsulation using a KEM algorithm with a private key =head1 SYNOPSIS @@ -10,6 +10,8 @@ EVP_PKEY_decapsulate_init, EVP_PKEY_decapsulate #include int EVP_PKEY_decapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); + int EVP_PKEY_auth_decapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpub, + const OSSL_PARAM params[]); int EVP_PKEY_decapsulate(EVP_PKEY_CTX *ctx, unsigned char *unwrapped, size_t *unwrappedlen, const unsigned char *wrapped, size_t wrappedlen); @@ -22,16 +24,35 @@ on the context in the same way as calling L. Note that I usually is produced using L, specifying the private key to use. +The EVP_PKEY_auth_decapsulate_init() function is similar to +EVP_PKEY_decapsulate_init() but also passes an I authentication public +key that is used during decapsulation. + The EVP_PKEY_decapsulate() function performs a private key decapsulation operation using I. The data to be decapsulated is specified using the -I and I parameters. -If I is NULL then the size of the output secret buffer -is written to I<*unwrappedlen>. If I is not NULL and the -call is successful then the decapsulated secret data is written to I -and the amount of data written to I<*unwrappedlen>. Note that, if I -is not NULL in this call, the value it points to must be initialised to the length of -I, so that the call can validate it is of sufficient size to hold the -result of the operation. +I and I parameters (which must both non-NULL). + +The I parameter is an output argument, to which the decapsulated +shared secret is written. +The shared secret may not match the peer's value even when decapsulation +returns success. +Instead, the shared secret must be used to derive a key that is used to +authenticate data subsequently received from the peer. +If I is NULL then the size of the output shared secret buffer is +written to I<*unwrappedlen> and no decapsulation is performed, this makes it +possible to determine the required buffer size at run time. Otherwise, the +decapsulated secret data is written to I and the length of shared +secret is written to I<*unwrappedlen>. + +Note that the value pointed to by I (which must NOT be B) +must be initialised to the length of I, so that the call can +validate it is of sufficient size to hold the result of the operation. + +Absent detailed prior knowledge of the internals of the specific KEM +algorithm, callers SHOULD NOT assume that the returned shared secret +is necessarily of the maximum possible length. +The length returned via I<*unwrappedlen> SHOULD be used to determine the actual +length of the output. =head1 NOTES @@ -40,9 +61,10 @@ for the operation may be set or modified using L. =head1 RETURN VALUES -EVP_PKEY_decapsulate_init() and EVP_PKEY_decapsulate() return 1 for -success and 0 or a negative value for failure. In particular a return value of -2 -indicates the operation is not supported by the private key algorithm. +EVP_PKEY_decapsulate_init(), EVP_PKEY_auth_decapsulate_init() and +EVP_PKEY_decapsulate() return 1 for success and 0 or a negative value for +failure. In particular a return value of -2 indicates the operation is not +supported by the private key algorithm. =head1 EXAMPLES @@ -78,7 +100,7 @@ Decapsulate data using RSA: /* malloc failure */ /* Decapsulated secret data is secretlen bytes long */ - if (EVP_PKEY_decapsulaterctx, secret, &secretlen, in, inlen) <= 0) + if (EVP_PKEY_decapsulate(ctx, secret, &secretlen, in, inlen) <= 0) /* Error */ @@ -87,14 +109,24 @@ Decapsulate data using RSA: L, L, L, +L, +L, +L, +L, +L =head1 HISTORY -These functions were added in OpenSSL 3.0. +The functions EVP_PKEY_decapsulate_init() and EVP_PKEY_decapsulate() were added +in OpenSSL 3.0. + +The function EVP_PKEY_auth_decapsulate_init() was added in OpenSSL 3.2. + +Support for B was added in OpenSSL 3.5. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_decrypt.pod b/doc/man3/EVP_PKEY_decrypt.pod index b6f9bad5f18a..7d6807d68b6e 100644 --- a/doc/man3/EVP_PKEY_decrypt.pod +++ b/doc/man3/EVP_PKEY_decrypt.pod @@ -51,6 +51,27 @@ return 1 for success and 0 or a negative value for failure. In particular a return value of -2 indicates the operation is not supported by the public key algorithm. +=head1 WARNINGS + +In OpenSSL versions before 3.2.0, when used in PKCS#1 v1.5 padding, +both the return value from the EVP_PKEY_decrypt() and the B provided +information useful in mounting a Bleichenbacher attack against the +used private key. They had to be processed in a side-channel free way. + +Since version 3.2.0, the EVP_PKEY_decrypt() method when used with PKCS#1 +v1.5 padding as implemented in the B provider implements +the implicit rejection mechanism (see +B in L). +That means it doesn't return an error when it detects an error in padding, +instead it returns a pseudo-randomly generated message, removing the need +of side-channel secure code from applications using OpenSSL. +If OpenSSL is configured to use a provider that doesn't implement implicit +rejection, the code still needs to handle the returned values +using side-channel free code. +Side-channel free handling of the error stack can be performed using +either a pair of unconditional L and L +calls or by using the L call. + =head1 EXAMPLES Decrypt data using OAEP (for RSA keys): @@ -105,7 +126,7 @@ These functions were added in OpenSSL 1.0.0. =head1 COPYRIGHT -Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_derive.pod b/doc/man3/EVP_PKEY_derive.pod index bfbe14b1ffff..ec19afad52e4 100644 --- a/doc/man3/EVP_PKEY_derive.pod +++ b/doc/man3/EVP_PKEY_derive.pod @@ -114,7 +114,7 @@ added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_encapsulate.pod b/doc/man3/EVP_PKEY_encapsulate.pod index eb51836d7951..a82eaded592f 100644 --- a/doc/man3/EVP_PKEY_encapsulate.pod +++ b/doc/man3/EVP_PKEY_encapsulate.pod @@ -2,7 +2,7 @@ =head1 NAME -EVP_PKEY_encapsulate_init, EVP_PKEY_encapsulate +EVP_PKEY_encapsulate_init, EVP_PKEY_auth_encapsulate_init, EVP_PKEY_encapsulate - Key encapsulation using a KEM algorithm with a public key =head1 SYNOPSIS @@ -10,6 +10,8 @@ EVP_PKEY_encapsulate_init, EVP_PKEY_encapsulate #include int EVP_PKEY_encapsulate_init(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); + int EVP_PKEY_auth_encapsulate_init(EVP_PKEY_CTX *ctx, EVP_PKEY *authpriv, + const OSSL_PARAM params[]); int EVP_PKEY_encapsulate(EVP_PKEY_CTX *ctx, unsigned char *wrappedkey, size_t *wrappedkeylen, unsigned char *genkey, size_t *genkeylen); @@ -22,34 +24,54 @@ on the context in the same way as calling L. Note that I is usually is produced using L, specifying the public key to use. +The EVP_PKEY_auth_encapsulate_init() function is similar to +EVP_PKEY_encapsulate_init() but also passes an I authentication private +key that is used during encapsulation. + The EVP_PKEY_encapsulate() function performs a public key encapsulation operation using I. -The symmetric secret generated in I can be used as key material. -The ciphertext in I is its encapsulated form, which can be sent -to another party, who can use L to retrieve it -using their private key. -If I is NULL then the maximum size of the output buffer -is written to the I<*wrappedkeylen> parameter unless I is NULL -and the maximum size of the generated key buffer is written to I<*genkeylen> -unless I is NULL. -If I is not NULL and the call is successful then the -internally generated key is written to I and its size is written to -I<*genkeylen>. The encapsulated version of the generated key is written to -I and its size is written to I<*wrappedkeylen>. Note that if -I is not NULL, then the value it points to must initially hold the size of -the I buffer so that its size can be validated by the call, ensuring -it is large enough to hold the result written to I. +The shared secret writen to I can be used as an input for key +derivation, typically for various symmetric algorithms. +Its size is written to I, which must be initialised to the +size of the provided buffer. + +The ciphertext written to I is an encapsulated form, which +is expected to be only usable by the holder of the private key corresponding +to wthe public key associated with I. +This ciphertext is then communicated to the private-key holder, who can use +L to securely recover the same shared secret. + +If I is NULL then the maximum size of the output buffer is written +to the I<*wrappedkeylen> parameter unless I is NULL and the +maximum size of the generated key buffer is written to I<*genkeylen> unless +I is NULL. + +If I is not NULL and the call is successful then the generated +shared secret is written to I and its size is written to +I<*genkeylen> (which must be non-NULL). +The encapsulated ciphertext is written to I and +its size is written to I<*wrappedkeylen> (must also be non-NULL), +The value pointed to by I initially hold the size of the +I buffer so that its size can be validated by the call, ensuring it +is large enough to hold the result written to I. + +Absent detailed prior knowledge of the internals of the specific KEM +algorithm, callers SHOULD NOT assume that the returned shared secret and +ciphertext are necessarily of the maximum possible length. +The lengths returned via I<*wrappedkeylen> and I<*genkeylen> SHOULD +be used to determine the actual lengths of the outputs. =head1 NOTES -After the call to EVP_PKEY_encapsulate_init() algorithm-specific parameters +After the call to EVP_PKEY_encapsulate_init(), algorithm-specific parameters for the operation may be set or modified using L. =head1 RETURN VALUES -EVP_PKEY_encapsulate_init() and EVP_PKEY_encapsulate() return 1 for -success and 0 or a negative value for failure. In particular a return value of -2 -indicates the operation is not supported by the public key algorithm. +EVP_PKEY_encapsulate_init(), EVP_PKEY_auth_encapsulate_init() and +EVP_PKEY_encapsulate() return 1 for success and 0 or a negative value for +failure. In particular a return value of -2 indicates the operation is not +supported by the public key algorithm. =head1 EXAMPLES @@ -96,14 +118,23 @@ Encapsulate an RSASVE key (for RSA keys). L, L, L, +L, +L, +L, +L, +L =head1 HISTORY -These functions were added in OpenSSL 3.0. +The functions EVP_PKEY_encapsulate_init() and EVP_PKEY_encapsulate() were +added in OpenSSL 3.0. +The function EVP_PKEY_auth_encapsulate_init() was added in OpenSSL 3.2. + +Support for B was added in OpenSSL 3.5. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_encrypt.pod b/doc/man3/EVP_PKEY_encrypt.pod index 53b2e0edd2e8..c5d91e1c18b9 100644 --- a/doc/man3/EVP_PKEY_encrypt.pod +++ b/doc/man3/EVP_PKEY_encrypt.pod @@ -108,7 +108,7 @@ These functions were added in OpenSSL 1.0.0. =head1 COPYRIGHT -Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod index 3e9e06d1a202..39a68be86acd 100644 --- a/doc/man3/EVP_PKEY_fromdata.pod +++ b/doc/man3/EVP_PKEY_fromdata.pod @@ -34,8 +34,8 @@ EVP_PKEY_fromdata() creates the structure to store a key or key parameters, given data from I, I and a context that's been initialized with EVP_PKEY_fromdata_init(). The result is written to I<*ppkey>. I is described in L. -The parameters that can be used for various types of key are as described by the -diverse "Common parameters" sections of the +The parameters that can be used for various types of key are as described by +the various "Common parameters" sections of the L(7)|EVP_PKEY-RSA(7)/Common RSA parameters>, L(7)|EVP_PKEY-DSA(7)/Common DSA & DH parameters>, L(7)|EVP_PKEY-DH(7)/Common DH parameters>, @@ -43,7 +43,11 @@ L(7)|EVP_PKEY-EC(7)/Common EC parameters>, L(7)|EVP_PKEY-ED448(7)/Common X25519, X448, ED25519 and ED448 parameters>, L(7)|EVP_PKEY-X25519(7)/Common X25519, X448, ED25519 and ED448 parameters>, L(7)|EVP_PKEY-X448(7)/Common X25519, X448, ED25519 and ED448 parameters>, -and L(7)|EVP_PKEY-ED25519(7)/Common X25519, X448, ED25519 and ED448 parameters> pages. +L(7)|EVP_PKEY-ED25519(7)/Common X25519, X448, ED25519 and ED448 parameters>, +L|EVP_PKEY-ML-DSA(7)/Common parameters> +and +L|EVP_PKEY-ML-KEM(7)/Common parameters> +pages. =for comment the awful list of links above is made this way so we get nice rendering as a man-page while still getting proper links in HTML @@ -257,19 +261,32 @@ example with L. =head1 SEE ALSO -L, L, L, -L, L, -L, L, L, L, -L, L, L, -L +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L. =head1 HISTORY These functions were added in OpenSSL 3.0. +Support for B, B and B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_get_size.pod b/doc/man3/EVP_PKEY_get_size.pod index 37bb9bb4c45b..44b91cb00eb5 100644 --- a/doc/man3/EVP_PKEY_get_size.pod +++ b/doc/man3/EVP_PKEY_get_size.pod @@ -22,6 +22,7 @@ EVP_PKEY_bits, EVP_PKEY_security_bits, EVP_PKEY_size EVP_PKEY_get_size() returns the maximum suitable size for the output buffers for almost all operations that can be done with I. +This corresponds to the provider parameter B. The primary documented use is with L and L, but it isn't limited there. The returned size is also large enough for the output buffer of L, @@ -38,9 +39,11 @@ receive that length), to avoid bugs. EVP_PKEY_get_bits() returns the cryptographic length of the cryptosystem to which the key in I belongs, in bits. Note that the definition of cryptographic length is specific to the key cryptosystem. +This length corresponds to the provider parameter B. EVP_PKEY_get_security_bits() returns the number of security bits of the given I, bits of security is defined in NIST SP800-57. +This corresponds to the provider parameter B. =head1 RETURN VALUES @@ -66,6 +69,7 @@ L. =head1 SEE ALSO +L, L, L, L, diff --git a/doc/man3/EVP_PKEY_gettable_params.pod b/doc/man3/EVP_PKEY_gettable_params.pod index acf20b54e554..8dd0fc543e5d 100644 --- a/doc/man3/EVP_PKEY_gettable_params.pod +++ b/doc/man3/EVP_PKEY_gettable_params.pod @@ -125,7 +125,7 @@ These functions were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_keygen.pod b/doc/man3/EVP_PKEY_keygen.pod index 433123618606..9cdea5b36220 100644 --- a/doc/man3/EVP_PKEY_keygen.pod +++ b/doc/man3/EVP_PKEY_keygen.pod @@ -100,8 +100,21 @@ If I is C, a B parameter must be given to specify the size of the RSA key. If I is C, a string parameter must be given to specify the name of the EC curve. -If I is C, C, C, C, or C -no further parameter is needed. +If I is: +C, +C, +C, +C, +C, +C, +C, +C, +C, +C, or +C +no further parameters are needed. Other key types may be possible if they are +supplied by the loaded providers. EVP_PKEY_Q_keygen() may be usable with such +key types as long as they do not require further parameters. =head1 RETURN VALUES @@ -226,7 +239,7 @@ EVP_PKEY_Q_keygen() and EVP_PKEY_generate() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_meth_get_count.pod b/doc/man3/EVP_PKEY_meth_get_count.pod index 2e2a3fc13e31..4950a58b2472 100644 --- a/doc/man3/EVP_PKEY_meth_get_count.pod +++ b/doc/man3/EVP_PKEY_meth_get_count.pod @@ -51,7 +51,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_new.pod b/doc/man3/EVP_PKEY_new.pod index 1c75c7571994..eccc21aac63f 100644 --- a/doc/man3/EVP_PKEY_new.pod +++ b/doc/man3/EVP_PKEY_new.pod @@ -94,8 +94,19 @@ EVP_PKEY_new_raw_private_key_ex() allocates a new B. Unless an engine should be used for the key type, a provider for the key is found using the library context I and the property query string I. The I argument indicates what kind of key this is. The value should be a -string for a public key algorithm that supports raw private keys, i.e one of -"X25519", "ED25519", "X448" or "ED448". I points to the raw private key +string for a public key algorithm that supports raw private keys, e.g., one of: +C, +C, +C, +C, +C, +C, +C, +C, +C, +or +C. +I points to the raw private key data for this B which should be of length I. The length should be appropriate for the type of the key. The public key data will be automatically derived from the given private key data (if appropriate for the @@ -119,13 +130,23 @@ EVP_PKEY_new_raw_public_key_ex() works in the same way as EVP_PKEY_new_raw_private_key_ex() except that I points to the raw public key data. The B structure will be initialised without any private key information. Algorithm types that support raw public keys are -"X25519", "ED25519", "X448" or "ED448". +B, +B, +B, +B, +C, +C, +C, +B, +B, +and +B. EVP_PKEY_new_raw_public_key() works in the same way as -EVP_PKEY_new_raw_private_key() except that I points to the raw public key -data. The B structure will be initialised without any private key -information. Algorithm types that support raw public keys are -B, B, B or B. +EVP_PKEY_new_raw_private_key_ex() except that I points to the raw public +key data. +The B structure will be initialised without any private key +information. EVP_PKEY_new_mac_key() works in the same way as EVP_PKEY_new_raw_private_key(). New applications should use EVP_PKEY_new_raw_private_key() instead. @@ -137,8 +158,25 @@ actually written. If the buffer I is NULL then I<*len> is populated with the number of bytes required to hold the key. The calling application is responsible for ensuring that the buffer is large enough to receive the private key data. This function only works for algorithms that support raw private keys. -Currently this is: B, B, B, -B, B, B or B. +These include: +B, +B, +B, +B, +B, +B, +and +B. +EVP_PKEY_get_raw_private_key() also works with +C, +C, +C, +B, +B and +B +keys, which don't have legacy numeric I assigments, but their raw form is +nevertheless available. + EVP_PKEY_get_raw_public_key() fills the buffer provided by I with raw public key data. The size of the I buffer should be in I<*len> on entry @@ -147,8 +185,21 @@ actually written. If the buffer I is NULL then I<*len> is populated with the number of bytes required to hold the key. The calling application is responsible for ensuring that the buffer is large enough to receive the public key data. This function only works for algorithms that support raw public keys. -Currently this is: B, B, B or -B. +These include: +B, +B, +B, +and +B +EVP_PKEY_get_raw_public_key() also works with +C, +C, +C, +B, +B and +B +keys, which don't have legacy numeric I assigments, but their raw form is +nevertheless available. EVP_PKEY_new_CMAC_key() works in the same way as EVP_PKEY_new_raw_private_key() except it is only for the B algorithm type. In addition to the @@ -183,8 +234,19 @@ EVP_PKEY_get_raw_public_key() return 1 for success and 0 for failure. =head1 SEE ALSO -L, L, L or -L +L, +L, +L, +L, +L, +L. +L, +L, +L, +L, +L, +L, +L. =head1 HISTORY @@ -208,9 +270,11 @@ The documentation of B was amended in OpenSSL 3.0 to allow there to be the private part of the keypair without the public part, where this was previously implied to be disallowed. +Support for B and B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_set1_encoded_public_key.pod b/doc/man3/EVP_PKEY_set1_encoded_public_key.pod index cf27919a2c3f..07a3284135f9 100644 --- a/doc/man3/EVP_PKEY_set1_encoded_public_key.pod +++ b/doc/man3/EVP_PKEY_set1_encoded_public_key.pod @@ -27,18 +27,24 @@ see L: =head1 DESCRIPTION EVP_PKEY_set1_encoded_public_key() can be used to set the public key value -within an existing EVP_PKEY object. For the built-in OpenSSL algorithms this -currently only works for those that support key exchange. Parameters are not -set as part of this operation, so typically an application will create an -EVP_PKEY first, set the parameters on it, and then call this function. +within an existing EVP_PKEY object, which does not yet have either a public or +private key assigned. +For the built-in OpenSSL algorithms this currently only works for those that +support key exchange or key encapsulation. +Parameters are not set as part of this operation, so typically an application +will create an EVP_PKEY first, set the parameters on it, and then call this +function. For example setting the parameters might be done using L. The format for the encoded public key will depend on the algorithm in use. For DH it should be encoded as a positive integer in big-endian form. For EC is should be a point conforming to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic -Curve Cryptography") standard. For X25519 and X448 it should be encoded in a -format as defined by RFC7748. +Curve Cryptography") standard. For B and B it should be encoded +in the format defined by RFC7748. +For B, B and B, this is the public key +format defined in B (the 12-bit per-coefficient encoded public I +vector and 32-byte matrix seed I). The key to be updated is supplied in B. The buffer containing the encoded key is pointed to be B. The length of the buffer is supplied in B. @@ -117,9 +123,17 @@ performing a key exchange operation. =head1 SEE ALSO -L, L, -L, L, -L, L, L, L +L, +L, +L, +L, +L, +L, +L, +L, +L, +L, +L. =head1 HISTORY @@ -129,9 +143,11 @@ added in OpenSSL 3.0. EVP_PKEY_set1_tls_encodedpoint() and EVP_PKEY_get1_tls_encodedpoint() were deprecated in OpenSSL 3.0. +Support for B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_sign.pod b/doc/man3/EVP_PKEY_sign.pod index 6752432bd58e..b88a9893f52f 100644 --- a/doc/man3/EVP_PKEY_sign.pod +++ b/doc/man3/EVP_PKEY_sign.pod @@ -2,8 +2,9 @@ =head1 NAME -EVP_PKEY_sign_init, EVP_PKEY_sign_init_ex, EVP_PKEY_sign -- sign using a public key algorithm +EVP_PKEY_sign_init, EVP_PKEY_sign_init_ex, EVP_PKEY_sign_init_ex2, +EVP_PKEY_sign, EVP_PKEY_sign_message_init, EVP_PKEY_sign_message_update, +EVP_PKEY_sign_message_final - sign using a public key algorithm =head1 SYNOPSIS @@ -11,6 +12,14 @@ EVP_PKEY_sign_init, EVP_PKEY_sign_init_ex, EVP_PKEY_sign int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); + int EVP_PKEY_sign_init_ex2(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo, + const OSSL_PARAM params[]); + int EVP_PKEY_sign_message_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo, + const OSSL_PARAM params[]); + int EVP_PKEY_sign_message_update(EVP_PKEY_CTX *ctx, + unsigned char *in, size_t inlen); + int EVP_PKEY_sign_message_final(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, size_t sigsize); int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen); @@ -26,37 +35,120 @@ for more information about implicit fetches. EVP_PKEY_sign_init_ex() is the same as EVP_PKEY_sign_init() but additionally sets the passed parameters I on the context before returning. -The EVP_PKEY_sign() function performs a public key signing operation -using I. The data to be signed is specified using the I and -I parameters. If I is NULL then the maximum size of the output -buffer is written to the I parameter. If I is not NULL then -before the call the I parameter should contain the length of the -I buffer, if the call is successful the signature is written to -I and the amount of data written to I. +EVP_PKEY_sign_init_ex2() initializes a public key algorithm context I for +signing a pre-computed message digest using the algorithm given by I and +the key given through L or L. +A context I without a pre-loaded key cannot be used with this function. +This function provides almost the same functionality as EVP_PKEY_sign_init_ex(), +but is uniquely intended to be used with a pre-computed messsage digest, and +allows pre-determining the exact conditions for that message digest, if a +composite signature algorithm (such as RSA-SHA256) was fetched. +Following a call to this function, setting parameters that modifies the digest +implementation or padding is not normally supported. + +EVP_PKEY_sign_message_init() initializes a public key algorithm context I +for signing an unlimited size message using the algorithm given by I and +the key given through L or L. +Passing the message is supported both in a one-shot fashion using +EVP_PKEY_sign(), and through the combination of EVP_PKEY_sign_message_update() +and EVP_PKEY_sign_message_final(). +This function enables using algorithms that can process input of arbitrary +length, such as ED25519, RSA-SHA256 and similar. + +EVP_PKEY_sign_message_update() adds I bytes from I to the data to be +processed for signature. The signature algorithm specification and +implementation determine how the input bytes are processed and if there's a +limit on the total size of the input. See L below for a deeper +explanation. + +EVP_PKEY_sign_message_final() signs the processed data and places the data in +I, and the number of signature bytes in I<*siglen>, if the number of +bytes doesn't surpass the size given by I. +I may be NULL, and in that case, only I<*siglen> is updated with the +number of signature bytes. + +EVP_PKEY_sign() is a one-shot function that can be used with all the init +functions above. +When initialization was done with EVP_PKEY_sign_init(), EVP_PKEY_sign_init_ex() +or EVP_PKEY_sign_init_ex2(), the data specified by I and I is +signed after appropriate padding. +When initialization was done with EVP_PKEY_sign_message_init(), the data +specified by I and I is digested by the implied message digest +algorithm, and the result is signed after appropriate padding. +If I is NULL then the maximum size of the output buffer is written to the +I parameter. +If I is not NULL, then before the call the I parameter should +contain the length of the I buffer, and if the call is successful the +signature is written to I and the amount of data written to I. =head1 NOTES -EVP_PKEY_sign() does not hash the data to be signed, and therefore is -normally used to sign digests. For signing arbitrary messages, see the -L and -L signing interfaces instead. +=begin comment -After the call to EVP_PKEY_sign_init() algorithm specific control -operations can be performed to set any appropriate parameters for the -operation (see L). +These notes are largely replicated in EVP_PKEY_verify.pod, please keep them +in sync. -The function EVP_PKEY_sign() can be called more than once on the same -context if several operations are performed using the same parameters. +=end comment + +=head2 General + +Some signature implementations only accumulate the input data and do no +further processing before signing it (they expect the input to be a digest), +while others compress the data, typically by internally producing a digest, +and signing the result. +Some of them support both modes of operation at the same time. +The caller is expected to know how the chosen algorithm is supposed to behave +and under what conditions. + +For example, an RSA implementation can be expected to only expect a message +digest as input, while ED25519 can be expected to process the input with a hash, +i.e. to produce the message digest internally, and while RSA-SHA256 can be +expected to handle either mode of operation, depending on if the operation was +initialized with EVP_PKEY_sign_init_ex2() or with EVP_PKEY_sign_message_init(). + +Similarly, an RSA implementation usually expects additional details to be set, +like the message digest algorithm that the input is supposed to be digested +with, as well as the padding mode (see L and +L and similar others), while an RSA-SHA256 +implementation usually has these details pre-set and immutable. + +The functions described here can't be used to combine separate algorithms. In +particular, neither L nor the B +parameter "digest" (B) can be used to combine a +signature algorithm with a hash algorithm to process the input. In other +words, it's not possible to specify a I pre-loaded with an RSA pkey, or +an I that fetched C and try to specify SHA256 separately to get the +functionality of RSA-SHA256. If combining algorithms in that manner is +desired, please use L and associated functions. + +=head2 Performing multiple signatures + +When initialized using EVP_PKEY_sign_init_ex() or EVP_PKEY_sign_init_ex2(), +EVP_PKEY_sign() can be called more than once on the same context to have +several one-shot operations performed using the same parameters. + +When initialized using EVP_PKEY_sign_message_init(), it's not possible to +call EVP_PKEY_sign() multiple times. =head1 RETURN VALUES -EVP_PKEY_sign_init() and EVP_PKEY_sign() return 1 for success and 0 -or a negative value for failure. In particular a return value of -2 -indicates the operation is not supported by the public key algorithm. +All functions return 1 for success and 0 or a negative value for failure. + +In particular, EVP_PKEY_sign_init() and its other variants may return -2 to +indicate that the operation is not supported by the public key algorithm. =head1 EXAMPLES -Sign data using RSA with PKCS#1 padding and SHA256 digest: +=begin comment + +These examples are largely replicated in EVP_PKEY_verify.pod, please keep them +in sync. + +=end comment + +=head2 RSA with PKCS#1 padding for SHA256 + +Sign data using RSA with PKCS#1 padding and a SHA256 digest as input: #include #include @@ -73,7 +165,7 @@ Sign data using RSA with PKCS#1 padding and SHA256 digest: * point to the SHA-256 digest to be signed. */ ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); - if (!ctx) + if (ctx == NULL) /* Error occurred */ if (EVP_PKEY_sign_init(ctx) <= 0) /* Error */ @@ -88,7 +180,7 @@ Sign data using RSA with PKCS#1 padding and SHA256 digest: sig = OPENSSL_malloc(siglen); - if (!sig) + if (sig == NULL) /* malloc failure */ if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0) @@ -96,6 +188,152 @@ Sign data using RSA with PKCS#1 padding and SHA256 digest: /* Signature is siglen bytes written to buffer sig */ +=head2 RSA-SHA256 with a pre-computed digest + +Sign a digest with RSA-SHA256 using one-shot functions. To be noted is that +RSA-SHA256 is assumed to be an implementation of C, +for which the padding is pre-determined to be B, and the +input digest is assumed to have been computed using SHA256. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* md is a SHA-256 digest in this example. */ + unsigned char *md, *sig; + size_t mdlen = 32, siglen; + EVP_PKEY *signing_key; + + /* + * NB: assumes signing_key and md are set up before the next + * step. signing_key must be an RSA private key and md must + * point to the SHA-256 digest to be signed. + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL) + /* Error occurred */ + if (EVP_PKEY_sign_init_ex2(ctx, alg, NULL) <= 0) + /* Error */ + + /* Determine buffer length */ + if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0) + /* Error */ + + sig = OPENSSL_malloc(siglen); + + if (sig == NULL) + /* malloc failure */ + + if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0) + /* Error */ + + /* Signature is siglen bytes written to buffer sig */ + + +=head2 RSA-SHA256, one-shot + +Sign a document with RSA-SHA256 using one-shot functions. +To be noted is that RSA-SHA256 is assumed to be an implementation of +C, for which the padding is pre-determined to be +B. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* in is the input in this example. */ + unsigned char *in, *sig; + /* inlen is the length of the input in this example. */ + size_t inlen, siglen; + EVP_PKEY *signing_key; + EVP_SIGNATURE *alg; + + /* + * NB: assumes signing_key, in and inlen are set up before + * the next step. signing_key must be an RSA private key, + * in must point to data to be digested and signed, and + * inlen must be the size of the data in bytes. + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL || alg == NULL) + /* Error occurred */ + if (EVP_PKEY_sign_message_init(ctx, alg, NULL) <= 0) + /* Error */ + + /* Determine sig buffer length */ + if (EVP_PKEY_sign(ctx, NULL, &siglen, in, inlen) <= 0) + /* Error */ + + sig = OPENSSL_malloc(siglen); + + if (sig == NULL) + /* malloc failure */ + + if (EVP_PKEY_sign(ctx, sig, &siglen, in, inlen) <= 0) + /* Error */ + + /* Signature is siglen bytes written to buffer sig */ + + +=head2 RSA-SHA256, using update and final + +This is the same as the previous example, but allowing stream-like +functionality. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* in is the input in this example. */ + unsigned char *in, *sig; + /* inlen is the length of the input in this example. */ + size_t inlen, siglen; + EVP_PKEY *signing_key; + EVP_SIGNATURE *alg; + + /* + * NB: assumes signing_key, in and inlen are set up before + * the next step. signing_key must be an RSA private key, + * in must point to data to be digested and signed, and + * inlen must be the size of the data in bytes. + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL || alg == NULL) + /* Error occurred */ + if (EVP_PKEY_sign_message_init(ctx, alg, NULL) <= 0) + /* Error */ + + while (inlen > 0) { + if (EVP_PKEY_sign_message_update(ctx, in, inlen)) <= 0) + /* Error */ + if (inlen > 256) { + inlen -= 256; + in += 256; + } else { + inlen = 0; + } + } + + /* Determine sig buffer length */ + if (EVP_PKEY_sign_message_final(ctx, NULL, &siglen) <= 0) + /* Error */ + + sig = OPENSSL_malloc(siglen); + + if (sig == NULL) + /* malloc failure */ + + if (EVP_PKEY_sign_message_final(ctx, sig, &siglen) <= 0) + /* Error */ + + /* Signature is siglen bytes written to buffer sig */ + =head1 SEE ALSO @@ -114,9 +352,13 @@ OpenSSL 1.0.0. The EVP_PKEY_sign_init_ex() function was added in OpenSSL 3.0. +The EVP_PKEY_sign_init_ex2(), EVP_PKEY_sign_message_init(), +EVP_PKEY_sign_message_update() and EVP_PKEY_sign_message_final() functions +where added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_todata.pod b/doc/man3/EVP_PKEY_todata.pod index 71867236f987..9dee379a2672 100644 --- a/doc/man3/EVP_PKEY_todata.pod +++ b/doc/man3/EVP_PKEY_todata.pod @@ -41,19 +41,30 @@ EVP_PKEY_todata() and EVP_PKEY_export() return 1 for success and 0 for failure. =head1 SEE ALSO -L, L, +L, +L, L, -L, L, L, L, -L, L, L, +L, +L, +L, L +L, +L, +L, +L, +L, +L, +L. =head1 HISTORY These functions were added in OpenSSL 3.0. +Support for B, B and B was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_verify.pod b/doc/man3/EVP_PKEY_verify.pod index 77023cab8704..e5bd70a90d21 100644 --- a/doc/man3/EVP_PKEY_verify.pod +++ b/doc/man3/EVP_PKEY_verify.pod @@ -2,8 +2,10 @@ =head1 NAME -EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify -- signature verification using a public key algorithm +EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify_init_ex2, +EVP_PKEY_verify, EVP_PKEY_verify_message_init, EVP_PKEY_verify_message_update, +EVP_PKEY_verify_message_final, EVP_PKEY_CTX_set_signature - signature +verification using a public key algorithm =head1 SYNOPSIS @@ -11,6 +13,15 @@ EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); + int EVP_PKEY_verify_init_ex2(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo, + const OSSL_PARAM params[]); + int EVP_PKEY_verify_message_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo, + const OSSL_PARAM params[]); + int EVP_PKEY_CTX_set_signature(EVP_PKEY_CTX *pctx, + const unsigned char *sig, size_t siglen); + int EVP_PKEY_verify_message_update(EVP_PKEY_CTX *ctx, + unsigned char *in, size_t inlen); + int EVP_PKEY_verify_message_final(EVP_PKEY_CTX *ctx); int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, const unsigned char *tbs, size_t tbslen); @@ -18,7 +29,7 @@ EVP_PKEY_verify_init, EVP_PKEY_verify_init_ex, EVP_PKEY_verify =head1 DESCRIPTION EVP_PKEY_verify_init() initializes a public key algorithm context I for -signing using the algorithm given when the context was created +verification using the algorithm given when the context was created using L or variants thereof. The algorithm is used to fetch a B method implicitly, see L for more information about implicit fetches. @@ -26,27 +37,113 @@ for more information about implicit fetches. EVP_PKEY_verify_init_ex() is the same as EVP_PKEY_verify_init() but additionally sets the passed parameters I on the context before returning. -The EVP_PKEY_verify() function performs a public key verification operation -using I. The signature is specified using the I and -I parameters. The verified data (i.e. the data believed originally -signed) is specified using the I and I parameters. +EVP_PKEY_verify_init_ex2() is the same as EVP_PKEY_verify_init_ex(), but works +with an explicitly fetched B I. +A context I without a pre-loaded key cannot be used with this function. +Depending on what algorithm was fetched, certain details revolving around the +treatment of the input to EVP_PKEY_verify() may be pre-determined, and in that +case, those details may normally not be changed. +See L below for a deeper explanation. + +EVP_PKEY_verify_message_init() initializes a public key algorithm context +I for verifying an unlimited size message using the algorithm given by +I and the key given through L or +L. +Passing the message is supported both in a one-shot fashion using +EVP_PKEY_verify(), and through the combination of EVP_PKEY_verify_update() and +EVP_PKEY_verify_final(). +This function enables using algorithms that can process input of arbitrary +length, such as ED25519, RSA-SHA256 and similar. + +EVP_PKEY_CTX_set_signature() specifies the I bytes long signature +I to be verified against by EVP_PKEY_verify_final(). +It I be used together with EVP_PKEY_verify_update() and +EVP_PKEY_verify_final(). +See L below for a deeper explanation. + +EVP_PKEY_verify_update() adds I bytes from I to the data to be +processed for verification. The signature algorithm specification and +implementation determine how the input bytes are processed and if there's a +limit on the total size of the input. See L below for a deeper +explanation. + +EVP_PKEY_verify_final() verifies the processed data, given only I. +The signature to verify against must have been given with +EVP_PKEY_CTX_set_signature(). + +EVP_PKEY_verify() is a one-shot function that performs the same thing as +EVP_PKEY_CTX_set_signature() call with I and I as parameters, +followed by a single EVP_PKEY_verify_update() call with I and I, +followed by EVP_PKEY_verify_final() call. =head1 NOTES -After the call to EVP_PKEY_verify_init() algorithm specific control -operations can be performed to set any appropriate parameters for the -operation. +=begin comment -The function EVP_PKEY_verify() can be called more than once on the same -context if several operations are performed using the same parameters. +These notes are largely replicated in EVP_PKEY_sign.pod, please keep them +in sync. + +=end comment + +=head2 General + +Some signature implementations only accumulate the input data and do no +further processing before verifying it (they expect the input to be a digest), +while others compress the data, typically by internally producing a digest, +and signing the result, which is then verified against a given signature. +Some of them support both modes of operation at the same time. +The caller is expected to know how the chosen algorithm is supposed to behave +and under what conditions. + +For example, an RSA implementation can be expected to only expect a digest as +input, while ED25519 can be expected to process the input with a hash, i.e. +to produce the digest internally, and while RSA-SHA256 can be expected to +handle either mode of operation, depending on if the operation was initialized +with EVP_PKEY_verify_init_ex2() or with EVP_PKEY_verify_message_init(). + +Similarly, an RSA implementation usually expects additional details to be set, +like the message digest algorithm that the input is supposed to be digested +with, as well as the padding mode (see L and +L and similar others), while an RSA-SHA256 +implementation usually has these details pre-set and immutable. + +The functions described here can't be used to combine separate algorithms. In +particular, neither L nor the B +parameter "digest" (B) can be used to combine a +signature algorithm with a hash algorithm to process the input. In other +words, it's not possible to specify a I pre-loaded with an RSA pkey, or +an I that fetched C and try to specify SHA256 separately to get the +functionality of RSA-SHA256. If combining algorithms in that manner is +desired, please use L and associated functions, or +L and associated functions. + +=head2 Performing multiple verifications + +When initialized using EVP_PKEY_verify_init_ex() or EVP_PKEY_verify_init_ex2(), +EVP_PKEY_verify() can be called more than once on the same context to have +several one-shot operations performed using the same parameters. + +When initialized using EVP_PKEY_verify_message_init(), it's not possible to +call EVP_PKEY_verify() multiple times. + +=head2 On EVP_PKEY_CTX_set_signature() + +Some signature algorithms (such as LMS) require the signature verification +data be specified before verifying the message. +Other algorithms allow the signature to be specified late. +To allow either way (which may depend on the application's flow of input), the +signature to be verified against I be specified using this function when +using EVP_PKEY_verify_message_update() and EVP_PKEY_verify_message_final() to +perform the verification. =head1 RETURN VALUES -EVP_PKEY_verify_init() and EVP_PKEY_verify() return 1 if the verification was -successful and 0 if it failed. Unlike other functions the return value 0 from -EVP_PKEY_verify() only indicates that the signature did not verify -successfully (that is tbs did not match the original data or the signature was -of invalid form) it is not an indication of a more serious error. +All functions return 1 for success and 0 or a negative value for failure. +However, unlike other functions, the return value 0 from EVP_PKEY_verify(), +EVP_PKEY_verify_recover() and EVP_PKEY_verify_message_final() only indicates +that the signature did not verify successfully (that is tbs did not match the +original data or the signature was of invalid form) it is not an indication of +a more serious error. A negative value indicates an error other that signature verification failure. In particular a return value of -2 indicates the operation is not supported by @@ -54,7 +151,16 @@ the public key algorithm. =head1 EXAMPLES -Verify signature using PKCS#1 and SHA256 digest: +=begin comment + +These examples are largely replicated in EVP_PKEY_sign.pod, please keep them +in sync. + +=end comment + +=head2 RSA with PKCS#1 padding for SHA256 + +Verify signature using PKCS#1 padding and a SHA256 digest as input: #include #include @@ -69,7 +175,7 @@ Verify signature using PKCS#1 and SHA256 digest: * and that verify_key is an RSA public key */ ctx = EVP_PKEY_CTX_new(verify_key, NULL /* no engine */); - if (!ctx) + if (ctx == NULL) /* Error occurred */ if (EVP_PKEY_verify_init(ctx) <= 0) /* Error */ @@ -86,6 +192,138 @@ Verify signature using PKCS#1 and SHA256 digest: * other error. */ +=head2 RSA-SHA256 with a pre-computed digest + +Verify a digest with RSA-SHA256 using one-shot functions. To be noted is that +RSA-SHA256 is assumed to be an implementation of C, +for which the padding is pre-determined to be B, and the +input digest is assumed to have been computed using SHA256. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* md is a SHA-256 digest in this example. */ + unsigned char *md, *sig; + size_t mdlen = 32, siglen; + EVP_PKEY *signing_key; + + /* + * NB: assumes verify_key, sig, siglen, md and mdlen are already set up + * and that verify_key is an RSA public key + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL) + /* Error occurred */ + if (EVP_PKEY_verify_init_ex2(ctx, alg, NULL) <= 0) + /* Error */ + + /* Determine buffer length */ + if (EVP_PKEY_verify(ctx, sig, siglen, md, mdlen) <= 0) + /* Error or signature doesn't verify */ + + /* Perform operation */ + ret = EVP_PKEY_verify(ctx, sig, siglen, md, mdlen); + + /* + * ret == 1 indicates success, 0 verify failure and < 0 for some + * other error. + */ + +=head2 RSA-SHA256, one-shot + +Verify a document with RSA-SHA256 using one-shot functions. +To be noted is that RSA-SHA256 is assumed to be an implementation of +C, for which the padding is pre-determined to be +B. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* in the input in this example. */ + unsigned char *in, *sig; + /* inlen is the length of the input in this example. */ + size_t inlen, siglen; + EVP_PKEY *signing_key; + EVP_SIGNATURE *alg; + + /* + * NB: assumes signing_key, in and inlen are set up before + * the next step. signing_key must be an RSA private key, + * in must point to data to be digested and signed, and + * inlen must be the size of the data in bytes. + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL || alg == NULL) + /* Error occurred */ + if (EVP_PKEY_verify_message_init(ctx, alg, NULL) <= 0) + /* Error */ + + /* Perform operation */ + ret = EVP_PKEY_verify(ctx, sig, siglen, in, inlen); + + /* + * ret == 1 indicates success, 0 verify failure and < 0 for some + * other error. + */ + +=head2 RSA-SHA256, using update and final + +This is the same as the previous example, but allowing stream-like +functionality. + + #include + #include + + EVP_PKEY_CTX *ctx; + /* in is the input in this example. */ + unsigned char *in, *sig; + /* inlen is the length of the input in this example. */ + size_t inlen, siglen; + EVP_PKEY *signing_key; + EVP_SIGNATURE *alg; + + /* + * NB: assumes signing_key, in and inlen are set up before + * the next step. signing_key must be an RSA private key, + * in must point to data to be digested and signed, and + * inlen must be the size of the data in bytes. + */ + ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); + alg = EVP_SIGNATURE_fetch(NULL, "RSA-SHA256", NULL); + + if (ctx == NULL || alg == NULL) + /* Error occurred */ + if (EVP_PKEY_verify_message_init(ctx, alg, NULL) <= 0) + /* Error */ + + /* We have the signature, specify it early */ + EVP_PKEY_CTX_set_signature(ctx, sig, siglen); + + /* Perform operation */ + while (inlen > 0) { + if (EVP_PKEY_verify_message_update(ctx, in, inlen)) <= 0) + /* Error */ + if (inlen > 256) { + inlen -= 256; + in += 256; + } else { + inlen = 0; + } + } + ret = EVP_PKEY_verify_message_final(ctx); + + /* + * ret == 1 indicates success, 0 verify failure and < 0 for some + * other error. + */ + + =head1 SEE ALSO L, @@ -102,9 +340,13 @@ OpenSSL 1.0.0. The EVP_PKEY_verify_init_ex() function was added in OpenSSL 3.0. +The EVP_PKEY_verify_init_ex2(), EVP_PKEY_verify_message_init(), +EVP_PKEY_verify_message_update(), EVP_PKEY_verify_message_final() and +EVP_PKEY_CTX_set_signature() functions where added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_PKEY_verify_recover.pod b/doc/man3/EVP_PKEY_verify_recover.pod index 7f0a06c03960..d859f68a4652 100644 --- a/doc/man3/EVP_PKEY_verify_recover.pod +++ b/doc/man3/EVP_PKEY_verify_recover.pod @@ -3,7 +3,7 @@ =head1 NAME EVP_PKEY_verify_recover_init, EVP_PKEY_verify_recover_init_ex, -EVP_PKEY_verify_recover +EVP_PKEY_verify_recover_init_ex2, EVP_PKEY_verify_recover - recover signature using a public key algorithm =head1 SYNOPSIS @@ -13,6 +13,8 @@ EVP_PKEY_verify_recover int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]); + int EVP_PKEY_verify_recover_init_ex2(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo, + const OSSL_PARAM params[]); int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen, const unsigned char *sig, size_t siglen); @@ -29,6 +31,14 @@ EVP_PKEY_verify_recover_init_ex() is the same as EVP_PKEY_verify_recover_init() but additionally sets the passed parameters I on the context before returning. +EVP_PKEY_verify_recover_init_ex2() is the same as EVP_PKEY_verify_recover_init_ex(), +but works with an explicitly fetched B I. +A context I without a pre-loaded key cannot be used with this function. +Depending on what algorithm was fetched, certain details revolving around the +treatment of the input to EVP_PKEY_verify() may be pre-determined, and in that +case, those details may normally not be changed. +See L below for a deeper explanation. + The EVP_PKEY_verify_recover() function recovers signed data using I. The signature is specified using the I and I parameters. If I is NULL then the maximum size of the output @@ -51,6 +61,10 @@ After the call to EVP_PKEY_verify_recover_init() algorithm specific control operations can be performed to set any appropriate parameters for the operation. +After the call to EVP_PKEY_verify_recover_init_ex2(), algorithm specific control +operations may not be needed if the chosen algorithm implies that those controls +pre-set (and immutable). + The function EVP_PKEY_verify_recover() can be called more than once on the same context if several operations are performed using the same parameters. @@ -118,7 +132,7 @@ The EVP_PKEY_verify_recover_init_ex() function was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/EVP_RAND.pod b/doc/man3/EVP_RAND.pod index e5f75010499c..fdb9ef9dcfd1 100644 --- a/doc/man3/EVP_RAND.pod +++ b/doc/man3/EVP_RAND.pod @@ -3,7 +3,7 @@ =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_CTX_new, EVP_RAND_CTX_free, EVP_RAND_CTX_up_ref, 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, @@ -30,6 +30,7 @@ EVP_RAND_STATE_ERROR - EVP RAND routines 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); + int EVP_RAND_CTX_up_ref(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[]); @@ -266,6 +267,12 @@ Returns the state of the random number generator. Returns the bit strength of the random number generator. +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This option is used by the OpenSSL FIPS provider and is not supported +by all EVP_RAND sources. + =back For rands that are also deterministic random bit generators (DRBGs), these @@ -376,6 +383,8 @@ B structure or NULL if an error occurred. EVP_RAND_CTX_free() does not return a value. +EVP_RAND_CTX_up_ref() returns 1 on success, 0 on error. + EVP_RAND_nonce() returns the length of the nonce. EVP_RAND_get_strength() returns the strength of the random number generator @@ -402,7 +411,9 @@ L =head1 HISTORY -This functionality was added to OpenSSL 3.0. +EVP_RAND_CTX_up_ref() was added in OpenSSL 3.1. + +The remaining functions were added in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man3/EVP_SignInit.pod b/doc/man3/EVP_SignInit.pod index 11832ff76180..553ce0e34778 100644 --- a/doc/man3/EVP_SignInit.pod +++ b/doc/man3/EVP_SignInit.pod @@ -66,12 +66,19 @@ due to external circumstances (see L), the operation will fail. The call to EVP_SignFinal() internally finalizes a copy of the digest context. This means that calls to EVP_SignUpdate() and EVP_SignFinal() can be called -later to digest and sign additional data. +later to digest and sign additional data.cApplications may disable this +behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via +L. Since only a copy of the digest context is ever finalized the context must be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak will occur. +Note that not all providers support continuation, in case the selected +provider does not allow to duplicate contexts EVP_SignFinal() will +finalize the digest context and attempting to process additional data via +EVP_SignUpdate() will result in an error. + =head1 BUGS Older versions of this documentation wrongly stated that calls to @@ -102,7 +109,7 @@ The function EVP_SignFinal_ex() was added in OpenSSL 3.0. =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 diff --git a/doc/man3/EVP_VerifyInit.pod b/doc/man3/EVP_VerifyInit.pod index a6d5772c3b83..04598046712d 100644 --- a/doc/man3/EVP_VerifyInit.pod +++ b/doc/man3/EVP_VerifyInit.pod @@ -62,12 +62,19 @@ transparent to the algorithm used and much more flexible. The call to EVP_VerifyFinal() internally finalizes a copy of the digest context. This means that calls to EVP_VerifyUpdate() and EVP_VerifyFinal() can be called -later to digest and verify additional data. +later to digest and verify additional data. Applications may disable this +behavior by setting the EVP_MD_CTX_FLAG_FINALISE context flag via +L. Since only a copy of the digest context is ever finalized the context must be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak will occur. +Note that not all providers support continuation, in case the selected +provider does not allow to duplicate contexts EVP_VerifyFinal() will +finalize the digest context and attempting to process additional data via +EVP_VerifyUpdate() will result in an error. + =head1 BUGS Older versions of this documentation wrongly stated that calls to @@ -97,7 +104,7 @@ The function EVP_VerifyFinal_ex() was added in OpenSSL 3.0. =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 diff --git a/doc/man3/EVP_blake2b512.pod b/doc/man3/EVP_blake2b512.pod index 55bd9f3bce77..7bf08f6495fa 100644 --- a/doc/man3/EVP_blake2b512.pod +++ b/doc/man3/EVP_blake2b512.pod @@ -38,9 +38,8 @@ calling these functions multiple times and should consider using L with L instead. See L 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. +Both algorithms support a variable-length digest, +but this is only available through L. =head1 RETURN VALUES diff --git a/doc/man3/EVP_set_default_properties.pod b/doc/man3/EVP_set_default_properties.pod index 2d862772c251..0c0f67c7cbc3 100644 --- a/doc/man3/EVP_set_default_properties.pod +++ b/doc/man3/EVP_set_default_properties.pod @@ -3,14 +3,15 @@ =head1 NAME EVP_set_default_properties, EVP_default_properties_enable_fips, -EVP_default_properties_is_fips_enabled -- Set default properties for future algorithm fetches +EVP_default_properties_is_fips_enabled, EVP_get1_default_properties +- manage default properties for future algorithm fetches =head1 SYNOPSIS #include int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq); + char *EVP_get1_default_properties(OSSL_LIB_CTX *libctx); int EVP_default_properties_enable_fips(OSSL_LIB_CTX *libctx, int enable); int EVP_default_properties_is_fips_enabled(OSSL_LIB_CTX *libctx); @@ -28,6 +29,10 @@ given with I (NULL signifies the default library context). Any previous default property for the specified library context will be dropped. +EVP_get1_default_properties() gets the default properties set for all future EVP +algorithm fetches, implicit as well as explicit, for the specific library +context. + EVP_default_properties_enable_fips() sets the 'fips=yes' to be a default property if I is non zero, otherwise it clears 'fips' from the default property query for the given I. It merges the fips default property query with any @@ -42,6 +47,10 @@ EVP_set_default_properties() and EVP_default_properties_enable_fips() are not thread safe. They are intended to be called only during the initialisation phase of a I. +EVP_get1_default_properties() is not thread safe. The application must ensure +that the context reference is valid and default fetching properties are not +being modified by a different thread. + =head1 RETURN VALUES EVP_set_default_properties() and EVP_default_properties_enable_fips() return 1 @@ -51,17 +60,24 @@ failure occurs. EVP_default_properties_is_fips_enabled() returns 1 if the 'fips=yes' default property is set for the given I, otherwise it returns 0. +EVP_get1_default_properties() returns allocated memory that must be freed by +L on success and NULL on failure. + =head1 SEE ALSO L =head1 HISTORY -The functions described here were added in OpenSSL 3.0. +The functions EVP_set_default_properties(), EVP_default_properties_enable_fips(), +EVP_default_properties_is_fips_enabled() were added in OpenSSL 3.0. + +The function EVP_get1_default_properties() was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/MD5.pod b/doc/man3/MD5.pod index 99bf82116015..e56eafc16ff2 100644 --- a/doc/man3/MD5.pod +++ b/doc/man3/MD5.pod @@ -70,7 +70,7 @@ MD2_Final() places the message digest in B, which must have space for MD2_DIGEST_LENGTH == 16 bytes of output, and erases the B. MD4_Init(), MD4_Update(), MD4_Final(), MD5_Init(), MD5_Update(), and -MD5_Final() are analogous using an B and B structure. +MD5_Final() are analogous using an B and B structure. The parameter B be NULL. Applications should use the higher level functions L diff --git a/doc/man3/MDC2_Init.pod b/doc/man3/MDC2_Init.pod index f29c9b78dc25..37b2ba38153b 100644 --- a/doc/man3/MDC2_Init.pod +++ b/doc/man3/MDC2_Init.pod @@ -70,7 +70,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OBJ_nid2obj.pod b/doc/man3/OBJ_nid2obj.pod index 94eb6cc5899f..62f506149964 100644 --- a/doc/man3/OBJ_nid2obj.pod +++ b/doc/man3/OBJ_nid2obj.pod @@ -89,7 +89,8 @@ OBJ_dup() returns a copy of I. OBJ_create() adds a new object to the internal table. I is the numerical form of the object, I the short name and I the long name. A new NID is returned for the created object in case of -success and NID_undef in case of failure. +success and NID_undef in case of failure. Any of I, I and +I may be NULL, but not all at once. OBJ_length() returns the size of the content octets of I. @@ -142,6 +143,8 @@ These functions cannot return B because an B can represent both an internal, constant, OID and a dynamically-created one. The latter cannot be constant because it needs to be freed after use. +These functions were not thread safe in OpenSSL 3.0 and before. + =head1 RETURN VALUES OBJ_nid2obj() returns an B structure or B is an @@ -180,12 +183,6 @@ Create a new object directly: obj = OBJ_txt2obj("1.2.3.4", 1); -=head1 BUGS - -Neither OBJ_create() nor OBJ_add_sigid() do any locking and are thus not -thread safe. Moreover, none of the other functions should be called while -concurrent calls to these two functions are possible. - =head1 SEE ALSO L diff --git a/doc/man3/OCSP_resp_find_status.pod b/doc/man3/OCSP_resp_find_status.pod index 0fa1a3cf249a..bc5db7086252 100644 --- a/doc/man3/OCSP_resp_find_status.pod +++ b/doc/man3/OCSP_resp_find_status.pod @@ -210,7 +210,7 @@ L =head1 COPYRIGHT -Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OCSP_sendreq_new.pod b/doc/man3/OCSP_sendreq_new.pod index ce2749ed1ba6..97e1ac4d3dd1 100644 --- a/doc/man3/OCSP_sendreq_new.pod +++ b/doc/man3/OCSP_sendreq_new.pod @@ -115,7 +115,7 @@ were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OPENSSL_LH_COMPFUNC.pod b/doc/man3/OPENSSL_LH_COMPFUNC.pod index f62c57172cb7..7812cc2348ad 100644 --- a/doc/man3/OPENSSL_LH_COMPFUNC.pod +++ b/doc/man3/OPENSSL_LH_COMPFUNC.pod @@ -2,7 +2,7 @@ =head1 NAME -LHASH, DECLARE_LHASH_OF, +LHASH, LHASH_OF, DEFINE_LHASH_OF_EX, DEFINE_LHASH_OF, OPENSSL_LH_COMPFUNC, OPENSSL_LH_HASHFUNC, OPENSSL_LH_DOALL_FUNC, LHASH_DOALL_ARG_FN_TYPE, IMPLEMENT_LHASH_HASH_FN, IMPLEMENT_LHASH_COMP_FN, @@ -12,7 +12,8 @@ lh_TYPE_doall, lh_TYPE_doall_arg, lh_TYPE_num_items, lh_TYPE_get_down_load, lh_TYPE_set_down_load, lh_TYPE_error, OPENSSL_LH_new, OPENSSL_LH_free, OPENSSL_LH_flush, OPENSSL_LH_insert, OPENSSL_LH_delete, OPENSSL_LH_retrieve, -OPENSSL_LH_doall, OPENSSL_LH_doall_arg, OPENSSL_LH_num_items, +OPENSSL_LH_doall, OPENSSL_LH_doall_arg, OPENSSL_LH_doall_arg_thunk, +OPENSSL_LH_set_thunks, OPENSSL_LH_num_items, OPENSSL_LH_get_down_load, OPENSSL_LH_set_down_load, OPENSSL_LH_error - dynamic hash table @@ -22,11 +23,18 @@ OPENSSL_LH_get_down_load, OPENSSL_LH_set_down_load, OPENSSL_LH_error #include - DECLARE_LHASH_OF(TYPE); + LHASH_OF(TYPE) + + DEFINE_LHASH_OF_EX(TYPE); LHASH_OF(TYPE) *lh_TYPE_new(OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC compare); void lh_TYPE_free(LHASH_OF(TYPE) *table); void lh_TYPE_flush(LHASH_OF(TYPE) *table); + OPENSSL_LHASH *OPENSSL_LH_set_thunks(OPENSSL_LHASH *lh, + OPENSSL_LH_HASHFUNCTHUNK hw, + OPENSSL_LH_COMPFUNCTHUNK cw, + OPENSSL_LH_DOALL_FUNC_THUNK daw, + OPENSSL_LH_DOALL_FUNCARG_THUNK daaw) TYPE *lh_TYPE_insert(LHASH_OF(TYPE) *table, TYPE *data); TYPE *lh_TYPE_delete(LHASH_OF(TYPE) *table, TYPE *data); @@ -35,6 +43,9 @@ OPENSSL_LH_get_down_load, OPENSSL_LH_set_down_load, OPENSSL_LH_error void lh_TYPE_doall(LHASH_OF(TYPE) *table, OPENSSL_LH_DOALL_FUNC func); void lh_TYPE_doall_arg(LHASH_OF(TYPE) *table, OPENSSL_LH_DOALL_FUNCARG func, TYPE *arg); + void OPENSSL_LH_doall_arg_thunk(OPENSSL_LHASH *lh, + OPENSSL_LH_DOALL_FUNCARG_THUNK daaw, + OPENSSL_LH_DOALL_FUNCARG fn, void *arg) unsigned long lh_TYPE_num_items(OPENSSL_LHASH *lh); unsigned long lh_TYPE_get_down_load(OPENSSL_LHASH *lh); @@ -66,6 +77,10 @@ OPENSSL_LH_get_down_load, OPENSSL_LH_set_down_load, OPENSSL_LH_error #define LH_LOAD_MULT /* integer constant */ +The following macro is deprecated: + + DEFINE_LHASH_OF(TYPE); + =head1 DESCRIPTION This library implements type-checked dynamic hash tables. The hash @@ -73,6 +88,12 @@ table entries can be arbitrary structures. Usually they consist of key and value fields. In the description here, B> is used a placeholder for any of the OpenSSL datatypes, such as I. +To define a new type-checked dynamic hash table, use B(). +B() was previously used for this purpose, but is now +deprecated. The B() macro provides all functionality of +B() except for certain deprecated statistics functions (see +OPENSSL_LH_stats(3)). + B_new>() creates a new B(B>) structure to store arbitrary data entries, and specifies the 'hash' and 'compare' callbacks to be used in organising the table's entries. The I @@ -220,6 +241,9 @@ B> functions are implemented as type checked wrappers around the B functions. Most applications should not call the B functions directly. +OPENSSL_LH_set_thunks() and OPENSSL_LH_doall_arg_thunk(), while public by +necessity, are actually internal functions and should not be used. + =head1 RETURN VALUES B_new>() and OPENSSL_LH_new() return NULL on error, otherwise a @@ -297,6 +321,12 @@ L In OpenSSL 1.0.0, the lhash interface was revamped for better type checking. +In OpenSSL 3.1, B() was introduced and B() +was deprecated. + +OPENSSL_LH_doall_arg_thunk(), OPENSSL_LH_set_thunks() were added in +OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OPENSSL_LH_stats.pod b/doc/man3/OPENSSL_LH_stats.pod index b86de52cb58b..fb95928d8f20 100644 --- a/doc/man3/OPENSSL_LH_stats.pod +++ b/doc/man3/OPENSSL_LH_stats.pod @@ -10,14 +10,19 @@ OPENSSL_LH_node_stats_bio, OPENSSL_LH_node_usage_stats_bio - LHASH statistics #include - void OPENSSL_LH_stats(LHASH *table, FILE *out); +The following functions have been deprecated since OpenSSL 3.1, and can be +hidden entirely by defining B with a suitable version value, +see L: + void OPENSSL_LH_node_stats(LHASH *table, FILE *out); void OPENSSL_LH_node_usage_stats(LHASH *table, FILE *out); - void OPENSSL_LH_stats_bio(LHASH *table, BIO *out); void OPENSSL_LH_node_stats_bio(LHASH *table, BIO *out); void OPENSSL_LH_node_usage_stats_bio(LHASH *table, BIO *out); + void OPENSSL_LH_stats(LHASH *table, FILE *out); + void OPENSSL_LH_stats_bio(LHASH *table, BIO *out); + =head1 DESCRIPTION The B structure records statistics about most aspects of @@ -43,6 +48,8 @@ record a miss. OPENSSL_LH_stats_bio(), OPENSSL_LH_node_stats_bio() and OPENSSL_LH_node_usage_stats_bio() are the same as the above, except that the output goes to a B. +These functions are deprecated and should no longer be used. + =head1 RETURN VALUES These functions do not return values. @@ -57,6 +64,10 @@ when using the LHASH data structure. L, L +=head1 HISTORY + +These functions were deprecated in version 3.1. + =head1 COPYRIGHT Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OPENSSL_config.pod b/doc/man3/OPENSSL_config.pod index 3fe6dd0e496b..60f1c5a6582c 100644 --- a/doc/man3/OPENSSL_config.pod +++ b/doc/man3/OPENSSL_config.pod @@ -77,7 +77,7 @@ deprecated in OpenSSL 1.1.0 by OPENSSL_init_crypto(). =head1 COPYRIGHT -Copyright 2004-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OPENSSL_fork_prepare.pod b/doc/man3/OPENSSL_fork_prepare.pod index 6f8277c110da..646c0932078a 100644 --- a/doc/man3/OPENSSL_fork_prepare.pod +++ b/doc/man3/OPENSSL_fork_prepare.pod @@ -60,7 +60,7 @@ These functions were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OPENSSL_ia32cap.pod b/doc/man3/OPENSSL_ia32cap.pod index c6c1c0185ad8..2b0dc93d494c 100644 --- a/doc/man3/OPENSSL_ia32cap.pod +++ b/doc/man3/OPENSSL_ia32cap.pod @@ -10,81 +10,77 @@ OPENSSL_ia32cap - the x86[_64] processor capabilities vector =head1 DESCRIPTION -OpenSSL supports a range of x86[_64] instruction set extensions. These -extensions are denoted by individual bits in capability vector returned -by processor in EDX:ECX register pair after executing CPUID instruction -with EAX=1 input value (see Intel Application Note #241618). This vector -is copied to memory upon toolkit initialization and used to choose -between different code paths to provide optimal performance across wide -range of processors. For the moment of this writing following bits are -significant: +OpenSSL supports a range of x86[_64] instruction set extensions and +features. These extensions are denoted by individual bits or groups of bits +stored internally as ten 32-bit capability vectors and for simplicity +represented logically below as five 64-bit vectors. This logical +vector (LV) representation is used to streamline the definition of the +OPENSSL_ia32cap environment variable. + +Upon toolkit initialization, the capability vectors are populated through +successive executions of the CPUID instruction, after which any OPENSSL_ia32cap +environment variable capability bit modifications are applied. After toolkit +initialization is complete, populated vectors are then used to choose +between different code paths to provide optimal performance across a wide +range of x86[_64] based processors. + +Further CPUID information can be found in the Intel(R) Architecture +Instruction Set Extensions Programming Reference, and the AMD64 Architecture +Programmer's Manual (Volume 3). + +=head2 Notable Capability Bits for LV0 + +The following are notable capability bits from logical vector 0 (LV0) +resulting from the following execution of CPUID.(EAX=01H).EDX and +CPUID.(EAX=01H).ECX: =over 4 -=item bit #4 denoting presence of Time-Stamp Counter. +=item bit #0+4 denoting presence of Time-Stamp Counter; -=item bit #19 denoting availability of CLFLUSH instruction; +=item bit #0+19 denoting availability of CLFLUSH instruction; -=item bit #20, reserved by Intel, is used to choose among RC4 code paths; +=item bit #0+20, reserved by Intel, is used to choose among RC4 code paths; -=item bit #23 denoting MMX support; +=item bit #0+23 denoting MMX support; -=item bit #24, FXSR bit, denoting availability of XMM registers; +=item bit #0+24, FXSR bit, denoting availability of XMM registers; -=item bit #25 denoting SSE support; +=item bit #0+25 denoting SSE support; -=item bit #26 denoting SSE2 support; +=item bit #0+26 denoting SSE2 support; -=item bit #28 denoting Hyperthreading, which is used to distinguish +=item bit #0+28 denoting Hyperthreading, which is used to distinguish cores with shared cache; -=item bit #30, reserved by Intel, denotes specifically Intel CPUs; +=item bit #0+30, reserved by Intel, denotes specifically Intel CPUs; -=item bit #33 denoting availability of PCLMULQDQ instruction; +=item bit #0+33 denoting availability of PCLMULQDQ instruction; -=item bit #41 denoting SSSE3, Supplemental SSE3, support; +=item bit #0+41 denoting SSSE3, Supplemental SSE3, support; -=item bit #43 denoting AMD XOP support (forced to zero on non-AMD CPUs); +=item bit #0+43 denoting AMD XOP support (forced to zero on non-AMD CPUs); -=item bit #54 denoting availability of MOVBE instruction; +=item bit #0+54 denoting availability of MOVBE instruction; -=item bit #57 denoting AES-NI instruction set extension; +=item bit #0+57 denoting AES-NI instruction set extension; -=item bit #58, XSAVE bit, lack of which in combination with MOVBE is used +=item bit #0+58, XSAVE bit, lack of which in combination with MOVBE is used to identify Atom Silvermont core; -=item bit #59, OSXSAVE bit, denoting availability of YMM registers; +=item bit #0+59, OSXSAVE bit, denoting availability of YMM registers; -=item bit #60 denoting AVX extension; +=item bit #0+60 denoting AVX extension; -=item bit #62 denoting availability of RDRAND instruction; +=item bit #0+62 denoting availability of RDRAND instruction; =back -For example, in 32-bit application context clearing bit #26 at run-time -disables high-performance SSE2 code present in the crypto library, while -clearing bit #24 disables SSE2 code operating on 128-bit XMM register -bank. You might have to do the latter if target OpenSSL application is -executed on SSE2 capable CPU, but under control of OS that does not -enable XMM registers. Historically address of the capability vector copy -was exposed to application through OPENSSL_ia32cap_loc(), but not -anymore. Now the only way to affect the capability detection is to set -B environment variable prior target application start. To -give a specific example, on Intel P4 processor -C, or better yet -C would achieve the desired -effect. Alternatively you can reconfigure the toolkit with no-sse2 -option and recompile. +=head2 Notable Capability Bits for LV1 -Less intuitive is clearing bit #28, or ~0x10000000 in the "environment -variable" terms. The truth is that it's not copied from CPUID output -verbatim, but is adjusted to reflect whether or not the data cache is -actually shared between logical cores. This in turn affects the decision -on whether or not expensive countermeasures against cache-timing attacks -are applied, most notably in AES assembler module. - -The capability vector is further extended with EBX value returned by -CPUID with EAX=7 and ECX=0 as input. Following bits are significant: +The following are notable capability bits from logical vector 1 (LV1) +resulting from the following execution of CPUID.(EAX=07H,ECX=0H).EBX and +CPUID.(EAX=07H,ECX=0H).ECX: =over 4 @@ -103,8 +99,7 @@ and RORX; =item bit #64+19 denoting availability of ADCX and ADOX instructions; -=item bit #64+21 denoting availability of VPMADD52[LH]UQ instructions, -aka AVX512IFMA extension; +=item bit #64+21 denoting availability of AVX512IFMA extension; =item bit #64+29 denoting availability of SHA extension; @@ -118,10 +113,109 @@ aka AVX512IFMA extension; =back -To control this extended capability word use C<:> as delimiter when -setting up B environment variable. For example assigning -C<:~0x20> would disable AVX2 code paths, and C<:0> - all post-AVX -extensions. +=head2 Notable Capability Bits for LV2 + +The following are notable capability bits from logical vector 2 (LV2) +resulting from the following execution of CPUID.(EAX=07H,ECX=0H).EDX and +CPUID.(EAX=07H,ECX=1H).EAX: + +=over 4 + +=item bit #128+15 denoting availability of Hybrid CPU; + +=item bit #128+29 denoting support for IA32_ARCH_CAPABILITIES MSR; + +=item bit #128+32 denoting availability of SHA512 extension; + +=item bit #128+33 denoting availability of SM3 extension; + +=item bit #128+34 denoting availability of SM4 extension; + +=item bit #128+55 denoting availability of AVX-IFMA extension; + +=back + +=head2 Notable Capability Bits for LV3 + +The following are notable capability bits from logical vector 3 (LV3) +resulting from the following execution of CPUID.(EAX=07H,ECX=1H).EDX and +CPUID.(EAX=07H,ECX=1H).EBX: + +=over 4 + +=item bit #192+19 denoting availability of AVX10 Converged Vector ISA extension; + +=item bit #192+21 denoting availability of APX_F extension; + +=back + +=head2 Notable Capability Bits for LV4 + +The following are notable capability bits from logical vector 4 (LV4) +resulting from the following execution of CPUID.(EAX=07H,ECX=1H).ECX and +CPUID.(EAX=24H,ECX=0H).EBX: + +=over 4 + +=item bits #256+32+[0:7] denoting AVX10 Converged Vector ISA Version (8 bits); + +=item bit #256+48 denoting AVX10 XMM support; + +=item bit #256+49 denoting AVX10 YMM support; + +=item bit #256+50 denoting AVX10 ZMM support; + +=back + +=head2 OPENSSL_ia32cap environment variable + +The B environment variable provides a mechanism to override +the default capability vector values at library initialization time. +The variable consists of a series of 64-bit numbers representing each +of the logical vectors (LV) described above. Each value is delimited by a 'B<:>'. +Decimal/Octal/Hexadecimal values representations are supported. + +C + +Used in this form, each non-null logical vector will *overwrite* the entire corresponding +capability vector pair with the provided value. To keep compatibility with the +behaviour of the original OPENSSL_ia32cap environment variable +, the next capability vector pairs will be set to zero. + +To illustrate, the following will zero all capability bits in logical vectors 1 and further +(disable all post-AVX extensions): + +C + +The following will zero all capability bits in logical vectors 2 and further: + +C + +The following will zero all capability bits only in logical vector 1: +C + +A more likely usage scenario would be to disable specific instruction set extensions. +The 'B<~>' character is used to specify a bit mask of the extensions to be disabled for +a particular logical vector. + +To illustrate, the following will disable AVX2 code paths and further extensions: + +C + +The following will disable AESNI (LV0 bit 57) and VAES (LV1 bit 41) +extensions and therefore any code paths using those extensions but leave +the rest of the logical vectors unchanged: + +C + +=head1 NOTES + +Not all capability bits are copied from CPUID output verbatim. An example +of this is the somewhat less intuitive clearing of LV0 bit #28, or ~0x10000000 +in the "environment variable" terms. It has been adjusted to reflect whether or +not the data cache is actually shared between logical cores. This in turn affects +the decision on whether or not expensive countermeasures against cache-timing attacks +are applied, most notably in AES assembler module. =head1 RETURN VALUES diff --git a/doc/man3/OPENSSL_instrument_bus.pod b/doc/man3/OPENSSL_instrument_bus.pod index 1af07b29c7ed..c5e3d3fca415 100644 --- a/doc/man3/OPENSSL_instrument_bus.pod +++ b/doc/man3/OPENSSL_instrument_bus.pod @@ -43,7 +43,7 @@ Otherwise number of recorded values is returned. =head1 COPYRIGHT -Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OPENSSL_malloc.pod b/doc/man3/OPENSSL_malloc.pod index 20441e76ac65..d02eb47e9a6e 100644 --- a/doc/man3/OPENSSL_malloc.pod +++ b/doc/man3/OPENSSL_malloc.pod @@ -3,11 +3,11 @@ =head1 NAME OPENSSL_malloc_init, -OPENSSL_malloc, OPENSSL_zalloc, OPENSSL_realloc, OPENSSL_free, -OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse, -CRYPTO_malloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free, +OPENSSL_malloc, OPENSSL_aligned_alloc, OPENSSL_zalloc, OPENSSL_realloc, +OPENSSL_free, OPENSSL_clear_realloc, OPENSSL_clear_free, OPENSSL_cleanse, +CRYPTO_malloc, CRYPTO_aligned_alloc, CRYPTO_zalloc, CRYPTO_realloc, CRYPTO_free, OPENSSL_strdup, OPENSSL_strndup, -OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat, +OPENSSL_memdup, OPENSSL_strlcpy, OPENSSL_strlcat, OPENSSL_strtoul, CRYPTO_strdup, CRYPTO_strndup, OPENSSL_mem_debug_push, OPENSSL_mem_debug_pop, CRYPTO_mem_debug_push, CRYPTO_mem_debug_pop, @@ -28,6 +28,7 @@ OPENSSL_MALLOC_FD int OPENSSL_malloc_init(void); void *OPENSSL_malloc(size_t num); + void *OPENSSL_aligned_alloc(size_t num, size_t alignment, void **freeptr); void *OPENSSL_zalloc(size_t num); void *OPENSSL_realloc(void *addr, size_t num); void OPENSSL_free(void *addr); @@ -35,12 +36,15 @@ OPENSSL_MALLOC_FD char *OPENSSL_strndup(const char *str, size_t s); size_t OPENSSL_strlcat(char *dst, const char *src, size_t size); size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size); + int OPENSSL_strtoul(char *src, char **endptr, int base, unsigned long *num); void *OPENSSL_memdup(void *data, size_t s); void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num); void OPENSSL_clear_free(void *str, size_t num); void OPENSSL_cleanse(void *ptr, size_t len); void *CRYPTO_malloc(size_t num, const char *file, int line); + void *CRYPTO_aligned_alloc(size_t num, size_t align, void **freeptr, + const char *file, int line); void *CRYPTO_zalloc(size_t num, const char *file, int line); void *CRYPTO_realloc(void *p, size_t num, const char *file, int line); void CRYPTO_free(void *str, const char *, int); @@ -96,6 +100,20 @@ OPENSSL_malloc(), OPENSSL_realloc(), and OPENSSL_free() are like the C malloc(), realloc(), and free() functions. OPENSSL_zalloc() calls memset() to zero the memory before returning. +OPENSSL_aligned_alloc() operates just as OPENSSL_malloc does, but it +allows for the caller to specify an alignment value, for instances in +which the default alignment of malloc is insufficient for the callers +needs. Note, the alignment value must be a power of 2, and the size +specified must be a multiple of the alignment. +NOTE: The call to OPENSSL_aligned_alloc() accepts a 3rd argument, I +which must point to a void pointer. On some platforms, there is no available +library call to obtain memory allocations greater than what malloc provides. In +this case, OPENSSL_aligned_alloc implements its own alignment routine, +allocating additional memory and offsetting the returned pointer to be on the +requested alignment boundary. In order to safely free allocations made by this +method, the caller must return the value in the I variable, rather than +the returned pointer. + OPENSSL_clear_realloc() and OPENSSL_clear_free() should be used when the buffer at B holds sensitive information. The old buffer is filled with zero's by calling OPENSSL_cleanse() @@ -118,6 +136,12 @@ OPENSSL_strlcpy(), OPENSSL_strlcat() and OPENSSL_strnlen() are equivalents of the common C library functions and are provided for portability. +OPENSSL_strtoul() is a wrapper around the POSIX function strtoul, with the same +behaviors listed in the POSIX documentation, with the additional behavior that +it validates the input I and I parameters for not being NULL, and confirms +that at least a single byte of input has been consumed in the translation, +returning an error in the event that no bytes were consumed. + If no allocations have been done, it is possible to "swap out" the default implementations for OPENSSL_malloc(), OPENSSL_realloc() and OPENSSL_free() and replace them with alternate versions. @@ -147,7 +171,8 @@ It is a set of fields separated by semicolons, which each field is a count to 100). If the count is zero, then it lasts forever. For example, C<100;@25> or C<100@0;0@25> means the first 100 allocations pass, then all other allocations (until the program exits or crashes) have a 25% chance of -failing. +failing. The length of the value of B must be 256 or +fewer characters. If the variable B is parsed as a positive integer, then it is taken as an open file descriptor. This is used in conjunction with @@ -169,7 +194,7 @@ OPENSSL_malloc_init(), OPENSSL_free(), OPENSSL_clear_free() CRYPTO_free(), CRYPTO_clear_free() and CRYPTO_get_mem_functions() return no value. -OPENSSL_malloc(), OPENSSL_zalloc(), OPENSSL_realloc(), +OPENSSL_malloc(), OPENSSL_aligned_alloc(), OPENSSL_zalloc(), OPENSSL_realloc(), OPENSSL_clear_realloc(), CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_realloc(), CRYPTO_clear_realloc(), @@ -186,6 +211,35 @@ OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(), CRYPTO_mem_debug_push(), and CRYPTO_mem_debug_pop() are deprecated and are no-ops that always return 0. +OPENSSL_strtoul() returns 1 on success and 0 in the event that an error has +occurred. Specifically, 0 is returned in the following events: + +=over 4 + +=item * + +If the underlying call to strtoul returned a non zero errno value + +=item * + +If the translation did not consume the entire input string, and the passed +endptr value was NULL + +=item * + +If no characters were consumed in the translation + +=back + +Note that a success condition does not imply that the expected +translation has been performed. For instance calling + + OPENSSL_strtoul("0x12345", &endptr, 10, &num); + +will result in a successful translation with num having the value 0, and +*endptr = 'x'. Be sure to validate how much data was consumed when calling this +function. + =head1 HISTORY OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(), @@ -195,7 +249,8 @@ CRYPTO_mem_leaks_cb(), CRYPTO_set_mem_debug(), CRYPTO_mem_ctrl() were deprecated in OpenSSL 3.0. The memory-leak checking has been deprecated in OpenSSL 3.0 in favor of clang's memory and leak sanitizer. - +OPENSSL_aligned_alloc(), CRYPTO_aligned_alloc(), OPENSSL_strtoul() were +added in OpenSSL 3.4. =head1 COPYRIGHT diff --git a/doc/man3/OPENSSL_s390xcap.pod b/doc/man3/OPENSSL_s390xcap.pod index f40524115324..a4ca0654be54 100644 --- a/doc/man3/OPENSSL_s390xcap.pod +++ b/doc/man3/OPENSSL_s390xcap.pod @@ -25,7 +25,7 @@ processed from left to right (whitespace is ignored): OPENSSL_s390xcap=";;..." -There are three types of tokens: +There are four types of tokens: =over 4 @@ -34,8 +34,8 @@ There are three types of tokens: The name of a processor generation. A bit in the environment variable's mask is set to one if and only if the specified processor generation implements the corresponding instruction set extension. Possible values -are B, B, B, B, B, B, B, B -and B. +are B, B, B, B, B, B, B, B, +B, and B. =item :: @@ -51,6 +51,11 @@ Store-facility-list-extended (stfle) followed by three 64-bit masks. The part of the environment variable's mask corresponding to the stfle instruction is set to the specified 192-bit mask. +=item nocex + +Deactivate modular exponentiation and CRT operation offloading to +Crypto Express Adapters. + =back The 64-bit masks are specified in hexadecimal notation. The 0x prefix is @@ -69,6 +74,7 @@ the numbering is continuous across 64-bit mask boundaries. : # 76 1<<51 message-security assist extension 3 # 77 1<<50 message-security assist extension 4 + # 86 1<<41 message-security-assist extension 12 : #129 1<<62 vector facility #134 1<<57 vector packed decimal facility @@ -105,6 +111,8 @@ the numbering is continuous across 64-bit mask boundaries. # 50 1<<13 KM-XTS-AES-128 # 52 1<<11 KM-XTS-AES-256 : + # 82 1<<45 KM-XTS-AES-128-MSA10 + # 84 1<<43 KM-XTS-AES-256-MSA10 kmc : # 18 1<<45 KMC-AES-128 @@ -117,6 +125,10 @@ the numbering is continuous across 64-bit mask boundaries. # 19 1<<44 KMAC-AES-192 # 20 1<<43 KMAC-AES-256 : + # 112 1<<15 KMAC-SHA-224 + # 113 1<<14 KMAC-SHA-256 + # 114 1<<13 KMAC-SHA-384 + # 115 1<<12 KMAC-SHA-512 kmctr: : @@ -189,7 +201,7 @@ Disables the KM-XTS-AES and the KIMD-SHAKE function codes: =head1 COPYRIGHT -Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OPENSSL_strcasecmp.pod b/doc/man3/OPENSSL_strcasecmp.pod index 1bb8b18c5013..fe529f2d9605 100644 --- a/doc/man3/OPENSSL_strcasecmp.pod +++ b/doc/man3/OPENSSL_strcasecmp.pod @@ -35,9 +35,13 @@ unpredictably suffer when they use localization (e.g. Turkish locale is well-known with a specific I/i cases). These functions use C locale for string comparison. +=head1 HISTORY + +These functions were added in OpenSSL 3.0.3. + =head1 COPYRIGHT -Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index f2a38b0adef4..0df0e78367e9 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -5,6 +5,7 @@ OSSL_CMP_CTX_new, OSSL_CMP_CTX_free, OSSL_CMP_CTX_reinit, +OSSL_CMP_CTX_get0_libctx, OSSL_CMP_CTX_get0_propq, OSSL_CMP_CTX_set_option, OSSL_CMP_CTX_get_option, OSSL_CMP_CTX_set_log_cb, @@ -24,7 +25,9 @@ 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_trusted, OSSL_CMP_CTX_set0_trustedStore, +OSSL_CMP_CTX_get0_trusted, OSSL_CMP_CTX_get0_trustedStore, OSSL_CMP_CTX_set1_untrusted, OSSL_CMP_CTX_get0_untrusted, @@ -36,10 +39,12 @@ 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_get0_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_serialNumber, OSSL_CMP_CTX_set1_subjectName, OSSL_CMP_CTX_push1_subjectAltName, OSSL_CMP_CTX_set0_reqExtensions, @@ -56,6 +61,7 @@ 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_validatedSrvCert, OSSL_CMP_CTX_get0_newCert, OSSL_CMP_CTX_get1_newChain, OSSL_CMP_CTX_get1_caPubs, @@ -71,6 +77,8 @@ OSSL_CMP_CTX_set1_senderNonce 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); + OSSL_LIB_CTX *OSSL_CMP_CTX_get0_libctx(const OSSL_CMP_CTX *ctx); + const char *OSSL_CMP_CTX_get0_propq(const 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); @@ -99,7 +107,9 @@ OSSL_CMP_CTX_set1_senderNonce 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); + #define OSSL_CMP_CTX_set0_trusted OSSL_CMP_CTX_set0_trustedStore int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store); + #define OSSL_CMP_CTX_get0_trusted OSSL_CMP_CTX_get0_trustedStore 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); @@ -118,6 +128,8 @@ OSSL_CMP_CTX_set1_senderNonce 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); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_CTX_get0_geninfo_ITAVs(const OSSL_CMP_CTX *ctx); int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut); @@ -125,6 +137,7 @@ OSSL_CMP_CTX_set1_senderNonce 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_serialNumber(OSSL_CMP_CTX *ctx, const ASN1_INTEGER *sn); 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); @@ -151,6 +164,7 @@ OSSL_CMP_CTX_set1_senderNonce 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_validatedSrvCert(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); @@ -185,6 +199,12 @@ from the last executed transaction. It also clears any ITAVs that were added by OSSL_CMP_CTX_push0_genm_ITAV(). All other field values (i.e., CMP options) are retained for potential reuse. +OSSL_CMP_CTX_get0_libctx() returns the I argument that was used +when constructing I with OSSL_CMP_CTX_new(), which may be NULL. + +OSSL_CMP_CTX_get0_propq() returns the I argument that was used +when constructing I with OSSL_CMP_CTX_new(), which may be NULL. + 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. @@ -221,6 +241,17 @@ The following options can be set: A value <= 0 means no limitation (waiting indefinitely). Default is 0. +=item B + + Use this option to indicate to the HTTP implementation + whether TLS is going to be used for the connection (resulting in HTTPS). + The value 1 indicates that TLS is used for client-side HTTP connections, + which needs to be implemented via a callback function set by + OSSL_CMP_CTX_set_http_cb(). + The value 0 indicates that TLS is not used. + Default is -1 for backward compatibility: TLS is used by the client side + if and only if OSSL_CMP_CTX_set_http_cb_arg() sets a non-NULL I. + =item B Number of days new certificates are asked to be valid for. @@ -242,7 +273,8 @@ The following options can be set: Select the proof of possession method to use. Possible values are: - OSSL_CRMF_POPO_NONE - ProofOfPossession field omitted + OSSL_CRMF_POPO_NONE - ProofOfPossession field omitted, + which implies central key generation OSSL_CRMF_POPO_RAVERIFIED - assert that the RA has already verified the PoPo OSSL_CRMF_POPO_SIGNATURE - sign a value with private key, @@ -319,6 +351,11 @@ RFC 4210. this way has not been authenticated (at least not at CMP level). Taking it over as a trust anchor implements trust-on-first-use (TOFU). +=item B + + Do not cache certificates received in the extraCerts CMP message field. + Otherwise they are stored to potentially help validate further messages. + =back OSSL_CMP_CTX_get_option() reads the current value of the given option @@ -344,10 +381,14 @@ The default is C. OSSL_CMP_CTX_set1_server() sets the given server I
(which may be a hostname or IP address or NULL) in the given I. +If OSSL_CMP_CTX_get_transfer_cb_arg() sets a non-NULL argument, +this server address information is used for diagnostic output only. OSSL_CMP_CTX_set_serverPort() sets the port of the CMP server to connect to. If not used or the I argument is 0 the default port applies, which is 80 for HTTP and 443 for HTTPS. +If OSSL_CMP_CTX_get_transfer_cb_arg() sets a non-NULL argument, +this server port information is used for diagnostic output only. 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). @@ -368,25 +409,22 @@ Defaults to the environment variable C if set, else C. 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); + typedef BIO *(*HTTP_bio_cb_t) (BIO *bio, void *arg, int connect, int detail); -The callback may modify the I provided by L, -whereby it may make use of a custom defined argument I -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 argument being 1 and the I -argument being 1 if HTTPS is requested, i.e., SSL/TLS should be enabled. On -disconnect I is 0 and I 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(). +The callback may modify the I provided by L +as described for the I parameter of L. +The callback may make use of a custom defined argument I, +as described for the I parameter of L. +The argument is stored in the OSSL_CMP_CTX using OSSL_CMP_CTX_set_http_cb_arg(). +See also the B option described above. -OSSL_CMP_CTX_set_http_cb_arg() sets an argument, respectively a pointer to -a structure containing arguments, +OSSL_CMP_CTX_set_http_cb_arg() sets the argument, respectively a pointer to +a structure containing arguments such as an B structure, optionally to be used by the http connect/disconnect callback function. I is not consumed, and it must therefore explicitly be freed when not needed any more. I may be NULL to clear the entry. +If a non-NULL argument is set, it is an error to use OSSL_CMP_CTX_set1_proxy() +or OSSL_CMP_CTX_set1_no_proxy() for setting non-NULL strings. OSSL_CMP_CTX_get_http_cb_arg() gets the argument, respectively the pointer to a structure containing arguments, previously set by @@ -398,8 +436,6 @@ 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. The callback should send the CMP request message it obtains via the I parameter and on success return the response, else it must return NULL. @@ -418,8 +454,8 @@ OSSL_CMP_CTX_set_transfer_cb_arg() or NULL if unset. OSSL_CMP_CTX_set1_srvCert() sets the expected server cert in I and trusts it directly (even if it is expired) when verifying signed response messages. -This pins the accepted CMP server and -results in ignoring whatever may be set using OSSL_CMP_CTX_set0_trustedStore(). +This pins the accepted CMP server +and results in ignoring whatever may be set using OSSL_CMP_CTX_set0_trusted(). Any previously set value is freed. The I argument may be NULL to clear the entry. If set, the subject of the certificate is also used @@ -436,8 +472,9 @@ Note that this gives slightly more freedom than OSSL_CMP_CTX_set1_srvCert(), which pins the server to the holder of a particular certificate, while the expected sender name will continue to match after updates of the server cert. -OSSL_CMP_CTX_set0_trustedStore() -sets in the CMP context I the certificate store of type X509_STORE +OSSL_CMP_CTX_set0_trusted() is an alias of the original +OSSL_CMP_CTX_set0_trustedStore(). +It sets in the CMP context I 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 @@ -445,8 +482,9 @@ used for signature-based peer authentication. Any store entry already set before is freed. When given a NULL parameter the entry is cleared. -OSSL_CMP_CTX_get0_trustedStore() -extracts from the CMP context I the pointer to the currently set +OSSL_CMP_CTX_get0_trusted() is an alias of the original +OSSL_CMP_CTX_get0_trustedStore(). +It extracts from the CMP context I 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 @@ -454,19 +492,23 @@ 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. +This list of untrusted certificates in I will get augmented by extraCerts +in received CMP messages unless B is set. -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_get0_untrusted() returns a pointer to the +list of untrusted certs in I, which may be empty if unset. -OSSL_CMP_CTX_set1_cert() sets the CMP signer certificate, also called protection -certificate, related to the private key for signature-based message protection. +OSSL_CMP_CTX_set1_cert() sets the CMP I, +also called I, +related to the private key used for signature-based CMP message protection. Therefore the public key of this I 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 will be used as the sender field of outgoing -messages, while the subject of any cert set via OSSL_CMP_CTX_set1_oldCert() +messages, while the subject of any cert set via OSSL_CMP_CTX_set1_oldCert(), +the subject of any PKCS#10 CSR set via OSSL_CMP_CTX_set1_p10CSR(), and any value set via OSSL_CMP_CTX_set1_subjectName() are used as fallback. The I argument may be NULL to clear the entry. @@ -523,12 +565,16 @@ 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 to the stack in the I to be -added to the GeneralInfo field of the CMP PKIMessage header of a request +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_get0_geninfo_ITAVs() returns the list of ITAVs set in I +for inclusion in the generalInfo field of the CMP PKIMessage header of requests +or NULL if not set. + OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be sent to remote. @@ -546,6 +592,9 @@ 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_serialNumber() sets the serial number optionally used to +select the certificate to be revoked in Revocation Requests (RR). + 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, @@ -578,17 +627,22 @@ 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 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. +For RR, this is ignored if an issuer name and a serial number are provided using +OSSL_CMP_CTX_set1_issuer() and OSSL_CMP_CTX_set1_serialNumber(), respectively. +For IR/CR/KUR this sets the I, +which otherwise defaults to the CMP signer certificate. +The I determined this way, if any, is used for providing +default public key, subject DN, Subject Alternative Names, and issuer DN entries +in the requested certificate template of IR/CR/KUR messages. + 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. +If such a CSR is provided, its subject and public key fields are also +used as fallback values for the certificate template of IR/CR/KUR/RR messages, +and any extensions included are added to the template of IR/CR/KUR messages. OSSL_CMP_CTX_push0_genm_ITAV() adds I to the stack in the I which will be the body of a General Message sent with this context. @@ -603,6 +657,8 @@ 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, and if this fails it takes the received extraCerts as fallback. The resulting cert chain can be retrieved using OSSL_CMP_CTX_get1_newChain(). +This chain excludes the leaf certificate, i.e., the newly enrolled certificate. +Also the trust anchor (the root certificate) is not included. OSSL_CMP_CTX_set_certConf_cb() sets the callback used for evaluating the newly enrolled certificate before the library sends, depending on its result, @@ -668,6 +724,13 @@ F<< >>. 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_validatedSrvCert() returns +the successfully validated certificate, if any, that the CMP server used +in the current transaction for signature-based response message protection, +or NULL if the server used MAC-based protection. +The value is relevant only at the end of a successful transaction. +It may be used to check the authorization of the server based on its cert. + OSSL_CMP_CTX_get0_newCert() returns the pointer to the newly obtained certificate in case it is available, else NULL. @@ -700,13 +763,16 @@ CMP is defined in RFC 4210 (and CRMF in RFC 4211). OSSL_CMP_CTX_free() and OSSL_CMP_CTX_print_errors() do not return anything. OSSL_CMP_CTX_new(), +OSSL_CMP_CTX_get0_libctx(), OSSL_CMP_CTX_get0_propq(), OSSL_CMP_CTX_get_http_cb_arg(), OSSL_CMP_CTX_get_transfer_cb_arg(), -OSSL_CMP_CTX_get0_trustedStore(), +OSSL_CMP_CTX_get0_trusted(), OSSL_CMP_CTX_get0_untrusted(), +OSSL_CMP_CTX_get0_geninfo_ITAVs(), OSSL_CMP_CTX_get0_newPkey(), OSSL_CMP_CTX_get_certConf_cb_arg(), OSSL_CMP_CTX_get0_statusString(), +OSSL_CMP_CTX_get0_validatedSrvCert(), OSSL_CMP_CTX_get0_newCert(), OSSL_CMP_CTX_get0_newChain(), OSSL_CMP_CTX_get1_caPubs(), and @@ -737,7 +803,7 @@ Set up a CMP client context for sending requests and verifying responses: 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); + OSSL_CMP_CTX_set0_trusted(cmp_ctx, ts); Set up symmetric credentials for MAC-based message protection such as PBM: @@ -794,17 +860,31 @@ the id-it-signKeyPairTypes OID and prints info on the General Response contents: L, L, L, L, L, L, -L +L, L =head1 HISTORY The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_CTX_get0_trustedStore() was renamed to OSSL_CMP_CTX_get0_trusted() and +OSSL_CMP_CTX_set0_trustedStore() was renamed to OSSL_CMP_CTX_set0_trusted(), +using macros, while keeping the old names for backward compatibility, +in OpenSSL 3.2. + OSSL_CMP_CTX_reset_geninfo_ITAVs() was added in OpenSSL 3.0.8. +OSSL_CMP_CTX_set1_serialNumber(), +OSSL_CMP_CTX_get0_libctx(), OSSL_CMP_CTX_get0_propq(), and +OSSL_CMP_CTX_get0_validatedSrvCert() were added in OpenSSL 3.2. + +OSSL_CMP_CTX_get0_geninfo_ITAVs() was added in OpenSSL 3.3. + +Support for central key generation, requested via B, +was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod index 36bdf1917f39..6e79e9a0e3c3 100644 --- a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod +++ b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod @@ -3,7 +3,8 @@ =head1 NAME OSSL_CMP_HDR_get0_transactionID, -OSSL_CMP_HDR_get0_recipNonce +OSSL_CMP_HDR_get0_recipNonce, +OSSL_CMP_HDR_get0_geninfo_ITAVs - functions manipulating CMP message headers =head1 SYNOPSIS @@ -14,6 +15,8 @@ OSSL_CMP_HDR_get0_recipNonce OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr); =head1 DESCRIPTION @@ -22,6 +25,9 @@ PKIHeader. OSSL_CMP_HDR_get0_recipNonce returns the recipient nonce of the given PKIHeader. +OSSL_CMP_HDR_get0_geninfo_ITAVs() returns the list of ITAVs +in the generalInfo field of the given PKIHeader. + =head1 NOTES CMP is defined in RFC 4210. @@ -35,6 +41,8 @@ or NULL if the respective entry does not exist and on error. The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_HDR_get0_geninfo_ITAVs() was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_ITAV_set0.pod b/doc/man3/OSSL_CMP_ITAV_set0.pod index 593af73fcdd5..13d7868a6deb 100644 --- a/doc/man3/OSSL_CMP_ITAV_set0.pod +++ b/doc/man3/OSSL_CMP_ITAV_set0.pod @@ -6,25 +6,29 @@ OSSL_CMP_ITAV_create, OSSL_CMP_ITAV_set0, OSSL_CMP_ITAV_get0_type, OSSL_CMP_ITAV_get0_value, -OSSL_CMP_ITAV_push0_stack_item +OSSL_CMP_ITAV_push0_stack_item, +OSSL_CMP_ITAV_new0_certProfile, +OSSL_CMP_ITAV_get0_certProfile - OSSL_CMP_ITAV utility functions =head1 SYNOPSIS - #include - 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); + #include - int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, - OSSL_CMP_ITAV *itav); + 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); + OSSL_CMP_ITAV + *OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile); + int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out); =head1 DESCRIPTION -Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL - ITAV is short for InfoTypeAndValue. This type is defined in RFC 4210 section 5.3.19 and Appendix F. It is used at various places in CMP messages, e.g., in the generalInfo PKIHeader field, to hold a key-value pair. @@ -45,21 +49,37 @@ the I as generic B pointer. OSSL_CMP_ITAV_push0_stack_item() pushes I to the stack pointed to by I<*itav_sk_p>. It creates a new stack if I<*itav_sk_p> points to NULL. +OSSL_CMP_ITAV_new0_certProfile() creates a new B structure +of type B that includes the optionally given list of profile names. +On success, ownership of the list is with the new B structure. + +OSSL_CMP_ITAV_get0_certProfile() on success assigns to I<*out> +an internal pointer to the +list of certificate profile names contained in the infoValue field of I. +The pointer may be NULL if no profile name is included. +It is an error if the infoType of I is not B. + =head1 NOTES -CMP is defined in RFC 4210 (and CRMF in RFC 4211). +CMP is defined in RFC 4210 and RFC 9480 (and CRMF in RFC 4211). + +OIDs to use as types in B can be found at +L. +The respective OpenSSL NIDs, such as B, +are defined in the F<< >> header file. =head1 RETURN VALUES -OSSL_CMP_ITAV_create() returns a pointer to the ITAV structure on success, -or NULL on error. +OSSL_CMP_ITAV_create() and OSSL_CMP_ITAV_new0_certProfile() +return a pointer to an ITAV structure on success, or NULL on error. OSSL_CMP_ITAV_set0() does not return a value. OSSL_CMP_ITAV_get0_type() and OSSL_CMP_ITAV_get0_value() return the respective pointer or NULL if their input is NULL. -OSSL_CMP_ITAV_push0_stack_item() returns 1 on success, 0 on error. +OSSL_CMP_ITAV_push0_stack_item() and OSSL_CMP_ITAV_get0_certProfile() +return 1 on success, 0 on error. =head1 EXAMPLES @@ -81,10 +101,9 @@ included in the requests' PKIHeader's genInfo field. OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_create(type, val); if (itav == NULL) ... - OSSL_CMP_CTX *ctx = OSSL_CMP_CTX_new(); - if (ctx == NULL || !OSSL_CMP_CTX_geninfo_push0_ITAV(ctx, itav)) { + if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) { OSSL_CMP_ITAV_free(itav); /* also frees type and val */ - goto err; + ... } ... @@ -99,6 +118,9 @@ L, L, L The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_ITAV_new0_certProfile() and OSSL_CMP_ITAV_get0_certProfile() +were added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod index b3175683c782..f8f535f30b02 100644 --- a/doc/man3/OSSL_CMP_MSG_get0_header.pod +++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod @@ -4,6 +4,7 @@ OSSL_CMP_MSG_get0_header, OSSL_CMP_MSG_get_bodytype, +OSSL_CMP_MSG_get0_certreq_publickey, OSSL_CMP_MSG_update_transactionID, OSSL_CMP_MSG_update_recipNonce, OSSL_CMP_CTX_setup_CRM, @@ -19,6 +20,7 @@ i2d_OSSL_CMP_MSG_bio OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg); int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg); + X509_PUBKEY *OSSL_CMP_MSG_get0_certreq_publickey(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); @@ -33,6 +35,9 @@ 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_get0_certreq_publickey() expects that I is a certificate request +message and returns the public key in its certificate template if present. + OSSL_CMP_MSG_update_transactionID() updates the transactionID field in the header of the given message according to the CMP_CTX. If I does not contain a transaction ID, a fresh one is created before. @@ -118,6 +123,8 @@ 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_MSG_get0_certreq_publickey() returns a public key or NULL on error. + OSSL_CMP_CTX_setup_CRM() returns a pointer to a B on success, NULL on error. @@ -146,9 +153,11 @@ The OpenSSL CMP support was added in OpenSSL 3.0. OSSL_CMP_MSG_update_recipNonce() was added in OpenSSL 3.0.9. +OSSL_CMP_MSG_get0_certreq_publickey() was added in OpenSSL 3.3. + =head1 COPYRIGHT -Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_MSG_http_perform.pod b/doc/man3/OSSL_CMP_MSG_http_perform.pod index d675da91143d..c8d1a4fb47e7 100644 --- a/doc/man3/OSSL_CMP_MSG_http_perform.pod +++ b/doc/man3/OSSL_CMP_MSG_http_perform.pod @@ -14,11 +14,21 @@ OSSL_CMP_MSG_http_perform =head1 DESCRIPTION -OSSL_CMP_MSG_http_perform() sends the given PKIMessage I -to the CMP server specified in I via L -and optionally L, using -any "CMP alias" optionally specified via L. -The default port is 80 for HTTP and 443 for HTTPS; the default path is "/". +OSSL_CMP_MSG_http_perform() sends the given PKIMessage I to the +CMP server specified in I and returns the result obtained from it. + +If L has been used to set the transfer +callback argument then the provided pointer I is taken as +a two-element B array to use for the exchange with the server +as described for the I and I parameters of L. +For instance, the two BIO pointers may be equal and refer to a TLS connection, +such as in BRSKI-AE where a pre-established TLS channel is reused for CMP. + +Otherwise the server specified via L +and optionally L is contacted, +where the default port is 80 for HTTP and 443 for HTTPS. +The HTTP path (aka "CMP alias" in this context) to use is by default C, +otherwise the string specified via L. On success the function returns the server's response PKIMessage. The function makes use of any HTTP callback function @@ -38,19 +48,22 @@ HTTP transfer for CMP is defined in RFC 6712. =head1 RETURN VALUES -OSSL_CMP_MSG_http_perform() returns a CMP message on success, else NULL. +OSSL_CMP_MSG_http_perform() +returns the received CMP response message on success, else NULL. =head1 SEE ALSO -L, L. +L, L, and L. =head1 HISTORY The OpenSSL CMP support was added in OpenSSL 3.0. +The OSSL_CMP_MSG_http_perform() use of transfer_cb_arg was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod index 12b1bfa88a1d..7484a7a04966 100644 --- a/doc/man3/OSSL_CMP_SRV_CTX_new.pod +++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod @@ -13,6 +13,9 @@ OSSL_CMP_SRV_genm_cb_t, OSSL_CMP_SRV_error_cb_t, OSSL_CMP_SRV_pollReq_cb_t, OSSL_CMP_SRV_CTX_init, +OSSL_CMP_SRV_delayed_delivery_cb_t, +OSSL_CMP_SRV_clean_transaction_cb_t, +OSSL_CMP_SRV_CTX_init_trans, OSSL_CMP_SRV_CTX_get0_cmp_ctx, OSSL_CMP_SRV_CTX_get0_custom_ctx, OSSL_CMP_SRV_CTX_set_send_unprotected_errors, @@ -71,6 +74,13 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm OSSL_CMP_SRV_error_cb_t process_error, OSSL_CMP_SRV_certConf_cb_t process_certConf, OSSL_CMP_SRV_pollReq_cb_t process_pollReq); + typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); + typedef int (*OSSL_CMP_SRV_clean_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const ASN1_OCTET_STRING *id); + int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_delayed_delivery_cb_t delay, + OSSL_CMP_SRV_clean_transaction_cb_t clean); 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); @@ -114,6 +124,20 @@ All arguments except I may be NULL. If a callback for some message type is not given this means that the respective type of CMP message is not supported by the server. +OSSL_CMP_SRV_CTX_init_trans() sets in I the optional callback +functions for initiating delayed delivery and cleaning up a transaction. +If the function is NULL then delivery of responses is never delayed. +Otherwise I takes a custom server context and a request message as input. +It must return 1 if delivery of the respective response shall be delayed, +0 if not, and -1 on error. +If the function is NULL then no specific cleanup is performed. +Otherwise I takes a custom server context and a transaction ID pointer +as input, where the pointer is NULL in case a new transaction is being started +and otherwise provides the ID of the transaction being terminated. +The function should reset the respective portions of the state +and free related memory. +It must return 1 on success and 0 on error. + OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B from the I. OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context from @@ -157,6 +181,10 @@ All other functions return 1 on success, 0 on error. The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_SRV_CTX_init_trans() +supporting delayed delivery of all types of response messages +was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_exec_certreq.pod b/doc/man3/OSSL_CMP_exec_certreq.pod index 0cabc3bad5ac..ce6826c6754b 100644 --- a/doc/man3/OSSL_CMP_exec_certreq.pod +++ b/doc/man3/OSSL_CMP_exec_certreq.pod @@ -13,7 +13,11 @@ OSSL_CMP_P10CR, OSSL_CMP_KUR, OSSL_CMP_try_certreq, OSSL_CMP_exec_RR_ses, -OSSL_CMP_exec_GENM_ses +OSSL_CMP_exec_GENM_ses, +OSSL_CMP_get1_caCerts, +OSSL_CMP_get1_rootCaKeyUpdate, +OSSL_CMP_get1_crlUpdate, +OSSL_CMP_get1_certReqTemplate - functions implementing CMP client transactions =head1 SYNOPSIS @@ -33,8 +37,18 @@ OSSL_CMP_exec_GENM_ses 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); + STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx); + int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out); + int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx, + const X509 *oldWithOld, X509 **newWithNew, + X509 **newWithOld, X509 **oldWithNew); + int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert, + const X509_CRL *last_crl, + X509_CRL **crl); + int OSSL_CMP_get1_certReqTemplate(OSSL_CMP_CTX *ctx, + OSSL_CRMF_CERTTEMPLATE **certTemplate, + OSSL_CMP_ATAVS **keySpec); =head1 DESCRIPTION This is the OpenSSL API for doing CMP (Certificate Management Protocol) @@ -71,8 +85,8 @@ Typically I is NULL, then the template ingredients are taken from I and need to be filled in using L, L, L, etc. For P10CR, L needs to be used instead. -The enrollment session may be blocked by sleeping until the addressed -CA (or an intermediate PKI component) can fully process and answer the request. +The enrollment session may be blocked (with polling and sleeping in between) +until the server side can fully process and ultimately answer the request. OSSL_CMP_try_certreq() is an alternative to the above functions that is more flexible regarding what to do after receiving a checkAfter value. @@ -99,21 +113,73 @@ a negative value as the I argument then OSSL_CMP_try_certreq() aborts the CMP transaction by sending an error message to the server. OSSL_CMP_exec_RR_ses() requests the revocation of the certificate -specified in the I using L. +specified in the I using the issuer DN and serial number set by +OSSL_CMP_CTX_set1_issuer(3) and OSSL_CMP_CTX_set1_serialNumber(3), respectively, +otherwise the issuer DN and serial number +of the certificate set by L, +otherwise the subject DN and public key +of the certificate signing request set by L. RFC 4210 is vague in which PKIStatus should be returned by the server. We take "accepted" and "grantedWithMods" as clear success and handle "revocationWarning" and "revocationNotification" just as warnings because CAs typically return them as an indication that the certificate was already revoked. "rejection" is a clear error. The values "waiting" and "keyUpdateWarning" make no sense for revocation and thus are treated as an error as well. +The revocation session may be blocked (with polling and sleeping in between) +until the server can fully process and ultimately answer the request. -OSSL_CMP_exec_GENM_ses() sends a general message containing the sequence of +OSSL_CMP_exec_GENM_ses() sends a genm general message containing the sequence of infoType and infoValue pairs (InfoTypeAndValue; short: B) optionally provided in the I using L. -On success it records in I the status B -and returns the list of Bs received in the GENP message. -This can be used, for instance, to poll for CRLs or CA Key Updates. +The message exchange may be blocked (with polling and sleeping in between) +until the server can fully process and ultimately answer the request. +On success the function records in I status B +and returns the list of Bs received in a genp response message. +This can be used, for instance, +with infoType C to obtain the set of signature +algorithm identifiers that the CA will certify for subject public keys. See RFC 4210 section 5.3.19 and appendix E.5 for details. +Functions implementing more specific genm/genp exchanges are described next. + +OSSL_CMP_get1_caCerts() uses a genm/genp message exchange with infoType caCerts +to obtain a list of CA certificates from the CMP server referenced by I. +On success it assigns to I<*out> the list of certificates received, +which must be freed by the caller. +NULL output means that no CA certificates were provided by the server. + +OSSL_CMP_get1_rootCaKeyUpdate() uses a genm request message +with infoType rootCaCert to obtain from the CMP server referenced by I +in a genp response message with infoType rootCaKeyUpdate any update of the +given root CA certificate I and verifies it as far as possible. +See RFC 4210 section 4.4 for details. +On success it assigns to I<*newWithNew> the root certificate received. +When the I and I output parameters are not NULL, +it assigns to them the corresponding transition certificates. +NULL means that the respective certificate was not provided by the server. +All certificates obtained this way must be freed by the caller. + +B +The I certificate is meant to be a certificate that will be trusted. +The trust placed in it cannot be stronger than the trust placed in +the I certificate if present, otherwise it cannot be stronger than +the weakest trust in any of the certificates in the trust store of I. + +OSSL_CMP_get1_crlUpdate() uses a genm request message with infoType crlStatusList +to obtain CRL from the CMP server referenced by I in a genp response message +with infoType crls. It uses I and I to create +a request with a status field as described for L. +On success it assigns to I<*crl> the CRL received. +NULL means that no CRL was provided by the server. +The CRL obtained this way must be freed by the caller. + +OSSL_CMP_get1_certReqTemplate() uses a genm request message with +infoType certReqTemplate to obtain a certificate request template from the +CMP server referenced by I. On success it assigns to I<*certTemplate> +the certificate template received. NULL output means that no certificate +request template was provided by the server. +The optional I output parameter is assigned the key specification +if received, otherwise it set to NULL. +Both must be freed by the caller. =head1 NOTES @@ -123,12 +189,16 @@ The CMP client implementation is limited to one request per CMP message (and consequently to at most one response component per CMP message). When a client obtains from a CMP server CA certificates that it is going to -trust, for instance via the caPubs field of a certificate response, +trust, for instance via the caPubs field of a certificate response or using +functions like OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate(), authentication of the CMP server is particularly critical. So special care must be taken setting up server authentication in I using functions such as -L (for certificate-based authentication) or +L (for certificate-based authentication) or L (for MAC-based protection). +If authentication is certificate-based, L +should be used to obtain the server validated certificate +and perform an authorization check based on it. =head1 RETURN VALUES @@ -146,7 +216,10 @@ In the latter case L yields NULL and the output parameter I has been used to assign the received value unless I is NULL. -OSSL_CMP_exec_RR_ses() returns 1 on success, 0 on error. +OSSL_CMP_exec_RR_ses(), OSSL_CMP_get1_caCerts(), +OSSL_CMP_get1_rootCaKeyUpdate(), OSSL_CMP_get1_crlUpdate() +and OSSL_CMP_get1_certReqTemplate() +return 1 on success, 0 on error. OSSL_CMP_exec_GENM_ses() returns NULL on error, otherwise a pointer to the sequence of B received, which may be empty. @@ -163,15 +236,24 @@ L, L, L, L, L, L, L, L, -L +L, L =head1 HISTORY The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate() +were added in OpenSSL 3.2. + +Support for delayed delivery of all types of response messages +was added in OpenSSL 3.3. + +OSSL_CMP_get1_crlUpdate() and OSSL_CMP_get1_certReqTemplate() +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_log_open.pod b/doc/man3/OSSL_CMP_log_open.pod index f540c1938297..d348feeea58b 100644 --- a/doc/man3/OSSL_CMP_log_open.pod +++ b/doc/man3/OSSL_CMP_log_open.pod @@ -114,7 +114,7 @@ The OpenSSL CMP support was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_CMP_validate_msg.pod b/doc/man3/OSSL_CMP_validate_msg.pod index c5e68065beff..af060a8eb8a0 100644 --- a/doc/man3/OSSL_CMP_validate_msg.pod +++ b/doc/man3/OSSL_CMP_validate_msg.pod @@ -30,13 +30,15 @@ is preferably the one provided by a call to L. If no such sender cert has been pinned then candidate sender certificates are taken from the list of certificates received in the I extraCerts, then any certificates provided before via L, and -then all trusted certificates provided via L, -where a candidate is acceptable only if has not expired, its subject DN matches +then all trusted certificates provided via L. +A candidate certificate is acceptable only if it is currently valid +(or the trust store contains a verification callback that overrides the verdict +that the certificate is expired or not yet valid), its subject DN matches the I sender DN (as far as present), and its subject key identifier -is present and matches the senderKID (as far as the latter present). +is present and matches the senderKID (as far as the latter is present). Each acceptable cert is tried in the given order to see if the message signature check succeeds and the cert and its path can be verified -using any trust store set via L. +using any trust store set via L. If the option OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR was set by calling L, for an Initialization Response (IP) message @@ -69,7 +71,7 @@ return 1 on success, 0 on error or validation failed. L, L, L, L, -L, L +L, L =head1 HISTORY diff --git a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod index 51296599e5c7..6c095c0ee0e8 100644 --- a/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod +++ b/doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod @@ -3,14 +3,20 @@ =head1 NAME OSSL_CRMF_MSG_get0_tmpl, -OSSL_CRMF_CERTTEMPLATE_get0_serialNumber, +OSSL_CRMF_CERTTEMPLATE_get0_publicKey, OSSL_CRMF_CERTTEMPLATE_get0_subject, OSSL_CRMF_CERTTEMPLATE_get0_issuer, +OSSL_CRMF_CERTTEMPLATE_get0_serialNumber, OSSL_CRMF_CERTTEMPLATE_get0_extensions, OSSL_CRMF_CERTID_get0_serialNumber, OSSL_CRMF_CERTID_get0_issuer, +OSSL_CRMF_ENCRYPTEDKEY_get1_encCert, +OSSL_CRMF_ENCRYPTEDKEY_get1_pkey, +OSSL_CRMF_ENCRYPTEDKEY_init_envdata, +OSSL_CRMF_ENCRYPTEDVALUE_decrypt, OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert, -OSSL_CRMF_MSG_get_certReqId +OSSL_CRMF_MSG_get_certReqId, +OSSL_CRMF_MSG_centralkeygen_requested - functions reading from CRMF CertReqMsg structures =head1 SYNOPSIS @@ -18,12 +24,14 @@ OSSL_CRMF_MSG_get_certReqId #include OSSL_CRMF_CERTTEMPLATE *OSSL_CRMF_MSG_get0_tmpl(const OSSL_CRMF_MSG *crm); - const ASN1_INTEGER - *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl); + X509_PUBKEY + *OSSL_CRMF_CERTTEMPLATE_get0_publicKey(const OSSL_CRMF_CERTTEMPLATE *tmpl); const X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_subject(const OSSL_CRMF_CERTTEMPLATE *tmpl); const X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl); + const ASN1_INTEGER + *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl); X509_EXTENSIONS *OSSL_CRMF_CERTTEMPLATE_get0_extensions(const OSSL_CRMF_CERTTEMPLATE *tmpl); @@ -31,19 +39,36 @@ OSSL_CRMF_MSG_get_certReqId *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid); const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid); + X509 *OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(const OSSL_CRMF_ENCRYPTEDKEY *ecert, + OSSL_LIB_CTX *libctx, const char *propq, + EVP_PKEY *pkey, unsigned int flags); + EVP_PKEY + *OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(OSSL_CRMF_ENCRYPTEDKEY *encryptedKey, + X509_STORE *ts, STACK_OF(X509) *extra, + EVP_PKEY *pkey, X509 *cert, + ASN1_OCTET_STRING *secret, + OSSL_LIB_CTX *libctx, const char *propq); + OSSL_CRMF_ENCRYPTEDKEY + *OSSL_CRMF_ENCRYPTEDKEY_init_envdata(CMS_EnvelopedData *envdata); + + unsigned char + *OSSL_CRMF_ENCRYPTEDVALUE_decrypt(const OSSL_CRMF_ENCRYPTEDVALUE *enc, + OSSL_LIB_CTX *libctx, const char *propq, + EVP_PKEY *pkey, int *outlen); X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert, OSSL_LIB_CTX *libctx, const char *propq, EVP_PKEY *pkey); int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm); - + int OSSL_CRMF_MSG_centralkeygen_requested(const OSSL_CRMF_MSG *crm, + const X509_REQ *p10cr); =head1 DESCRIPTION OSSL_CRMF_MSG_get0_tmpl() retrieves the certificate template of I. -OSSL_CRMF_CERTTEMPLATE_get0_serialNumber() retrieves the serialNumber of the +OSSL_CRMF_CERTTEMPLATE_get0_publicKey() retrieves the public key of the given certificate template I. OSSL_CRMF_CERTTEMPLATE_get0_subject() retrieves the subject name of the @@ -52,6 +77,9 @@ given certificate template I. OSSL_CRMF_CERTTEMPLATE_get0_issuer() retrieves the issuer name of the given certificate template I. +OSSL_CRMF_CERTTEMPLATE_get0_serialNumber() retrieves the serialNumber of the +given certificate template I. + OSSL_CRMF_CERTTEMPLATE_get0_extensions() retrieves the X.509 extensions of the given certificate template I, or NULL if not present. @@ -61,6 +89,33 @@ of the given CertId I. OSSL_CRMF_CERTID_get0_issuer retrieves the issuer name of the given CertId I, which must be of ASN.1 type GEN_DIRNAME. +OSSL_CRMF_ENCRYPTEDKEY_get1_encCert() decrypts the certificate in the given +encryptedKey I, using the private key I, library context +I and property query string I (see L). +This is needed for the indirect POPO method as in RFC 4210 section 5.2.8.2. +The function returns the decrypted certificate as a copy, leaving its ownership +with the caller, who is responsible for freeing it. + +OSSL_CRMF_ENCRYPTEDKEY_get1_pkey() decrypts the private key in I. +If I is not of type B, +decryption uses the private key I. +The library context I and property query I are taken into account as usual. +The rest of this paragraph is relevant only if CMS support not disabled for the OpenSSL build +and I is of type case B. +Decryption uses the I parameter if not NULL; +otherwise uses the private key and the certificate I +related to I, where I is recommended to be given if available. +On success, the function verifies the decrypted data as signed data, +using the trust store I and any untrusted certificates in I. +Doing so, it checks for the purpose "CMP Key Generation Authority" (cmKGA). + +OSSL_CRMF_ENCRYPTEDKEY_init_envdata() returns I, intialized with +the enveloped data I. + +OSSL_CRMF_ENCRYPTEDVALUE_decrypt() decrypts the encrypted value in the given +encryptedValue I, using the private key I, library context +I and property query string I (see L). + OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert() decrypts the certificate in the given encryptedValue I, using the private key I, library context I and property query string I (see L). @@ -70,12 +125,21 @@ with the caller, who is responsible for freeing it. OSSL_CRMF_MSG_get_certReqId() retrieves the certReqId of I. +OSSL_CRMF_MSG_centralkeygen_requested() returns 1 if central key generation +is requested i.e., the public key in the certificate request (I is taken if it is non-NULL, +otherwise I) is NULL or has an empty key value (with length zero). +In case I is non-NULL, this is checked for consistency with its B field +(must be NULL if and only if central key generation is requested). +Otherwise it returns 0, and on error a negative value. =head1 RETURN VALUES OSSL_CRMF_MSG_get_certReqId() returns the certificate request ID as a nonnegative integer or -1 on error. +OSSL_CRMF_MSG_centralkeygen_requested() returns 1 if central key generation +is requested, 0 if it is not requested, and a negative value on error. + All other functions return a pointer with the intended result or NULL on error. =head1 SEE ALSO @@ -86,9 +150,15 @@ RFC 4211 The OpenSSL CRMF support was added in OpenSSL 3.0. +OSSL_CRMF_CERTTEMPLATE_get0_publicKey() was added in OpenSSL 3.2. + +OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(), OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(), +OSSL_CRMF_ENCRYPTEDKEY_init_envdata(), OSSL_CRMF_ENCRYPTEDVALUE_decrypt() +and OSSL_CRMF_MSG_centralkeygen_requested() were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_DECODER_CTX.pod b/doc/man3/OSSL_DECODER_CTX.pod index bace3ee0cfed..33b09c836db8 100644 --- a/doc/man3/OSSL_DECODER_CTX.pod +++ b/doc/man3/OSSL_DECODER_CTX.pod @@ -47,8 +47,8 @@ OSSL_DECODER_INSTANCE_get_input_structure int OSSL_DECODER_CTX_set_input_structure(OSSL_DECODER_CTX *ctx, const char *input_structure); int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder); - int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, - OSSL_LIB_CTX *libctx, + int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx, + OSSL_LIB_CTX *libctx, const char *propq); int OSSL_DECODER_CTX_get_num_decoders(OSSL_DECODER_CTX *ctx); diff --git a/doc/man3/OSSL_DISPATCH.pod b/doc/man3/OSSL_DISPATCH.pod index 1aca4019dcbc..232b6dca826c 100644 --- a/doc/man3/OSSL_DISPATCH.pod +++ b/doc/man3/OSSL_DISPATCH.pod @@ -2,7 +2,7 @@ =head1 NAME -OSSL_DISPATCH - OpenSSL Core type to define a dispatchable function table +OSSL_DISPATCH, OSSL_DISPATCH_END - OpenSSL Core type to define a dispatchable function table =head1 SYNOPSIS @@ -14,14 +14,15 @@ OSSL_DISPATCH - OpenSSL Core type to define a dispatchable function table void (*function)(void); }; + #define OSSL_DISPATCH_END + =head1 DESCRIPTION This type is a tuple of function identity and function pointer. Arrays of this type are passed between the OpenSSL libraries and the providers to describe what functionality one side provides to the other. -Arrays of this type must be terminated with a tuple having function identity -zero and function pointer NULL. +Arrays of this type must be terminated with the OSSL_DISPATCH_END macro. =head2 B fields @@ -71,7 +72,7 @@ B was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-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 diff --git a/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod index 8ba3bdd46718..3bf9c10e374e 100644 --- a/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod +++ b/doc/man3/OSSL_ENCODER_CTX_new_for_pkey.pod @@ -136,7 +136,7 @@ The functions described here were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_ESS_check_signing_certs.pod b/doc/man3/OSSL_ESS_check_signing_certs.pod index 24145ead1728..726dbc285c59 100644 --- a/doc/man3/OSSL_ESS_check_signing_certs.pod +++ b/doc/man3/OSSL_ESS_check_signing_certs.pod @@ -78,7 +78,7 @@ OSSL_ESS_check_signing_certs() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_HTTP_REQ_CTX.pod b/doc/man3/OSSL_HTTP_REQ_CTX.pod index d6c4cdfa0ca7..210f33801cae 100644 --- a/doc/man3/OSSL_HTTP_REQ_CTX.pod +++ b/doc/man3/OSSL_HTTP_REQ_CTX.pod @@ -15,6 +15,7 @@ OSSL_HTTP_REQ_CTX_exchange, OSSL_HTTP_REQ_CTX_get0_mem_bio, OSSL_HTTP_REQ_CTX_get_resp_len, OSSL_HTTP_REQ_CTX_set_max_response_length, +OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines, OSSL_HTTP_is_alive - HTTP client low-level functions @@ -34,7 +35,7 @@ OSSL_HTTP_is_alive const char *name, const char *value); int OSSL_HTTP_REQ_CTX_set_expected(OSSL_HTTP_REQ_CTX *rctx, - const char *content_type, int asn1, + const char *expected_content_type, int expect_asn1, int timeout, int keep_alive); int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type, const ASN1_ITEM *it, const ASN1_VALUE *req); @@ -47,6 +48,8 @@ OSSL_HTTP_is_alive size_t OSSL_HTTP_REQ_CTX_get_resp_len(const OSSL_HTTP_REQ_CTX *rctx); void OSSL_HTTP_REQ_CTX_set_max_response_length(OSSL_HTTP_REQ_CTX *rctx, unsigned long len); + void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx, + size_t count); int OSSL_HTTP_is_alive(const OSSL_HTTP_REQ_CTX *rctx); @@ -94,16 +97,26 @@ OSSL_HTTP_REQ_CTX_set_expected() optionally sets in I some expectations of the HTTP client on the response. Due to the structure of an HTTP request, if the I argument is nonzero the function must be used before calling OSSL_HTTP_REQ_CTX_set1_req(). -If the I parameter -is not NULL then the client will check that the given content type string + +If the I argument is not NULL, the client will +check in a case-insensitive way that the specified C string value is included in the HTTP header of the response and return an error if not. -If the I parameter is nonzero a structure in ASN.1 encoding will be +In the C header line the specified string should be present either +as a whole, or in case the specified string does not include a C<;> character, +it is sufficient that the specified string appears as a prefix +in the header line, followed by a C<;> character and any further text. +For instance, if the I argument specifies C, +this is matched by C, C, etc. + +If the I parameter is nonzero a structure in ASN.1 encoding will be expected as the response content and input streaming is disabled. This means that an ASN.1 sequence header is required, its length field is checked, and OSSL_HTTP_REQ_CTX_get0_mem_bio() should be used to get the buffered response. -Otherwise (by default) any input format is allowed without length checks. +Otherwise (by default) any input format is allowed, +with body length checks being performed on error messages only. In this case the BIO given as I argument to OSSL_HTTP_REQ_CTX_new() should be used directly to read the response contents, which may support streaming. + If the I parameter is > 0 this indicates the maximum number of seconds the subsequent HTTP transfer (sending the request and receiving a response) is allowed to take. @@ -111,6 +124,7 @@ I == 0 enables waiting indefinitely, i.e., no timeout can occur. This is the default. I < 0 takes over any value set via the I argument of L with the default being 0, which means no timeout. + If the I parameter is 0, which is the default, the connection is not kept open after receiving a response. This is the default behavior for HTTP 1.0. If the value is 1 or 2 then a persistent connection is requested. @@ -137,6 +151,16 @@ that were given when calling OSSL_HTTP_REQ_CTX_new(). The function may need to be called again if its result is -1, which indicates L. In such a case it is advisable to sleep a little in between, using L on the read BIO to prevent a busy loop. +See OSSL_HTTP_REQ_CTX_set_expected() how the response content type, +the response body, the HTTP transfer timeout, and "keep-alive" are treated. +Any error message body is consumed +if a C header is not included or its value starts with C. +This is used for tracing the body contents if HTTP tracing is enabled. +If the C header is present in the response +and its value exceeds the maximum allowed response content length +or the response is an error message with its body length exceeding this value +or the content is an ASN.1-encoded structure with a length exceeding this value +or both length indications are present but disagree then an error occurs. OSSL_HTTP_REQ_CTX_nbio_d2i() is like OSSL_HTTP_REQ_CTX_nbio() but on success in addition parses the response, which must be a DER-encoded ASN.1 structure, @@ -163,14 +187,18 @@ its contents can be read via this BIO, which does not support streaming. The returned BIO pointer must not be freed by the caller. OSSL_HTTP_REQ_CTX_get_resp_len() returns the size of the response contents -in I if provided by the server as header field, else 0. +in I if provided by the server as C header field, else 0. OSSL_HTTP_REQ_CTX_set_max_response_length() sets the maximum allowed response content length for I to I. If not set or I is 0 then the B is used, which currently is 100 KiB. -If the C header is present and exceeds this value or -the content is an ASN.1 encoded structure with a length exceeding this value -or both length indications are present but disagree then an error occurs. + +OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines() changes the limit for +the number of HTTP header lines allowed to be received in a response. +The default limit is B, currently 256. +If the limit is not 0 and the number of lines exceeds the limit, +then the HTTP_R_RESPONSE_TOO_MANY_HDRLINES error is indicated. +Setting the limit to 0 disables the check. OSSL_HTTP_is_alive() can be used to query if the HTTP connection given by I is still alive, i.e., has not been closed. @@ -218,13 +246,20 @@ This may be omitted if the GET method is used and "keep-alive" is not requested. When the request context is fully prepared, the HTTP exchange may be performed with OSSL_HTTP_REQ_CTX_nbio() or OSSL_HTTP_REQ_CTX_exchange(). +=head1 NOTES + +When built with tracing enabled, OSSL_HTTP_REQ_CTX_nbio() and all functions +using it, such as OSSL_HTTP_REQ_CTX_exchange() and L, +may be traced using B. +See also L and L. + =head1 RETURN VALUES OSSL_HTTP_REQ_CTX_new() returns a pointer to a B, or NULL on error. -OSSL_HTTP_REQ_CTX_free() and OSSL_HTTP_REQ_CTX_set_max_response_length() -do not return values. +OSSL_HTTP_REQ_CTX_free(), OSSL_HTTP_REQ_CTX_set_max_response_length(), and +OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines() do not return values. OSSL_HTTP_REQ_CTX_set_request_line(), OSSL_HTTP_REQ_CTX_add1_header(), OSSL_HTTP_REQ_CTX_set1_req(), and OSSL_HTTP_REQ_CTX_set_expected() @@ -253,15 +288,18 @@ L, L, L, L, -L +L, +L, and L. =head1 HISTORY -The functions described here were added in OpenSSL 3.0. +OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines() was added in OpenSSL 3.3. + +All other functions described here were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_HTTP_parse_url.pod b/doc/man3/OSSL_HTTP_parse_url.pod index 4379c122d66a..bc29fb18d14b 100644 --- a/doc/man3/OSSL_HTTP_parse_url.pod +++ b/doc/man3/OSSL_HTTP_parse_url.pod @@ -102,7 +102,7 @@ OCSP_parse_url() was deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_HTTP_transfer.pod b/doc/man3/OSSL_HTTP_transfer.pod index 6da1d91b9f37..eaa0986666fc 100644 --- a/doc/man3/OSSL_HTTP_transfer.pod +++ b/doc/man3/OSSL_HTTP_transfer.pod @@ -62,6 +62,7 @@ for connecting to the given server and the optionally given I, defaulting to 80 for HTTP or 443 for HTTPS. Then this internal BIO is used for setting up a connection and for exchanging one or more request and response. + If I is given and I is NULL then this I is used instead. If both I and I are given (which may be memory BIOs for instance) then no explicit connection is set up, but @@ -69,7 +70,8 @@ I is used for writing requests and I for reading responses. As soon as the client has flushed I the server must be ready to provide a response or indicate a waiting condition via I. -If I is given, it is an error to provide I or I arguments, +If I is given, +it is an error to provide non-NULL I or I arguments, while I and I arguments may be given to support diagnostic output. If I is NULL the optional I parameter can be used to set an HTTP(S) proxy to use (unless overridden by "no_proxy" settings). @@ -101,8 +103,8 @@ I is a BIO connect/disconnect callback function with prototype BIO *(*OSSL_HTTP_bio_cb_t)(BIO *bio, void *arg, int connect, int detail) The callback function may modify the BIO provided in the I argument, -whereby it may make use of a custom defined argument I, -which may for instance point to an B structure. +whereby it may use an optional custom defined argument I, +which can for instance point to an B structure. During connection establishment, just after calling BIO_do_connect_retry(), the callback function is invoked with the I argument being 1 and I being 1 if I is nonzero (i.e., HTTPS is requested), else 0. @@ -110,7 +112,7 @@ On disconnect I is 0 and I is 1 if no error occurred, else 0. For instance, on connect the callback may push an SSL BIO to implement HTTPS; after disconnect it may do some diagnostic output and pop and free the SSL BIO. -The callback function must return either the potentially modified BIO I. +The callback function must return either the potentially modified BIO I or NULL to indicate failure, in which case it should not modify the BIO. Here is a simple example that supports TLS connections (but not via a proxy): @@ -137,6 +139,8 @@ Here is a simple example that supports TLS connections (but not via a proxy): } After disconnect the modified BIO will be deallocated using BIO_free_all(). +The optional callback function argument I is not consumed, +so must be freed by the caller when not needed any more. The I parameter specifies the response header maximum line length. A value <= 0 means that the B (4KiB) is used. @@ -174,24 +178,10 @@ else HTTP POST with the contents of I and optional I, where the length of the data in I does not need to be determined in advance: the BIO will be read on-the-fly while sending the request, which supports streaming. The optional list I may contain additional custom HTTP header lines. -If the parameter I -is not NULL then the client will check that the given content type string -is included in the HTTP header of the response and return an error if not. -If the I parameter is nonzero, -a structure in ASN.1 encoding will be expected as response content. The I parameter specifies the maximum allowed response content length, where the value 0 indicates no limit. -If the I parameter is > 0 this indicates the maximum number of seconds -the subsequent HTTP transfer (sending the request and receiving a response) -is allowed to take. -A value of 0 enables waiting indefinitely, i.e., no timeout. -A value < 0 indicates that the I parameter value given -when opening the HTTP transfer will be used instead. -If I is 0 the connection is not kept open -after receiving a response, which is the default behavior for HTTP 1.0. -If the value is 1 or 2 then a persistent connection is requested. -If the value is 2 then a persistent connection is required, -i.e., an error occurs in case the server does not grant it. +For the meaning of the I, I, I, +and I parameters, see L. OSSL_HTTP_exchange() exchanges any form of HTTP request and response as specified by I, which must include both connection and request data, @@ -202,7 +192,7 @@ is not NULL the latter pointer is used to provide any new location that the server may return with HTTP code 301 (MOVED_PERMANENTLY) or 302 (FOUND). In this case the function returns NULL and the caller is responsible for deallocating the URL with L. -If the response header contains one or more "Content-Length" header lines and/or +If the response header contains one or more C lines and/or an ASN.1-encoded response is expected, which should include a total length, the length indications received are checked for consistency and for not exceeding any given maximum response length. @@ -250,6 +240,10 @@ C, C, C, C, C, and C, have been chosen for maximal compatibility with other HTTP client implementations such as wget, curl, and git. +When built with tracing enabled, OSSL_HTTP_transfer() and all functions using it +may be traced using B. +See also L and L. + =head1 RETURN VALUES OSSL_HTTP_open() returns on success a B, else NULL. @@ -271,7 +265,9 @@ OSSL_HTTP_close() returns 0 if anything went wrong while disconnecting, else 1. L, L, L, L, -L +L, +L, +L, and L. =head1 HISTORY @@ -279,7 +275,7 @@ All the functions described here were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_LIB_CTX.pod b/doc/man3/OSSL_LIB_CTX.pod index ad203299e986..215db61820e5 100644 --- a/doc/man3/OSSL_LIB_CTX.pod +++ b/doc/man3/OSSL_LIB_CTX.pod @@ -2,8 +2,9 @@ =head1 NAME -OSSL_LIB_CTX, OSSL_LIB_CTX_new, OSSL_LIB_CTX_new_from_dispatch, -OSSL_LIB_CTX_new_child, OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config, +OSSL_LIB_CTX, OSSL_LIB_CTX_get_data, OSSL_LIB_CTX_new, +OSSL_LIB_CTX_new_from_dispatch, OSSL_LIB_CTX_new_child, +OSSL_LIB_CTX_free, OSSL_LIB_CTX_load_config, OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default - OpenSSL library context @@ -22,6 +23,7 @@ OSSL_LIB_CTX_get0_global_default, OSSL_LIB_CTX_set0_default void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx); OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void); OSSL_LIB_CTX *OSSL_LIB_CTX_set0_default(OSSL_LIB_CTX *ctx); + void *OSSL_LIB_CTX_get_data(OSSL_LIB_CTX *ctx, int index); =head1 DESCRIPTION @@ -85,7 +87,8 @@ library context. OSSL_LIB_CTX_load_config() loads a configuration file using the given I. This can be used to associate a library context with providers that are loaded -from a configuration. +from a configuration. This function must not be called concurrently from +multiple threads on a single I. OSSL_LIB_CTX_free() frees the given I, unless it happens to be the default OpenSSL library context. If the argument is NULL, nothing is done. @@ -110,6 +113,14 @@ in the mean time. This means that the calling thread must not free the library context that was the default at the start of the async job before that job has finished. +OSSL_LIB_CTX_get_data() returns a memory address whose interpretation depends +on the index. The index argument refers to a context member which is +to be retrieved. The values for index are all private to OpenSSL currently +and so applications should not typically call this function. +If ctx is NULL then the function operates on the default library context. +OSSL_LIB_CTX_get_data() returns a memory address whose interpretation +depends on the index. + =head1 RETURN VALUES OSSL_LIB_CTX_new(), OSSL_LIB_CTX_get0_global_default() and @@ -120,10 +131,15 @@ OSSL_LIB_CTX_free() doesn't return any value. OSSL_LIB_CTX_load_config() returns 1 on success, 0 on error. +OSSL_LIB_CTX_get_data() returns a memory address whose interpretation +depends on the index. + =head1 HISTORY All of the functions described on this page were added in OpenSSL 3.0. +OSSL_LIB_CTX_get_data() was introduced in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_PARAM_BLD.pod b/doc/man3/OSSL_PARAM_BLD.pod index 8598ed0626e0..a9dea41211f0 100644 --- a/doc/man3/OSSL_PARAM_BLD.pod +++ b/doc/man3/OSSL_PARAM_BLD.pod @@ -74,8 +74,16 @@ OSSL_PARAM objects of the specified size and correct type for the I argument. I is stored by value and an expression or auto variable can be used. +When B> denotes an integer type, signed integer types will normally +get the OSSL_PARAM type B params. +When B> denotes an unsigned integer type will get the OSSL_PARAM type +B. + OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object that holds the specified BIGNUM I. +When the I is zero or positive, its OSSL_PARAM type becomes +B. +When the I is negative, its OSSL_PARAM type becomes B. If I is marked as being securely allocated, its OSSL_PARAM representation will also be securely allocated. The I argument is stored by reference and the underlying BIGNUM object @@ -85,6 +93,9 @@ OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object that holds the specified BIGNUM I. The object will be padded to occupy exactly I bytes, if insufficient space is specified an error results. +When the I is zero or positive, its OSSL_PARAM type becomes +B. +When the I is negative, its OSSL_PARAM type becomes B. If I is marked as being securely allocated, its OSSL_PARAM representation will also be securely allocated. The I argument is stored by reference and the underlying BIGNUM object @@ -127,8 +138,10 @@ on error. =head1 NOTES -OSSL_PARAM_BLD_push_BN() and OSSL_PARAM_BLD_push_BN_pad() currently only -support nonnegative Bs. They return an error on negative Bs. +OSSL_PARAM_BLD_push_BN() and OSSL_PARAM_BLD_push_BN_pad() only +support nonnegative Bs. They return an error on negative +Bs. +To pass signed Bs, use OSSL_PARAM_BLD_push_signed_BN(). =head1 EXAMPLES diff --git a/doc/man3/OSSL_PARAM_int.pod b/doc/man3/OSSL_PARAM_int.pod index 105fe3241f87..dae0de083a62 100644 --- a/doc/man3/OSSL_PARAM_int.pod +++ b/doc/man3/OSSL_PARAM_int.pod @@ -331,11 +331,10 @@ 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 Bs, and by consequence, only -B. OSSL_PARAM_construct_BN() currently -constructs an L structure with the data type -B. +OSSL_PARAM_get_BN() and OSSL_PARAM_set_BN() only support nonnegative +Bs when the desired data type is B. +OSSL_PARAM_construct_BN() currently constructs an L structure +with the data type B. For OSSL_PARAM_construct_utf8_ptr() and OSSL_PARAM_consstruct_octet_ptr(), I is not relevant if the purpose is to send the L array diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod index 40a4ea100572..1c1818a1f065 100644 --- a/doc/man3/OSSL_PROVIDER.pod +++ b/doc/man3/OSSL_PROVIDER.pod @@ -3,13 +3,16 @@ =head1 NAME OSSL_PROVIDER_set_default_search_path, +OSSL_PROVIDER_get0_default_search_path, OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_try_load, OSSL_PROVIDER_unload, +OSSL_PROVIDER_load_ex, OSSL_PROVIDER_try_load_ex, OSSL_PROVIDER_available, OSSL_PROVIDER_do_all, OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params, OSSL_PROVIDER_query_operation, OSSL_PROVIDER_unquery_operation, OSSL_PROVIDER_get0_provider_ctx, OSSL_PROVIDER_get0_dispatch, OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_get0_name, OSSL_PROVIDER_get_capabilities, -OSSL_PROVIDER_self_test +OSSL_PROVIDER_add_conf_parameter, OSSL_PROVIDER_get_conf_parameters, +OSSL_PROVIDER_conf_get_bool, OSSL_PROVIDER_self_test - provider routines =head1 SYNOPSIS @@ -20,10 +23,16 @@ OSSL_PROVIDER_self_test int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, const char *path); + const char *OSSL_PROVIDER_get0_default_search_path(OSSL_LIB_CTX *libctx); OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name); + OSSL_PROVIDER *OSSL_PROVIDER_load_ex(OSSL_LIB_CTX *, const char *name, + OSSL_PARAM *params); OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name, int retain_fallbacks); + OSSL_PROVIDER *OSSL_PROVIDER_try_load_ex(OSSL_LIB_CTX *, const char *name, + OSSL_PARAM *params, + int retain_fallbacks); int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov); int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name); int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx, @@ -51,6 +60,12 @@ OSSL_PROVIDER_self_test const char *capability, OSSL_CALLBACK *cb, void *arg); + int OSSL_PROVIDER_add_conf_parameter(OSSL_PROVIDER *prov, const char *name, + const char *value); + int OSSL_PROVIDER_get_conf_parameters(OSSL_PROVIDER *prov, + OSSL_PARAM params[]); + int OSSL_PROVIDER_conf_get_bool(const OSSL_PROVIDER *prov, + const char *name, int defval); int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov); =head1 DESCRIPTION @@ -72,6 +87,11 @@ that is to be used for looking for providers in the specified I. If left unspecified, an environment variable and a fall back default value will be used instead. +OSSL_PROVIDER_get0_default_search_path() retrieves the default search I +that is to be used for looking for providers in the specified I. +If successful returns the path or empty string; the path is valid until the +context is released or OSSL_PROVIDER_set_default_search_path() is called. + OSSL_PROVIDER_add_builtin() is used to add a built in provider to B store in the given library context, by associating a provider name with a provider initialization function. @@ -94,6 +114,13 @@ loaded and initialized or if I is nonzero. If the provider loads successfully and I is zero, the fallback providers are disabled. +OSSL_PROVIDER_load_ex() and OSSL_PROVIDER_try_load_ex() are the variants +of the previous functions accepting an C array of the parameters +that are passed as the configuration of the loaded provider. The parameters +of any type but C are silently ignored. If the +parameters are provided, they replace B the ones specified in the +configuration file. + OSSL_PROVIDER_unload() unloads the given provider. For a provider added with OSSL_PROVIDER_add_builtin(), this simply runs its teardown function. @@ -117,6 +144,33 @@ The caller must prepare the L array before calling this function, and the variables acting as buffers for this parameter array should be filled with data when it returns successfully. +OSSL_PROVIDER_add_conf_parameter() sets the provider configuration parameter +I to I. +Provider configuration parameters are managed by the OpenSSL core and normally +set in the configuration file, but can also be set early in the main program +before a provider is in use by multiple threads. +Parameters that only affect provider initialisation must, for now, be set in +the configuration file, only parameters that are also queried later have any +affect when set via this interface. +Only text parameters can be given, and it's up to the provider to +interpret them. + +OSSL_PROVIDER_get_conf_parameters() retrieves global configuration parameters +associated with I. +These configuration parameters are stored for each provider by the OpenSSL core, +not the provider itself, parameters managed by the provider are queried via +B described above. +The parameters are returned by reference, not as copies, and so the elements of +the I array must have B as their B. + +OSSL_PROVIDER_conf_get_bool() parses the global configuration parameter I +associated with provider I as a boolean value, returning a default value +I when unable to retrieve or parse the parameter. +Parameter values equal (case-insensitively) to C<1>, C, C, or C +yield a true (nonzero) result. +Parameter values equal (case-insensitively) to C<0>, C, C, or C +yield a false (zero) result. + OSSL_PROVIDER_self_test() is used to run a provider's self tests on demand. If the self tests fail then the provider will fail to provide any further services and algorithms. L may be called @@ -157,9 +211,14 @@ L. =head1 RETURN VALUES OSSL_PROVIDER_set_default_search_path(), OSSL_PROVIDER_add(), -OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params() and +OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params(), +OSSL_PROVIDER_add_conf_parameter(), OSSL_PROVIDER_get_conf_parameters() +and OSSL_PROVIDER_get_capabilities() return 1 on success, or 0 on error. +OSSL_PROVIDER_get0_default_search_path() returns a pointer to a path on success, +or NULL on error or if the path has not previously been set. + OSSL_PROVIDER_load() and OSSL_PROVIDER_try_load() return a pointer to a provider object on success, or NULL on error. @@ -211,9 +270,18 @@ L, L, L The type and functions described here were added in OpenSSL 3.0. +The I and I functions were +added in OpenSSL 3.2. + +The +I, +I, and +I functions +were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OSSL_STORE_open.pod b/doc/man3/OSSL_STORE_open.pod index fe51912e84c0..1b3b0764aeca 100644 --- a/doc/man3/OSSL_STORE_open.pod +++ b/doc/man3/OSSL_STORE_open.pod @@ -4,7 +4,7 @@ OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn, OSSL_STORE_open, OSSL_STORE_open_ex, -OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, +OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, OSSL_STORE_delete, OSSL_STORE_error, OSSL_STORE_close - Types and functions to read objects from a URI @@ -30,6 +30,9 @@ OSSL_STORE_error, OSSL_STORE_close OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx); int OSSL_STORE_eof(OSSL_STORE_CTX *ctx); + int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + const OSSL_PARAM params[]); int OSSL_STORE_error(OSSL_STORE_CTX *ctx); int OSSL_STORE_close(OSSL_STORE_CTX *ctx); @@ -104,6 +107,8 @@ Any other value is an error. OSSL_STORE_load() takes a B and tries to load the next available object and return it wrapped with B. +OSSL_STORE_delete() deletes the object identified by I. + OSSL_STORE_eof() takes a B and checks if we've reached the end of data. @@ -152,7 +157,8 @@ or an error occurred, 0 otherwise. OSSL_STORE_error() returns 1 if an error occurred in an OSSL_STORE_load() call, otherwise 0. -OSSL_STORE_ctrl() and OSSL_STORE_close() returns 1 on success, or 0 on failure. +OSSL_STORE_delete(), OSSL_STORE_ctrl() and OSSL_STORE_close() return 1 on +success, or 0 on failure. =head1 SEE ALSO @@ -161,6 +167,8 @@ L =head1 HISTORY +OSSL_STORE_delete() was added in OpenSSL 3.2. + OSSL_STORE_open_ex() was added in OpenSSL 3.0. B, OSSL_STORE_post_process_info_fn(), OSSL_STORE_open(), @@ -170,13 +178,11 @@ were added in OpenSSL 1.1.1. Handling of NULL I argument for OSSL_STORE_close() was introduced in OpenSSL 1.1.1h. -OSSL_STORE_open_ex() was added in OpenSSL 3.0. - OSSL_STORE_ctrl() and OSSL_STORE_vctrl() were deprecated in OpenSSL 3.0. =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 diff --git a/doc/man3/OSSL_trace_enabled.pod b/doc/man3/OSSL_trace_enabled.pod index bad5b1515353..987dd7f91af2 100644 --- a/doc/man3/OSSL_trace_enabled.pod +++ b/doc/man3/OSSL_trace_enabled.pod @@ -7,6 +7,7 @@ OSSL_TRACE_BEGIN, OSSL_TRACE_END, OSSL_TRACE_CANCEL, OSSL_TRACE, OSSL_TRACE1, OSSL_TRACE2, OSSL_TRACE3, OSSL_TRACE4, OSSL_TRACE5, OSSL_TRACE6, OSSL_TRACE7, OSSL_TRACE8, OSSL_TRACE9, OSSL_TRACEV, +OSSL_TRACE_STRING, OSSL_TRACE_STRING_MAX, OSSL_trace_string, OSSL_TRACE_ENABLED - OpenSSL Tracing API @@ -33,10 +34,16 @@ OSSL_TRACE_ENABLED } OSSL_TRACE_END(category); /* one-shot trace macros */ + OSSL_TRACE(category, text) OSSL_TRACE1(category, format, arg1) OSSL_TRACE2(category, format, arg1, arg2) ... OSSL_TRACE9(category, format, arg1, ..., arg9) + OSSL_TRACE_STRING(category, text, full, data, len) + + #define OSSL_TRACE_STRING_MAX 80 + int OSSL_trace_string(BIO *out, int text, int full, + const unsigned char *data, size_t size); /* check whether a trace category is enabled */ if (OSSL_TRACE_ENABLED(category)) { @@ -49,8 +56,8 @@ The functions described here are mainly interesting for those who provide OpenSSL functionality, either in OpenSSL itself or in engine modules or similar. -If tracing is enabled (see L below), these functions are used to -generate free text tracing output. +If the tracing facility is enabled (see L below), +these functions are used to generate free text tracing output. The tracing output is divided into types which are enabled individually by the application. @@ -59,13 +66,13 @@ L. The fallback type B should I be used with the functions described here. -Tracing for a specific category is enabled if a so called +Tracing for a specific category is enabled at run-time if a so-called I is attached to it. A trace channel is simply a BIO object to which the application can write its trace output. The application has two different ways of registering a trace channel, -either by directly providing a BIO object using OSSL_trace_set_channel(), -or by providing a callback routine using OSSL_trace_set_callback(). +either by directly providing a BIO object using L, +or by providing a callback routine using L. The latter is wrapped internally by a dedicated BIO object, so for the tracing code both channel types are effectively indistinguishable. We call them a I and a I, @@ -86,7 +93,9 @@ but rather uses a set of convenience macros, see the L section below. =head2 Functions OSSL_trace_enabled() can be used to check if tracing for the given -I is enabled. +I is enabled, i.e., if the tracing facility has been statically +enabled (see L below) and a trace channel has been +registered using L or L. OSSL_trace_begin() is used to start a tracing section, and get the channel for the given I in form of a BIO. @@ -100,6 +109,12 @@ is I. The result of trying to produce tracing output outside of such sections is undefined. +OSSL_trace_string() outputs I of length I as a string on BIO I. +If I is 0, the function masks any included control characters apart from +newlines and makes sure for nonempty input that the output ends with a newline. +Unless I is nonzero, the length is limited (with a suitable warning) +to B characters, which currently is 80. + =head2 Macros There are a number of convenience macros defined, to make tracing @@ -110,7 +125,7 @@ used as follows to wrap a trace section: OSSL_TRACE_BEGIN(TLS) { - BIO_fprintf(trc_out, ... ); + BIO_printf(trc_out, ... ); } OSSL_TRACE_END(TLS); @@ -120,7 +135,7 @@ This will normally expand to: BIO *trc_out = OSSL_trace_begin(OSSL_TRACE_CATEGORY_TLS); if (trc_out != NULL) { ... - BIO_fprintf(trc_out, ...); + BIO_printf(trc_out, ...); } OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); } while (0); @@ -134,7 +149,7 @@ trace section: OSSL_TRACE_CANCEL(TLS); goto err; } - BIO_fprintf(trc_out, ... ); + BIO_printf(trc_out, ... ); } OSSL_TRACE_END(TLS); @@ -147,7 +162,7 @@ This will normally expand to: OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); goto err; } - BIO_fprintf(trc_out, ... ); + BIO_printf(trc_out, ... ); } OSSL_trace_end(OSSL_TRACE_CATEGORY_TLS, trc_out); } while (0); @@ -163,13 +178,22 @@ printf-style trace output with n format field arguments (n=1,...,9). It expands to: OSSL_TRACE_BEGIN(category) { - BIO_printf(trc_out, format, arg1, ..., argN) + BIO_printf(trc_out, format, arg1, ..., argN); } OSSL_TRACE_END(category) Internally, all one-shot macros are implemented using a generic OSSL_TRACEV() macro, since C90 does not support variadic macros. This helper macro has a rather weird synopsis and should not be used directly. +The macro call C +outputs I of length I as a string +if tracing for the given I is enabled. +It expands to: + + OSSL_TRACE_BEGIN(category) { + OSSL_trace_string(trc_out, text, full, data, len); + } OSSL_TRACE_END(category) + The OSSL_TRACE_ENABLED() macro can be used to conditionally execute some code only if a specific trace category is enabled. In some situations this is simpler than entering a trace section using @@ -253,7 +277,7 @@ For example, take this example from L section above: OSSL_TRACE_CANCEL(TLS); goto err; } - BIO_fprintf(trc_out, ... ); + BIO_printf(trc_out, ... ); } OSSL_TRACE_END(TLS); @@ -266,7 +290,7 @@ When the tracing API isn't operational, that will expand to: ((void)0); goto err; } - BIO_fprintf(trc_out, ... ); + BIO_printf(trc_out, ... ); } } while (0); @@ -280,13 +304,22 @@ operational and enabled, otherwise 0. OSSL_trace_begin() returns a B pointer if the given I is enabled, otherwise NULL. +OSSL_trace_string() returns the number of characters emitted, or -1 on error. + +=head1 SEE ALSO + +L, L + =head1 HISTORY The OpenSSL Tracing API was added in OpenSSL 3.0. +OSSL_TRACE_STRING(), OSSL_TRACE_STRING_MAX, and OSSL_trace_string +were added in OpenSSL 3.2. + =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 diff --git a/doc/man3/OSSL_trace_set_channel.pod b/doc/man3/OSSL_trace_set_channel.pod index f93242643c40..0db38e8db0d2 100644 --- a/doc/man3/OSSL_trace_set_channel.pod +++ b/doc/man3/OSSL_trace_set_channel.pod @@ -21,13 +21,13 @@ OSSL_trace_set_callback, OSSL_trace_cb - Enabling trace output =head1 DESCRIPTION -If available (see L below), the application can request +If available (see L below), the application can request internal trace output. This output comes in form of free text for humans to read. The trace output is divided into categories which can be enabled individually. -Every category can be enabled individually by attaching a so called +Every category can be enabled individually by attaching a so-called I to it, which in the simplest case is just a BIO object to which the application can write the tracing output for this category. Alternatively, the application can provide a tracer callback in order to @@ -38,6 +38,11 @@ For the tracing code, both trace channel types are indistinguishable. These are called a I and a I, respectively. +L can be used to check whether tracing is currently +enabled for the given category. +Functions like L and macros like L +can be used for producing free-text trace output. + =head2 Functions OSSL_trace_set_channel() is used to enable the given trace C @@ -58,7 +63,7 @@ OSSL_trace_set_callback() is used to enable the given trace I by giving it the tracer callback I with the associated data I, which will simply be passed through to I whenever it's called. The callback function is internally wrapped by a -dedicated BIO object, the so called I. +dedicated BIO object, the so-called I. This should be used when it's desirable to do form the trace output to something suitable for application needs where a prefix and suffix line aren't enough. @@ -201,6 +206,10 @@ Traces encoder operations. Traces decrementing certain ASN.1 structure references. +=item B + +Traces the HTTP client, such as message headers being sent and received. + =back There is also B, which works as a fallback @@ -314,6 +323,11 @@ When the library is built with tracing disabled, the macro B is defined in F<< >> and all functions described here are inoperational, i.e. will do nothing. +=head1 SEE ALSO + +L, L, L, +L + =head1 HISTORY OSSL_trace_set_channel(), OSSL_trace_set_prefix(), diff --git a/doc/man3/OpenSSL_add_all_algorithms.pod b/doc/man3/OpenSSL_add_all_algorithms.pod index 07403a32d534..750acdeab534 100644 --- a/doc/man3/OpenSSL_add_all_algorithms.pod +++ b/doc/man3/OpenSSL_add_all_algorithms.pod @@ -53,7 +53,7 @@ not be used. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/OpenSSL_version.pod b/doc/man3/OpenSSL_version.pod index e1cf16e2a109..e5dff33dcdda 100644 --- a/doc/man3/OpenSSL_version.pod +++ b/doc/man3/OpenSSL_version.pod @@ -162,6 +162,15 @@ The value has the same syntax as the environment variable. For x86 the string looks like C or C if not available. +=item OPENSSL_WINCTX + +The Windows install context. +The Windows install context is used to compute the OpenSSL registry key name +on Windows. The full registry key is +C, where C<{major}>, +C<{minor}> and C<{context}> are OpenSSL's major version number, minor version +number and the Windows install context, respectively. + =back For an unknown I, the text C is returned. @@ -211,6 +220,15 @@ automatically configured but may be set via an environment variable. The value has the same syntax as the environment variable. For x86 the string looks like C. +=item OPENSSL_INFO_WINDOWS_CONTEXT + +The Windows install context. +The Windows install context is used to compute the OpenSSL registry key name +on Windows. The full registry key is +C, where C<{major}>, +C<{minor}> and C<{context}> are OpenSSL's major version number, minor version +number and the Windows install context, respectively. + =back For an unknown I, NULL is returned. diff --git a/doc/man3/PEM_read.pod b/doc/man3/PEM_read.pod index c76039f711c2..8946af22629c 100644 --- a/doc/man3/PEM_read.pod +++ b/doc/man3/PEM_read.pod @@ -2,19 +2,14 @@ =head1 NAME -PEM_write, PEM_write_bio, -PEM_read, PEM_read_bio, PEM_do_header, PEM_get_EVP_CIPHER_INFO +PEM_read, PEM_read_bio, PEM_do_header, PEM_get_EVP_CIPHER_INFO, PEM_write, +PEM_write_bio, PEM_ASN1_write, PEM_ASN1_write_bio, PEM_ASN1_write_bio_ctx - PEM encoding routines =head1 SYNOPSIS #include - int PEM_write(FILE *fp, const char *name, const char *header, - const unsigned char *data, long len); - int PEM_write_bio(BIO *bp, const char *name, const char *header, - const unsigned char *data, long len); - int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, long *len); int PEM_read_bio(BIO *bp, char **name, char **header, @@ -24,6 +19,23 @@ PEM_read, PEM_read_bio, PEM_do_header, PEM_get_EVP_CIPHER_INFO int PEM_do_header(EVP_CIPHER_INFO *cinfo, unsigned char *data, long *len, pem_password_cb *cb, void *u); + int PEM_write(FILE *fp, const char *name, const char *header, + const unsigned char *data, long len); + int PEM_write_bio(BIO *bp, const char *name, const char *header, + const unsigned char *data, long len); + int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + const void *x, const EVP_CIPHER *enc, + const unsigned char *kstr, int klen, + pem_password_cb *callback, void *u); + int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, + const void *x, const EVP_CIPHER *enc, + const unsigned char *kstr, int klen, + pem_password_cb *callback, void *u); + int PEM_ASN1_write_bio_ctx(OSSL_i2d_of_void_ctx *i2d, void *vctx, + const char *name, BIO *bp, const void *x, + const EVP_CIPHER *enc, const unsigned char *kstr, + int klen, pem_password_cb *callback, void *u); + =head1 DESCRIPTION These functions read and write PEM-encoded objects, using the PEM @@ -89,9 +101,9 @@ nor PEM_get_EVP_CIPHER_INFO() need be called. =head1 RETURN VALUES -PEM_read() and PEM_read_bio() return 1 on success and 0 on failure, the latter -includes the case when no more PEM objects remain in the input file. -To distinguish end of file from more serious errors the caller must peek at the +PEM_read(), and PEM_read_bio() return 1 on success and 0 on failure, the latter +includes the case when no more PEM objects remain in the input file. To +distinguish end of file from more serious errors the caller must peek at the error stack and check for B, which indicates that no more PEM objects were found. See L, L. @@ -114,15 +126,26 @@ PEM_do_header() makes no assumption regarding the pass phrase received from the password callback. It will simply be treated as a byte sequence. +PEM_write() and PEM_write_bio() return the number of encoded bytes (not +counting the PEM header and end marker) written on success or 0 on failure. + +PEM_ASN1_write_bio(), and PEM_ASN1_write_bio_ctx() return 1 on success and 0 on +failure. The latter function passes an additional application-provided context +value to the B function that serialises the input ASN.1 object. + =head1 SEE ALSO L, L, L, L +=head1 HISTORY + +The PEM_ASN1_write_bio_ctx() function was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod index f1635b89808a..22a5d606b0db 100644 --- a/doc/man3/PEM_read_bio_PrivateKey.pod +++ b/doc/man3/PEM_read_bio_PrivateKey.pod @@ -26,6 +26,8 @@ PEM_write_bio_Parameters, PEM_read_bio_DSAparams, PEM_read_DSAparams, PEM_write_bio_DSAparams, PEM_write_DSAparams, PEM_read_bio_DHparams, PEM_read_DHparams, PEM_write_bio_DHparams, PEM_write_DHparams, PEM_read_bio_X509, PEM_read_X509, PEM_write_bio_X509, PEM_write_X509, +PEM_read_bio_X509_ACERT, PEM_read_X509_ACERT, +PEM_write_bio_X509_ACERT, PEM_write_X509_ACERT, PEM_read_bio_X509_AUX, PEM_read_X509_AUX, PEM_write_bio_X509_AUX, PEM_write_X509_AUX, PEM_read_bio_X509_REQ, PEM_read_X509_REQ, PEM_write_bio_X509_REQ, PEM_write_X509_REQ, PEM_write_bio_X509_REQ_NEW, @@ -108,6 +110,13 @@ PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines int PEM_write_bio_X509(BIO *bp, X509 *x); int PEM_write_X509(FILE *fp, X509 *x); + X509_ACERT *PEM_read_bio_X509_ACERT(BIO *bp, X509_ACERT **x, + pem_password_cb *cb, void *u); + X509_ACERT *PEM_read_X509_ACERT(FILE *fp, X509_ACERT **x, + pem_password_cb *cb, void *u); + int PEM_write_bio_X509_ACERT(BIO *bp, X509_ACERT *x); + int PEM_write_X509_ACERT(FILE *fp, X509_ACERT *x); + X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u); X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u); int PEM_write_bio_X509_AUX(BIO *bp, X509 *x); @@ -287,6 +296,9 @@ The B functions process an X509 certificate using an X509 structure. They will also process a trusted X509 certificate but any trust settings are discarded. +The B functions process an X509 attribute certificate using +an X509_ACERT structure. + The B functions process a trusted X509 certificate using an X509 structure. @@ -308,7 +320,7 @@ structure. The PEM functions have many common arguments. The I BIO parameter (if present) specifies the BIO to read from -or write to. +or write to. The I BIO parameter B be NULL. The I FILE parameter (if present) specifies the FILE pointer to read from or write to. @@ -573,6 +585,9 @@ PEM_write_bio_DSAparams(), PEM_write_DSAparams(), PEM_read_bio_DHparams(), PEM_read_DHparams(), PEM_write_bio_DHparams() and PEM_write_DHparams() were deprecated in 3.0. +PEM_read_bio_X509_ACERT(), PEM_read_X509_ACERT(), +PEM_write_bio_X509_ACERT(), PEM_write_X509_ACERT() +were added in OpenSSL 3.4. =head1 COPYRIGHT diff --git a/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod b/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod index 7073c0d5cec0..8ed67fbdf721 100644 --- a/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod +++ b/doc/man3/PKCS12_SAFEBAG_get0_attrs.pod @@ -40,7 +40,7 @@ L =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PKCS12_SAFEBAG_get1_cert.pod b/doc/man3/PKCS12_SAFEBAG_get1_cert.pod index ecd212c775ec..28bed08e3d40 100644 --- a/doc/man3/PKCS12_SAFEBAG_get1_cert.pod +++ b/doc/man3/PKCS12_SAFEBAG_get1_cert.pod @@ -5,7 +5,8 @@ PKCS12_SAFEBAG_get0_attr, PKCS12_SAFEBAG_get0_type, PKCS12_SAFEBAG_get_nid, PKCS12_SAFEBAG_get_bag_nid, PKCS12_SAFEBAG_get0_bag_obj, PKCS12_SAFEBAG_get0_bag_type, -PKCS12_SAFEBAG_get1_cert, PKCS12_SAFEBAG_get1_crl, +PKCS12_SAFEBAG_get1_cert_ex, PKCS12_SAFEBAG_get1_cert, +PKCS12_SAFEBAG_get1_crl_ex, PKCS12_SAFEBAG_get1_crl, PKCS12_SAFEBAG_get0_safes, PKCS12_SAFEBAG_get0_p8inf, PKCS12_SAFEBAG_get0_pkcs8 - Get objects from a PKCS#12 safeBag @@ -20,7 +21,11 @@ PKCS12_SAFEBAG_get0_pkcs8 - Get objects from a PKCS#12 safeBag int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag); const ASN1_TYPE *PKCS12_SAFEBAG_get0_bag_obj(const PKCS12_SAFEBAG *bag); const ASN1_OBJECT *PKCS12_SAFEBAG_get0_bag_type(const PKCS12_SAFEBAG *bag); + X509_CRL *PKCS12_SAFEBAG_get1_cert_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq); X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag); + X509_CRL *PKCS12_SAFEBAG_get1_crl_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq); X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag); const STACK_OF(PKCS12_SAFEBAG) *PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag); const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag); @@ -41,8 +46,13 @@ arbitrary for Bs. PKCS12_SAFEBAG_get0_bag_type() gets this type as an PKCS12_SAFEBAG_get0_bag_obj() retrieves the object contained within the safeBag. -PKCS12_SAFEBAG_get1_cert() and PKCS12_SAFEBAG_get1_crl() return new B or -B objects from the item in the safeBag. +PKCS12_SAFEBAG_get1_cert_ex() and PKCS12_SAFEBAG_get1_crl_ex() return new B or +B objects from the item in the safeBag. I and I are used when +fetching algorithms, and may optionally be set to NULL. + +PKCS12_SAFEBAG_get1_cert() and PKCS12_SAFEBAG_get1_crl() are the same as +PKCS12_SAFEBAG_get1_cert_ex() and PKCS12_SAFEBAG_get1_crl_ex() and set the I and +I to NULL. This will use the default library context. PKCS12_SAFEBAG_get0_p8inf() and PKCS12_SAFEBAG_get0_pkcs8() return the PKCS8 object from a PKCS8shroudedKeyBag or a keyBag. @@ -62,9 +72,14 @@ L, L, L +=head1 HISTORY + +The functions PKCS12_SAFEBAG_get1_cert_ex() and PKCS12_SAFEBAG_get1_crl_ex() were +added in OpenSSL 3.2. + =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 diff --git a/doc/man3/PKCS12_create.pod b/doc/man3/PKCS12_create.pod index 7048f1318576..5dae7fccb7f2 100644 --- a/doc/man3/PKCS12_create.pod +++ b/doc/man3/PKCS12_create.pod @@ -2,7 +2,7 @@ =head1 NAME -PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure +PKCS12_create, PKCS12_create_ex, PKCS12_create_cb, PKCS12_create_ex2 - create a PKCS#12 structure =head1 SYNOPSIS @@ -16,6 +16,13 @@ PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure int iter, int mac_iter, int keytype, OSSL_LIB_CTX *ctx, const char *propq); + typedef int PKCS12_create_cb(PKCS12_SAFEBAG *bag, void *cbarg); + + PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, + int iter, int mac_iter, int keytype, + OSSL_LIB_CTX *ctx, const char *propq, + PKCS12_create_cb *cb, void *cbarg); =head1 DESCRIPTION PKCS12_create() creates a PKCS#12 structure. @@ -34,6 +41,14 @@ I is the type of key. PKCS12_create_ex() is identical to PKCS12_create() but allows for a library context I and property query I to be used to select algorithm implementations. +PKCS12_create_ex2() is identical to PKCS12_create_ex() but allows for a user defined +callback I of type B to be specified and also allows for an +optional argument I to be passed back to the callback. + +The I if specified will be called for every safebag added to the +PKCS12 structure and allows for optional application processing on the associated +safebag. For example one such use could be to add attributes to the safebag. + =head1 NOTES The parameters I, I, I, I and I @@ -82,6 +97,9 @@ PKCS12_create() makes assumptions regarding the encoding of the given pass phrase. See L for more information. +If I is specified, then it should return 1 for success and -1 for a fatal error. +A return of 0 is intended to mean to not add the bag after all. + =head1 RETURN VALUES PKCS12_create() returns a valid B structure or NULL if an error occurred. @@ -100,6 +118,7 @@ L =head1 HISTORY PKCS12_create_ex() was added in OpenSSL 3.0. +PKCS12_create_ex2() was added in OpenSSL 3.2. The defaults for encryption algorithms, MAC algorithm, and the MAC key derivation iteration count were changed in OpenSSL 3.0 to more modern diff --git a/doc/man3/PKCS12_decrypt_skey.pod b/doc/man3/PKCS12_decrypt_skey.pod index 97c6823a3c74..d58c05ffebbb 100644 --- a/doc/man3/PKCS12_decrypt_skey.pod +++ b/doc/man3/PKCS12_decrypt_skey.pod @@ -45,7 +45,7 @@ PKCS12_decrypt_skey_ex() was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PKCS12_gen_mac.pod b/doc/man3/PKCS12_gen_mac.pod index a72df145fedd..ebeee98f04e6 100644 --- a/doc/man3/PKCS12_gen_mac.pod +++ b/doc/man3/PKCS12_gen_mac.pod @@ -3,7 +3,8 @@ =head1 NAME PKCS12_gen_mac, PKCS12_setup_mac, PKCS12_set_mac, -PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure +PKCS12_set_pbmac1_pbkdf2, PKCS12_verify_mac, PKCS12_get0_mac - +Functions to create and manipulate a PKCS#12 MAC structure =head1 SYNOPSIS @@ -15,9 +16,19 @@ PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, const EVP_MD *md_type); + int PKCS12_set_pbmac1_pbkdf2(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type, + const char *prf_md_name); int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, const EVP_MD *md_type); + void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, + const X509_ALGOR **pmacalg, + const ASN1_OCTET_STRING **psalt, + const ASN1_INTEGER **piter, + const PKCS12 *p12); + =head1 DESCRIPTION PKCS12_gen_mac() generates an HMAC over the entire PKCS#12 object using the @@ -31,10 +42,15 @@ PKCS12_setup_mac() sets the MAC part of the PKCS#12 structure with the supplied parameters. PKCS12_set_mac() sets the MAC and MAC parameters into the PKCS#12 object. +PKCS12_set_pbmac1_pbkdf2() sets the MAC and MAC parameters into the PKCS#12 +object when B with PBKDF2 is used for protection of the PKCS#12 object. I is the passphrase to use in the HMAC. I is the salt value to use, -I is the iteration count and I is the message digest -function to use. +I is the iteration count and I is the message digest function to +use. I specifies the digest used for the PBKDF2 in PBMAC1 KDF. + +PKCS12_get0_mac() retrieves any included MAC value, B object, +I, and I count from the PKCS12 object. =head1 NOTES @@ -43,17 +59,18 @@ If I is NULL then a suitable salt will be generated and used. If I is 1 then an iteration count will be omitted from the PKCS#12 structure. -PKCS12_gen_mac(), PKCS12_verify_mac() and PKCS12_set_mac() make assumptions -regarding the encoding of the given passphrase. See L -for more information. +PKCS12_gen_mac(), PKCS12_verify_mac(), PKCS12_set_mac() and +PKCS12_set_pbmac1_pbkdf2() make assumptions regarding the encoding of the +given passphrase. See L for more information. =head1 RETURN VALUES -All functions return 1 on success and 0 if an error occurred. +All functions returning an integer return 1 on success and 0 if an error occurred. =head1 CONFORMING TO IETF RFC 7292 (L) +IETF RFC 9579 (L) =head1 SEE ALSO @@ -62,9 +79,13 @@ L, L, L +=head1 HISTORY + +The I function was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PKCS5_PBE_keyivgen.pod b/doc/man3/PKCS5_PBE_keyivgen.pod index 72de3153b97d..f697628db13b 100644 --- a/doc/man3/PKCS5_PBE_keyivgen.pod +++ b/doc/man3/PKCS5_PBE_keyivgen.pod @@ -127,6 +127,12 @@ associated parameters for the PBKDF2 algorithm. PKCS5_pbe_set0_algor() and PKCS5_pbe_set0_algor_ex() set the PBE algorithm OID and parameters into the supplied B. +If I is NULL, then I specifies the size in bytes of the random salt to +generate. If I is 0 then a default size is used. +For PBE related functions such as PKCS5_pbe_set_ex() the default salt length is 8 bytes. +For PBE2 related functions that use PBKDF2 such as PKCS5_pbkdf2_set(), +PKCS5_pbe2_set_scrypt() and PKCS5_pbe2_set() the default salt length is 16 bytes. + =head1 NOTES The *_keyivgen() functions are typically used in PKCS#12 to encrypt objects. @@ -165,9 +171,13 @@ PKCS5_pbkdf2_set_ex() were added in OpenSSL 3.0. From OpenSSL 3.0 the PBKDF1 algorithm used in PKCS5_PBE_keyivgen() and PKCS5_PBE_keyivgen_ex() has been moved to the legacy provider as an EVP_KDF. +In OpenSSL 3.2 the default salt length changed from 8 bytes to 16 bytes for PBE2 +related functions such as PKCS5_pbe2_set(). +This is required for PBKDF2 FIPS compliance. + =head1 COPYRIGHT -Copyright 2021 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 diff --git a/doc/man3/PKCS5_PBKDF2_HMAC.pod b/doc/man3/PKCS5_PBKDF2_HMAC.pod index 8b5feff9192c..3da271bdbff7 100644 --- a/doc/man3/PKCS5_PBKDF2_HMAC.pod +++ b/doc/man3/PKCS5_PBKDF2_HMAC.pod @@ -67,7 +67,7 @@ L =head1 COPYRIGHT -Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PKCS7_sign_add_signer.pod b/doc/man3/PKCS7_sign_add_signer.pod index d1271fe7f424..24353484abc7 100644 --- a/doc/man3/PKCS7_sign_add_signer.pod +++ b/doc/man3/PKCS7_sign_add_signer.pod @@ -100,7 +100,7 @@ The PPKCS7_sign_add_signer() function was added in OpenSSL 1.0.0. =head1 COPYRIGHT -Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/PKCS7_verify.pod b/doc/man3/PKCS7_verify.pod index 2f5f75aa2897..b9e1ee303582 100644 --- a/doc/man3/PKCS7_verify.pod +++ b/doc/man3/PKCS7_verify.pod @@ -19,6 +19,8 @@ PKCS7_verify() is very similar to L. It verifies a PKCS#7 signedData structure given in I. The optional I parameter refers to a set of certificates in which to search for signer's certificates. +It is also used +as a source of untrusted intermediate CA certificates for chain building. I may contain extra untrusted CA certificates that may be used for chain building as well as CRLs that may be used for certificate validation. I may be NULL or point to @@ -131,7 +133,7 @@ L, L =head1 COPYRIGHT -Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RAND_add.pod b/doc/man3/RAND_add.pod index 10a68114330a..dd39b8ca4347 100644 --- a/doc/man3/RAND_add.pod +++ b/doc/man3/RAND_add.pod @@ -101,7 +101,7 @@ not be used. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RAND_bytes.pod b/doc/man3/RAND_bytes.pod index 8440a7318564..9d3bd349cb1a 100644 --- a/doc/man3/RAND_bytes.pod +++ b/doc/man3/RAND_bytes.pod @@ -3,7 +3,7 @@ =head1 NAME RAND_bytes, RAND_priv_bytes, RAND_bytes_ex, RAND_priv_bytes_ex, -RAND_pseudo_bytes - generate random data +RAND_pseudo_bytes, RAND_set1_random_provider - generate random data =head1 SYNOPSIS @@ -17,6 +17,8 @@ RAND_pseudo_bytes - generate random data int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, size_t num, unsigned int strength); + int RAND_set1_random_provider(OSSL_LIB_CTX *ctx, OSSL_PROVIDER *p); + The following function has been deprecated since OpenSSL 1.1.0, and can be hidden entirely by defining B with a suitable version value, see L: @@ -26,7 +28,7 @@ see L: =head1 DESCRIPTION RAND_bytes() generates B random bytes using a cryptographically -secure pseudo random generator (CSPRNG) and stores them in B. +secure pseudo random generator (CSPRNG) and stores them in B. B B be NULL. RAND_priv_bytes() has the same semantics as RAND_bytes(). It is intended to be used for generating values that should remain private. If using the @@ -46,6 +48,12 @@ If the default RAND_METHOD has been changed then for compatibility reasons the RAND_METHOD will be used in preference and the DRBG of the library context ignored. +RAND_set1_random_provider() specifies a provider, I, which will be used +by the library context I for all of the generate calls above instead +of the built-in in DRBGs and entropy source. Pass NULL for the provider +to disable the random provider functionality. In this case, the built-in DRBGs +and entropy source will be used. This call should not be considered thread safe. + =head1 NOTES By default, the OpenSSL CSPRNG supports a security level of 256 bits, provided it @@ -72,6 +80,8 @@ return 1 on success, -1 if not supported by the current RAND method, or 0 on other failure. The error code can be obtained by L. +RAND_set1_random_provider() returns 1 on success and 0 on failure. + =head1 SEE ALSO L, @@ -97,11 +107,15 @@ The RAND_priv_bytes() function was added in OpenSSL 1.1.1. The RAND_bytes_ex() and RAND_priv_bytes_ex() functions were added in OpenSSL 3.0 +=item * + +The RAND_set1_random_provider() function was added in OpenSSL 3.5 + =back =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RAND_cleanup.pod b/doc/man3/RAND_cleanup.pod index ce61a9f2b12e..5b8461598822 100644 --- a/doc/man3/RAND_cleanup.pod +++ b/doc/man3/RAND_cleanup.pod @@ -36,7 +36,7 @@ See L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RAND_get0_primary.pod b/doc/man3/RAND_get0_primary.pod index 408d02077f29..c68b850255d8 100644 --- a/doc/man3/RAND_get0_primary.pod +++ b/doc/man3/RAND_get0_primary.pod @@ -4,7 +4,9 @@ RAND_get0_primary, RAND_get0_public, -RAND_get0_private +RAND_get0_private, +RAND_set0_public, +RAND_set0_private - get access to the global EVP_RAND_CTX instances =head1 SYNOPSIS @@ -14,6 +16,8 @@ RAND_get0_private EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx); EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx); EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx); + int RAND_set0_public(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand); + int RAND_set0_private(OSSL_LIB_CTX *ctx, EVP_RAND_CTX *rand); =head1 DESCRIPTION @@ -25,7 +29,10 @@ by RAND_bytes() and RAND_priv_bytes(), respectively. The I DRBG is a global instance, which is not intended to be used directly, but is used internally to reseed the other two instances. -These functions here provide access to the shared DRBG instances. +The three get functions provide access to the shared DRBG instances. + +The two set functions allow the public and private DRBG instances to be +replaced by another random number generator. =head1 RETURN VALUES @@ -38,8 +45,8 @@ for the given OSSL_LIB_CTX B. RAND_get0_private() returns a pointer to the I DRBG instance for the given OSSL_LIB_CTX B. -In all the above cases the B parameter can -be NULL in which case the default OSSL_LIB_CTX is used. +RAND_set0_public() and RAND_set0_private() return 1 on success and 0 +on error. =head1 NOTES @@ -61,6 +68,10 @@ To set the type of DRBG that will be instantiated, use the L call before accessing the random number generation infrastructure. +The two set functions, operate on the current thread. If you want to +use the same random number generator across all threads, each thread +must individually call the set functions. + =head1 SEE ALSO L, @@ -68,11 +79,13 @@ L =head1 HISTORY -These functions were added in OpenSSL 3.0. +RAND_set0_public() and RAND_set0_private() were added in OpenSSL 3.1. + +The remaining functions were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RAND_set_DRBG_type.pod b/doc/man3/RAND_set_DRBG_type.pod index 423ebfad656f..4d26029c2fe2 100644 --- a/doc/man3/RAND_set_DRBG_type.pod +++ b/doc/man3/RAND_set_DRBG_type.pod @@ -41,7 +41,15 @@ is made too late. The default DRBG is "CTR-DRBG" using the "AES-256-CTR" cipher. -The default seed source is "SEED-SRC". +The default seed source can be configured when OpenSSL is compiled by +setting B<-DOPENSSL_DEFAULT_SEED_SRC=SEED-SRC>. If not set then +"SEED-SRC" is used. + +=head1 EXAMPLES + + unsigned char bytes[100]; + RAND_set_seed_source_type(NULL, "JITTER", NULL); + RAND_bytes(bytes, 100); =head1 SEE ALSO diff --git a/doc/man3/RC4_set_key.pod b/doc/man3/RC4_set_key.pod index 296f88eb6f20..3f6e362f76c2 100644 --- a/doc/man3/RC4_set_key.pod +++ b/doc/man3/RC4_set_key.pod @@ -68,7 +68,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RIPEMD160_Init.pod b/doc/man3/RIPEMD160_Init.pod index 48937a647f5a..7339bd480a12 100644 --- a/doc/man3/RIPEMD160_Init.pod +++ b/doc/man3/RIPEMD160_Init.pod @@ -73,7 +73,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_check_key.pod b/doc/man3/RSA_check_key.pod index d9c0097772c4..a9e3d36aa67a 100644 --- a/doc/man3/RSA_check_key.pod +++ b/doc/man3/RSA_check_key.pod @@ -84,7 +84,7 @@ RSA_check_key_ex() appeared after OpenSSL 1.0.2. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_get0_key.pod b/doc/man3/RSA_get0_key.pod index 1c1fa5bfcda3..ffcc04e3be5f 100644 --- a/doc/man3/RSA_get0_key.pod +++ b/doc/man3/RSA_get0_key.pod @@ -184,7 +184,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_padding_add_PKCS1_type_1.pod b/doc/man3/RSA_padding_add_PKCS1_type_1.pod index 9f7025c49755..36ae18563f21 100644 --- a/doc/man3/RSA_padding_add_PKCS1_type_1.pod +++ b/doc/man3/RSA_padding_add_PKCS1_type_1.pod @@ -121,8 +121,8 @@ L. =head1 WARNINGS -The result of RSA_padding_check_PKCS1_type_2() is a very sensitive -information which can potentially be used to mount a Bleichenbacher +The result of RSA_padding_check_PKCS1_type_2() is exactly the +information which is used to mount a classical Bleichenbacher padding oracle attack. This is an inherent weakness in the PKCS #1 v1.5 padding design. Prefer PKCS1_OAEP padding. If that is not possible, the result of RSA_padding_check_PKCS1_type_2() should be @@ -137,6 +137,9 @@ as this would create a small timing side channel which could be used to mount a Bleichenbacher attack against any padding mode including PKCS1_OAEP. +You should prefer the use of EVP PKEY APIs for PKCS#1 v1.5 decryption +as they implement the necessary workarounds internally. + =head1 SEE ALSO L, diff --git a/doc/man3/RSA_print.pod b/doc/man3/RSA_print.pod index 27495b2241af..96ca3df1131c 100644 --- a/doc/man3/RSA_print.pod +++ b/doc/man3/RSA_print.pod @@ -67,7 +67,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_public_encrypt.pod b/doc/man3/RSA_public_encrypt.pod index 1d38073aeada..cbe4e2261186 100644 --- a/doc/man3/RSA_public_encrypt.pod +++ b/doc/man3/RSA_public_encrypt.pod @@ -52,8 +52,8 @@ Encrypting user data directly with RSA is insecure. =back -B must not be more than RSA_size(B) - 11 for the PKCS #1 v1.5 -based padding modes, not more than RSA_size(B) - 42 for +When encrypting B must not be more than RSA_size(B) - 11 for the +PKCS #1 v1.5 based padding modes, not more than RSA_size(B) - 42 for RSA_PKCS1_OAEP_PADDING and exactly RSA_size(B) for RSA_NO_PADDING. When a padding mode other than RSA_NO_PADDING is in use, then RSA_public_encrypt() will include some random bytes into the ciphertext @@ -92,6 +92,20 @@ which can potentially be used to mount a Bleichenbacher padding oracle attack. This is an inherent weakness in the PKCS #1 v1.5 padding design. Prefer RSA_PKCS1_OAEP_PADDING. +In OpenSSL before version 3.2.0, both the return value and the length of +returned value could be used to mount the Bleichenbacher attack. +Since version 3.2.0, the default provider in OpenSSL does not return an +error when padding checks fail. Instead it generates a random +message based on used private +key and provided ciphertext so that application code doesn't have to implement +a side-channel secure error handling. +Applications that want to be secure against side-channel attacks with +providers that don't implement implicit rejection, still need to +handle the returned values using side-channel free code. +Side-channel free handling of the error stack can be performed using +either a pair of unconditional L and L +calls or by using the L call. + =head1 CONFORMING TO SSL, PKCS #1 v2.0 @@ -99,7 +113,7 @@ SSL, PKCS #1 v2.0 =head1 SEE ALSO L, L, -L +L, L, L =head1 HISTORY @@ -107,7 +121,7 @@ Both of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_set_method.pod b/doc/man3/RSA_set_method.pod index 6e45d6b60b9d..21cfeed27b46 100644 --- a/doc/man3/RSA_set_method.pod +++ b/doc/man3/RSA_set_method.pod @@ -185,7 +185,7 @@ was replaced to always return NULL in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_sign.pod b/doc/man3/RSA_sign.pod index e883caf7682f..a85a2575376b 100644 --- a/doc/man3/RSA_sign.pod +++ b/doc/man3/RSA_sign.pod @@ -67,7 +67,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod b/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod index 6548bdb78a06..77c8a202a7f1 100644 --- a/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod +++ b/doc/man3/RSA_sign_ASN1_OCTET_STRING.pod @@ -68,7 +68,7 @@ All of these functions were deprecated in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SCT_print.pod b/doc/man3/SCT_print.pod index fbcbce2760c3..97dd58f7bcfe 100644 --- a/doc/man3/SCT_print.pod +++ b/doc/man3/SCT_print.pod @@ -47,7 +47,7 @@ These functions were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_COMP_add_compression_method.pod b/doc/man3/SSL_COMP_add_compression_method.pod index 924553805eea..4b32023959cd 100644 --- a/doc/man3/SSL_COMP_add_compression_method.pod +++ b/doc/man3/SSL_COMP_add_compression_method.pod @@ -60,7 +60,21 @@ when a matching identifier is found. There is no way to restrict the list of compression methods supported on a per connection basis. If enabled during compilation, the OpenSSL library will have the -COMP_zlib() compression method available. +following compression methods available: + +=over 4 + +=item COMP_zlib() + +=item COMP_brotli() + +=item COMP_brotli_oneshot() + +=item COMP_zstd() + +=item COMP_zstd_oneshot() + +=back =head1 RETURN VALUES @@ -96,7 +110,7 @@ The SSL_COMP_get0_name() and SSL_comp_get_id() functions were added in OpenSSL 1 =head1 COPYRIGHT -Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod index ae6ca432829e..e2c1e6984703 100644 --- a/doc/man3/SSL_CONF_cmd.pod +++ b/doc/man3/SSL_CONF_cmd.pod @@ -46,7 +46,10 @@ As of OpenSSL 1.1.0, compression is off by default. Enables support for SSL/TLS compression, same as clearing B. This command was introduced in OpenSSL 1.1.0. -As of OpenSSL 1.1.0, compression is off by default. +As of OpenSSL 1.1.0, compression is off by default. TLS compression can only be +used in security level 1 or lower. From OpenSSL 3.2.0 and above the default +security level is 2, so this option will have no effect without also changing +the security level. See L. =item B<-no_ticket> @@ -95,6 +98,12 @@ Only used by servers. Requires B<-serverpref>. In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means that there will be no forward secrecy for the resumed session. +=item B<-prefer_no_dhe_kex> + +In TLSv1.3, on resumption let the server prefer a non-(ec)dhe based key +exchange mode over an (ec)dhe based one. Requires B<-allow_no_dhe_kex>. +Equivalent to B. Only used by servers. + =item B<-strict> Enables strict mode protocol handling. Equivalent to setting @@ -109,15 +118,20 @@ algorithms to support. The B argument should be a colon separated list of signature algorithms in order of decreasing preference of the form B -or B. B is one of B, B or B and +or B. For the default providers shipped with OpenSSL, +B is one of B, B or B and B is a supported algorithm OID short name such as B, B, -B, B of B. Note: algorithm and hash names are case -sensitive. B is one of the signature schemes defined in -TLSv1.3, specified using the IETF name, e.g., B, -B, or B. +B, B or B. +B is one of the signature schemes defined +in TLSv1.3, specified using the IETF name, e.g., B, +B, or B. Additional providers may make available +further algorithms via the TLS-SIGALG capability. +Signature scheme names and public key algorithm names (but not the hash names) +in the B form are case-insensitive. +See L. -If this option is not set then all signature algorithms supported by the -OpenSSL library are permissible. +If this option is not set then all signature algorithms supported by all +activated providers are permissible. Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by using B as the B or by using one of the B @@ -140,18 +154,45 @@ value set for B<-sigalgs> will be used instead. This sets the supported groups. For clients, the groups are sent using the supported groups extension. For servers, it is used to determine which group to use. This setting affects groups used for signatures (in TLSv1.2 -and earlier) and key exchange. The first group listed will also be used -for the B sent by a client in a TLSv1.3 B. +and earlier) and key exchange. -The B argument is a colon separated list of groups. The group can -be either the B name (e.g. B), some other commonly used name -where applicable (e.g. B, B) or an OpenSSL OID name -(e.g. B). Group names are case sensitive. The list should be -in order of preference with the most preferred group first. +In its simplest form the I argument is a colon separated list of +groups. The preferred names are those listed in the IANA +L +registry. -Currently supported groups for B are B, B, B, -B, B, B, B, B, B, -B. +For some groups, OpenSSL supports additional aliases. +Such an alias could be a B name (e.g. B), an OpenSSL OID name +(e.g. B), or some other commonly used name. +Group names are case-insensitive in OpenSSL 3.5 and later. +The list should be in order of preference with the most preferred group first. + +The first group listed will also be used for the B sent by a client +in a TLSv1.3 B. + +The commands below list the IANA names for TLS 1.2 and TLS 1.3, +respectively: + + $ openssl list -tls1_2 -tls-groups + $ openssl list -tls1_3 -tls-groups + +The recommended groups (in order of decreasing performance) for TLS 1.3 are presently: + +B, +B, +B, +and +B. + +The stronger security margins of the last two, come at a significant +performance penalty. + +An enriched alternative syntax, that enables clients to send multiple keyshares +and allows servers to prioritise some groups over others, is described in +L. +Since TLS 1.2 has neither keyshares nor a hello retry mechanism, with TLS 1.2 +the enriched syntax is ultimately equivalent to just a simple ordered list of +groups, as with the simple form above. =item B<-curves> I @@ -159,13 +200,35 @@ This is a synonym for the B<-groups> command. =item B<-named_curve> I -This sets the temporary curve used for ephemeral ECDH modes. Only used -by servers. +This sets the temporary curve used for ephemeral ECDH modes. +This is only applicable in TLS 1.0 and 1.1, and should not be used with later +protocol versions. -The B argument is a curve name or the special value B which +The I argument is a curve name or the special value B which picks an appropriate curve based on client and server preferences. The curve can be either the B name (e.g. B) or an OpenSSL OID name -(e.g. B). Curve names are case sensitive. +(e.g. B). +Even with TLS 1.0 and 1.1, the default value of C is strongly recommended +over choosing a specific curve. +Curve names are case-insensitive in OpenSSL 3.5 and later. + +=item B<-tx_cert_comp> + +Enables support for sending TLSv1.3 compressed certificates. + +=item B<-no_tx_cert_comp> + +Disables support for sending TLSv1.3 compressed certificates. + +=item B<-rx_cert_comp> + +Enables support for receiving TLSv1.3 compressed certificates. + +=item B<-no_rx_cert_comp> + +Disables support for receiving TLSv1.3 compressed certificates. + +=item B<-comp> =item B<-cipher> I @@ -197,9 +260,15 @@ deprecated alternative commands below. =item B<-record_padding> I -Attempts to pad TLSv1.3 records so that they are a multiple of B -in length on send. A B of 0 or 1 turns off padding. Otherwise, -the B must be >1 or <=16384. +Controls use of TLSv1.3 record layer padding. B is a string of the +form "number[,number]" where the (required) first number is the padding block +size (in octets) for application data, and the optional second number is the +padding block size for handshake and alert messages. If the optional second +number is omitted, the same padding will be applied to all messages. + +Padding attempts to pad TLSv1.3 records so that they are a multiple of the set +length on send. A value of 0 or 1 turns off padding as relevant. Otherwise, the +values must be >1 or <=16384. =item B<-debug_broken_protocol> @@ -329,9 +398,15 @@ operations are permitted. =item B -Attempts to pad TLSv1.3 records so that they are a multiple of B in -length on send. A B of 0 or 1 turns off padding. Otherwise, the -B must be >1 or <=16384. +Controls use of TLSv1.3 record layer padding. B is a string of the form +"number[,number]" where the (required) first number is the padding block size +(in octets) for application data, and the optional second number is the padding +block size for handshake and alert messages. If the optional second number is +omitted, the same padding will be applied to all messages. + +Padding attempts to pad TLSv1.3 records so that they are a multiple of the set +length on send. A value of 0 or 1 turns off padding as relevant. Otherwise, the +values must be >1 or <=16384. =item B @@ -342,16 +417,20 @@ servers it is used to determine which signature algorithms to support. The B argument should be a colon separated list of signature algorithms in order of decreasing preference of the form B or -B. B -is one of B, B or B and B is a supported algorithm -OID short name such as B, B, B, B of B. -Note: algorithm and hash names are case sensitive. +B. For the default providers shipped with OpenSSL, +B is one of B, B or B and B is a supported +algorithm OID short name such as B, B, B, B +or B. B is one of the signature schemes defined in TLSv1.3, -specified using the IETF name, e.g., B, B, +specified using the IANA name, e.g., B, B, or B. +Signature scheme names and public key algorithm names (but not the hash names) +in the B form are case-insensitive. +Additional providers may make available further signature schemes via the +TLS_SIGALG capability. See L. -If this option is not set then all signature algorithms supported by the -OpenSSL library are permissible. +If this option is not set then all signature algorithms supported by all +activated providers are permissible. Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by using B as the B or by using one of the B @@ -379,15 +458,28 @@ signatures (in TLSv1.2 and earlier) and key exchange. The first group listed will also be used for the B sent by a client in a TLSv1.3 B. -The B argument is a colon separated list of groups. The group can be -either the B name (e.g. B), some other commonly used name where -applicable (e.g. B, B) or an OpenSSL OID name -(e.g. B). Group names are case sensitive. The list should be in -order of preference with the most preferred group first. +The B argument is a colon separated list of groups. The preferred +names are those listed in the IANA +L +registry. +For some groups, OpenSSL supports additional aliases. +Such an alias could be a B name (e.g. B), an OpenSSL OID name +(e.g. B), or some other commonly used name. +Group names are case-insensitive in OpenSSL 3.5 and later. +The list should be in order of preference with the most preferred group first. -Currently supported groups for B are B, B, B, -B, B, B, B, B, B, -B. +The commands below list the available groups for TLS 1.2 and TLS 1.3, +respectively: + + $ openssl list -tls1_2 -tls-groups + $ openssl list -tls1_3 -tls-groups + +An enriched alternative syntax, that enables clients to send multiple keyshares +and allows servers to prioritise some groups over others, is described in +L. +Since TLS 1.2 has neither keyshares nor a hello retry mechanism, with TLS 1.2 +the enriched syntax is ultimately equivalent to just a simple ordered list of +groups, as with the simple form above. =item B @@ -505,6 +597,11 @@ B: In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means that there will be no forward secrecy for the resumed session. Equivalent to B. +B: In TLSv1.3, on resumption let the server prefer a +non-(ec)dhe based key exchange mode over an (ec)dhe based one. Requires +B. Equivalent to B. Only used by +servers. + B: If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This has the effect of making TLSv1.3 look more like TLSv1.2 so that middleboxes that do not understand TLSv1.3 will not drop the connection. This @@ -532,6 +629,30 @@ B: Enables kernel TLS if support has been compiled in, and it is supported by the negotiated ciphersuites and extensions. Equivalent to B. +B: Enable strict certificate checking. Equivalent to +setting B with SSL_CTX_set_cert_flags(). + +B: support sending compressed certificates, enabled by +default. Inverse of B: that is, +B<-TxCertificateCompression> is the same as setting B. + +B: support receiving compressed certificates, enabled by +default. Inverse of B: that is, +B<-RxCertificateCompression> is the same as setting B. + +B: use the zerocopy TX mode of sendfile(), which gives +a performance boost when used with KTLS hardware offload. Note that invalid TLS +records might be transmitted if the file is changed while being sent. This +option has no effect if B is not enabled. Equivalent to +B. This option only applies to Linux. +KTLS sendfile on FreeBSD doesn't offer an option to disable zerocopy and +always runs in this mode. + +B: Equivalent to B. +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. + =item B The B argument is a comma separated list of flags to set. @@ -733,9 +854,32 @@ B and B were added in OpenSSL 1.1.1. The B option is no longer set by default from OpenSSL 3.0. +The B and B options were +added in OpenSSL 3.2. + +B was added in OpenSSL 3.3. + +OpenSSL 3.5 introduces support for post-quantum (PQ) TLS key exchange via the +B, B and B TLS groups. +These are based on the underlying B, B and +B algorithms from FIPS 203. + +OpenSSL 3.5 also introduces support for three B ECDH PQ key exchange +TLS groups: B, B and +B. +They offer CPU performance comparable to the associated ECDH group, though at +the cost of significantly larger key exchange messages. +The third group, B is substantially more CPU-intensive, +largely as a result of the high CPU cost of ECDH for the underlying B +group. +Also its key exchange messages at close to 1700 bytes are larger than the +roughly 1200 bytes for the first two groups. + +As of OpenSSL 3.5 key exchange group names are case-insensitive. + =head1 COPYRIGHT -Copyright 2012-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2012-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_dane_enable.pod b/doc/man3/SSL_CTX_dane_enable.pod index 5a3977b70a4f..d558e63895fd 100644 --- a/doc/man3/SSL_CTX_dane_enable.pod +++ b/doc/man3/SSL_CTX_dane_enable.pod @@ -306,10 +306,13 @@ the lifetime of the SSL connection. int depth = SSL_get0_dane_authority(ssl, NULL, &mspki); if (depth >= 0) { (void) SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, NULL, NULL); - printf("DANE TLSA %d %d %d %s at depth %d\n", usage, selector, mtype, - (mspki != NULL) ? "TA public key verified certificate" : - depth ? "matched TA certificate" : "matched EE certificate", - depth); + printf("DANE TLSA %d %d %d ", usage, selector, mtype); + if (SSL_get0_peer_rpk(ssl) == NULL) + printf("%s certificate at depth %d\n", + (mspki != NULL) ? "signed the peer" : + mdpth ? "matched the TA" : "matched the EE", mdpth); + else + printf(bio, "matched the peer raw public key\n"); } if (peername != NULL) { /* Name checks were in scope and matched the peername */ @@ -373,7 +376,7 @@ These functions were added in OpenSSL 1.1.0. =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 diff --git a/doc/man3/SSL_CTX_flush_sessions.pod b/doc/man3/SSL_CTX_flush_sessions.pod index 2ab7c883828c..dc43f285556b 100644 --- a/doc/man3/SSL_CTX_flush_sessions.pod +++ b/doc/man3/SSL_CTX_flush_sessions.pod @@ -2,19 +2,28 @@ =head1 NAME -SSL_CTX_flush_sessions - remove expired sessions +SSL_CTX_flush_sessions_ex, SSL_CTX_flush_sessions - remove expired sessions =head1 SYNOPSIS #include + void SSL_CTX_flush_sessions_ex(SSL_CTX *ctx, time_t tm); + +The following functions have been deprecated since OpenSSL 3.4, and can be +hidden entirely by defining B with a suitable version value, +see L: + void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm); =head1 DESCRIPTION -SSL_CTX_flush_sessions() causes a run through the session cache of +SSL_CTX_flush_sessions_ex() causes a run through the session cache of B to remove sessions expired at time B. +SSL_CTX_flush_sessions() is an older variant of the function that is not +Y2038 safe due to usage of long datatype instead of time_t. + =head1 NOTES If enabled, the internal session cache will collect all sessions established @@ -23,20 +32,20 @@ As sessions will not be reused ones they are expired, they should be removed from the cache to save resources. This can either be done automatically whenever 255 new sessions were established (see L) -or manually by calling SSL_CTX_flush_sessions(). +or manually by calling SSL_CTX_flush_sessions_ex(). The parameter B specifies the time which should be used for the expiration test, in most cases the actual time given by time(0) will be used. -SSL_CTX_flush_sessions() will only check sessions stored in the internal +SSL_CTX_flush_sessions_ex() will only check sessions stored in the internal cache. When a session is found and removed, the remove_session_cb is however called to synchronize with the external cache (see L). =head1 RETURN VALUES -SSL_CTX_flush_sessions() does not return a value. +SSL_CTX_flush_sessions_ex() does not return a value. =head1 SEE ALSO @@ -45,9 +54,13 @@ L, L, L +=head1 HISTORY + +SSL_CTX_flush_sessions_ex() was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_load_verify_locations.pod b/doc/man3/SSL_CTX_load_verify_locations.pod index b0dc8babd2d1..7e3b2771f29d 100644 --- a/doc/man3/SSL_CTX_load_verify_locations.pod +++ b/doc/man3/SSL_CTX_load_verify_locations.pod @@ -31,7 +31,7 @@ SSL_CTX_load_verify_locations(), SSL_CTX_load_verify_dir(), SSL_CTX_load_verify_file(), SSL_CTX_load_verify_store() specifies the locations for B, at which CA certificates for verification purposes are located. The certificates available via B, B and -B are trusted. +B are trusted. B B be NULL Details of the certificate verification and chain checking process are described in L. @@ -47,6 +47,7 @@ The default CA certificates file is called F in the default OpenSSL directory. Alternatively the B environment variable can be defined to override this location. +B B be NULL. SSL_CTX_set_default_verify_dir() is similar to SSL_CTX_set_default_verify_paths() except that just the default directory is diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod old mode 100644 new mode 100755 index cbd8f713468b..017eefd3176a --- a/doc/man3/SSL_CTX_set1_curves.pod +++ b/doc/man3/SSL_CTX_set1_curves.pod @@ -3,9 +3,10 @@ =head1 NAME SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups, -SSL_set1_groups_list, SSL_get1_groups, SSL_get_shared_group, -SSL_get_negotiated_group, SSL_CTX_set1_curves, SSL_CTX_set1_curves_list, -SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve +SSL_set1_groups_list, SSL_get1_groups, SSL_get0_iana_groups, +SSL_get_shared_group, SSL_get_negotiated_group, SSL_CTX_set1_curves, +SSL_CTX_set1_curves_list, SSL_set1_curves, SSL_set1_curves_list, +SSL_get1_curves, SSL_get_shared_curve, SSL_CTX_get0_implemented_groups - EC supported curve functions =head1 SYNOPSIS @@ -19,6 +20,7 @@ SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve int SSL_set1_groups_list(SSL *ssl, char *list); int SSL_get1_groups(SSL *ssl, int *groups); + int SSL_get0_iana_groups(SSL *ssl, uint16_t **out); int SSL_get_shared_group(SSL *s, int n); int SSL_get_negotiated_group(SSL *s); @@ -31,6 +33,9 @@ SSL_set1_curves, SSL_set1_curves_list, SSL_get1_curves, SSL_get_shared_curve int SSL_get1_curves(SSL *ssl, int *curves); int SSL_get_shared_curve(SSL *s, int n); + int SSL_CTX_get0_implemented_groups(SSL_CTX *ctx, int all, + STACK_OF(OPENSSL_CSTRING) *names); + =head1 DESCRIPTION For all of the functions below that set the supported groups there must be at @@ -38,23 +43,136 @@ least one group in the list. A number of these functions identify groups via a unique integer NID value. However, support for some groups may be added by external providers. In this case there will be no NID assigned for the group. When setting such groups applications should use the "list" form of these -functions (i.e. SSL_CTX_set1_groups_list() and SSL_set1_groups_list). +functions (i.e. SSL_CTX_set1_groups_list() and SSL_set1_groups_list()). SSL_CTX_set1_groups() sets the supported groups for B to B -groups in the array B. The array consist of all NIDs of groups in -preference order. For a TLS client the groups are used directly in the -supported groups extension. For a TLS server the groups are used to -determine the set of shared groups. Currently supported groups for -B are B, B, B, -B, B, B, B, -B, B and B. +groups in the array B. The array consist of all NIDs of supported groups. +The supported groups for B include: +B, +B, +B, +B, +B, +B, +B, +B, +B, +B, +B, +B, and +B. +OpenSSL will use this array in different ways based on the TLS version, and +whether the groups are used in a client or server. + +For a TLS client, the groups are used directly in the supported groups +extension. The extension's preference order, to be evaluated by the server, is +determined by the order of the elements in the array. + +For a TLS 1.2 server, the groups determine the selected group. If +B is set, the order of the elements in the +array determines the selected group. Otherwise, the order is ignored and the +client's order determines the selection. + +For a TLS 1.3 server, the groups determine the selected group, but +selection is more complex. A TLS 1.3 client sends both a group list as well as a +predicted subset of groups. Choosing a group outside the predicted subset incurs +an extra roundtrip. However, in some situations, the most preferred group may +not be predicted. OpenSSL considers all supported groups in I to be comparable +in security and prioritizes avoiding roundtrips above either client or server +preference order. If an application uses an external provider to extend OpenSSL +with, e.g., a post-quantum algorithm, this behavior may allow a network attacker +to downgrade connections to a weaker algorithm. It is therefore recommended +to use SSL_CTX_set1_groups_list() with the ability to specify group tuples. SSL_CTX_set1_groups_list() sets the supported groups for B to -string B. The string is a colon separated list of group NIDs or -names, for example "P-521:P-384:P-256:X25519:ffdhe2048". Currently supported -groups for B are B, B, B, B, B, -B, B, B, B, B. Support -for other groups may be added by external providers. +string I. In contrast to SSL_CTX_set1_groups(), the names of the +groups, rather than their NIDs, are used. + +The commands below list the available groups for TLS 1.2 and TLS 1.3, +respectively: + + $ openssl list -tls1_2 -tls-groups + $ openssl list -tls1_3 -tls-groups + +Each group can be either the B name (e.g. B), some other commonly +used name where applicable (e.g. B, B) or an OpenSSL OID name +(e.g. B). +Group names are case-insensitive in OpenSSL 3.5 and later. +The preferred group names are those defined by +L. + +The I can be used to define several group tuples of comparable security +levels, and can specify which key shares should be sent by a client. +The specified list elements can optionally be ignored, if not implemented +(listing unknown groups otherwise results in error). +It is also possible to specify the built-in default set of groups, and to explicitly +remove a group from that list. + +In its simplest form, the string I is just a colon separated list +of group names, for example "P-521:P-384:P-256:X25519:ffdhe2048". The first +group listed will also be used for the B sent by a client in a +TLSv1.3 B. For servers note the discussion above. The list should +be in order of preference with the most preferred group first. + +Group tuples of comparable security are defined by separating them from each +other by a tuple separator C. Keyshares to be sent by a client are specified +by prepending a C<*> to the group name, while any C<*> will be ignored by a +server. The following string I for example defines three tuples when +used on the server-side, and triggers the generation of three key shares +when used on the client-side: P-521:*P-256/*P-384/*X25519:P-384:ffdhe2048. + +If a group name is preceded with the C character, it will be ignored if an +implementation is missing. If a group name is preceded with the C<-> character, it +will be removed from the list of groups if present (including not sending a +key share for this group), ignored otherwise. The pseudo group name +C can be used to select the OpenSSL built-in default list of groups. + +For a TLS 1.3 client, all the groups in the string I are added to the +supported groups extension of a C, in the order in which they are listed, +thereby interpreting tuple separators as group separators. The extension's +preference order, to be evaluated by the server, is determined by the +order of the elements in the array, see below. + +If a group name is preceded by C<*>, a key share will be sent for this group. +When preceding C with C<*>, a key share will be sent for the first group +of the OpenSSL built-in default list of groups. If no C<*> is used anywhere in the list, +a single key share for the leftmost valid group is sent. A maximum of 4 key shares +are supported. Example: "P-521:*P-256/*P-384" will add P-521, P-256 and P-384 to the +supported groups extension in a C and will send key shares for P-256 and P-384. + +For a TLS 1.3 server, the groups in the string I will be used to determine which group +is used for the key agreement. The preference order of the group tuples is determined +by the order of the tuples in the array, and the preference order of the groups within +a group tuple is determined by the order of the groups in the tuple. Server preference +can be enforced by setting B using +B (default: client preference). + +The server will select the group to be used for a key agreement using the following +pseudo-code algorithm: + + FOR each group tuple + IF client preference (= default) + FOR each client key-share group + IF current key-share group is also part of current group tuple: SH, return success + FOR each client supported groups + IF current supported group is also part of current group tuple: HRR, return success + ELSE (= server preference = with SSL_OP_CIPHER_SERVER_PREFERENCE option set) + FOR each group in current tuple + IF current group is also part of client key-share groups: SH, return success + FOR each group in current tuple + IF current group is also part of client supported groups: HRR, return success + return failure + + with : SH: Server hello with current group + HRR: Server retry request with current group + +Hence, if a client supports a group in a server group tuple, but does not send a key +share for this group, a Hello Retry Request (HRR) is triggered, asking the client +to send a new Hello message with a more preferred keyshare. See examples below. + +A group name can optionally be preceded by any of C<*>, C or C<->, in any order, with +the exception that only C<*> is allowed to precede C. Separator characters +C<:> and C are only allowed inside the I and not at the very beginning or end. SSL_set1_groups() and SSL_set1_groups_list() are similar except they set supported groups for the SSL structure B. @@ -68,6 +186,13 @@ order. It can return zero if the client did not send a supported groups extension. If a supported group NID is unknown then the value is set to the bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group. +SSL_get0_iana_groups() retrieves the list of groups sent by the +client in the supported_groups extension. The B<*out> array of bytes +is populated with the host-byte-order representation of the uint16_t group +identifiers, as assigned by IANA. The group list is returned in the same order +that was received in the ClientHello. The return value is the number of groups, +not the number of bytes written. + SSL_get_shared_group() returns the NID of the shared group B for a server-side SSL B. If B is -1 then the total number of shared groups is returned, which may be zero. Other than for diagnostic purposes, @@ -85,7 +210,22 @@ TLS versions, when a session has been resumed, it always reflects the group used for key exchange during the initial handshake (otherwise it is from the current, non-resumption, connection). This can be called by either client or server. If the NID for the shared group is unknown then the value is set to the -bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group. +bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group. See also +L which returns the name of the negotiated group +directly and is generally preferred over SSL_get_negotiated_group(). + +SSL_CTX_get0_implemented_groups() populates a stack with the names of TLS +groups that are compatible with the TLS version of the B argument. +The returned names are references to internal constants and must not be +modified or freed. When B is nonzero, the returned list includes not +only the preferred IANA names of the groups, but also any associated aliases. +If the SSL_CTX is version-flexible, the groups will be those compatible +with any configured minimum and maximum protocol versions. +The B stack should be allocated by the caller and be empty, the +matching group names are appended to the provided stack. +The B<-tls-groups> and B<-all-tls-groups> options of the +L command output these lists for either +TLS 1.2 or TLS 1.3 (by default). All these functions are implemented as macros. @@ -103,11 +243,14 @@ consider using the SSL_CONF interface instead of manually parsing options. =head1 RETURN VALUES -SSL_CTX_set1_groups(), SSL_CTX_set1_groups_list(), SSL_set1_groups() and -SSL_set1_groups_list(), return 1 for success and 0 for failure. +SSL_CTX_set1_groups(), SSL_CTX_set1_groups_list(), SSL_set1_groups(), +SSL_set1_groups_list(), and SSL_CTX_get0_implemented_groups() return 1 for +success and 0 for failure. SSL_get1_groups() returns the number of groups, which may be zero. +SSL_get0_iana_groups() returns the number of (uint16_t) groups, which may be zero. + SSL_get_shared_group() returns the NID of shared group B or NID_undef if there is no shared group B; or the total number of shared groups if B is -1. @@ -118,10 +261,63 @@ returns -1. SSL_get_negotiated_group() returns the NID of the negotiated group used for key exchange, or NID_undef if there was no negotiated group. +=head1 EXAMPLES + +Assume the server I is "P-521:P-256/P-384/X25519:ffdhe2048" and client +I is "P-521:*P-384" when connecting to such a server, meaning that the +client supports C but does not send a key share for this group to the +server, and the client supports C including key share for this group. +With both server and client preference, an HRR will be triggered for C +despite the availability of a key share for P-384, which overlaps with a lower +priority server-side tuple. + +As a separate example, consider a server I "A:B/C:D/E:F". Listed in order +of highest preference to least, 3 group tuples are created: "A:B", "C:D", and +"E:F". Here are some examples of a client I where setting server/client +preference will not change the outcome: + +- "A:D:*F": Both prefer "A", but the server didn't receive a keyshare for the +most-preferred tuple in which there's at least one group supported by both. +Therefore, an HRR is triggered for "A". + +- "B:*C": Both prefer "B" from the first group tuple "A:B", so an HRR is +triggered for "B". + +- "C:*F": Both prefer "C" from the second group tuple "C:D", so an HRR is +triggered for "C". + +- "C:*D": Even though both prefer "C" over "D", the server will accept +the key share for "D". Within a tuple, existing keyshares trump preference +order. + +- "*C:*D": The server accepts the "C" key share. + +- "F": Even though it is not prepended with a "*", the client will send a key +share for "F". The server will then accept the key share for "F". + +- "*E:C:A": The server prefers "A" from the "A:B" group tuple, so an HRR is +triggered for "A". + +- "*E:B:*A": The server uses the key share for "A". + +Here are some examples where setting server/client preference will change the +result: + +- "*D:*C" + - Client preference: The server uses the key share for "D". + - Server preference: The server uses the key share for "C". + +- "B:A:*C" + - Client preference: The server triggers an HRR for "B". For the server, +"A" and "B" are considered comparable in security. But because the client +prefers "B", the server will trigger an HRR for "B". + - Server preference: The server triggers an HRR for "A". + =head1 SEE ALSO L, -L +L, +L =head1 HISTORY @@ -129,9 +325,33 @@ The curve functions were added in OpenSSL 1.0.2. The equivalent group functions were added in OpenSSL 1.1.1. The SSL_get_negotiated_group() function was added in OpenSSL 3.0.0. +Support for ignoring unknown groups in SSL_CTX_set1_groups_list() and +SSL_set1_groups_list() was added in OpenSSL 3.3. + +Support for B was added in OpenSSL 3.5. + +OpenSSL 3.5 also introduces support for three I ECDH PQ key exchange +TLS groups: B, B and +B. +They offer CPU performance comparable to the associated ECDH group, though at +the cost of significantly larger key exchange messages. +The third group, B is substantially more CPU-intensive, +largely as a result of the high CPU cost of ECDH for the underlying B +group. +Also its key exchange messages at close to 1700 bytes are larger than the +roughly 1200 bytes for the first two groups. + +As of OpenSSL 3.5 key exchange group names are case-insensitive. + +B was first implemented in OpenSSL 3.5. + +Earlier versions of this document described the list as a preference order. +However, OpenSSL's behavior as a TLS 1.3 server is to consider I +supported groups as comparable in security. + =head1 COPYRIGHT -Copyright 2013-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2013-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set1_sigalgs.pod b/doc/man3/SSL_CTX_set1_sigalgs.pod index eb3100634626..0ab9654a34e7 100644 --- a/doc/man3/SSL_CTX_set1_sigalgs.pod +++ b/doc/man3/SSL_CTX_set1_sigalgs.pod @@ -34,6 +34,11 @@ must be a null terminated string consisting of a colon separated list of elements, where each element is either a combination of a public key algorithm and a digest separated by B<+>, or a TLS 1.3-style named SignatureScheme such as rsa_pss_pss_sha256. +Signature scheme names and public key algorithm names (but not the digest +names) in the B form are case-insensitive. +If a list entry is preceded with the C character, it will be ignored if an +implementation is missing. + SSL_CTX_set1_client_sigalgs(), SSL_set1_client_sigalgs(), SSL_CTX_set1_client_sigalgs_list() and SSL_set1_client_sigalgs_list() set @@ -106,9 +111,16 @@ using a string: L, L, L +=head1 HISTORY + +Support for ignoring unknown signature algorithms in +SSL_CTX_set1_sigalgs_list(), SSL_set1_sigalgs_list(), +SSL_CTX_set1_client_sigalgs_list() and SSL_set1_client_sigalgs_list() +was added in OpenSSL 3.3. + =head1 COPYRIGHT -Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set1_verify_cert_store.pod b/doc/man3/SSL_CTX_set1_verify_cert_store.pod index 19ea92a905f2..ba8a380bb819 100644 --- a/doc/man3/SSL_CTX_set1_verify_cert_store.pod +++ b/doc/man3/SSL_CTX_set1_verify_cert_store.pod @@ -59,7 +59,7 @@ affected if the parent SSL_CTX store pointer is set to a new value. The verification store is used to verify the certificate chain sent by the peer: that is an SSL/TLS client will use the verification store to verify -the server's certificate chain and a SSL/TLS server will use it to verify +the server's certificate chain and an SSL/TLS server will use it to verify any client certificate chain. The chain store is used to build the certificate chain. diff --git a/doc/man3/SSL_CTX_set_alpn_select_cb.pod b/doc/man3/SSL_CTX_set_alpn_select_cb.pod index 2997a9955756..dd5517df4d32 100644 --- a/doc/man3/SSL_CTX_set_alpn_select_cb.pod +++ b/doc/man3/SSL_CTX_set_alpn_select_cb.pod @@ -120,6 +120,11 @@ the client can request any protocol it chooses. The value returned from this function need not be a member of the list of supported protocols provided by the callback. +NPN functionality cannot be used with QUIC SSL objects. Use of ALPN is mandatory +when using QUIC SSL objects. SSL_CTX_set_next_protos_advertised_cb() and +SSL_CTX_set_next_proto_select_cb() have no effect if called on a QUIC SSL +context. + =head1 NOTES The protocol-lists must be in wire-format, which is defined as a vector of diff --git a/doc/man3/SSL_CTX_set_cert_store.pod b/doc/man3/SSL_CTX_set_cert_store.pod index 246f413136b6..ec58d3274771 100644 --- a/doc/man3/SSL_CTX_set_cert_store.pod +++ b/doc/man3/SSL_CTX_set_cert_store.pod @@ -25,7 +25,7 @@ of B to/with B. The B's reference count is incremented. If another X509_STORE object is currently set in B, it will be X509_STORE_free()ed. SSL_CTX_get_cert_store() returns a pointer to the current certificate -verification storage. +verification storage. B B be NULL. =head1 NOTES diff --git a/doc/man3/SSL_CTX_set_cert_verify_callback.pod b/doc/man3/SSL_CTX_set_cert_verify_callback.pod index be59a548cbd9..4d510f3041d4 100644 --- a/doc/man3/SSL_CTX_set_cert_verify_callback.pod +++ b/doc/man3/SSL_CTX_set_cert_verify_callback.pod @@ -20,7 +20,7 @@ the time when L is called. =head1 NOTES -When a peer certificate has been received during a SSL/TLS handshake, +When a peer certificate has been received during an SSL/TLS handshake, a verification function is called regardless of the verification mode. If the application does not explicitly specify a verification callback function, the built-in verification function is used. diff --git a/doc/man3/SSL_CTX_set_cipher_list.pod b/doc/man3/SSL_CTX_set_cipher_list.pod index 08d7693f420e..1df33ba11daf 100644 --- a/doc/man3/SSL_CTX_set_cipher_list.pod +++ b/doc/man3/SSL_CTX_set_cipher_list.pod @@ -29,7 +29,7 @@ SSL_CTX_set_cipher_list() sets the list of available ciphers (TLSv1.2 and below) for B using the control string B. The format of the string is described in L. The list of ciphers is inherited by all B objects created from B. This function does not impact TLSv1.3 -ciphersuites. Use SSL_CTX_set_ciphersuites() to configure those. +ciphersuites. Use SSL_CTX_set_ciphersuites() to configure those. B B be NULL. SSL_set_cipher_list() sets the list of ciphers (TLSv1.2 and below) only for B. @@ -50,6 +50,10 @@ ciphersuite names in order of preference. Valid TLSv1.3 ciphersuite names are: =item TLS_AES_128_CCM_8_SHA256 +=item TLS_SHA384_SHA384 - integrity-only + +=item TLS_SHA256_SHA256 - integrity-only + =back An empty list is permissible. The default value for this setting is: diff --git a/doc/man3/SSL_CTX_set_client_hello_cb.pod b/doc/man3/SSL_CTX_set_client_hello_cb.pod index d592102028ce..74468ab8ac15 100644 --- a/doc/man3/SSL_CTX_set_client_hello_cb.pod +++ b/doc/man3/SSL_CTX_set_client_hello_cb.pod @@ -2,7 +2,7 @@ =head1 NAME -SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_client_hello_get0_legacy_version, SSL_client_hello_get0_random, SSL_client_hello_get0_session_id, SSL_client_hello_get0_ciphers, SSL_client_hello_get0_compression_methods, SSL_client_hello_get1_extensions_present, SSL_client_hello_get0_ext - callback functions for early server-side ClientHello processing +SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_client_hello_get0_legacy_version, SSL_client_hello_get0_random, SSL_client_hello_get0_session_id, SSL_client_hello_get0_ciphers, SSL_client_hello_get0_compression_methods, SSL_client_hello_get1_extensions_present, SSL_client_hello_get_extension_order, SSL_client_hello_get0_ext - callback functions for early server-side ClientHello processing =head1 SYNOPSIS @@ -18,6 +18,8 @@ SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_ const unsigned char **out); int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen); + int SSL_client_hello_get_extension_order(SSL *s, uint16_t *exts, + size_t *num_exts); int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out, size_t *outlen); @@ -68,6 +70,20 @@ in the ClientHello. B<*outlen> contains the number of elements in the array. In situations when the ClientHello has no extensions, the function will return success with B<*out> set to NULL and B<*outlen> set to 0. +SSL_client_hello_get_extension_order() is similar to +SSL_client_hello_get1_extensions_present(), without internal memory allocation. +When called with B set to NULL, returns the number of extensions +(e.g., to allocate storage for a subsequent call). Otherwise, B<*exts> is populated +with the ExtensionType values in the order that the corresponding extensions +appeared in the ClientHello. B<*num_exts> is an input/output parameter, used +as input to supply the size of storage allocated by the caller, and as output to +indicate how many ExtensionType values were written. If the input B<*num_exts> +is smaller then the number of extensions in question, that is treated as an error. +A subsequent call with B set to NULL can retrieve the size of storage needed. +A ClientHello that contained no extensions is treated as success, with B<*num_exts> +set to 0. + + =head1 NOTES The ClientHello callback provides a vast window of possibilities for application @@ -107,6 +123,8 @@ SSL_client_hello_get0_ext() returns 1 if the extension of type 'type' is present SSL_client_hello_get1_extensions_present() returns 1 on success and 0 on failure. +SSL_client_hello_get_extension_order() returns 1 on success and 0 on failure. + =head1 SEE ALSO L, L, @@ -119,10 +137,12 @@ SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(), SSL_client_hello_get0_ciphers(), SSL_client_hello_get0_compression_methods(), SSL_client_hello_get0_ext(), and SSL_client_hello_get1_extensions_present() were added in OpenSSL 1.1.1. +SSL_client_hello_get_extension_order() +was added in OpenSSL 3.2.0. =head1 COPYRIGHT -Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_ct_validation_callback.pod b/doc/man3/SSL_CTX_set_ct_validation_callback.pod index 962f5ebd7989..784fb255a87e 100644 --- a/doc/man3/SSL_CTX_set_ct_validation_callback.pod +++ b/doc/man3/SSL_CTX_set_ct_validation_callback.pod @@ -101,7 +101,7 @@ otherwise. When SCT processing is enabled, OCSP stapling will be enabled. This is because one possible source of SCTs is the OCSP response from a server. -The time returned by SSL_SESSION_get_time() will be used to evaluate whether any +The time returned by SSL_SESSION_get_time_ex() will be used to evaluate whether any presented SCTs have timestamps that are in the future (and therefore invalid). =head1 RESTRICTIONS @@ -135,7 +135,7 @@ L =head1 COPYRIGHT -Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_info_callback.pod b/doc/man3/SSL_CTX_set_info_callback.pod index c1c6a67f85a7..3159c0294a00 100644 --- a/doc/man3/SSL_CTX_set_info_callback.pod +++ b/doc/man3/SSL_CTX_set_info_callback.pod @@ -33,7 +33,7 @@ When B is NULL, no callback function is used. SSL_set_info_callback() sets the B function, that can be used to obtain state information for B during connection setup and use. When B is NULL, the callback setting currently valid for -B is used. +B is used. B B be NULL. SSL_CTX_get_info_callback() returns a pointer to the currently set information callback function for B. @@ -160,7 +160,7 @@ L =head1 COPYRIGHT -Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_keylog_callback.pod b/doc/man3/SSL_CTX_set_keylog_callback.pod index 27dfb3419e3a..1fa71d00f5a3 100644 --- a/doc/man3/SSL_CTX_set_keylog_callback.pod +++ b/doc/man3/SSL_CTX_set_keylog_callback.pod @@ -42,7 +42,7 @@ L =head1 COPYRIGHT -Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_max_cert_list.pod b/doc/man3/SSL_CTX_set_max_cert_list.pod index ea18ccb3ff0e..3d878f47f437 100644 --- a/doc/man3/SSL_CTX_set_max_cert_list.pod +++ b/doc/man3/SSL_CTX_set_max_cert_list.pod @@ -55,7 +55,7 @@ than the default, as the buffer is handled dynamically and only uses the memory actually required by the data sent by the peer. If the maximum certificate chain size allowed is exceeded, the handshake will -fail with a SSL_R_EXCESSIVE_MESSAGE_SIZE error. +fail with an SSL_R_EXCESSIVE_MESSAGE_SIZE error. =head1 RETURN VALUES diff --git a/doc/man3/SSL_CTX_set_min_proto_version.pod b/doc/man3/SSL_CTX_set_min_proto_version.pod index 2adf9acce00a..9a2da37ab729 100644 --- a/doc/man3/SSL_CTX_set_min_proto_version.pod +++ b/doc/man3/SSL_CTX_set_min_proto_version.pod @@ -42,6 +42,9 @@ Currently supported versions are B, B, B, B, B for TLS and B, B for DTLS. +In the current version of OpenSSL only QUICv1 is supported in conjunction with +TLSv1.3. Calling these functions on a QUIC object has no effect. + =head1 RETURN VALUES These setter functions return 1 on success and 0 on failure. The getter @@ -64,7 +67,7 @@ were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2016-2019 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 diff --git a/doc/man3/SSL_CTX_set_mode.pod b/doc/man3/SSL_CTX_set_mode.pod index 4b0c4dcd17d5..325e086c5484 100644 --- a/doc/man3/SSL_CTX_set_mode.pod +++ b/doc/man3/SSL_CTX_set_mode.pod @@ -46,6 +46,9 @@ SSL_write() returns successful, B bytes have been written and the next call to SSL_write_ex() or SSL_write() must only send the n-r bytes left, imitating the behaviour of write(). +This mode cannot be enabled while in the middle of an incomplete write +operation. + =item SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Make it possible to retry SSL_write_ex() or SSL_write() with changed buffer @@ -137,7 +140,7 @@ SSL_MODE_ASYNC was added in OpenSSL 1.1.0. =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 diff --git a/doc/man3/SSL_CTX_set_msg_callback.pod b/doc/man3/SSL_CTX_set_msg_callback.pod index 9f7a17433d29..f046c77b535b 100644 --- a/doc/man3/SSL_CTX_set_msg_callback.pod +++ b/doc/man3/SSL_CTX_set_msg_callback.pod @@ -5,7 +5,8 @@ SSL_CTX_set_msg_callback, SSL_CTX_set_msg_callback_arg, SSL_set_msg_callback, -SSL_set_msg_callback_arg +SSL_set_msg_callback_arg, +SSL_trace - install callback for observing protocol messages =head1 SYNOPSIS @@ -24,10 +25,13 @@ SSL_set_msg_callback_arg size_t len, SSL *ssl, void *arg)); void SSL_set_msg_callback_arg(SSL *ssl, void *arg); + void SSL_trace(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + =head1 DESCRIPTION SSL_CTX_set_msg_callback() or SSL_set_msg_callback() can be used to -define a message callback function I for observing all SSL/TLS +define a message callback function I for observing all SSL/TLS/QUIC protocol messages (such as handshake messages) that are received or sent, as well as other events that occur during processing. SSL_CTX_set_msg_callback_arg() and SSL_set_msg_callback_arg() @@ -40,7 +44,7 @@ L. SSL_set_msg_callback() and SSL_set_msg_callback_arg() modify the actual settings of an B object. Using a B pointer for I disables the message callback. -When I is called by the SSL/TLS library the function arguments have the +When I is called by the SSL/TLS/QUIC library the function arguments have the following meaning: =over 4 @@ -53,8 +57,10 @@ when a protocol message has been sent. =item I The protocol version according to which the protocol message is -interpreted by the library such as B, B etc. -This is set to 0 for the SSL3_RT_HEADER pseudo content type (see NOTES below). +interpreted by the library such as B, B, +B etc. For the SSL3_RT_HEADER pseudo +content type (see NOTES below) this value will be the decoded +version/legacy_version field of the record header. =item I @@ -82,6 +88,13 @@ SSL_CTX_set_msg_callback_arg() or SSL_set_msg_callback_arg(). =back +The SSL_trace() function can be used as a pre-written callback in a call to +SSL_CTX_set_msg_callback() or SSL_set_msg_callback(). It requires a BIO to be +set as the callback argument via SSL_CTX_set_msg_callback_arg() or +SSL_set_msg_callback_arg(). Setting this callback will cause human readable +diagostic tracing information about an SSL/TLS/QUIC connection to be written to +the BIO. + =head1 NOTES Protocol messages are passed to the callback function after decryption @@ -105,7 +118,7 @@ of data. The following pseudo content types are currently defined: =item B -Used when a record is sent or received. The B contains the record header +Used when a TLS record is sent or received. The B contains the record header bytes only. =item B @@ -115,6 +128,32 @@ records the content type in the record header is always SSL3_RT_APPLICATION_DATA. The real content type for the record is contained in an "inner" content type. B contains the encoded "inner" content type byte. +=item B + +Used when a QUIC datagram is sent or received. + +=item B + +Used when a QUIC packet is sent or received. + +=item B + +Used when a QUIC frame is sent or received. This is only used for non-crypto +and stream data related frames. The full QUIC frame data is supplied. + +=item B + +Used when a QUIC stream data or crypto frame is sent or received. Only the QUIC +frame header data is supplied. + +=item B + +Used when a sequence of one or more QUIC padding frames is sent or received. +A padding frame consists of a single byte and it is common to have multiple +such frames in a sequence. Rather than supplying each frame individually the +callback will supply all the padding frames in one go via this pseudo content +type. + =back =head1 RETURN VALUES @@ -130,9 +169,19 @@ L, L The pseudo content type B was added in OpenSSL 1.1.1. +The pseudo content types B, B, +B, B and +B were added in OpenSSL 3.2. + +In versions previous to OpenSSL 3.0 I was called with 0 as I for +the pseudo content type B for TLS records. + +In versions previous to OpenSSL 3.2 I was called with 0 as I for +the pseudo content type B for DTLS records. + =head1 COPYRIGHT -Copyright 2001-2018 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 diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod index 176f8d25fc31..a6c922ecf92c 100644 --- a/doc/man3/SSL_CTX_set_options.pod +++ b/doc/man3/SSL_CTX_set_options.pod @@ -24,6 +24,7 @@ SSL_get_secure_renegotiation_support - manipulate SSL options =head1 DESCRIPTION SSL_CTX_set_options() adds the options set via bit-mask in B to B. +B B be NULL. Options already set before are not cleared! SSL_set_options() adds the options set via bit-mask in B to B. @@ -70,7 +71,7 @@ CSP 3.x. =item SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS -Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol +Disables a countermeasure against an 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. @@ -110,6 +111,12 @@ this option to enable it. 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_PREFER_NO_DHE_KEX + +In TLSv1.3, on resumption let the server prefer a non-(ec)dhe based key +exchange mode over an (ec)dhe based one. Ignored without B +being set as well. Always ignored on the client. + =item SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION Allow legacy insecure renegotiation between OpenSSL and unpatched clients or @@ -129,7 +136,7 @@ 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 +By default TLS and QUIC SSL objects 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) @@ -141,6 +148,14 @@ responsible for cleansing all other buffers. Most notably, this applies to buffers passed to functions like L, L but also like L. +TLS connections do not buffer data to be sent in plaintext. QUIC stream +objects do buffer plaintext data to be sent and this option will also cause +that data to be cleansed when it is discarded. + +This option can be set differently on individual QUIC stream objects and +has no effect on QUIC connection objects (except where a default stream is +being used). + =item SSL_OP_COOKIE_EXCHANGE Turn on Cookie Exchange as described in RFC4347 Section 4.2.1. Only affects @@ -175,6 +190,16 @@ 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_KTLS_TX_ZEROCOPY_SENDFILE + +With this option, sendfile() will use the zerocopy mode, which gives a +performance boost when used with KTLS hardware offload. Note that invalid TLS +records might be transmitted if the file is changed while being sent. This +option has no effect if B is not enabled. + +This option only applies to Linux. KTLS sendfile on FreeBSD doesn't offer an +option to disable zerocopy and always runs in this mode. + =item SSL_OP_ENABLE_MIDDLEBOX_COMPAT If set then dummy Change Cipher Spec (CCS) messages are sent in TLSv1.3. This @@ -214,10 +239,30 @@ functionality is not required. Those applications can turn this feature off by setting this option. This is a server-side option only. It is ignored by clients. +=item SSL_OP_NO_TX_CERTIFICATE_COMPRESSION + +Normally clients and servers will transparently attempt to negotiate the +RFC8879 certificate compression option on TLSv1.3 connections. + +If this option is set, the certificate compression extension is ignored +upon receipt and compressed certificates will not be sent to the peer. + +=item SSL_OP_NO_RX_CERTIFICATE_COMPRESSION + +Normally clients and servers will transparently attempt to negotiate the +RFC8879 certificate compression option on TLSv1.3 connections. + +If this option is set, the certificate compression extension will not be sent +and compressed certificates will not be accepted from the peer. + =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(). +Do not use TLS record compression even if it is supported. This option is set by +default. To switch it off use SSL_clear_options(). Note that TLS record +compression is not recommended and is not available at security level 2 or +above. From OpenSSL 3.2 the default security level is 2, so clearing this option +will have no effect without also changing the default security level. See +L. =item SSL_OP_NO_ENCRYPT_THEN_MAC @@ -312,7 +357,7 @@ 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 +the client sends an 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.) @@ -417,6 +462,47 @@ renegotiation between OpenSSL clients and unpatched servers B, while B allows initial connections and renegotiation between OpenSSL and unpatched clients or servers. +=head2 Applicability of options to QUIC connections and streams + +These options apply to SSL objects referencing a QUIC connection: + +=over 4 + +=item SSL_OP_ALLOW_NO_DHE_KEX + +=item SSL_OP_NO_TX_CERTIFICATE_COMPRESSION + +=item SSL_OP_NO_RX_CERTIFICATE_COMPRESSION + +=item SSL_OP_NO_TICKET + +=item SSL_OP_PRIORITIZE_CHACHA + +=back + +These options apply to SSL objects referencing a QUIC stream: + +=over 4 + +=item SSL_OP_CLEANSE_PLAINTEXT + +=back + +Options on QUIC connections are initialized from the options set on SSL_CTX +before a QUIC connection SSL object is created. Options on QUIC streams are +initialised from the options configured on the QUIC connection SSL object +they are created from. + +Setting options which relate to QUIC streams on a QUIC connection SSL object has +no direct effect on the QUIC connection SSL object itself, but will change the +options set on the default stream (if there is one) and will also determine the +default options set on any future streams which are created. + +Other options not mentioned above do not have an effect and will be ignored. + +Options which relate to QUIC streams may also be set directly on QUIC stream SSL +objects. Setting connection-related options on such an object has no effect. + =head1 RETURN VALUES SSL_CTX_set_options() and SSL_set_options() return the new options bit-mask diff --git a/doc/man3/SSL_CTX_set_psk_client_callback.pod b/doc/man3/SSL_CTX_set_psk_client_callback.pod index 7ccea7273f83..dd302983fdde 100644 --- a/doc/man3/SSL_CTX_set_psk_client_callback.pod +++ b/doc/man3/SSL_CTX_set_psk_client_callback.pod @@ -169,7 +169,7 @@ were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_quiet_shutdown.pod b/doc/man3/SSL_CTX_set_quiet_shutdown.pod index a99c4c6b9c81..f0c919255505 100644 --- a/doc/man3/SSL_CTX_set_quiet_shutdown.pod +++ b/doc/man3/SSL_CTX_set_quiet_shutdown.pod @@ -2,7 +2,8 @@ =head1 NAME -SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown, SSL_get_quiet_shutdown - manipulate shutdown behaviour +SSL_CTX_set_quiet_shutdown, SSL_CTX_get_quiet_shutdown, SSL_set_quiet_shutdown, +SSL_get_quiet_shutdown - manipulate shutdown behaviour =head1 SYNOPSIS @@ -30,9 +31,12 @@ B may be 0 or 1. SSL_get_quiet_shutdown() returns the "quiet shutdown" setting of B. +These functions are not supported for QUIC SSL objects. SSL_set_quiet_shutdown() +has no effect if called on a QUIC SSL object. + =head1 NOTES -Normally when a SSL connection is finished, the parties must send out +Normally when an SSL connection is finished, the parties must send out close_notify alert messages using L for a clean shutdown. @@ -51,7 +55,7 @@ The default is normal shutdown behaviour as described by the TLS standard. SSL_CTX_set_quiet_shutdown() and SSL_set_quiet_shutdown() do not return diagnostic information. -SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown return the current +SSL_CTX_get_quiet_shutdown() and SSL_get_quiet_shutdown() return the current setting. =head1 SEE ALSO @@ -62,7 +66,7 @@ L, L =head1 COPYRIGHT -Copyright 2001-2018 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 diff --git a/doc/man3/SSL_CTX_set_read_ahead.pod b/doc/man3/SSL_CTX_set_read_ahead.pod index c2fc6fd7dc8e..9e6409dbbc9c 100644 --- a/doc/man3/SSL_CTX_set_read_ahead.pod +++ b/doc/man3/SSL_CTX_set_read_ahead.pod @@ -34,6 +34,9 @@ SSL_CTX_get_read_ahead() and SSL_get_read_ahead() indicate whether reading ahead has been set or not. SSL_CTX_get_default_read_ahead() is identical to SSL_CTX_get_read_ahead(). +These functions cannot be used with QUIC SSL objects. SSL_set_read_ahead() +has no effect if called on a QUIC SSL object. + =head1 NOTES These functions have no impact when used with DTLS. The return values for @@ -64,7 +67,7 @@ L, L =head1 COPYRIGHT -Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_record_padding_callback.pod b/doc/man3/SSL_CTX_set_record_padding_callback.pod index 7bf43c3f0d15..c572c7898d9c 100644 --- a/doc/man3/SSL_CTX_set_record_padding_callback.pod +++ b/doc/man3/SSL_CTX_set_record_padding_callback.pod @@ -9,7 +9,9 @@ SSL_set_record_padding_callback_arg, SSL_CTX_get_record_padding_callback_arg, SSL_get_record_padding_callback_arg, SSL_CTX_set_block_padding, -SSL_set_block_padding - install callback to specify TLS 1.3 record padding +SSL_CTX_set_block_padding_ex, +SSL_set_block_padding, +SSL_set_block_padding_ex - install callback to specify TLS 1.3 record padding =head1 SYNOPSIS @@ -26,6 +28,8 @@ SSL_set_block_padding - install callback to specify TLS 1.3 record padding int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size); int SSL_set_block_padding(SSL *ssl, size_t block_size); + int SSL_CTX_set_block_padding_ex(SSL_CTX *ctx, size_t app_block_size, size_t hs_block_size); + int SSL_set_block_padding_ex(SSL *ssl, size_t app_block_size, size_t hs_block_size); =head1 DESCRIPTION @@ -46,6 +50,10 @@ SSL_CTX_set_block_padding() and SSL_set_block_padding() pads the record to a mul of the B. A B of 0 or 1 disables block padding. The limit of B is SSL3_RT_MAX_PLAIN_LENGTH. +SSL_CTX_set_block_padding_ex() and SSL_set_block_padding_ex() do similarly but +allow the caller to separately specify the padding block size to be applied to +handshake and application data messages. + The callback is invoked for every record before encryption. The B parameter is the TLS record type that is being processed; may be one of SSL3_RT_APPLICATION_DATA, SSL3_RT_HANDSHAKE, or SSL3_RT_ALERT. @@ -53,6 +61,10 @@ The B parameter is the current plaintext length of the record before encryp The B parameter is the value set via SSL_CTX_set_record_padding_callback_arg() or SSL_set_record_padding_callback_arg(). +These functions cannot be used with QUIC SSL objects. +SSL_set_record_padding_callback() and SSL_set_block_padding() fail if called on +a QUIC SSL object. + =head1 RETURN VALUES The SSL_CTX_get_record_padding_callback_arg() and SSL_get_record_padding_callback_arg() @@ -92,9 +104,12 @@ The record padding API was added for TLS 1.3 support in OpenSSL 1.1.1. The return type of SSL_CTX_set_record_padding_callback() function was changed to int in OpenSSL 3.0. +The functions SSL_set_block_padding_ex() and SSL_CTX_set_block_padding_ex() +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_security_level.pod b/doc/man3/SSL_CTX_set_security_level.pod index a4595490013b..b490c74039bf 100644 --- a/doc/man3/SSL_CTX_set_security_level.pod +++ b/doc/man3/SSL_CTX_set_security_level.pod @@ -75,33 +75,31 @@ OpenSSL. The security level corresponds to a minimum of 80 bits of security. Any parameters offering below 80 bits of security are excluded. As a result RSA, DSA and DH keys shorter than 1024 bits and ECC keys shorter than 160 bits -are prohibited. All export cipher suites are prohibited since they all offer -less than 80 bits of security. SSL version 2 is prohibited. Any cipher suite -using MD5 for the MAC is also prohibited. Note that signatures using SHA1 -and MD5 are also forbidden at this level as they have less than 80 security -bits. +are prohibited. Any cipher suite using MD5 for the MAC is also prohibited. Any +cipher suites using CCM with a 64 bit authentication tag are prohibited. Note +that signatures using SHA1 and MD5 are also forbidden at this level as they +have less than 80 security bits. Additionally, SSLv3, TLS 1.0, TLS 1.1 and +DTLS 1.0 are all disabled at this level. =item B Security level set to 112 bits of security. As a result RSA, DSA and DH keys shorter than 2048 bits and ECC keys shorter than 224 bits are prohibited. In addition to the level 1 exclusions any cipher suite using RC4 is also -prohibited. SSL version 3 is also not allowed. Compression is disabled. +prohibited. Compression is disabled. =item B Security level set to 128 bits of security. As a result RSA, DSA and DH keys shorter than 3072 bits and ECC keys shorter than 256 bits are prohibited. In addition to the level 2 exclusions cipher suites not offering forward -secrecy are prohibited. TLS versions below 1.1 are not permitted. Session -tickets are disabled. +secrecy are prohibited. Session tickets are disabled. =item B Security level set to 192 bits of security. As a result RSA, DSA and DH keys shorter than 7680 bits and ECC keys shorter than 384 bits are -prohibited. Cipher suites using SHA1 for the MAC are prohibited. TLS -versions below 1.2 are not permitted. +prohibited. Cipher suites using SHA1 for the MAC are prohibited. =item B @@ -117,7 +115,7 @@ I =head1 NOTES The default security level can be configured when OpenSSL is compiled by -setting B<-DOPENSSL_TLS_SECURITY_LEVEL=level>. If not set then 1 is used. +setting B<-DOPENSSL_TLS_SECURITY_LEVEL=level>. If not set then 2 is used. The security framework disables or reject parameters inconsistent with the set security level. In the past this was difficult as applications had to set @@ -181,7 +179,7 @@ These functions were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2014-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_split_send_fragment.pod b/doc/man3/SSL_CTX_set_split_send_fragment.pod index 2231f5b127e5..8f92ec1ec76f 100644 --- a/doc/man3/SSL_CTX_set_split_send_fragment.pod +++ b/doc/man3/SSL_CTX_set_split_send_fragment.pod @@ -123,6 +123,11 @@ 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. +These functions cannot be used with QUIC SSL objects. +SSL_set_max_send_fragment(), SSL_set_max_pipelines(), +SSL_set_split_send_fragment(), SSL_set_default_read_buffer_len() and +SSL_set_tlsext_max_fragment_length() fail if called on a QUIC SSL object. + =head1 RETURN VALUES All non-void functions return 1 on success and 0 on failure. diff --git a/doc/man3/SSL_CTX_set_ssl_version.pod b/doc/man3/SSL_CTX_set_ssl_version.pod index 10aa63f729c8..2de853314325 100644 --- a/doc/man3/SSL_CTX_set_ssl_version.pod +++ b/doc/man3/SSL_CTX_set_ssl_version.pod @@ -47,6 +47,10 @@ it would usually be preferable to create a new SSL_CTX object than to try to reuse an existing one in this fashion. Its usage is considered deprecated. +SSL_set_ssl_method() cannot be used to change a non-QUIC SSL object to a QUIC +SSL object or vice versa, or change a QUIC SSL object from one QUIC method to +another. + =head1 RETURN VALUES The following return values can occur for SSL_CTX_set_ssl_version() @@ -79,7 +83,7 @@ SSL_CTX_set_ssl_version() was deprecated in OpenSSL 3.0. =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 diff --git a/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod b/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod index e91f32b7f8ec..5d1e063f0122 100644 --- a/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod +++ b/doc/man3/SSL_CTX_set_tlsext_use_srtp.pod @@ -56,6 +56,38 @@ This corresponds to the profile of the same name defined in RFC7714. This corresponds to the profile of the same name defined in RFC7714. +=item SRTP_DOUBLE_AEAD_AES_128_GCM_AEAD_AES_128_GCM + +This corresponds to the profile of the same name defined in RFC8723. + +=item SRTP_DOUBLE_AEAD_AES_256_GCM_AEAD_AES_256_GCM + +This corresponds to the profile of the same name defined in RFC8723. + +=item SRTP_ARIA_128_CTR_HMAC_SHA1_80 + +This corresponds to the profile of the same name defined in RFC8269. + +=item SRTP_ARIA_128_CTR_HMAC_SHA1_32 + +This corresponds to the profile of the same name defined in RFC8269. + +=item SRTP_ARIA_256_CTR_HMAC_SHA1_80 + +This corresponds to the profile of the same name defined in RFC8269. + +=item SRTP_ARIA_256_CTR_HMAC_SHA1_32 + +This corresponds to the profile of the same name defined in RFC8269. + +=item SRTP_AEAD_ARIA_128_GCM + +This corresponds to the profile of the same name defined in RFC8269. + +=item SRTP_AEAD_ARIA_256_GCM + +This corresponds to the profile of the same name defined in RFC8269. + =back Supplying an unrecognised protection profile name will result in an error. @@ -84,6 +116,10 @@ master key length and the salt length as defined for the protection profile in use. This provides the client write master key, the server write master key, the client write master salt and the server write master salt in that order. +These functions cannot be used with QUIC SSL objects. +SSL_CTX_set_tlsext_use_srtp() fails if called on a QUIC SSL context. +SSL_set_tlsext_use_srtp() fails if called on a QUIC SSL object. + =head1 RETURN VALUES SSL_CTX_set_tlsext_use_srtp() and SSL_set_tlsext_use_srtp() return 0 on success @@ -102,7 +138,7 @@ L =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 diff --git a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod index 4799ada6844b..a14f334cfca8 100644 --- a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod +++ b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod @@ -112,7 +112,7 @@ L, L =head1 COPYRIGHT -Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_CTX_set_verify.pod b/doc/man3/SSL_CTX_set_verify.pod index 346aa8452974..58774796cd92 100644 --- a/doc/man3/SSL_CTX_set_verify.pod +++ b/doc/man3/SSL_CTX_set_verify.pod @@ -32,7 +32,7 @@ SSL_CTX_set_post_handshake_auth SSL_CTX_set_verify() sets the verification flags for B to be B and specifies the B function to be used. If no callback function -shall be specified, the NULL pointer can be used for B. +shall be specified, the NULL pointer can be used for B. B B be NULL. SSL_set_verify() sets the verification flags for B to be B and specifies the B function to be used. If no callback function @@ -218,6 +218,9 @@ Only one certificate request may be outstanding at any time. When post-handshake authentication occurs, a refreshed NewSessionTicket message is sent to the client. +Post-handshake authentication cannot be used with QUIC. +SSL_set_post_handshake_auth() has no effect if called on a QUIC SSL object. + =head1 BUGS In client mode, it is not checked whether the SSL_VERIFY_PEER flag diff --git a/doc/man3/SSL_CTX_use_certificate.pod b/doc/man3/SSL_CTX_use_certificate.pod index dd6f831b8658..2a9227c2ae50 100644 --- a/doc/man3/SSL_CTX_use_certificate.pod +++ b/doc/man3/SSL_CTX_use_certificate.pod @@ -88,7 +88,7 @@ certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA. SSL_use_certificate_chain_file() is similar except it loads the certificate chain into B. -SSL_CTX_use_PrivateKey() adds B as private key to B. +SSL_CTX_use_PrivateKey() adds B as private key to B. B B be NULL. SSL_CTX_use_RSAPrivateKey() adds the private key B of type RSA to B. SSL_use_PrivateKey() adds B as private key to B; SSL_use_RSAPrivateKey() adds B as private key of type RSA to B. @@ -126,7 +126,7 @@ from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. SSL_CTX_use_RSAPrivateKey_file() adds the first private RSA key found in B to B. SSL_use_PrivateKey_file() adds the first private key found in B to B; SSL_use_RSAPrivateKey_file() adds the first private -RSA key found to B. +RSA key found to B. B B be NULL. SSL_CTX_check_private_key() checks the consistency of a private key with the corresponding certificate loaded into B. If more than one diff --git a/doc/man3/SSL_SESSION_free.pod b/doc/man3/SSL_SESSION_free.pod index 4af750a358ba..f785dfe43dee 100644 --- a/doc/man3/SSL_SESSION_free.pod +++ b/doc/man3/SSL_SESSION_free.pod @@ -41,7 +41,7 @@ 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 +count (usage information) correct and not delete an 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 diff --git a/doc/man3/SSL_SESSION_get0_hostname.pod b/doc/man3/SSL_SESSION_get0_hostname.pod index f560e7751d84..f7add16d7bdd 100644 --- a/doc/man3/SSL_SESSION_get0_hostname.pod +++ b/doc/man3/SSL_SESSION_get0_hostname.pod @@ -24,10 +24,8 @@ SSL_SESSION_set1_alpn_selected =head1 DESCRIPTION SSL_SESSION_get0_hostname() retrieves the SNI value that was sent by the -client when the session was created if it was accepted by the server and TLSv1.2 -or below was negotiated. Otherwise NULL is returned. Note that in TLSv1.3 the -SNI hostname is negotiated with each handshake including resumption handshakes -and is therefore never associated with the session. +client when the session was created if it was accepted by the server. Otherwise +NULL is returned. The value returned is a pointer to memory maintained within B and should not be free'd. @@ -67,7 +65,7 @@ SSL_SESSION_set1_alpn_selected() functions were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_SESSION_get_time.pod b/doc/man3/SSL_SESSION_get_time.pod index 00b693bae6f8..173d928ac0a6 100644 --- a/doc/man3/SSL_SESSION_get_time.pod +++ b/doc/man3/SSL_SESSION_get_time.pod @@ -3,7 +3,7 @@ =head1 NAME SSL_SESSION_get_time, SSL_SESSION_set_time, SSL_SESSION_get_timeout, -SSL_SESSION_set_timeout, +SSL_SESSION_set_timeout, SSL_SESSION_get_time_ex, SSL_SESSION_set_time_ex, SSL_get_time, SSL_set_time, SSL_get_timeout, SSL_set_timeout - retrieve and manipulate session time and timeout settings @@ -11,23 +11,31 @@ SSL_get_time, SSL_set_time, SSL_get_timeout, SSL_set_timeout #include - long SSL_SESSION_get_time(const SSL_SESSION *s); - long SSL_SESSION_set_time(SSL_SESSION *s, long tm); long SSL_SESSION_get_timeout(const SSL_SESSION *s); long SSL_SESSION_set_timeout(SSL_SESSION *s, long tm); - long SSL_get_time(const SSL_SESSION *s); - long SSL_set_time(SSL_SESSION *s, long tm); long SSL_get_timeout(const SSL_SESSION *s); long SSL_set_timeout(SSL_SESSION *s, long tm); + time_t SSL_SESSION_get_time_ex(const SSL_SESSION *s); + time_t SSL_SESSION_set_time_ex(SSL_SESSION *s, time_t tm); + +The following functions have been deprecated since OpenSSL 3.4, and can be +hidden entirely by defining B with a suitable version value, +see L: + + long SSL_SESSION_get_time(const SSL_SESSION *s); + long SSL_SESSION_set_time(SSL_SESSION *s, long tm); + long SSL_get_time(const SSL_SESSION *s); + long SSL_set_time(SSL_SESSION *s, long tm); + =head1 DESCRIPTION -SSL_SESSION_get_time() returns the time at which the session B was +SSL_SESSION_get_time_ex() returns the time at which the session B was established. The time is given in seconds since the Epoch and therefore compatible to the time delivered by the time() call. -SSL_SESSION_set_time() replaces the creation time of the session B with +SSL_SESSION_set_time_ex() replaces the creation time of the session B with the chosen value B. SSL_SESSION_get_timeout() returns the timeout value set for session B @@ -36,6 +44,11 @@ in seconds. SSL_SESSION_set_timeout() sets the timeout value for session B in seconds to B. +SSL_SESSION_get_time() and SSL_SESSION_set_time() functions use +the long datatype instead of time_t and are therefore deprecated due to not +being Y2038-safe on 32 bit systems. Note that such systems still need +to be configured to use 64 bit time_t to be able to avoid overflow in system time. + The SSL_get_time(), SSL_set_time(), SSL_get_timeout(), and SSL_set_timeout() functions are synonyms for the SSL_SESSION_*() counterparts. @@ -50,23 +63,36 @@ of the session. =head1 RETURN VALUES -SSL_SESSION_get_time() and SSL_SESSION_get_timeout() return the currently +SSL_SESSION_get_time_ex() and SSL_SESSION_get_timeout() return the currently valid values. -SSL_SESSION_set_time() and SSL_SESSION_set_timeout() return 1 on success. +SSL_SESSION_set_time_ex() returns time on success. + +SSL_SESSION_set_timeout() returns 1 on success. If any of the function is passed the NULL pointer for the session B, 0 is returned. +=head1 BUGS + +The data type long is typically 32 bits on many systems, hence the old +functions SSL_SESSION_get_time() and SSL_SESSION_set_time() are not always +Y2038 safe. + =head1 SEE ALSO L, L, L +=head1 HISTORY + +The functions SSL_SESSION_get_time_ex() and SSL_SESSION_set_time_ex() were +added in OpenSSL 3.3. + =head1 COPYRIGHT -Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_alloc_buffers.pod b/doc/man3/SSL_alloc_buffers.pod index 678640a56933..8810001df846 100644 --- a/doc/man3/SSL_alloc_buffers.pod +++ b/doc/man3/SSL_alloc_buffers.pod @@ -26,6 +26,9 @@ can be used to make sure the buffers are preallocated. This can be used to avoid allocation during data processing or with CRYPTO_set_mem_functions() to control where and how buffers are allocated. +These functions are no-ops when used with QUIC SSL objects. For QUIC, +SSL_free_buffers() always fails, and SSL_alloc_buffers() always succeeds. + =head1 RETURN VALUES The following return values can occur: @@ -58,7 +61,7 @@ L =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 diff --git a/doc/man3/SSL_clear.pod b/doc/man3/SSL_clear.pod index f5fc6e68ed2b..9867da4d25b2 100644 --- a/doc/man3/SSL_clear.pod +++ b/doc/man3/SSL_clear.pod @@ -28,12 +28,15 @@ set the SSL_SENT_SHUTDOWN state. If a session was closed cleanly, the session object will be kept and all settings corresponding. This explicitly means, that e.g. the special method used during the session will be kept for the next handshake. So if the -session was a TLSv1 session, a SSL client object will use a TLSv1 client -method for the next handshake and a SSL server object will use a TLSv1 +session was a TLSv1 session, an SSL client object will use a TLSv1 client +method for the next handshake and an SSL server object will use a TLSv1 server method, even if TLS_*_methods were chosen on startup. This will might lead to connection failures (see L) for a description of the method's properties. +This function is not supported on QUIC SSL objects and returns failure if called +on such an object. + =head1 WARNINGS SSL_clear() resets the SSL object to allow for another connection. The @@ -74,7 +77,7 @@ L =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 diff --git a/doc/man3/SSL_connect.pod b/doc/man3/SSL_connect.pod index 4e9bd9ca079b..f0bd04bb34ad 100644 --- a/doc/man3/SSL_connect.pod +++ b/doc/man3/SSL_connect.pod @@ -14,7 +14,7 @@ SSL_connect - initiate the TLS/SSL handshake with an TLS/SSL server SSL_connect() initiates the TLS/SSL handshake with a server. The communication channel must already have been set and assigned to the B by setting an -underlying B. +underlying B. B B be NULL. =head1 NOTES diff --git a/doc/man3/SSL_do_handshake.pod b/doc/man3/SSL_do_handshake.pod index 819576b09ffd..dbdf061730ab 100644 --- a/doc/man3/SSL_do_handshake.pod +++ b/doc/man3/SSL_do_handshake.pod @@ -12,7 +12,7 @@ SSL_do_handshake - perform a TLS/SSL handshake =head1 DESCRIPTION -SSL_do_handshake() will wait for a SSL/TLS handshake to take place. If the +SSL_do_handshake() will wait for an SSL/TLS handshake to take place. If the connection is in client mode, the handshake will be started. The handshake routines may have to be explicitly set in advance using either L or diff --git a/doc/man3/SSL_free.pod b/doc/man3/SSL_free.pod index d262f55d151e..7fabaa2159f4 100644 --- a/doc/man3/SSL_free.pod +++ b/doc/man3/SSL_free.pod @@ -34,6 +34,38 @@ and L was not used to set the SSL_SENT_SHUTDOWN state, the session will also be removed from the session cache as required by RFC2246. +When used to free a QUIC stream SSL object, the respective sending and receiving +parts of the stream are reset unless those parts have already been concluded +normally: + +=over 4 + +=item + +If the stream has a sending part (in other words, if it is bidirectional or a +locally-initiated unidirectional stream) and that part has not been concluded +via a call to L or L on the QUIC +stream SSL object, a call to SSL_free() automatically resets the sending part of +the stream as though L were called with a QUIC application +error code of 0. + +=item + +If the stream has a receiving part (in other words, if it is bidirectional or a +remotely-initiated unidirectional stream), and the peer has not yet concluded +that part of the stream normally (such as via a call to +L on its own end), a call to SSL_free() automatically +requests the reset of the receiving part of the stream using a QUIC STOP_SENDING +frame with a QUIC application error code of 0. Note that as per the QUIC +protocol, this will automatically cause the peer to reset that part of the +stream in turn (which is its sending part). + +=back + +A QUIC stream SSL object maintains a reference to a QUIC connection SSL object +internally, therefore a QUIC stream SSL object and its parent QUIC connection +SSL object can be freed in either order. + =head1 RETURN VALUES SSL_free() does not provide diagnostic information. @@ -44,7 +76,7 @@ L =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 diff --git a/doc/man3/SSL_get_current_cipher.pod b/doc/man3/SSL_get_current_cipher.pod index b41d9daf2f1c..7add794ca897 100644 --- a/doc/man3/SSL_get_current_cipher.pod +++ b/doc/man3/SSL_get_current_cipher.pod @@ -22,7 +22,7 @@ SSL_get_pending_cipher - get SSL_CIPHER of a connection SSL_get_current_cipher() returns a pointer to an SSL_CIPHER object containing the description of the actually used cipher of a connection established with -the B object. +the B object. B B be NULL. See L for more details. SSL_get_cipher_name() obtains the @@ -61,7 +61,7 @@ L, L =head1 COPYRIGHT -Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod index e5a507217ed4..794598facb33 100644 --- a/doc/man3/SSL_get_error.pod +++ b/doc/man3/SSL_get_error.pod @@ -62,8 +62,8 @@ is set. See L for more details. The operation did not complete and can be retried later. -B is returned when the last operation was a read -operation from a nonblocking B. +For non-QUIC SSL objects, B is returned when the last +operation was a read operation from a nonblocking B. It means that not enough data was available at this time to complete the operation. If at a later time the underlying B has data available for reading the same @@ -74,9 +74,10 @@ still unprocessed data available at either the B or the B layer, even for a blocking B. See L for more information. -B is returned when the last operation was a write -to a nonblocking B and it was unable to sent all data to the B. -When the B is writable again, the same function can be called again. +For non-QUIC SSL objects, B is returned when the last +operation was a write to a nonblocking B and it was unable to send all data +to the B. When the B is writable again, the same function can be +called again. Note that the retry may again lead to an B or B condition. @@ -84,6 +85,15 @@ There is no fixed upper limit for the number of iterations that may be necessary until progress becomes visible at application protocol level. +For QUIC SSL objects, the meaning of B and +B have different but largely compatible semantics. Since +QUIC implements its own flow control and uses UDP datagrams, backpressure +conditions in terms of the underlying BIO providing network I/O are not directly +relevant to the circumstances in which these errors are produced. In particular, +B indicates that the OpenSSL internal send buffer for a +given QUIC stream has been filled. Likewise, B indicates +that the OpenSSL internal receive buffer for a given QUIC stream is empty. + It is safe to call SSL_read() or SSL_read_ex() when more data is available even when the call that set this error was an SSL_write() or SSL_write_ex(). However, if the call was an SSL_write() or SSL_write_ex(), it should be called diff --git a/doc/man3/SSL_get_peer_signature_nid.pod b/doc/man3/SSL_get_peer_signature_nid.pod index 7776f3e25738..5518a9cfc78c 100644 --- a/doc/man3/SSL_get_peer_signature_nid.pod +++ b/doc/man3/SSL_get_peer_signature_nid.pod @@ -2,21 +2,31 @@ =head1 NAME -SSL_get_peer_signature_nid, SSL_get_peer_signature_type_nid, -SSL_get_signature_nid, SSL_get_signature_type_nid - get TLS message signing -types +SSL_get0_peer_signature_name, SSL_get_peer_signature_nid, +SSL_get_peer_signature_type_nid, SSL_get0_signature_name, +SSL_get_signature_nid, SSL_get_signature_type_nid - +get TLS message signing types =head1 SYNOPSIS #include + int SSL_get0_peer_signature_name(const SSL *ssl, const char **sigalg); int SSL_get_peer_signature_nid(SSL *ssl, int *psig_nid); int SSL_get_peer_signature_type_nid(const SSL *ssl, int *psigtype_nid); + int SSL_get0_signature_name(SSL *ssl, const char **sigalg); int SSL_get_signature_nid(SSL *ssl, int *psig_nid); int SSL_get_signature_type_nid(const SSL *ssl, int *psigtype_nid); =head1 DESCRIPTION +SSL_get0_peer_signature_name() sets I<*sigalg> to the IANA name of the +L +used by the peer to sign the TLS handshake. +The caller must not free the returned pointer. +The returned string should be copied if it is to be retained beyond the +lifetime of the SSL connection. + SSL_get_peer_signature_nid() sets B<*psig_nid> to the NID of the digest used by the peer to sign TLS messages. It is implemented as a macro. @@ -27,23 +37,31 @@ where it is B. To differentiate between B and B signatures, it's necessary to check the type of public key in the peer's certificate. -SSL_get_signature_nid() and SSL_get_signature_type_nid() return the equivalent -information for the local end of the connection. +SSL_get0_signature_name(), SSL_get_signature_nid() and +SSL_get_signature_type_nid() return the equivalent information for the local +end of the connection. =head1 RETURN VALUES These functions return 1 for success and 0 for failure. There are several -possible reasons for failure: the cipher suite has no signature (e.g. it -uses RSA key exchange or is anonymous), the TLS version is below 1.2 or -the functions were called too early, e.g. before the peer signed a message. +possible reasons for failure: the peer or local end is a client and did not +sign the handshake (did not use a client certificate), the cipher suite has no +signature (e.g. it uses RSA key exchange or is anonymous), the TLS version is +below 1.2 or the functions were called too early, e.g. before the peer signed a +message. =head1 SEE ALSO L, L, +=head1 HISTORY + +The SSL_get0_peer_signature_name() and SSL_get0_signature_name() functions were +added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_get_session.pod b/doc/man3/SSL_get_session.pod index 8d5d1f6b4792..6631bdf324aa 100644 --- a/doc/man3/SSL_get_session.pod +++ b/doc/man3/SSL_get_session.pod @@ -103,7 +103,7 @@ L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_get_verify_result.pod b/doc/man3/SSL_get_verify_result.pod index 08c46c0576ba..ca76945886ab 100644 --- a/doc/man3/SSL_get_verify_result.pod +++ b/doc/man3/SSL_get_verify_result.pod @@ -13,7 +13,7 @@ SSL_get_verify_result - get result of peer certificate verification =head1 DESCRIPTION SSL_get_verify_result() returns the result of the verification of the -X509 certificate presented by the peer, if any. +X509 certificate presented by the peer, if any. I B be NULL. =head1 NOTES diff --git a/doc/man3/SSL_get_version.pod b/doc/man3/SSL_get_version.pod index d12927745a50..b8a0f5e3b15d 100644 --- a/doc/man3/SSL_get_version.pod +++ b/doc/man3/SSL_get_version.pod @@ -2,8 +2,8 @@ =head1 NAME -SSL_client_version, SSL_get_version, SSL_is_dtls, SSL_version - get the -protocol information of a connection +SSL_client_version, SSL_get_version, SSL_is_dtls, SSL_is_tls, SSL_is_quic, +SSL_version - get the protocol information of a connection =head1 SYNOPSIS @@ -14,21 +14,29 @@ protocol information of a connection const char *SSL_get_version(const SSL *ssl); int SSL_is_dtls(const SSL *ssl); + int SSL_is_tls(const SSL *ssl); + int SSL_is_quic(const SSL *ssl); int SSL_version(const SSL *s); =head1 DESCRIPTION -SSL_client_version() returns the numeric protocol version advertised by the -client in the legacy_version field of the ClientHello when initiating the -connection. Note that, for TLS, this value will never indicate a version greater -than TLSv1.2 even if TLSv1.3 is subsequently negotiated. SSL_get_version() -returns the name of the protocol used for the connection. SSL_version() returns -the numeric protocol version used for the connection. They should only be called -after the initial handshake has been completed. Prior to that the results -returned from these functions may be unreliable. +For SSL, TLS and DTLS protocols SSL_client_version() returns the numeric +protocol version advertised by the client in the legacy_version field of the +ClientHello when initiating the connection. Note that, for TLS, this value +will never indicate a version greater than TLSv1.2 even if TLSv1.3 is +subsequently negotiated. For QUIC connections it returns OSSL_QUIC1_VERSION. -SSL_is_dtls() returns one if the connection is using DTLS, zero if not. +SSL_get_version() returns the name of the protocol used for the connection. +SSL_version() returns the numeric protocol version used for the connection. +They should only be called after the initial handshake has been completed. +Prior to that the results returned from these functions may be unreliable. + +SSL_is_dtls() returns 1 if the connection is using DTLS or 0 if not. + +SSL_is_tls() returns 1 if the connection is using SSL/TLS or 0 if not. + +SSL_is_quic() returns 1 if the connection is using QUIC or 0 if not. =head1 RETURN VALUES @@ -57,6 +65,22 @@ The connection uses the TLSv1.2 protocol. The connection uses the TLSv1.3 protocol. +=item DTLSv0.9 + +The connection uses an obsolete pre-standardisation DTLS protocol + +=item DTLSv1 + +The connection uses the DTLSv1 protocol + +=item DTLSv1.2 + +The connection uses the DTLSv1.2 protocol + +=item QUICv1 + +The connection uses the QUICv1 protocol. + =item unknown This indicates an unknown protocol version. @@ -89,6 +113,22 @@ The connection uses the TLSv1.2 protocol. The connection uses the TLSv1.3 protocol (never returned for SSL_client_version()). +=item DTLS1_BAD_VER + +The connection uses an obsolete pre-standardisation DTLS protocol + +=item DTLS1_VERSION + +The connection uses the DTLSv1 protocol + +=item DTLS1_2_VERSION + +The connection uses the DTLSv1.2 protocol + +=item OSSL_QUIC1_VERSION + +The connection uses the QUICv1 protocol. + =back =head1 SEE ALSO @@ -97,11 +137,12 @@ L =head1 HISTORY -The SSL_is_dtls() function was added in OpenSSL 1.1.0. +The SSL_is_dtls() function was added in OpenSSL 1.1.0. The SSL_is_tls() and +SSL_is_quic() functions were added in OpenSSL 3.2. =head1 COPYRIGHT -Copyright 2001-2018 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 diff --git a/doc/man3/SSL_group_to_name.pod b/doc/man3/SSL_group_to_name.pod index 4551a1264c29..d23bed8ed43f 100644 --- a/doc/man3/SSL_group_to_name.pod +++ b/doc/man3/SSL_group_to_name.pod @@ -8,7 +8,7 @@ SSL_group_to_name - get name of group #include - const char *SSL_group_to_name(const SSL *ssl, int id); + const char *SSL_group_to_name(SSL *ssl, int id); =head1 DESCRIPTION @@ -33,7 +33,7 @@ L =head1 COPYRIGHT -Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_in_init.pod b/doc/man3/SSL_in_init.pod index 315d870284d8..02725d83bc3b 100644 --- a/doc/man3/SSL_in_init.pod +++ b/doc/man3/SSL_in_init.pod @@ -37,6 +37,8 @@ fully protected application data can be transferred or 0 otherwise. Note that in some circumstances (such as when early data is being transferred) SSL_in_init(), SSL_in_before() and SSL_is_init_finished() can all return 0. +B B be NULL. + SSL_in_connect_init() returns 1 if B is acting as a client and SSL_in_init() would return 1, or 0 otherwise. diff --git a/doc/man3/SSL_key_update.pod b/doc/man3/SSL_key_update.pod index 6d5b42e0b166..6238e67649e0 100644 --- a/doc/man3/SSL_key_update.pod +++ b/doc/man3/SSL_key_update.pod @@ -32,11 +32,11 @@ peer to additionally update its sending keys. It is an error if B is set to B. SSL_key_update() must only be called after the initial handshake has been -completed and TLSv1.3 has been negotiated, at the same time, the application -needs to ensure that the writing of data has been completed. The key update -will not take place until the next time an IO operation such as SSL_read_ex() -or SSL_write_ex() takes place on the connection. Alternatively SSL_do_handshake() -can be called to force the update to take place immediately. +completed and TLSv1.3 or QUIC has been negotiated, at the same time, the +application needs to ensure that the writing of data has been completed. The key +update will not take place until the next time an IO operation such as +SSL_read_ex() or SSL_write_ex() takes place on the connection. Alternatively +SSL_do_handshake() can be called to force the update to take place immediately. SSL_get_key_update_type() can be used to determine whether a key update operation has been scheduled but not yet performed. The type of the pending key @@ -77,6 +77,23 @@ the session in the new handshake. The SSL_renegotiate_pending() function returns 1 if a renegotiation or renegotiation request has been scheduled but not yet acted on, or 0 otherwise. +=head1 USAGE WITH QUIC + +SSL_key_update() can also be used to perform a key update when using QUIC. The +function must be called on a QUIC connection SSL object. This is normally done +automatically when needed. Since a locally initiated QUIC key update always +causes a peer to also trigger a key update, passing +B as B has the same effect as passing +B. + +The QUIC connection must have been fully established before a key update can be +performed, and other QUIC protocol rules govern how frequently QUIC key update +can be performed. SSL_key_update() will fail if these requirements are not met. + +Because QUIC key updates are always handled immediately, +SSL_get_key_update_type() always returns SSL_KEY_UPDATE_NONE when called on a +QUIC connection SSL object. + =head1 RETURN VALUES SSL_key_update(), SSL_renegotiate() and SSL_renegotiate_abbreviated() return 1 @@ -101,7 +118,7 @@ OpenSSL 1.1.1. =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 diff --git a/doc/man3/SSL_new.pod b/doc/man3/SSL_new.pod index 2b522769169b..d01996fba143 100644 --- a/doc/man3/SSL_new.pod +++ b/doc/man3/SSL_new.pod @@ -96,6 +96,9 @@ SSL_set0_client_CA_list() or similar functions =back +SSL_dup() is not supported on QUIC SSL objects and returns NULL if called on +such an object. + =head1 RETURN VALUES The following return values can occur: diff --git a/doc/man3/SSL_read.pod b/doc/man3/SSL_read.pod index 0bfc2a413540..206f06afe091 100644 --- a/doc/man3/SSL_read.pod +++ b/doc/man3/SSL_read.pod @@ -93,6 +93,14 @@ are buffered bytes available for immediate retrieval. In this case the read function can be called without blocking or actually receiving new data from the underlying socket. +When used with a QUIC SSL object, calling an I/O function such as SSL_read() +allows internal network event processing to be performed. It is important that +this processing is performed regularly. If an application is not using thread +assisted mode, an application should ensure that an I/O function such as +SSL_read() is called regularly, or alternatively ensure that SSL_handle_events() +is called regularly. See L and L for more +information. + =head1 RETURN VALUES SSL_read_ex() and SSL_peek_ex() will return 1 for success or 0 for failure. @@ -142,7 +150,7 @@ The SSL_read_ex() and SSL_peek_ex() functions were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2000-2020 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 diff --git a/doc/man3/SSL_read_early_data.pod b/doc/man3/SSL_read_early_data.pod index 13c3bcf6a65d..ec71c6eba9fb 100644 --- a/doc/man3/SSL_read_early_data.pod +++ b/doc/man3/SSL_read_early_data.pod @@ -241,6 +241,11 @@ protection feature will still be used even if a callback is present unless it has been explicitly disabled using the SSL_OP_NO_ANTI_REPLAY option. See L below. +These functions cannot currently be used with QUIC SSL objects. +SSL_set_max_early_data(), SSL_set_recv_max_early_data(), SSL_write_early_data(), +SSL_read_early_data(), SSL_get_early_data_status() and +SSL_set_allow_early_data_cb() fail if called on a QUIC SSL object. + =head1 NOTES The whole purpose of early data is to enable a client to start sending data to @@ -365,7 +370,7 @@ All of the functions described above were added in OpenSSL 1.1.1. =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 diff --git a/doc/man3/SSL_rstate_string.pod b/doc/man3/SSL_rstate_string.pod index 2c0cf560e4de..d1fa22243d61 100644 --- a/doc/man3/SSL_rstate_string.pod +++ b/doc/man3/SSL_rstate_string.pod @@ -42,23 +42,22 @@ The header of the record is being evaluated. The body of the record is being evaluated. -=item "RD"/"read done" - -The record has been completely processed. - =item "unknown"/"unknown" The read state is unknown. This should never happen. =back +When used with QUIC SSL objects, these functions always return "RH"/"read +header" in normal conditions. + =head1 SEE ALSO L =head1 COPYRIGHT -Copyright 2001-2016 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 diff --git a/doc/man3/SSL_set_async_callback.pod b/doc/man3/SSL_set_async_callback.pod index e0a665dc451b..db858a00ce58 100644 --- a/doc/man3/SSL_set_async_callback.pod +++ b/doc/man3/SSL_set_async_callback.pod @@ -121,7 +121,7 @@ SSL_get_async_status() were first added to OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/SSL_set_bio.pod b/doc/man3/SSL_set_bio.pod index aaffeedf779b..07f46ab4d783 100644 --- a/doc/man3/SSL_set_bio.pod +++ b/doc/man3/SSL_set_bio.pod @@ -95,6 +95,12 @@ reference is consumed for the B. Because of this complexity, this function should be avoided; use SSL_set0_rbio() and SSL_set0_wbio() instead. +Where a new BIO is set on a QUIC connection SSL object, blocking mode will be +disabled on that SSL object if the BIO cannot support blocking mode. If another +BIO is subsequently set on the SSL object which can support blocking mode, +blocking mode will not be automatically re-enabled. For more information, see +L. + =head1 RETURN VALUES SSL_set_bio(), SSL_set0_rbio() and SSL_set0_wbio() cannot fail. @@ -111,7 +117,7 @@ SSL_set0_rbio() and SSL_set0_wbio() were added in OpenSSL 1.1.0. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +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 diff --git a/doc/man3/SSL_set_fd.pod b/doc/man3/SSL_set_fd.pod index 691b068d73fc..a431183a328b 100644 --- a/doc/man3/SSL_set_fd.pod +++ b/doc/man3/SSL_set_fd.pod @@ -23,6 +23,10 @@ interface between the B and B. The BIO and hence the SSL engine inherit the behaviour of B. If B is nonblocking, the B will also have nonblocking behaviour. +When used on a QUIC connection SSL object, a B is automatically +created instead of a B. These functions fail if called +on a QUIC stream SSL object. + If there was already a BIO connected to B, BIO_free() will be called (for both the reading and writing side, if different). @@ -64,7 +68,7 @@ L, L , L =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 diff --git a/doc/man3/SSL_set_retry_verify.pod b/doc/man3/SSL_set_retry_verify.pod index 4eb7f449ed59..0f20a4930616 100644 --- a/doc/man3/SSL_set_retry_verify.pod +++ b/doc/man3/SSL_set_retry_verify.pod @@ -39,7 +39,7 @@ with the B to call the SSL_set_retry_verify() function: /* this should not happen but check anyway */ if (idx < 0 - || (ssl = X509_STORE_CTX_get_ex_data(ctx, idx)) == NULL) + || (ssl = X509_STORE_CTX_get_ex_data(ctx, idx)) == NULL) return 0; if (/* we need to retry verification callback */) diff --git a/doc/man3/SSL_set_shutdown.pod b/doc/man3/SSL_set_shutdown.pod index 54d541e4e4fe..9a7eb463a827 100644 --- a/doc/man3/SSL_set_shutdown.pod +++ b/doc/man3/SSL_set_shutdown.pod @@ -57,11 +57,21 @@ If a close_notify was received, SSL_RECEIVED_SHUTDOWN will be set, for setting SSL_SENT_SHUTDOWN the application must however still call L or SSL_set_shutdown() itself. +SSL_set_shutdown() is not supported for QUIC SSL objects. + =head1 RETURN VALUES SSL_set_shutdown() does not return diagnostic information. -SSL_get_shutdown() returns the current setting. +SSL_get_shutdown() returns the current shutdown state as set or based +on the actual connection state. + +SSL_get_shutdown() returns 0 if called on a QUIC stream SSL object. If it +is called on a QUIC connection SSL object, it returns a value with +SSL_SENT_SHUTDOWN set if CONNECTION_CLOSE has been sent to the peer and +it returns a value with SSL_RECEIVED_SHUTDOWN set if CONNECTION_CLOSE +has been received from the peer or the QUIC connection is fully terminated +for other reasons. =head1 SEE ALSO @@ -71,7 +81,7 @@ L, L =head1 COPYRIGHT -Copyright 2001-2018 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 diff --git a/doc/man3/SSL_shutdown.pod b/doc/man3/SSL_shutdown.pod index 6797006a283e..dd35a03eb368 100644 --- a/doc/man3/SSL_shutdown.pod +++ b/doc/man3/SSL_shutdown.pod @@ -2,7 +2,7 @@ =head1 NAME -SSL_shutdown - shut down a TLS/SSL connection +SSL_shutdown, SSL_shutdown_ex - shut down a TLS/SSL or QUIC connection =head1 SYNOPSIS @@ -10,141 +10,396 @@ SSL_shutdown - shut down a TLS/SSL connection int SSL_shutdown(SSL *ssl); + typedef struct ssl_shutdown_ex_args_st { + uint64_t quic_error_code; + const char *quic_reason; + } SSL_SHUTDOWN_EX_ARGS; + + __owur int SSL_shutdown_ex(SSL *ssl, uint64_t flags, + const SSL_SHUTDOWN_EX_ARGS *args, + size_t args_len); + =head1 DESCRIPTION -SSL_shutdown() shuts down an active TLS/SSL connection. It sends the -close_notify shutdown alert to the peer. +SSL_shutdown() shuts down an active connection represented by an SSL object. I B be NULL. -SSL_shutdown() tries to send the close_notify shutdown alert to the peer. -Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and -a currently open session is considered closed and good and will be kept in the -session cache for further reuse. +SSL_shutdown_ex() is an extended version of SSL_shutdown(). If non-NULL, I +must point to a B structure and I must be set to +C. The B structure must be +zero-initialized. If I is NULL, the behaviour is the same as passing a +zero-initialised B structure. Currently, all extended +arguments relate to usage with QUIC, therefore this call functions identically +to SSL_shutdown() when not being used with QUIC. -Note that SSL_shutdown() must not be called if a previous fatal error has -occurred on a connection i.e. if SSL_get_error() has returned SSL_ERROR_SYSCALL -or SSL_ERROR_SSL. +While the general operation of SSL_shutdown() is common between protocols, the +exact nature of how a shutdown is performed depends on the underlying protocol +being used. See the section below pertaining to each protocol for more +information. -The shutdown procedure consists of two steps: sending of the close_notify -shutdown alert, and reception of the peer's close_notify shutdown alert. -The order of those two steps depends on the application. +In general, calling SSL_shutdown() in nonblocking mode will initiate the +shutdown process and return 0 to indicate that the shutdown process has not yet +completed. Once the shutdown process has completed, subsequent calls to +SSL_shutdown() will return 1. See the RETURN VALUES section for more +information. -It is acceptable for an application to only send its shutdown alert and -then close the underlying connection without waiting for the peer's response. -This way resources can be saved, as the process can already terminate or -serve another connection. -This should only be done when it is known that the other side will not send more -data, otherwise there is a risk of a truncation attack. +SSL_shutdown() should not be called if a previous fatal error has occurred on a +connection; i.e., if L has returned B or +B. -When a client only writes and never reads from the connection, and the server -has sent a session ticket to establish a session, the client might not be able -to resume the session because it did not received and process the session ticket -from the server. -In case the application wants to be able to resume the session, it is recommended to -do a complete shutdown procedure (bidirectional close_notify alerts). +=head1 TLS AND DTLS-SPECIFIC CONSIDERATIONS -When the underlying connection shall be used for more communications, the -complete shutdown procedure must be performed, so that the peers stay -synchronized. +Shutdown for SSL/TLS and DTLS is implemented in terms of the SSL/TLS/DTLS +close_notify alert message. The shutdown process for SSL/TLS and DTLS +consists of two steps: -SSL_shutdown() only closes the write direction. -It is not possible to call SSL_write() after calling SSL_shutdown(). -The read direction is closed by the peer. +=over 4 -The behaviour of SSL_shutdown() additionally depends on the underlying BIO. -If the underlying BIO is B, SSL_shutdown() will only return once the -handshake step has been finished or an error occurred. +=item * -If the underlying BIO is B, SSL_shutdown() will also return -when the underlying BIO could not satisfy the needs of SSL_shutdown() -to continue the handshake. In this case a call to SSL_get_error() with the -return value of SSL_shutdown() will yield B or -B. The calling process then must repeat the call after -taking appropriate action to satisfy the needs of SSL_shutdown(). -The action depends on the underlying BIO. When using a nonblocking socket, -nothing is to be done, but select() can be used to check for the required -condition. When using a buffering BIO, like a BIO pair, data must be written -into or retrieved out of the BIO before being able to continue. +A close_notify shutdown alert message is sent to the peer. -After SSL_shutdown() returned 0, it is possible to call SSL_shutdown() again -to wait for the peer's close_notify alert. -SSL_shutdown() will return 1 in that case. -However, it is recommended to wait for it using SSL_read() instead. +=item * -SSL_shutdown() can be modified to only set the connection to "shutdown" -state but not actually send the close_notify alert messages, -see L. -When "quiet shutdown" is enabled, SSL_shutdown() will always succeed -and return 1. -Note that this is not standard compliant behaviour. -It should only be done when the peer has a way to make sure all -data has been received and doesn't wait for the close_notify alert -message, otherwise an unexpected EOF will be reported. +A close_notify shutdown alert message is received from the peer. -There are implementations that do not send the required close_notify alert. -If there is a need to communicate with such an implementation, and it's clear -that all data has been received, do not wait for the peer's close_notify alert. -Waiting for the close_notify alert when the peer just closes the connection -will result in an error being generated. -The error can be ignored using the B. -For more information see L. +=back -=head2 First to close the connection +These steps can occur in either order depending on whether the connection +shutdown process was first initiated by the local application or by the peer. -When the application is the first party to send the close_notify -alert, SSL_shutdown() will only send the alert and then set the -SSL_SENT_SHUTDOWN flag (so that the session is considered good and will -be kept in the cache). -If successful, SSL_shutdown() will return 0. +=head2 Locally-Initiated Shutdown -If a unidirectional shutdown is enough (the underlying connection shall be -closed anyway), this first successful call to SSL_shutdown() is sufficient. +Calling SSL_shutdown() on an SSL/TLS or DTLS SSL object initiates the shutdown +process and causes OpenSSL to try to send a close_notify shutdown alert to the +peer. The shutdown process will then be considered completed once the peer +responds in turn with a close_notify shutdown alert message. -In order to complete the bidirectional shutdown handshake, the peer needs -to send back a close_notify alert. -The SSL_RECEIVED_SHUTDOWN flag will be set after receiving and processing -it. +Calling SSL_shutdown() only closes the write direction of the connection; the +read direction is closed by the peer. Once SSL_shutdown() is called, +L can no longer be used, but L may still be used +until the peer decides to close the connection in turn. The peer might +continue sending data for some period of time before handling the local +application's shutdown indication. -The peer is still allowed to send data after receiving the close_notify -event. -When it is done sending data, it will send the close_notify alert. -SSL_read() should be called until all data is received. -SSL_read() will indicate the end of the peer data by returning <= 0 -and SSL_get_error() returning SSL_ERROR_ZERO_RETURN. +SSL_shutdown() does not affect an underlying network connection such as a TCP +connection, which remains open. -=head2 Peer closes the connection +=head2 Remotely-Initiated Shutdown -If the peer already sent the close_notify alert B it was -already processed implicitly inside another function -(L), the SSL_RECEIVED_SHUTDOWN flag is set. -SSL_read() will return <= 0 in that case, and SSL_get_error() will return -SSL_ERROR_ZERO_RETURN. -SSL_shutdown() will send the close_notify alert, set the SSL_SENT_SHUTDOWN -flag. -If successful, SSL_shutdown() will return 1. +If the peer was the first to initiate the shutdown process by sending a +close_notify alert message, an application will be notified of this as an EOF +condition when calling +L (i.e., L will fail and L will +return B), after all application data sent by the peer +prior to initiating the shutdown has been read. An application should handle +this condition by calling SSL_shutdown() to respond with a close_notify alert in +turn, completing the shutdown process, though it may choose to write additional +application data using L before doing so. If an application does +not call SSL_shutdown() in this case, a close_notify alert will not be sent and +the behaviour will not be fully standards compliant. -Whether SSL_RECEIVED_SHUTDOWN is already set can be checked using the -SSL_get_shutdown() (see also L call. +=head2 Shutdown Lifecycle + +Regardless of whether a shutdown was initiated locally or by the peer, if the +underlying BIO is blocking, a call to SSL_shutdown() will return firstly once a +close_notify alert message is written to the peer (returning 0), and upon a +second and subsequent call, once a corresponding message is received from the +peer (returning 1 and completing the shutdown process). Calls to SSL_shutdown() +with a blocking underlying BIO will also return if an error occurs. + +If the underlying BIO is nonblocking and the shutdown process is not yet +complete (for example, because a close_notify alert message has not yet been +received from the peer, or because a close_notify alert message needs to be sent +but would currently block), SSL_shutdown() returns 0 to indicate that the +shutdown process is still ongoing; in this case, a call to L +will yield B or B. + +An application can then detect completion of the shutdown process by calling +SSL_shutdown() again repeatedly until it returns 1, indicating that the shutdown +process is complete (with a close_notify alert having both been sent and +received). + +However, the preferred method of waiting for the shutdown to complete is to use +L until L indicates EOF by returning +B. This ensures any data received immediately before the +peer's close_notify alert is still provided to the application. It also ensures +any final handshake-layer messages received are processed (for example, messages +issuing new session tickets). + +If this approach is not used, the second call to SSL_shutdown() (to complete the +shutdown by confirming receipt of the peer's close_notify message) will fail if +it is called when the application has not read all pending application data +sent by the peer using L. + +When calling SSL_shutdown(), the B flag is set once an +attempt is made to send a close_notify alert, regardless of whether the attempt +was successful. The B flag is set once a close_notify +alert is received, which may occur during any call which processes incoming data +from the network, such as L or SSL_shutdown(). These flags +may be checked using L. + +=head2 Fast Shutdown + +Alternatively, it is acceptable for an application to call SSL_shutdown() once +(such that it returns 0) and then close the underlying connection without +waiting for the peer's response. This allows for a more rapid shutdown process +if the application does not wish to wait for the peer. + +This alternative "fast shutdown" approach should only be done if it is known +that the peer will not send more data, otherwise there is a risk of an +application exposing itself to a truncation attack. The full SSL_shutdown() +process, in which both parties send close_notify alerts and SSL_shutdown() +returns 1, provides a cryptographically authenticated indication of the end of a +connection. + +This approach of a single SSL_shutdown() call without waiting is preferable to +simply calling L or L as calling SSL_shutdown() +beforehand makes an SSL session eligible for subsequent reuse and notifies the +peer of connection shutdown. + +The fast shutdown approach can only be used if there is no intention to reuse +the underlying connection (e.g. a TCP connection) for further communication; in +this case, the full shutdown process must be performed to ensure +synchronisation. + +=head2 Effects on Session Reuse + +Calling SSL_shutdown() sets the SSL_SENT_SHUTDOWN flag (see +L), regardless of whether the transmission of the +close_notify alert was successful or not. This makes the SSL session eligible +for reuse; the SSL session is considered properly closed and can be reused for +future connections. + +=head2 Quiet Shutdown + +SSL_shutdown() can be modified to set the connection to the "shutdown" +state without actually sending a close_notify alert message; see +L. When "quiet shutdown" is enabled, +SSL_shutdown() will always succeed and return 1 immediately. + +This is not standards-compliant behaviour. It should only be done when the +application protocol in use enables the peer to ensure that all data has been +received, such that it doesn't need to wait for a close_notify alert, otherwise +application data may be truncated unexpectedly. + +=head2 Non-Compliant Peers + +There are SSL/TLS implementations that never send the required close_notify +alert message but simply close the underlying transport (e.g. a TCP connection) +instead. This will ordinarily result in an error being generated. + +If compatibility with such peers is desired, the option +B can be set. For more information, see +L. + +Note that use of this option means that the EOF condition for application data +does not receive cryptographic protection, and therefore renders an application +potentially vulnerable to truncation attacks. Thus, this option must only be +used in conjunction with an application protocol which indicates unambiguously +when all data has been received. + +An alternative approach is to simply avoid calling L if it is known +that no more data is going to be sent. This requires an application protocol +which indicates unambiguously when all data has been sent. + +=head2 Session Ticket Handling + +If a client application only writes to an SSL/TLS or DTLS connection and never +reads, OpenSSL may never process new SSL/TLS session tickets sent by the server. +This is because OpenSSL ordinarily processes handshake messages received from a +peer during calls to L by the application. + +Therefore, client applications which only write and do not read but which wish +to benefit from session resumption are advised to perform a complete shutdown +procedure by calling SSL_shutdown() until it returns 1, as described above. This +will ensure there is an opportunity for SSL/TLS session ticket messages to be +received and processed by OpenSSL. + +=head1 QUIC-SPECIFIC SHUTDOWN CONSIDERATIONS + +When used with a QUIC connection SSL object, SSL_shutdown() initiates a QUIC +immediate close using QUIC B frames. + +SSL_shutdown() cannot be used on QUIC stream SSL objects. To conclude a stream +normally, see L; to perform a non-normal stream +termination, see L. + +SSL_shutdown_ex() may be used instead of SSL_shutdown() by an application to +provide additional information to the peer on the reason why a connection is +being shut down. The information which can be provided is as follows: + +=over 4 + +=item I + +An optional 62-bit application error code to be signalled to the peer. The value +must be in the range [0, 2**62-1], else the call to SSL_shutdown_ex() fails. If +not provided, an error code of 0 is used by default. + +=item I + +An optional zero-terminated (UTF-8) reason string to be signalled to the peer. +The application is responsible for providing a valid UTF-8 string and OpenSSL +will not validate the string. If a reason is not provided, or SSL_shutdown() is +used, a zero-length string is used as the reason. If provided, the reason string +is copied and stored inside the QUIC connection SSL object and need not remain +allocated after the call to SSL_shutdown_ex() returns. Reason strings are +bounded by the path MTU and may be silently truncated if they are too long to +fit in a QUIC packet. + +Reason strings are intended for human diagnostic purposes only, and should not +be used for application signalling. + +=back + +The arguments to SSL_shutdown_ex() are used only on the first call to +SSL_shutdown_ex() (or SSL_shutdown()) for a given QUIC connection SSL object. +These arguments are ignored on subsequent calls. + +These functions do not affect an underlying network BIO or the resource it +represents; for example, a UDP datagram provided to a QUIC connection as the +network BIO will remain open. + +Note that when using QUIC, an application must call SSL_shutdown() if it wants +to ensure that all transmitted data was received by the peer. This is unlike a +TLS/TCP connection, where reliable transmission of buffered data is the +responsibility of the operating system. If an application calls SSL_free() on a +QUIC connection SSL object or exits before completing the shutdown process using +SSL_shutdown(), data which was written by the application using SSL_write(), but +could not yet be transmitted, or which was sent but lost in the network, may not +be received by the peer. + +When using QUIC, calling SSL_shutdown() allows internal network event processing +to be performed. It is important that this processing is performed regularly, +whether during connection usage or during shutdown. If an application is not +using thread assisted mode, an application conducting shutdown should either +ensure that SSL_shutdown() is called regularly, or alternatively ensure that +SSL_handle_events() is called regularly. See L and +L for more information. + +=head2 Application Data Drainage Behaviour + +When using QUIC, SSL_shutdown() or SSL_shutdown_ex() ordinarily waits until all +data written to a stream by an application has been acknowledged by the peer. In +other words, the shutdown process waits until all data written by the +application has been sent to the peer, and until the receipt of all such data is +acknowledged by the peer. Only once this process is completed is the shutdown +considered complete. + +An exception to this is streams which terminated in a non-normal fashion, for +example due to a stream reset; only streams which are non-terminated at the time +SSL_shutdown() is called, or which terminated in a normal fashion, have their +pending send buffers flushed in this manner. + +This behaviour of flushing streams during the shutdown process can be skipped by +setting the B flag in a call to +SSL_shutdown_ex(); in this case, data remaining in stream send buffers may not +be transmitted to the peer. This flag may be used when a non-normal application +condition has occurred and the delivery of data written to streams via +L is no longer relevant. + +=head2 Shutdown Mode + +Aspects of how QUIC handles connection closure must be taken into account by +applications. Ordinarily, QUIC expects a connection to continue to be serviced +for a substantial period of time after it is nominally closed. This is necessary +to ensure that any connection closure notification sent to the peer was +successfully received. However, a consequence of this is that a fully +RFC-compliant QUIC connection closure process could take of the order of +seconds. This may be unsuitable for some applications, such as short-lived +processes which need to exit immediately after completing an application-layer +transaction. + +As such, there are two shutdown modes available to users of QUIC connection SSL +objects: + +=over 4 + +=item RFC compliant shutdown mode + +This is the default behaviour. The shutdown process may take a period of time up +to three times the current estimated RTT to the peer. It is possible for the +closure process to complete much faster in some circumstances but this cannot be +relied upon. + +In blocking mode, the function will return once the closure process is complete. +In nonblocking mode, SSL_shutdown_ex() should be called until it returns 1, +indicating the closure process is complete and the connection is now fully shut +down. + +=item Rapid shutdown mode + +In this mode, the peer is notified of connection closure on a best effort basis +by sending a single QUIC packet. If that QUIC packet is lost, the peer will not +know that the connection has terminated until the negotiated idle timeout (if +any) expires. + +This will generally return 0 on success, indicating that the connection has not +yet been fully shut down (unless it has already done so, in which case it will +return 1). + +=back + +If B is specified in I, a rapid shutdown is +performed, otherwise an RFC-compliant shutdown is performed. + +If an application calls SSL_shutdown_ex() with B, an +application can subsequently change its mind about performing a rapid shutdown +by making a subsequent call to SSL_shutdown_ex() without the flag set. + +=head2 Peer-Initiated Shutdown + +In some cases, an application may wish to wait for a shutdown initiated by the +peer rather than triggered locally. To do this, call SSL_shutdown_ex() with +I specified in I. In blocking mode, this +waits until the peer initiates a shutdown or the connection otherwise becomes +terminated for another reason. In nonblocking mode it exits immediately with +either success or failure depending on whether a shutdown has occurred. + +If a locally initiated shutdown has already been triggered or the connection has +started terminating for another reason, this flag has no effect. + +B implies B, as +stream data cannot be flushed after a peer closes the connection. Stream data +may still be sent to the peer in any time spent waiting before the peer closes +the connection, though there is no guarantee of this. + +=head2 Nonblocking Mode + +SSL_shutdown() and SSL_shutdown_ex() block if the connection is configured in +blocking mode. This may be overridden by specifying +B in I when calling SSL_shutdown_ex(), which +causes the call to operate as though in nonblocking mode. =head1 RETURN VALUES -The following return values can occur: +For both SSL_shutdown() and SSL_shutdown_ex() the following return values can occur: =over 4 =item Z<>0 -The shutdown is not yet finished: the close_notify was sent but the peer -did not send it back yet. -Call SSL_read() to do a bidirectional shutdown. +The shutdown process is ongoing and has not yet completed. -Unlike most other function, returning 0 does not indicate an error. -L should not get called, it may misleadingly -indicate an error even though no error occurred. +For TLS and DTLS, this means that a close_notify alert has been sent but the +peer has not yet replied in turn with its own close_notify. + +For QUIC connection SSL objects, a CONNECTION_CLOSE frame may have been +sent but the connection closure process has not yet completed. + +Unlike most other functions, returning 0 does not indicate an error. +L should not be called; it may misleadingly indicate an error +even though no error occurred. =item Z<>1 -The shutdown was successfully completed. The close_notify alert was sent -and the peer's close_notify alert was received. +The shutdown was successfully completed. + +For TLS and DTLS, this means that a close_notify alert was sent and the peer's +close_notify alert was received. + +For QUIC connection SSL objects, this means that the connection closure process +has completed. =item E0 @@ -153,7 +408,10 @@ Call L with the return value B to find out the reason. It can occur if an action is needed to continue the operation for nonblocking BIOs. -It can also occur when not all data was read using SSL_read(). +It can also occur when not all data was read using SSL_read(), or if called +on a QUIC stream SSL object. + +This value is also returned when called on QUIC stream SSL objects. =back @@ -165,9 +423,13 @@ L, L L, L, L, L +=head1 HISTORY + +The SSL_shutdown_ex() function was added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2000-2020 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 diff --git a/doc/man3/SSL_want.pod b/doc/man3/SSL_want.pod index 1d274fd342a2..1eddeeba4d86 100644 --- a/doc/man3/SSL_want.pod +++ b/doc/man3/SSL_want.pod @@ -22,7 +22,7 @@ SSL_want_client_hello_cb - obtain state information TLS/SSL I/O operation =head1 DESCRIPTION -SSL_want() returns state information for the SSL object B. +SSL_want() returns state information for the SSL object B. B B be NULL. The other SSL_want_*() calls are shortcuts for the possible states returned by SSL_want(). @@ -99,6 +99,10 @@ SSL_want_x509_lookup(), SSL_want_retry_verify(), SSL_want_async(), SSL_want_async_job(), and SSL_want_client_hello_cb() return 1 when the corresponding condition is true or 0 otherwise. +=head1 QUIC-SPECIFIC CONSIDERATIONS + +For QUIC, these functions relate only to the TLS handshake layer. + =head1 SEE ALSO L, L @@ -110,7 +114,7 @@ were added in OpenSSL 1.1.1. =head1 COPYRIGHT -Copyright 2001-2022 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 diff --git a/doc/man3/SSL_write.pod b/doc/man3/SSL_write.pod index e03cce2ad62e..c6345efbb702 100644 --- a/doc/man3/SSL_write.pod +++ b/doc/man3/SSL_write.pod @@ -2,13 +2,19 @@ =head1 NAME -SSL_write_ex, SSL_write, SSL_sendfile - write bytes to a TLS/SSL connection +SSL_write_ex2, SSL_write_ex, SSL_write, SSL_sendfile, SSL_WRITE_FLAG_CONCLUDE - +write bytes to a TLS/SSL connection =head1 SYNOPSIS #include + #define SSL_WRITE_FLAG_CONCLUDE + ossl_ssize_t SSL_sendfile(SSL *s, int fd, off_t offset, size_t size, int flags); + int SSL_write_ex2(SSL *s, const void *buf, size_t num, + uint64_t flags, + size_t *written); int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written); int SSL_write(SSL *ssl, const void *buf, int num); @@ -18,6 +24,10 @@ SSL_write_ex() and SSL_write() write B bytes from the buffer B into the specified B connection. On success SSL_write_ex() will store the number of bytes written in B<*written>. +SSL_write_ex2() functions similarly to SSL_write_ex() but can also accept +optional flags which modify its behaviour. Calling SSL_write_ex2() with a +I argument of 0 is exactly equivalent to calling SSL_write_ex(). + SSL_sendfile() writes B bytes from offset B in the file descriptor B to the specified SSL connection B. This function provides efficient zero-copy semantics. SSL_sendfile() is available only when @@ -26,6 +36,39 @@ It is provided here to allow users to maintain the same interface. The meaning of B is platform dependent. Currently, under Linux it is ignored. +The I argument to SSL_write_ex2() can accept zero or more of the +following flags. Note that which flags are supported will depend on the kind of +SSL object and underlying protocol being used: + +=over 4 + +=item B + +This flag is only supported on QUIC stream SSL objects (or QUIC connection SSL +objects with a default stream attached). + +If this flag is set, and the call to SSL_write_ex2() succeeds, and all of the +data passed to the call is written (meaning that C<*written == num>), the +relevant QUIC stream's send part is concluded automatically as though +L was called (causing transmission of a FIN for the +stream). + +While using this flag is semantically equivalent to calling +L after a successful call to this function, using this +flag enables greater efficiency than making these two API calls separately, as +it enables the written stream data and the FIN flag indicating the end of the +stream to be scheduled as part of the same QUIC STREAM frame and QUIC packet. + +Setting this flag does not cause a stream's send part to be concluded if not all +of the data passed to the call was consumed. + +=back + +A call to SSL_write_ex2() fails if a flag is passed which is not supported or +understood by the given SSL object. An application should determine if a flag is +supported (for example, for B, that a QUIC stream SSL +object is being used) before attempting to use it. + =head1 NOTES In the paragraphs below a "write function" is defined as one of either @@ -66,6 +109,14 @@ operation is considered completed. The bytes are sent and a new write call with a new buffer (with the already sent bytes removed) must be started. A partial write is performed with the size of a message block, which is 16kB. +When used with a QUIC SSL object, calling an I/O function such as SSL_write() +allows internal network event processing to be performed. It is important that +this processing is performed regularly. If an application is not using thread +assisted mode, an application should ensure that an I/O function such as +SSL_write() is called regularly, or alternatively ensure that SSL_handle_events() +is called regularly. See L and L for more +information. + =head1 WARNINGS When a write function call has to be repeated because L @@ -81,16 +132,17 @@ the peer. =head1 RETURN VALUES -SSL_write_ex() will return 1 for success or 0 for failure. Success means that -all requested application data bytes have been written to the SSL connection or, -if SSL_MODE_ENABLE_PARTIAL_WRITE is in use, at least 1 application data byte has -been written to the SSL connection. Failure means that not all the requested -bytes have been written yet (if SSL_MODE_ENABLE_PARTIAL_WRITE is not in use) or -no bytes could be written to the SSL connection (if -SSL_MODE_ENABLE_PARTIAL_WRITE is in use). Failures can be retryable (e.g. the -network write buffer has temporarily filled up) or non-retryable (e.g. a fatal -network error). In the event of a failure call L to find out -the reason which indicates whether the call is retryable or not. +SSL_write_ex() and SSL_write_ex2() return 1 for success or 0 for failure. +Success means that all requested application data bytes have been written to the +SSL connection or, if SSL_MODE_ENABLE_PARTIAL_WRITE is in use, at least 1 +application data byte has been written to the SSL connection. Failure means that +not all the requested bytes have been written yet (if +SSL_MODE_ENABLE_PARTIAL_WRITE is not in use) or no bytes could be written to the +SSL connection (if SSL_MODE_ENABLE_PARTIAL_WRITE is in use). Failures can be +retryable (e.g. the network write buffer has temporarily filled up) or +non-retryable (e.g. a fatal network error). In the event of a failure call +L to find out the reason which indicates whether the call is +retryable or not. For SSL_write() the following return values can occur: @@ -143,10 +195,11 @@ L, L The SSL_write_ex() function was added in OpenSSL 1.1.1. The SSL_sendfile() function was added in OpenSSL 3.0. +The SSL_write_ex2() function was added in OpenSSL 3.3. =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/TS_VERIFY_CTX_set_certs.pod b/doc/man3/TS_VERIFY_CTX_set_certs.pod deleted file mode 100644 index 5a35302c4100..000000000000 --- a/doc/man3/TS_VERIFY_CTX_set_certs.pod +++ /dev/null @@ -1,61 +0,0 @@ -=pod - -=head1 NAME - -TS_VERIFY_CTX_set_certs, TS_VERIFY_CTS_set_certs -- set certificates for TS response verification - -=head1 SYNOPSIS - - #include - - STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx, - STACK_OF(X509) *certs); - STACK_OF(X509) *TS_VERIFY_CTS_set_certs(TS_VERIFY_CTX *ctx, - STACK_OF(X509) *certs); - -=head1 DESCRIPTION - -The Time-Stamp Protocol (TSP) is defined by RFC 3161. TSP is a protocol used to -provide long term proof of the existence of a certain datum before a particular -time. TSP defines a Time Stamping Authority (TSA) and an entity who shall make -requests to the TSA. Usually the TSA is denoted as the server side and the -requesting entity is denoted as the client. - -In TSP, when a server is sending a response to a client, the server normally -needs to sign the response data - the TimeStampToken (TST) - with its private -key. Then the client shall verify the received TST by the server's certificate -chain. - -TS_VERIFY_CTX_set_certs() is used to set the server's certificate chain when -verifying a TST. B is the verification context created in advance and -B is a stack of B certificates. - -TS_VERIFY_CTS_set_certs() is a misspelled version of TS_VERIFY_CTX_set_certs() -which takes the same parameters and returns the same result. - -=head1 RETURN VALUES - -TS_VERIFY_CTX_set_certs() returns the stack of B certificates the user -passes in via parameter B. - -=head1 SEE ALSO - -L - -=head1 HISTORY - -The spelling of TS_VERIFY_CTX_set_certs() was corrected in OpenSSL 3.0.0. -The misspelled version TS_VERIFY_CTS_set_certs() has been retained for -compatibility reasons, but it is deprecated in OpenSSL 3.0.0. - -=head1 COPYRIGHT - -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/doc/man3/X509V3_get_d2i.pod b/doc/man3/X509V3_get_d2i.pod index 88294ff710f2..330464e0c8da 100644 --- a/doc/man3/X509V3_get_d2i.pod +++ b/doc/man3/X509V3_get_d2i.pod @@ -4,9 +4,10 @@ X509V3_get_d2i, X509V3_add1_i2d, X509V3_EXT_d2i, X509V3_EXT_i2d, X509_get_ext_d2i, X509_add1_ext_i2d, +X509_ACERT_get_ext_d2i, X509_ACERT_add1_ext_i2d, X509_CRL_get_ext_d2i, X509_CRL_add1_ext_i2d, X509_REVOKED_get_ext_d2i, X509_REVOKED_add1_ext_i2d, -X509_get0_extensions, X509_CRL_get0_extensions, +X509_get0_extensions, X509_ACERT_get0_extensions, X509_CRL_get0_extensions, X509_REVOKED_get0_extensions - X509 extension decode and encode functions =head1 SYNOPSIS @@ -25,6 +26,10 @@ X509_REVOKED_get0_extensions - X509 extension decode and encode functions int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags); + void *X509_ACERT_get_ext_d2i(const X509_ACERT *x, int nid, int *crit, int *idx); + int X509_ACERT_add1_ext_i2d(X509_ACERT *x, int nid, void *value, int crit, + unsigned long flags); + void *X509_CRL_get_ext_d2i(const X509_CRL *crl, int nid, int *crit, int *idx); int X509_CRL_add1_ext_i2d(X509_CRL *crl, int nid, void *value, int crit, unsigned long flags); @@ -34,6 +39,7 @@ X509_REVOKED_get0_extensions - X509 extension decode and encode functions unsigned long flags); const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); + const STACK_OF(X509_EXTENSION) *X509_ACERT_get0_extensions(const X509 *x); const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *r); @@ -64,6 +70,10 @@ X509_get_ext_d2i() and X509_add1_ext_i2d() operate on the extensions of certificate I. They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). +X509_ACERT_get_ext_d2i() and X509_ACERT_add1_ext_i2d() operate on the extensions +of B structure I. They are otherwise identical to X509V3_get_d2i() +and X509V3_add1_i2d(). + X509_CRL_get_ext_d2i() and X509_CRL_add1_ext_i2d() operate on the extensions of CRL I. They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). @@ -72,9 +82,10 @@ X509_REVOKED_get_ext_d2i() and X509_REVOKED_add1_ext_i2d() operate on the extensions of B structure I (i.e for CRL entry extensions). They are otherwise identical to X509V3_get_d2i() and X509V3_add1_i2d(). -X509_get0_extensions(), X509_CRL_get0_extensions() and -X509_REVOKED_get0_extensions() return a STACK of all the extensions -of a certificate, a CRL or a CRL entry respectively. +X509_get0_extensions(), X509_ACERT_get0_extensions(), +X509_CRL_get0_extensions() and X509_REVOKED_get0_extensions() return a +STACK of all the extensions of a certificate, an attribute certificate, +a CRL or a CRL entry respectively. =head1 NOTES @@ -235,6 +246,11 @@ L, L, L +=head1 HISTORY + +X509_ACERT_get_ext_d2i(), X509_ACERT_add1_ext_i2d(), +X509_ACERT_get0_extensions() were added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/X509V3_set_ctx.pod b/doc/man3/X509V3_set_ctx.pod index 7819c344f751..6f9af309f4e2 100644 --- a/doc/man3/X509V3_set_ctx.pod +++ b/doc/man3/X509V3_set_ctx.pod @@ -16,29 +16,32 @@ X509V3_set_issuer_pkey - X.509 v3 extension generation utilities =head1 DESCRIPTION X509V3_set_ctx() fills in the basic fields of I of type B, -providing details potentially needed by functions producing X509 v3 extensions, -e.g., to look up values for filling in authority key identifiers. -Any of I, I, or I may be provided, pointing to a certificate, -certification request, or certificate revocation list, respectively. +providing details potentially needed by functions producing X509 v3 extensions. +These may make use of fields of the certificate I, the certification +request I, or the certificate revocation list I. +At most one of these three parameters can be non-NULL. When constructing the subject key identifier of a certificate by computing a hash value of its public key, the public key is taken from I or I. Similarly, when constructing subject alternative names from any email addresses contained in a subject DN, the subject DN is taken from I or I. -If I or I is provided, I should point to its issuer, -for instance to help generating an authority key identifier extension. -Note that if I is provided, I may be the same as I, -which means that I is self-issued (or even self-signed). +If I or I is provided, I should point to its issuer, for +instance as a reference for generating the authority key identifier extension. +I may be the same pointer value as I (which usually is an +indication that the I certificate is self-issued or even self-signed). +In this case the fallback source for generating the authority key identifier +extension will be taken from any value provided using X509V3_set_issuer_pkey(). I may be 0 or contain B, which means that just the syntax of -extension definitions is to be checked without actually producing an extension, +extension definitions is to be checked without actually producing any extension, or B, which means that each X.509v3 extension added as defined in some configuration section shall replace any already existing extension with the same OID. X509V3_set_issuer_pkey() explicitly sets the issuer private key of -the certificate that has been provided in I. -This should be done for self-issued certificates (which may be self-signed -or not) to provide fallback data for the authority key identifier extension. +the subject certificate that has been provided in I. +This should be done in case the I and I arguments to +X509V3_set_ctx() have the same pointer value +to provide fallback data for the authority key identifier extension. =head1 RETURN VALUES diff --git a/doc/man3/X509_ALGOR_dup.pod b/doc/man3/X509_ALGOR_dup.pod index 7696fc61cc8f..6133735ea595 100644 --- a/doc/man3/X509_ALGOR_dup.pod +++ b/doc/man3/X509_ALGOR_dup.pod @@ -2,7 +2,10 @@ =head1 NAME -X509_ALGOR_dup, X509_ALGOR_set0, X509_ALGOR_get0, X509_ALGOR_set_md, X509_ALGOR_cmp, X509_ALGOR_copy - AlgorithmIdentifier functions +X509_ALGOR_dup, +X509_ALGOR_set0, X509_ALGOR_get0, +X509_ALGOR_set_md, X509_ALGOR_cmp, +X509_ALGOR_copy - AlgorithmIdentifier functions =head1 SYNOPSIS @@ -18,23 +21,24 @@ X509_ALGOR_dup, X509_ALGOR_set0, X509_ALGOR_get0, X509_ALGOR_set_md, X509_ALGOR_ =head1 DESCRIPTION -X509_ALGOR_dup() returns a copy of B. +X509_ALGOR_dup() returns a copy of I. -X509_ALGOR_set0() sets the algorithm OID of B to B and the -associated parameter type to B with value B. If B is -B the parameter is omitted, otherwise B and B have -the same meaning as the B and B parameters to ASN1_TYPE_set(). +X509_ALGOR_set0() sets the algorithm OID of I to I and the +associated parameter type to I with value I. If I is +B the parameter is omitted, otherwise I and I have +the same meaning as the I and I parameters to ASN1_TYPE_set(). All the supplied parameters are used internally so must B be freed after -this call. +this call succeeded; +otherwise ownership remains with the caller and I remains untouched. X509_ALGOR_get0() is the inverse of X509_ALGOR_set0(): it returns the -algorithm OID in B<*paobj> and the associated parameter in B<*pptype> -and B<*ppval> from the B B. +algorithm OID in I<*paobj> and the associated parameter in I<*pptype> +and I<*ppval> from the B I. -X509_ALGOR_set_md() sets the B B to appropriate -values for the message digest B. +X509_ALGOR_set_md() sets the B I to appropriate +values for the message digest I. -X509_ALGOR_cmp() compares B and B and returns 0 if they have identical +X509_ALGOR_cmp() compares I and I and returns 0 if they have identical encodings and nonzero otherwise. X509_ALGOR_copy() copies the source values into the dest structs; making @@ -58,7 +62,7 @@ The X509_ALGOR_copy() was added in 1.1.1e. =head1 COPYRIGHT -Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_CRL_get0_by_serial.pod b/doc/man3/X509_CRL_get0_by_serial.pod index 67e4f4c3f802..e0061563bc7a 100644 --- a/doc/man3/X509_CRL_get0_by_serial.pod +++ b/doc/man3/X509_CRL_get0_by_serial.pod @@ -105,7 +105,7 @@ L =head1 COPYRIGHT -Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_LOOKUP.pod b/doc/man3/X509_LOOKUP.pod index 8f0240de2d13..de4eca7fdad7 100644 --- a/doc/man3/X509_LOOKUP.pod +++ b/doc/man3/X509_LOOKUP.pod @@ -92,7 +92,8 @@ associates and retrieves a pointer to application data to and from the given B, respectively. X509_LOOKUP_ctrl_ex() is used to set or get additional data to or from -a B structure or its associated L. +a B structure using any control function in the +associated L. The arguments of the control command are passed via I and I, its return value via I<*ret>. The library context I and property query I are used when fetching algorithms from providers. @@ -196,21 +197,29 @@ or NULL on error. X509_LOOKUP_init() and X509_LOOKUP_shutdown() return 1 on success, or 0 on error. -X509_LOOKUP_ctrl() returns -1 if the B doesn't have an +X509_LOOKUP_ctrl_ex() and X509_LOOKUP_ctrl() +return -1 if the B doesn't have an associated B, or 1 if the X<509_LOOKUP_METHOD> doesn't have a control function. Otherwise, it returns what the control function in the -B returns, which is usually 1 on success and 0 in -error. +B returns, which is usually 1 on success and 0 on error +but could also be -1 on failure. X509_LOOKUP_get_store() returns a B pointer if there is one, otherwise NULL. -X509_LOOKUP_by_subject_ex(), X509_LOOKUP_by_subject(), +X509_LOOKUP_by_subject_ex() returns 0 if there is no B +that implements any of the get_by_subject_ex() or get_by_subject() functions. +It calls get_by_subject_ex() if present, otherwise get_by_subject(), and returns +the result of the function, which is usually 1 on success and 0 on error. + +X509_LOOKUP_by_subject() is similar to X509_LOOKUP_by_subject_ex() +but passes NULL for both the libctx and propq. + X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() all return 0 if there is no B or that method doesn't implement the corresponding function. -Otherwise, it returns what the corresponding function in the +Otherwise, they return what the corresponding function in the B returns, which is usually 1 on success and 0 in error. diff --git a/doc/man3/X509_LOOKUP_meth_new.pod b/doc/man3/X509_LOOKUP_meth_new.pod index ef2c3cdd500a..19faae2e5fe2 100644 --- a/doc/man3/X509_LOOKUP_meth_new.pod +++ b/doc/man3/X509_LOOKUP_meth_new.pod @@ -150,7 +150,7 @@ object. Implementations must add objects they find to the B object using X509_STORE_add_cert() or X509_STORE_add_crl(). This increments -its reference count. However, the X509_STORE_CTX_get_by_subject() +its reference count. However, the L function also increases the reference count which leads to one too many references being held. Therefore, applications should additionally call X509_free() or X509_CRL_free() to decrement the @@ -179,6 +179,7 @@ pointers. =head1 SEE ALSO +L, L, L =head1 HISTORY diff --git a/doc/man3/X509_PUBKEY_new.pod b/doc/man3/X509_PUBKEY_new.pod index 3d22857b80b7..45f9c010c1ab 100644 --- a/doc/man3/X509_PUBKEY_new.pod +++ b/doc/man3/X509_PUBKEY_new.pod @@ -4,8 +4,9 @@ X509_PUBKEY_new_ex, X509_PUBKEY_new, X509_PUBKEY_free, X509_PUBKEY_dup, X509_PUBKEY_set, X509_PUBKEY_get0, X509_PUBKEY_get, -d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp, -i2d_PUBKEY_fp, i2d_PUBKEY_bio, X509_PUBKEY_set0_param, X509_PUBKEY_get0_param, +d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_ex_bio, d2i_PUBKEY_bio, +d2i_PUBKEY_ex_fp, d2i_PUBKEY_fp, i2d_PUBKEY_fp, i2d_PUBKEY_bio, +X509_PUBKEY_set0_public_key, X509_PUBKEY_set0_param, X509_PUBKEY_get0_param, X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions =head1 SYNOPSIS @@ -26,12 +27,19 @@ X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length); int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp); + EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, + const char *propq); EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); + + EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx, + const char *propq); EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); int i2d_PUBKEY_fp(const FILE *fp, EVP_PKEY *pkey); int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey); + void X509_PUBKEY_set0_public_key(X509_PUBKEY *pub, + unsigned char *penc, int penclen); int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, int ptype, void *pval, unsigned char *penc, int penclen); @@ -85,13 +93,23 @@ d2i_PUBKEY_bio(), d2i_PUBKEY_fp(), i2d_PUBKEY_bio() and i2d_PUBKEY_fp() are similar to d2i_PUBKEY() and i2d_PUBKEY() except they decode or encode using a B or B pointer. -X509_PUBKEY_set0_param() sets the public key parameters of I. The -OID associated with the algorithm is set to I. The type of the +d2i_PUBKEY_ex_bio() and d2i_PUBKEY_ex_fp() are similar to d2i_PUBKEY_ex() except +they decode using a B or B pointer. + +X509_PUBKEY_set0_public_key() sets the public-key encoding of I +to the I bytes contained in buffer I. +Any earlier public-key encoding in I is freed. +I may be NULL to indicate that there is no actual public key data. +Ownership of the I argument is passed to I. + +X509_PUBKEY_set0_param() sets the public-key parameters of I. +The OID associated with the algorithm is set to I. The type of the algorithm parameters is set to I using the structure I. -The encoding of the public key itself is set to the I -bytes contained in buffer I. On success ownership of all the supplied -parameters is passed to I so they must not be freed after the -call. +If I is not NULL the encoding of the public key itself is set +to the I bytes contained in buffer I and +any earlier public-key encoding in I is freed. +On success ownership of all the supplied arguments is passed to I +so they must not be freed after the call. X509_PUBKEY_get0_param() retrieves the public key parameters from I, I<*ppkalg> is set to the associated OID and the encoding consists of @@ -119,8 +137,17 @@ Otherwise they return a pointer to the newly allocated structure. X509_PUBKEY_free() does not return a value. -X509_PUBKEY_get0() and X509_PUBKEY_get() return a pointer to an B -structure or NULL if an error occurs. +X509_PUBKEY_get0(), X509_PUBKEY_get(), d2i_PUBKEY_ex(), d2i_PUBKEY(), +d2i_PUBKEY_ex_bio(), d2i_PUBKEY_bio(), d2i_PUBKEY_ex_fp() and d2i_PUBKEY_fp() +return a pointer to an B structure or NULL if an error occurs. + +i2d_PUBKEY() returns the number of bytes successfully encoded or a +negative value if an error occurs. + +i2d_PUBKEY_fp() and i2d_PUBKEY_bio() return 1 if successfully +encoded or 0 if an error occurs. + +X509_PUBKEY_set0_public_key() does not return a value. X509_PUBKEY_set(), X509_PUBKEY_set0_param() and X509_PUBKEY_get0_param() return 1 for success and 0 if an error occurred. @@ -138,9 +165,12 @@ L, The X509_PUBKEY_new_ex() and X509_PUBKEY_eq() functions were added in OpenSSL 3.0. +The X509_PUBKEY_set0_public_key(), d2i_PUBKEY_ex_bio() and d2i_PUBKEY_ex_fp() +functions were added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_REQ_get_extensions.pod b/doc/man3/X509_REQ_get_extensions.pod index 00ab1e3cfb41..26e2438e4f88 100644 --- a/doc/man3/X509_REQ_get_extensions.pod +++ b/doc/man3/X509_REQ_get_extensions.pod @@ -10,7 +10,7 @@ X509_REQ_add_extensions, X509_REQ_add_extensions_nid #include - STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); + STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(const X509_REQ *req); int X509_REQ_add_extensions(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts); int X509_REQ_add_extensions_nid(X509_REQ *req, const STACK_OF(X509_EXTENSION) *exts, int nid); @@ -22,13 +22,15 @@ found in the attributes of I. The returned list is empty if there are no such extensions in I. The caller is responsible for freeing the list obtained. -X509_REQ_add_extensions() adds to I a list of X.509 extensions I, -which must not be NULL, using the default B. -This function must not be called more than once on the same I. +X509_REQ_add_extensions_nid() adds to I a list of X.509 extensions I, +using I to identify the extensions attribute. +I is unchanged if I is NULL or an empty list. +This function may be called more than once on the same I and I. +In such case any previous extensions are augmented, where an extension to be +added that has the same OID as a pre-existing one replaces this earlier one. -X509_REQ_add_extensions_nid() is like X509_REQ_add_extensions() -except that I is used to identify the extensions attribute. -This function must not be called more than once with the same I and I. +X509_REQ_add_extensions() is like X509_REQ_add_extensions_nid() +except that the default B is used. =head1 RETURN VALUES diff --git a/doc/man3/X509_STORE_CTX_get_error.pod b/doc/man3/X509_STORE_CTX_get_error.pod index c992d5da27de..f1f5ce1eb750 100644 --- a/doc/man3/X509_STORE_CTX_get_error.pod +++ b/doc/man3/X509_STORE_CTX_get_error.pod @@ -31,19 +31,20 @@ These functions are typically called after certificate or chain verification using L or L 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. +X509_STORE_CTX_get_error() returns the error code of I. I B be NULL. See the L 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 to I. For example it might be used in a verification callback to set an error based on additional -checks. +checks. I B be NULL. X509_STORE_CTX_get_error_depth() returns the I 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. +I B be NULL. X509_STORE_CTX_set_error_depth() sets the error I. This can be used in combination with X509_STORE_CTX_set_error() to set the @@ -67,14 +68,15 @@ Once such a I certificate is no longer needed it can be freed with L. X509_STORE_CTX_get0_cert() retrieves an internal pointer to the -certificate being verified by the I. +certificate being verified by the I. It may be NULL if a raw public +key is being verified. 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 structure is freed. When it is no longer needed it should be free up using: - sk_X509_pop_free(chain, X509_free); + OSSL_STACK_OF_X509_free(chain); X509_verify_cert_error_string() returns a human readable error string for verification error I. @@ -460,6 +462,11 @@ The algorithm given in the certificate info is inconsistent A CA certificate is invalid. Either it is not a CA or its extensions are not consistent with the supplied purpose. +=item B + +No TLS records were configured to validate the raw public key, or DANE was not +enabled on the connection. + =back =head1 NOTES diff --git a/doc/man3/X509_STORE_CTX_new.pod b/doc/man3/X509_STORE_CTX_new.pod index 9929a98e0cf5..c219cee9d621 100644 --- a/doc/man3/X509_STORE_CTX_new.pod +++ b/doc/man3/X509_STORE_CTX_new.pod @@ -3,12 +3,16 @@ =head1 NAME X509_STORE_CTX_new_ex, X509_STORE_CTX_new, X509_STORE_CTX_cleanup, -X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack, +X509_STORE_CTX_free, X509_STORE_CTX_init, +X509_STORE_CTX_init_rpk, +X509_STORE_CTX_set0_trusted_stack, X509_STORE_CTX_set_cert, X509_STORE_CTX_set0_crls, +X509_STORE_CTX_set0_rpk, X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param, X509_STORE_CTX_get0_untrusted, X509_STORE_CTX_set0_untrusted, X509_STORE_CTX_get_num_untrusted, X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain, +X509_STORE_CTX_get0_rpk, X509_STORE_CTX_set_default, X509_STORE_CTX_set_verify, X509_STORE_CTX_verify_fn, @@ -28,11 +32,14 @@ X509_STORE_CTX_purpose_inherit int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *trust_store, X509 *target, STACK_OF(X509) *untrusted); + int X509_STORE_CTX_init_rpk(X509_STORE_CTX *ctx, X509_STORE *trust_store, + EVP_PKEY *rpk); void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *target); void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk); + void X509_STORE_CTX_set0_rpk(X509_STORE_CTX *ctx, EVP_PKEY *target); X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); @@ -43,6 +50,7 @@ X509_STORE_CTX_purpose_inherit int X509_STORE_CTX_get_num_untrusted(const X509_STORE_CTX *ctx); STACK_OF(X509) *X509_STORE_CTX_get0_chain(const X509_STORE_CTX *ctx); void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain); + EVP_PKEY *X509_STORE_CTX_get0_rpk(const X509_STORE_CTX *ctx); int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); @@ -90,6 +98,8 @@ they are provided simply as a list using X509_STORE_CTX_set0_trusted_stack(). The certificate to be verified is set to I, and a list of additional certificates may be provided in I, which will be untrusted but may be used to build the chain. +The I certificate is not copied (its reference count is not updated), +and the caller must not free it before verification is complete. Each of the I, I and I parameters can be NULL. Yet note that L and L will need a verification target. @@ -98,6 +108,14 @@ For L, which takes by default the first element of the list of untrusted certificates as its verification target, this can be also set indirectly using X509_STORE_CTX_set0_untrusted(). +X509_STORE_CTX_init_rpk() sets up I for a subsequent verification +operation for the I raw public key. +It behaves similarly to X509_STORE_CTX_init(). +The I raw public key can also be supplied separately, via +X509_STORE_CTX_set0_rpk(). +The I public key is not copied (its reference count is not updated), +and the caller must not free it before verification is complete. + X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of I to I. This is an alternative way of specifying trusted certificates instead of using an B where its complexity is not needed @@ -105,6 +123,14 @@ or to make sure that only the given set I of certificates are trusted. X509_STORE_CTX_set_cert() sets the target certificate to be verified in I to I. +The target certificate is not copied (its reference count is not updated), +and the caller must not free it before verification is complete. + +X509_STORE_CTX_set0_rpk() sets the target raw public key to be verified in I +to I, a non-NULL raw public key preempts any target certificate, which +is then ignored. +The I public key is not copied (its reference count is not updated), +and the caller must not free it before verification is complete. X509_STORE_CTX_set0_verified_chain() sets the validated chain to I. Ownership of the chain is transferred to I, @@ -113,6 +139,9 @@ and so it should not be free'd by the caller. X509_STORE_CTX_get0_chain() returns the internal pointer used by the I that contains the constructed (output) chain. +X509_STORE_CTX_get0_rpk() returns the internal pointer used by the +I that contains the raw public key. + X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate verification to I. These CRLs will only be used if CRL verification is enabled in the associated B structure. This might be @@ -193,14 +222,18 @@ verified in the I. Built-in available values for the I argument are B, B, B, B, B, B, B, -B and B. It is also -possible to create a custom purpose value. Setting a purpose will ensure that -the key usage declared within certificates in the chain being verified is -consistent with that purpose as well as, potentially, other checks. Every -purpose also has an associated default trust value which will also be set at the -same time. During verification this trust setting will be verified to check it -is consistent with the trust set by the system administrator for certificates in -the chain. +B, B and +B. It is also +possible to create a custom purpose value. Setting a purpose requests that +the key usage and extended key usage (EKU) extensions optionally declared within +the certificate and its chain are verified to be consistent with that purpose. +For SSL client, SSL server, and S/MIME purposes, the EKU is checked also for the +CA certificates along the chain, including any given trust anchor certificate. +Potentially also further checks are done (depending on the purpose given). +Every purpose also has an associated default trust value, which will also be set +at the same time. During verification, this trust setting will be verified +to check whether it is consistent with the trust set by the system administrator +for certificates in the chain. X509_STORE_CTX_set_trust() sets the trust value for the target certificate being verified in the I. Built-in available values for the I @@ -249,11 +282,15 @@ should be made or reference counts increased instead. X509_STORE_CTX_new() returns a newly allocated context or NULL if an error occurred. -X509_STORE_CTX_init() returns 1 for success or 0 if an error occurred. +X509_STORE_CTX_init() and X509_STORE_CTX_init_rpk() return 1 for success +or 0 if an error occurred. X509_STORE_CTX_get0_param() returns a pointer to an B structure or NULL if an error occurred. +X509_STORE_CTX_get0_rpk() returns a pointer to an B structure if +present, or NULL if absent. + X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(), X509_STORE_CTX_set0_trusted_stack(), X509_STORE_CTX_set_cert(), @@ -275,12 +312,14 @@ L The X509_STORE_CTX_set0_crls() function was added in OpenSSL 1.0.0. The X509_STORE_CTX_get_num_untrusted() function was added in OpenSSL 1.1.0. The X509_STORE_CTX_new_ex() function was added in OpenSSL 3.0. +The X509_STORE_CTX_init_rpk(), X509_STORE_CTX_get0_rpk(), and +X509_STORE_CTX_set0_rpk() functions were added in OpenSSL 3.2. There is no need to call X509_STORE_CTX_cleanup() explicitly since OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2009-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_STORE_CTX_set_verify_cb.pod b/doc/man3/X509_STORE_CTX_set_verify_cb.pod index fefe6a25a0fe..845ff8e91b86 100644 --- a/doc/man3/X509_STORE_CTX_set_verify_cb.pod +++ b/doc/man3/X509_STORE_CTX_set_verify_cb.pod @@ -9,13 +9,15 @@ X509_STORE_CTX_get_check_policy, X509_STORE_CTX_get_cert_crl, X509_STORE_CTX_get_check_crl, X509_STORE_CTX_get_get_crl, +X509_STORE_CTX_set_get_crl, X509_STORE_CTX_get_check_revocation, X509_STORE_CTX_get_check_issued, X509_STORE_CTX_get_get_issuer, X509_STORE_CTX_get_verify_cb, X509_STORE_CTX_set_verify_cb, X509_STORE_CTX_verify_cb, -X509_STORE_CTX_print_verify_cb +X509_STORE_CTX_print_verify_cb, +X509_STORE_CTX_set_current_reasons - get and set X509_STORE_CTX components such as verification callback =head1 SYNOPSIS @@ -33,13 +35,20 @@ X509_STORE_CTX_print_verify_cb X509_STORE_CTX_get_issuer_fn X509_STORE_CTX_get_get_issuer(X509_STORE_CTX *ctx); X509_STORE_CTX_check_issued_fn X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx); X509_STORE_CTX_check_revocation_fn X509_STORE_CTX_get_check_revocation(X509_STORE_CTX *ctx); + X509_STORE_CTX_get_crl_fn X509_STORE_CTX_get_get_crl(X509_STORE_CTX *ctx); + + void X509_STORE_CTX_set_get_crl(X509_STORE_CTX *ctx, + X509_STORE_CTX_get_crl_fn get_crl); + X509_STORE_CTX_check_crl_fn X509_STORE_CTX_get_check_crl(X509_STORE_CTX *ctx); X509_STORE_CTX_cert_crl_fn X509_STORE_CTX_get_cert_crl(X509_STORE_CTX *ctx); X509_STORE_CTX_check_policy_fn X509_STORE_CTX_get_check_policy(X509_STORE_CTX *ctx); X509_STORE_CTX_lookup_certs_fn X509_STORE_CTX_get_lookup_certs(X509_STORE_CTX *ctx); X509_STORE_CTX_lookup_crls_fn X509_STORE_CTX_get_lookup_crls(X509_STORE_CTX *ctx); X509_STORE_CTX_cleanup_fn X509_STORE_CTX_get_cleanup(X509_STORE_CTX *ctx); + void X509_STORE_CTX_set_current_reasons(X509_STORE_CTX *ctx, + unsigned int current_reasons); =head1 DESCRIPTION @@ -83,6 +92,17 @@ and X509_STORE_CTX_get_cleanup() return the function pointers cached from the corresponding B, please see L for more information. +X509_STORE_CTX_set_get_crl() sets the function to get the crl for a given +certificate I. +When found, the crl must be assigned to I<*crl>. +This function must return 0 on failure and 1 on success. +I + +X509_STORE_CTX_set_current_reasons() is used in conjunction with +X509_STORE_CTX_get_crl_fn. The X509_STORE_CTX_get_crl_fn callback must +use this method to set the reason why the certificate is invalid. + =head1 WARNINGS @@ -212,7 +232,7 @@ X509_STORE_CTX_print_verify_cb() was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved. +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 diff --git a/doc/man3/X509_STORE_add_cert.pod b/doc/man3/X509_STORE_add_cert.pod index dc76704207eb..7b57e04721b5 100644 --- a/doc/man3/X509_STORE_add_cert.pod +++ b/doc/man3/X509_STORE_add_cert.pod @@ -18,30 +18,30 @@ X509_STORE_load_locations_ex, X509_STORE_load_locations typedef x509_store_st X509_STORE; - int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); - int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + int X509_STORE_add_cert(X509_STORE *xs, X509 *x); + int X509_STORE_add_crl(X509_STORE *xs, X509_CRL *x); int X509_STORE_set_depth(X509_STORE *store, int depth); - int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); - int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); - int X509_STORE_set_trust(X509_STORE *ctx, int trust); + int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags); + int X509_STORE_set_purpose(X509_STORE *xs, int purpose); + int X509_STORE_set_trust(X509_STORE *xs, int trust); X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *store, X509_LOOKUP_METHOD *meth); - int X509_STORE_set_default_paths_ex(X509_STORE *ctx, OSSL_LIB_CTX *libctx, + int X509_STORE_set_default_paths_ex(X509_STORE *xs, OSSL_LIB_CTX *libctx, const char *propq); - int X509_STORE_set_default_paths(X509_STORE *ctx); - int X509_STORE_load_file_ex(X509_STORE *ctx, const char *file, + int X509_STORE_set_default_paths(X509_STORE *xs); + int X509_STORE_load_file_ex(X509_STORE *xs, const char *file, OSSL_LIB_CTX *libctx, const char *propq); - int X509_STORE_load_file(X509_STORE *ctx, const char *file); - int X509_STORE_load_path(X509_STORE *ctx, const char *dir); - int X509_STORE_load_store_ex(X509_STORE *ctx, const char *uri, + int X509_STORE_load_file(X509_STORE *xs, const char *file); + int X509_STORE_load_path(X509_STORE *xs, const char *dir); + int X509_STORE_load_store_ex(X509_STORE *xs, const char *uri, OSSL_LIB_CTX *libctx, const char *propq); - int X509_STORE_load_store(X509_STORE *ctx, const char *uri); - int X509_STORE_load_locations_ex(X509_STORE *ctx, const char *file, + int X509_STORE_load_store(X509_STORE *xs, const char *uri); + int X509_STORE_load_locations_ex(X509_STORE *xs, const char *file, const char *dir, OSSL_LIB_CTX *libctx, const char *propq); - int X509_STORE_load_locations(X509_STORE *ctx, + int X509_STORE_load_locations(X509_STORE *xs, const char *file, const char *dir); =head1 DESCRIPTION @@ -88,7 +88,7 @@ X509_STORE_set_depth(), X509_STORE_set_flags(), X509_STORE_set_purpose(), X509_STORE_set_trust(), and X509_STORE_set1_param() set the default values for the corresponding values used in certificate chain validation. Their behavior is documented in the corresponding B manual -pages, e.g., L. +pages, e.g., L. The B B be NULL. X509_STORE_add_lookup() finds or creates a L with the L I and adds it to the B @@ -162,7 +162,7 @@ X509_STORE_load_locations_ex() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_STORE_get0_param.pod b/doc/man3/X509_STORE_get0_param.pod index d9413fd49e15..95a1725bc388 100644 --- a/doc/man3/X509_STORE_get0_param.pod +++ b/doc/man3/X509_STORE_get0_param.pod @@ -3,30 +3,36 @@ =head1 NAME X509_STORE_get0_param, X509_STORE_set1_param, -X509_STORE_get0_objects, X509_STORE_get1_all_certs +X509_STORE_get1_objects, X509_STORE_get0_objects, X509_STORE_get1_all_certs - X509_STORE setter and getter functions =head1 SYNOPSIS #include - X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *ctx); - int X509_STORE_set1_param(X509_STORE *ctx, const X509_VERIFY_PARAM *pm); - STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *ctx); - STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *st); + X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *xs); + int X509_STORE_set1_param(X509_STORE *xs, const X509_VERIFY_PARAM *pm); + STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *xs); + STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *xs); + STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *xs); =head1 DESCRIPTION -X509_STORE_set1_param() sets the verification parameters -to B for B. +X509_STORE_set1_param() sets the verification parameters to I for I. X509_STORE_get0_param() retrieves an internal pointer to the verification -parameters for B. The returned pointer must not be freed by the +parameters for I. The returned pointer must not be freed by the calling application +X509_STORE_get1_objects() returns a snapshot of all objects in the store's X509 +cache. The cache contains B and B objects. The caller is +responsible for freeing the returned list. + X509_STORE_get0_objects() retrieves an internal pointer to the store's X509 object cache. The cache contains B and B objects. The -returned pointer must not be freed by the calling application. +returned pointer must not be freed by the calling application. If the store is +shared across multiple threads, it is not safe to use the result of this +function. Use X509_STORE_get1_objects() instead, which avoids this problem. X509_STORE_get1_all_certs() returns a list of all certificates in the store. The caller is responsible for freeing the returned list. @@ -38,6 +44,9 @@ B structure. X509_STORE_set1_param() returns 1 for success and 0 for failure. +X509_STORE_get1_objects() returns a pointer to a stack of the retrieved +objects on success, else NULL. + X509_STORE_get0_objects() returns a pointer to a stack of B. X509_STORE_get1_all_certs() returns a pointer to a stack of the retrieved @@ -52,10 +61,11 @@ L B and B were added in OpenSSL 1.1.0. B was added in OpenSSL 3.0. +B was added in OpenSSL 3.3. =head1 COPYRIGHT -Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_STORE_new.pod b/doc/man3/X509_STORE_new.pod index 5b3dadb243d7..9162080e0cf8 100644 --- a/doc/man3/X509_STORE_new.pod +++ b/doc/man3/X509_STORE_new.pod @@ -11,10 +11,10 @@ X509_STORE_lock,X509_STORE_unlock #include X509_STORE *X509_STORE_new(void); - void X509_STORE_free(X509_STORE *v); - int X509_STORE_lock(X509_STORE *v); - int X509_STORE_unlock(X509_STORE *v); - int X509_STORE_up_ref(X509_STORE *v); + void X509_STORE_free(X509_STORE *xs); + int X509_STORE_lock(X509_STORE *xs); + int X509_STORE_unlock(X509_STORE *xs); + int X509_STORE_up_ref(X509_STORE *xs); =head1 DESCRIPTION diff --git a/doc/man3/X509_STORE_set_verify_cb_func.pod b/doc/man3/X509_STORE_set_verify_cb_func.pod index b73341a0f70d..57fc6c9f6435 100644 --- a/doc/man3/X509_STORE_set_verify_cb_func.pod +++ b/doc/man3/X509_STORE_set_verify_cb_func.pod @@ -58,78 +58,78 @@ X509_STORE_CTX_lookup_certs_fn, X509_STORE_CTX_lookup_crls_fn const X509_NAME *nm); typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx); - void X509_STORE_set_verify_cb(X509_STORE *ctx, + void X509_STORE_set_verify_cb(X509_STORE *xs, X509_STORE_CTX_verify_cb verify_cb); X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE_CTX *ctx); - void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); + void X509_STORE_set_verify(X509_STORE *xs, X509_STORE_CTX_verify_fn verify); X509_STORE_CTX_verify_fn X509_STORE_CTX_get_verify(const X509_STORE_CTX *ctx); int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE_CTX *ctx); - void X509_STORE_set_get_issuer(X509_STORE *ctx, + void X509_STORE_set_get_issuer(X509_STORE *xs, X509_STORE_CTX_get_issuer_fn get_issuer); - void X509_STORE_set_check_issued(X509_STORE *ctx, + void X509_STORE_set_check_issued(X509_STORE *xs, X509_STORE_CTX_check_issued_fn check_issued); X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE_CTX *ctx); - void X509_STORE_set_check_revocation(X509_STORE *ctx, + void X509_STORE_set_check_revocation(X509_STORE *xs, X509_STORE_CTX_check_revocation_fn check_revocation); X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE_CTX *ctx); - void X509_STORE_set_get_crl(X509_STORE *ctx, + void X509_STORE_set_get_crl(X509_STORE *xs, X509_STORE_CTX_get_crl_fn get_crl); X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE_CTX *ctx); - void X509_STORE_set_check_crl(X509_STORE *ctx, + void X509_STORE_set_check_crl(X509_STORE *xs, X509_STORE_CTX_check_crl_fn check_crl); X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE_CTX *ctx); - void X509_STORE_set_cert_crl(X509_STORE *ctx, + void X509_STORE_set_cert_crl(X509_STORE *xs, X509_STORE_CTX_cert_crl_fn cert_crl); X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE_CTX *ctx); - void X509_STORE_set_check_policy(X509_STORE *ctx, + void X509_STORE_set_check_policy(X509_STORE *xs, X509_STORE_CTX_check_policy_fn check_policy); X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE_CTX *ctx); - void X509_STORE_set_lookup_certs(X509_STORE *ctx, + void X509_STORE_set_lookup_certs(X509_STORE *xs, X509_STORE_CTX_lookup_certs_fn lookup_certs); X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE_CTX *ctx); - void X509_STORE_set_lookup_crls(X509_STORE *ctx, + void X509_STORE_set_lookup_crls(X509_STORE *xs, X509_STORE_CTX_lookup_crls_fn lookup_crls); X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE_CTX *ctx); - void X509_STORE_set_cleanup(X509_STORE *ctx, + void X509_STORE_set_cleanup(X509_STORE *xs, X509_STORE_CTX_cleanup_fn cleanup); X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE_CTX *ctx); /* Aliases */ void X509_STORE_set_verify_cb_func(X509_STORE *st, X509_STORE_CTX_verify_cb verify_cb); - void X509_STORE_set_verify_func(X509_STORE *ctx, + void X509_STORE_set_verify_func(X509_STORE *xs, X509_STORE_CTX_verify_fn verify); - void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx, + void X509_STORE_set_lookup_crls_cb(X509_STORE *xs, X509_STORE_CTX_lookup_crls_fn lookup_crls); =head1 DESCRIPTION -X509_STORE_set_verify_cb() sets the verification callback of I to +X509_STORE_set_verify_cb() sets the verification callback of I to I overwriting the previous callback. The callback assigned with this function becomes a default for the one that can be assigned directly to the corresponding B, please see L for further information. X509_STORE_set_verify() sets the final chain verification function for -I to I. +I to I. Its purpose is to go through the chain of certificates and check that all signatures are valid and that the current time is within the limits of each certificate's first and last validity time. @@ -139,12 +139,14 @@ I X509_STORE_CTX_get1_issuer() tries to find a certificate from the I -component of I with a subject name matching the issuer name of I. -On success it assigns to I<*issuer> the first match that is currently valid, -or at least the most recently expired match if there is no currently valid one. +component of I that has a subject name matching the issuer name of I +and is accepted by the I function in I. +On success it assigns to I<*issuer> the first match that has a suitable validity +period or otherwise has the latest expiration date of all matching certificates. If the function returns 1 the caller is responsible for freeing I<*issuer>. +Note that this search does not support backtracking. -X509_STORE_set_get_issuer() sets the function I +X509_STORE_set_get_issuer() sets the function I that is used to get the "best" candidate issuer certificate of the given certificate I. When such a certificate is found, I must up-ref and assign it to I<*issuer> and then return 1. diff --git a/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod index 4627206174a5..267975778bdd 100644 --- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod +++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod @@ -4,6 +4,7 @@ X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose, +X509_VERIFY_PARAM_get_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, @@ -35,6 +36,7 @@ X509_VERIFY_PARAM_set1_ip_asc 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_get_purpose(X509_VERIFY_PARAM *param); 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); @@ -90,7 +92,9 @@ X509_VERIFY_PARAM_clear_flags() clears the flags B in B. X509_VERIFY_PARAM_set_purpose() sets the verification purpose in B to B. This determines the acceptable purpose of the certificate chain, for example B. -The purpose requirement is cleared if B is 0. +The purpose requirement is cleared if B is X509_PURPOSE_DEFAULT_ANY. + +X509_VERIFY_PARAM_get_purpose() returns the purpose in B. X509_VERIFY_PARAM_set_trust() sets the trust setting in B to B. @@ -223,7 +227,7 @@ 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 pointer specified above +X509_VERIFY_PARAM_get1_ip_asc(), return the string pointers specified above or NULL if the respective value has not been set or on error. X509_VERIFY_PARAM_get_flags() returns the current verification flags. @@ -240,6 +244,9 @@ X509_VERIFY_PARAM_get_depth() returns the current verification depth. X509_VERIFY_PARAM_get_auth_level() returns the current authentication security level. +X509_VERIFY_PARAM_get_purpose() returns the current purpose, +which may be B if unset. + =head1 VERIFICATION FLAGS The verification flags consists of zero or more of the following flags @@ -248,8 +255,8 @@ ored together. B enables CRL checking for the certificate chain leaf certificate. An error occurs if a suitable CRL cannot be found. -B enables CRL checking for the entire certificate -chain. +B expands CRL checking to the entire certificate +chain if B has also been enabled, and is otherwise ignored. B disables critical extension checking. By default any unhandled critical extensions in certificates or (if checked) CRLs result @@ -405,9 +412,11 @@ 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. +The X509_VERIFY_PARAM_get_purpose() function was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2009-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2009-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_check_private_key.pod b/doc/man3/X509_check_private_key.pod index 9c83a8ad20fb..67911cb6a4ba 100644 --- a/doc/man3/X509_check_private_key.pod +++ b/doc/man3/X509_check_private_key.pod @@ -10,17 +10,17 @@ request #include - int X509_check_private_key(X509 *x, EVP_PKEY *k); + int X509_check_private_key(const X509 *cert, EVP_PKEY *pkey); - int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k); + int X509_REQ_check_private_key(X509_REQ *req, EVP_PKEY *pkey); =head1 DESCRIPTION X509_check_private_key() function checks the consistency of private -key B with the public key in B. +key I with the public key in I. X509_REQ_check_private_key() is equivalent to X509_check_private_key() -except that B represents a certificate request of structure B. +except that I represents a certificate request of structure B. =head1 RETURN VALUES @@ -32,11 +32,11 @@ obtained using L. =head1 BUGS -The B functions don't check if B itself is indeed -a private key or not. It merely compares the public materials (e.g. exponent -and modulus of an RSA key) and/or key parameters (e.g. EC params of an EC key) -of a key pair. So if you pass a public key to these functions in B, it will -return success. +The X509_check_private_key() and X509_REQ_check_private_key() functions +do not check if I itself is indeed a private key or not. +They merely compare the public materials (e.g., exponent and modulus of an RSA +key) and/or key parameters (e.g. EC params of an EC key) of a key pair. +So they also return success if I is a matching public key. =head1 SEE ALSO diff --git a/doc/man3/X509_check_purpose.pod b/doc/man3/X509_check_purpose.pod index a3cfb78d6198..4e152be8fa5d 100644 --- a/doc/man3/X509_check_purpose.pod +++ b/doc/man3/X509_check_purpose.pod @@ -2,7 +2,19 @@ =head1 NAME -X509_check_purpose - Check the purpose of a certificate +X509_check_purpose, +X509_PURPOSE_get_count, +X509_PURPOSE_get_unused_id, +X509_PURPOSE_get_by_sname, +X509_PURPOSE_get_by_id, +X509_PURPOSE_add, +X509_PURPOSE_cleanup, +X509_PURPOSE_get0, +X509_PURPOSE_get_id, +X509_PURPOSE_get0_name, +X509_PURPOSE_get0_sname, +X509_PURPOSE_get_trust, +X509_PURPOSE_set - functions related to checking the purpose of a certificate =head1 SYNOPSIS @@ -10,9 +22,25 @@ X509_check_purpose - Check the purpose of a certificate int X509_check_purpose(X509 *x, int id, int ca); + int X509_PURPOSE_get_count(void); + int X509_PURPOSE_get_unused_id(OSSL_LIB_CTX *libctx); + int X509_PURPOSE_get_by_sname(const char *sname); + int X509_PURPOSE_get_by_id(int id); + int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck) (const X509_PURPOSE *, const X509 *, int), + const char *name, const char *sname, void *arg); + void X509_PURPOSE_cleanup(void); + + X509_PURPOSE *X509_PURPOSE_get0(int idx); + int X509_PURPOSE_get_id(const X509_PURPOSE *); + char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp); + char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); + int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); + int X509_PURPOSE_set(int *p, int purpose); + =head1 DESCRIPTION -This function checks if certificate I was created with the purpose +X509_check_purpose() checks if certificate I was created with the purpose represented by I. If I is nonzero, then certificate I is checked to determine if it's a possible CA with various levels of certainty possibly returned. The certificate I must be a complete certificate @@ -29,12 +57,51 @@ Below are the potential ID's that can be checked: # define X509_PURPOSE_ANY 7 # define X509_PURPOSE_OCSP_HELPER 8 # define X509_PURPOSE_TIMESTAMP_SIGN 9 + # define X509_PURPOSE_CODE_SIGN 10 The checks performed take into account the X.509 extensions keyUsage, extendedKeyUsage, and basicConstraints. +X509_PURPOSE_get_count() returns the number of currently defined purposes. + +X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used, +which is guaranteed to be unique and larger than B. +The I parameter should be used to provide the library context. +It is currently ignored as the purpose mapping table is global. + +X509_PURPOSE_get_by_sname() returns the index of +the purpose with the given short name or -1 if not found. + +X509_PURPOSE_get_by_id() returns the index of +the purpose with the given id or -1 if not found. + +X509_PURPOSE_add() adds or modifies a purpose entry identified by I. +Unless the id stays the same for an existing entry, I must be fresh, +which can be achieved by using the result of X509_PURPOSE_get_unused_id(). +The function also sets in the entry the trust id I, the given I, +the purpose (long) name I, the short name I, the purpose checking +funktion I of type B, +and its user data I which may be retrieved via the B pointer. + +X509_PURPOSE_cleanup() removes all purposes that are not pre-defined. + +X509_PURPOSE_get0() returns an B pointer or NULL on error. + +X509_PURPOSE_get_id() returns the id of the given B structure. + +X509_PURPOSE_get0_name() returns the (long) name of the given B. + +X509_PURPOSE_get0_sname() returns the short name of the given B. + +X509_PURPOSE_get_trust() returns the trust id of the given B. + +X509_PURPOSE_set() assigns the given I id to the location pointed at by +I

. +This resets to the any purpose if I is B. + =head1 RETURN VALUES +X509_check_purpose() returns the following values. For non-CA checks =over 4 @@ -68,9 +135,45 @@ For CA checks the below integers could be returned with the following meanings: =back +X509_PURPOSE_get_count() returns the number of currently defined purposes. + +X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used. + +X509_PURPOSE_get_by_sname() returns the index of +the purpose with the given short name or -1 if not found. + +X509_PURPOSE_get_by_id() returns the index of +the purpose with the given id or -1 if not found. + +int X509_PURPOSE_add() returns 1 on success, 0 on error. + +X509_PURPOSE_cleanup() does not return anything. + +X509_PURPOSE_get0() returns an B pointer or NULL on error. + +X509_PURPOSE_get_id() returns the id of the given B structure. + +X509_PURPOSE_get0_name() returns the (long) name of the given B. + +X509_PURPOSE_get0_sname() returns the short name of the given B. + +X509_PURPOSE_get_trust() returns the trust id of the given B. + +X509_PURPOSE_set() returns 1 on success, 0 on error. + +=head1 BUGS + +The X509_PURPOSE implementation so far is not thread-safe. +There may be race conditions retrieving purpose information while +X509_PURPOSE_add() or X509_PURPOSE_cleanup(void) is being called. + +=head1 HISTORY + +X509_PURPOSE_get_unused_id() was added in OpensSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at L. diff --git a/doc/man3/X509_cmp.pod b/doc/man3/X509_cmp.pod index 272a9d259e70..f22333d19e23 100644 --- a/doc/man3/X509_cmp.pod +++ b/doc/man3/X509_cmp.pod @@ -29,7 +29,8 @@ I and I. The comparison is based on the B result of the hash values of two B objects and the canonical (DER) encoding values. The X509_NAME_cmp() function compares two B objects indicated by -parameters I and I. The comparison is based on the B result of the +parameters I and I, any of which may be NULL. +The comparison is based on the B result of the canonical (DER) encoding values of the two objects using L. This procedure adheres to the matching rules for Distinguished Names (DN) given in RFC 4517 section 4.2.15 and RFC 5280 section 7.1. @@ -74,7 +75,7 @@ L, L =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_cmp_time.pod b/doc/man3/X509_cmp_time.pod index 36a5109eb144..30a09f25f9fb 100644 --- a/doc/man3/X509_cmp_time.pod +++ b/doc/man3/X509_cmp_time.pod @@ -78,7 +78,7 @@ X509_cmp_timeframe() was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_digest.pod b/doc/man3/X509_digest.pod index 29cce96370c6..7ef7f7ec63e2 100644 --- a/doc/man3/X509_digest.pod +++ b/doc/man3/X509_digest.pod @@ -81,7 +81,7 @@ The X509_digest_sig() function was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod index c8dd79ff71b7..d0b649738bc0 100644 --- a/doc/man3/X509_dup.pod +++ b/doc/man3/X509_dup.pod @@ -31,8 +31,12 @@ CMS_ContentInfo_free, CMS_ContentInfo_new, CMS_ContentInfo_new_ex, CMS_ContentInfo_print_ctx, +CMS_EnvelopedData_it, +CMS_EnvelopedData_dup, CMS_ReceiptRequest_free, CMS_ReceiptRequest_new, +CMS_SignedData_free, +CMS_SignedData_new, CRL_DIST_POINTS_free, CRL_DIST_POINTS_new, DIRECTORYSTRING_free, @@ -41,6 +45,7 @@ DISPLAYTEXT_free, DISPLAYTEXT_new, DIST_POINT_NAME_free, DIST_POINT_NAME_new, +DIST_POINT_NAME_dup, DIST_POINT_free, DIST_POINT_new, DSAparams_dup, @@ -76,6 +81,9 @@ GENERAL_NAME_free, GENERAL_NAME_new, GENERAL_SUBTREE_free, GENERAL_SUBTREE_new, +OSSL_IETF_ATTR_SYNTAX_free, +OSSL_IETF_ATTR_SYNTAX_it, +OSSL_IETF_ATTR_SYNTAX_new, IPAddressChoice_free, IPAddressChoice_new, IPAddressFamily_free, @@ -129,6 +137,49 @@ OCSP_SIGNATURE_free, OCSP_SIGNATURE_new, OCSP_SINGLERESP_free, OCSP_SINGLERESP_new, +OSSL_AA_DIST_POINT_free, +OSSL_AA_DIST_POINT_new, +OSSL_AA_DIST_POINT_it, +OSSL_ALLOWED_ATTRIBUTES_CHOICE_free, +OSSL_ALLOWED_ATTRIBUTES_CHOICE_new, +OSSL_ALLOWED_ATTRIBUTES_CHOICE_it, +OSSL_ALLOWED_ATTRIBUTES_ITEM_free, +OSSL_ALLOWED_ATTRIBUTES_ITEM_new, +OSSL_ALLOWED_ATTRIBUTES_ITEM_it, +OSSL_ALLOWED_ATTRIBUTES_SYNTAX_free, +OSSL_ALLOWED_ATTRIBUTES_SYNTAX_new, +OSSL_ALLOWED_ATTRIBUTES_SYNTAX_it, +OSSL_ATAV_free, +OSSL_ATAV_new, +OSSL_ATAV_it, +OSSL_ATTRIBUTE_DESCRIPTOR_free, +OSSL_ATTRIBUTE_DESCRIPTOR_new, +OSSL_ATTRIBUTE_DESCRIPTOR_it, +OSSL_ATTRIBUTE_MAPPING_free, +OSSL_ATTRIBUTE_MAPPING_new, +OSSL_ATTRIBUTE_MAPPING_it, +OSSL_ATTRIBUTE_MAPPINGS_free, +OSSL_ATTRIBUTE_MAPPINGS_new, +OSSL_ATTRIBUTE_MAPPINGS_it, +OSSL_ATTRIBUTE_TYPE_MAPPING_free, +OSSL_ATTRIBUTE_TYPE_MAPPING_new, +OSSL_ATTRIBUTE_TYPE_MAPPING_it, +OSSL_ATTRIBUTE_VALUE_MAPPING_free, +OSSL_ATTRIBUTE_VALUE_MAPPING_new, +OSSL_ATTRIBUTE_VALUE_MAPPING_it, +OSSL_ATTRIBUTES_SYNTAX_free, +OSSL_ATTRIBUTES_SYNTAX_it, +OSSL_ATTRIBUTES_SYNTAX_new, +OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_free, +OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_it, +OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_new, +OSSL_BASIC_ATTR_CONSTRAINTS_free, +OSSL_BASIC_ATTR_CONSTRAINTS_it, +OSSL_BASIC_ATTR_CONSTRAINTS_new, +OSSL_CMP_ATAVS_new, +OSSL_CMP_ATAVS_free, +OSSL_CMP_ATAVS_it, +OSSL_CMP_CRLSTATUS_free, OSSL_CMP_ITAV_dup, OSSL_CMP_ITAV_free, OSSL_CMP_MSG_dup, @@ -149,6 +200,12 @@ OSSL_CRMF_CERTID_new, OSSL_CRMF_CERTTEMPLATE_free, OSSL_CRMF_CERTTEMPLATE_it, OSSL_CRMF_CERTTEMPLATE_new, +OSSL_CRMF_CERTTEMPLATE_dup, +OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup, +OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free, +OSSL_CRMF_ENCRYPTEDKEY_free, +OSSL_CRMF_ENCRYPTEDKEY_it, +OSSL_CRMF_ENCRYPTEDKEY_new, OSSL_CRMF_ENCRYPTEDVALUE_free, OSSL_CRMF_ENCRYPTEDVALUE_it, OSSL_CRMF_ENCRYPTEDVALUE_new, @@ -168,6 +225,79 @@ OSSL_CRMF_PKIPUBLICATIONINFO_new, OSSL_CRMF_SINGLEPUBINFO_free, OSSL_CRMF_SINGLEPUBINFO_it, OSSL_CRMF_SINGLEPUBINFO_new, +OSSL_DAY_TIME_free, +OSSL_DAY_TIME_new, +OSSL_DAY_TIME_it, +OSSL_DAY_TIME_BAND_free, +OSSL_DAY_TIME_BAND_new, +OSSL_DAY_TIME_BAND_it, +OSSL_HASH_free, +OSSL_HASH_it, +OSSL_HASH_new, +OSSL_INFO_SYNTAX_free, +OSSL_INFO_SYNTAX_it, +OSSL_INFO_SYNTAX_new, +OSSL_INFO_SYNTAX_POINTER_free, +OSSL_INFO_SYNTAX_POINTER_it, +OSSL_INFO_SYNTAX_POINTER_new, +OSSL_PRIVILEGE_POLICY_ID_free, +OSSL_PRIVILEGE_POLICY_ID_it, +OSSL_PRIVILEGE_POLICY_ID_new, +OSSL_TARGET_CERT_free, +OSSL_TARGET_CERT_it, +OSSL_TARGET_CERT_new, +OSSL_TARGET_free, +OSSL_TARGET_it, +OSSL_TARGET_new, +OSSL_TARGETING_INFORMATION_free, +OSSL_TARGETING_INFORMATION_it, +OSSL_TARGETING_INFORMATION_new, +OSSL_TARGETS_free, +OSSL_TARGETS_it, +OSSL_TARGETS_new, +OSSL_IETF_ATTR_SYNTAX_VALUE_free, +OSSL_IETF_ATTR_SYNTAX_VALUE_it, +OSSL_IETF_ATTR_SYNTAX_VALUE_new, +OSSL_ISSUER_SERIAL_free, +OSSL_ISSUER_SERIAL_new, +OSSL_NAMED_DAY_free, +OSSL_NAMED_DAY_new, +OSSL_NAMED_DAY_it, +OSSL_OBJECT_DIGEST_INFO_free, +OSSL_OBJECT_DIGEST_INFO_new, +OSSL_ROLE_SPEC_CERT_ID_free, +OSSL_ROLE_SPEC_CERT_ID_new, +OSSL_ROLE_SPEC_CERT_ID_it, +OSSL_ROLE_SPEC_CERT_ID_SYNTAX_free, +OSSL_ROLE_SPEC_CERT_ID_SYNTAX_new, +OSSL_ROLE_SPEC_CERT_ID_SYNTAX_it, +OSSL_TIME_PERIOD_free, +OSSL_TIME_PERIOD_new, +OSSL_TIME_PERIOD_it, +OSSL_TIME_SPEC_ABSOLUTE_free, +OSSL_TIME_SPEC_ABSOLUTE_new, +OSSL_TIME_SPEC_ABSOLUTE_it, +OSSL_TIME_SPEC_free, +OSSL_TIME_SPEC_new, +OSSL_TIME_SPEC_it, +OSSL_TIME_SPEC_DAY_free, +OSSL_TIME_SPEC_DAY_new, +OSSL_TIME_SPEC_DAY_it, +OSSL_TIME_SPEC_MONTH_free, +OSSL_TIME_SPEC_MONTH_new, +OSSL_TIME_SPEC_MONTH_it, +OSSL_TIME_SPEC_TIME_free, +OSSL_TIME_SPEC_TIME_new, +OSSL_TIME_SPEC_TIME_it, +OSSL_TIME_SPEC_WEEKS_free, +OSSL_TIME_SPEC_WEEKS_new, +OSSL_TIME_SPEC_WEEKS_it, +OSSL_TIME_SPEC_X_DAY_OF_free, +OSSL_TIME_SPEC_X_DAY_OF_new, +OSSL_TIME_SPEC_X_DAY_OF_it, +OSSL_USER_NOTICE_SYNTAX_free, +OSSL_USER_NOTICE_SYNTAX_new, +OSSL_USER_NOTICE_SYNTAX_it, OTHERNAME_free, OTHERNAME_new, PBE2PARAM_free, @@ -176,6 +306,9 @@ PBEPARAM_free, PBEPARAM_new, PBKDF2PARAM_free, PBKDF2PARAM_new, +PBMAC1PARAM_free, +PBMAC1PARAM_it, +PBMAC1PARAM_new, PKCS12_BAGS_free, PKCS12_BAGS_new, PKCS12_MAC_DATA_free, @@ -262,6 +395,15 @@ TS_TST_INFO_free, TS_TST_INFO_new, USERNOTICE_free, USERNOTICE_new, +X509_ACERT_dup, +X509_ACERT_free, +X509_ACERT_it, +X509_ACERT_new, +X509_ACERT_INFO_free, +X509_ACERT_INFO_it, +X509_ACERT_INFO_new, +X509_ACERT_ISSUER_V2FORM_free, +X509_ACERT_ISSUER_V2FORM_new, X509_ALGOR_free, X509_ALGOR_it, X509_ALGOR_new, @@ -394,9 +536,77 @@ CMS_ContentInfo_new_ex() were added in OpenSSL 3.0. The functions DSAparams_dup(), RSAPrivateKey_dup() and RSAPublicKey_dup() were deprecated in 3.0. +CMS_EnvelopedData_it(), CMS_SignedData_free(), CMS_SignedData_new() +were added in OpenSSL 3.2. + +DIST_POINT_NAME_dup(), OSSL_IETF_ATTR_SYNTAX_free(), OSSL_IETF_ATTR_SYNTAX_it(), +OSSL_IETF_ATTR_SYNTAX_new(), OSSL_ATTRIBUTES_SYNTAX_free(), +OSSL_ATTRIBUTES_SYNTAX_it(), OSSL_ATTRIBUTES_SYNTAX_new(), +OSSL_BASIC_ATTR_CONSTRAINTS_free(), OSSL_BASIC_ATTR_CONSTRAINTS_it(), +OSSL_BASIC_ATTR_CONSTRAINTS_new(), OSSL_CMP_ATAVS_new(), OSSL_CMP_ATAVS_free(), +OSSL_CMP_ATAVS_it(), OSSL_CMP_CRLSTATUS_free(), OSSL_CRMF_CERTTEMPLATE_dup(), +OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup(), OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(), +OSSL_TARGET_free(), OSSL_TARGET_it(), OSSL_TARGET_new(), +OSSL_TARGETING_INFORMATION_free(), OSSL_TARGETING_INFORMATION_it(), +OSSL_TARGETING_INFORMATION_new(), OSSL_TARGETS_free(), +OSSL_TARGETS_it(), OSSL_TARGETS_new(), OSSL_IETF_ATTR_SYNTAX_VALUE_free(), +OSSL_IETF_ATTR_SYNTAX_VALUE_it(), OSSL_IETF_ATTR_SYNTAX_VALUE_new(), +OSSL_ISSUER_SERIAL_free(), OSSL_ISSUER_SERIAL_new(), +OSSL_OBJECT_DIGEST_INFO_free(), OSSL_OBJECT_DIGEST_INFO_new(), +OSSL_USER_NOTICE_SYNTAX_free(), OSSL_USER_NOTICE_SYNTAX_new(), +OSSL_USER_NOTICE_SYNTAX_it(), PBMAC1PARAM_free(), PBMAC1PARAM_it(), +PBMAC1PARAM_new(), X509_ACERT_dup(), X509_ACERT_free(), X509_ACERT_it(), +X509_ACERT_new(), X509_ACERT_INFO_free(), X509_ACERT_INFO_it(), +X509_ACERT_INFO_new(), X509_ACERT_ISSUER_V2FORM_free(), +X509_ACERT_ISSUER_V2FORM_new() +were added in OpenSSL 3.4. + +OSSL_AA_DIST_POINT_free(), OSSL_AA_DIST_POINT_new(), OSSL_AA_DIST_POINT_it(), +OSSL_ALLOWED_ATTRIBUTES_CHOICE_free(), OSSL_ALLOWED_ATTRIBUTES_CHOICE_new(), +OSSL_ALLOWED_ATTRIBUTES_CHOICE_it(), OSSL_ALLOWED_ATTRIBUTES_ITEM_free(), +OSSL_ALLOWED_ATTRIBUTES_ITEM_new(), OSSL_ALLOWED_ATTRIBUTES_ITEM_it(), +OSSL_ALLOWED_ATTRIBUTES_SYNTAX_free(), OSSL_ALLOWED_ATTRIBUTES_SYNTAX_new(), +OSSL_ALLOWED_ATTRIBUTES_SYNTAX_it(), +OSSL_ATAV_free(), OSSL_ATAV_it(), OSSL_ATAV_new(), +OSSL_ATTRIBUTE_DESCRIPTOR_free(), OSSL_ATTRIBUTE_DESCRIPTOR_new(), +OSSL_ATTRIBUTE_DESCRIPTOR_it(), +OSSL_ATTRIBUTE_MAPPINGS_free(), OSSL_ATTRIBUTE_MAPPINGS_it(), +OSSL_ATTRIBUTE_MAPPINGS_new(), OSSL_ATTRIBUTE_MAPPING_free(), +OSSL_ATTRIBUTE_MAPPING_it(), OSSL_ATTRIBUTE_MAPPING_new(), +OSSL_ATTRIBUTE_TYPE_MAPPING_free(), OSSL_ATTRIBUTE_TYPE_MAPPING_it(), +OSSL_ATTRIBUTE_TYPE_MAPPING_new(), OSSL_ATTRIBUTE_VALUE_MAPPING_free(), +OSSL_ATTRIBUTE_VALUE_MAPPING_it(), OSSL_ATTRIBUTE_VALUE_MAPPING_new(), +OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_free(), +OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_it(), OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX_new(), +OSSL_HASH_free(), OSSL_HASH_it(), OSSL_HASH_new(), OSSL_INFO_SYNTAX_free(), +OSSL_INFO_SYNTAX_it(), OSSL_INFO_SYNTAX_new(), OSSL_INFO_SYNTAX_POINTER_free(), +OSSL_INFO_SYNTAX_POINTER_it(), OSSL_INFO_SYNTAX_POINTER_new(), +OSSL_PRIVILEGE_POLICY_ID_free(), OSSL_PRIVILEGE_POLICY_ID_it(), +OSSL_PRIVILEGE_POLICY_ID_new(), OSSL_ROLE_SPEC_CERT_ID_free(), +OSSL_ROLE_SPEC_CERT_ID_new(), OSSL_ROLE_SPEC_CERT_ID_it(), +OSSL_ROLE_SPEC_CERT_ID_SYNTAX_free(), OSSL_ROLE_SPEC_CERT_ID_SYNTAX_new(), +OSSL_ROLE_SPEC_CERT_ID_SYNTAX_it(), OSSL_DAY_TIME_BAND_free(), +OSSL_DAY_TIME_BAND_it(), OSSL_DAY_TIME_BAND_new(), +OSSL_DAY_TIME_free(), OSSL_DAY_TIME_it(), OSSL_DAY_TIME_new(), +OSSL_NAMED_DAY_free(), OSSL_NAMED_DAY_it(), OSSL_NAMED_DAY_new(), +OSSL_TIME_PERIOD_free(), OSSL_TIME_PERIOD_it(), OSSL_TIME_PERIOD_new(), +OSSL_TIME_SPEC_ABSOLUTE_free(), OSSL_TIME_SPEC_ABSOLUTE_it(), +OSSL_TIME_SPEC_ABSOLUTE_new(), OSSL_TIME_SPEC_DAY_free(), +OSSL_TIME_SPEC_DAY_it(), OSSL_TIME_SPEC_DAY_new(), +OSSL_TIME_SPEC_MONTH_free(), OSSL_TIME_SPEC_MONTH_it(), +OSSL_TIME_SPEC_MONTH_new(), OSSL_TIME_SPEC_TIME_free(), +OSSL_TIME_SPEC_TIME_it(), OSSL_TIME_SPEC_TIME_new(), +OSSL_TIME_SPEC_WEEKS_free(), OSSL_TIME_SPEC_WEEKS_it(), +OSSL_TIME_SPEC_WEEKS_new(), OSSL_TIME_SPEC_X_DAY_OF_free(), +OSSL_TIME_SPEC_X_DAY_OF_it(), OSSL_TIME_SPEC_X_DAY_OF_new(), +OSSL_TIME_SPEC_free(), OSSL_TIME_SPEC_it(), OSSL_TIME_SPEC_new(), +CMS_EnvelopedData_dup(), OSSL_CRMF_ENCRYPTEDKEY_free(), +OSSL_CRMF_ENCRYPTEDKEY_it() and OSSL_CRMF_ENCRYPTEDKEY_new() +were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get0_notBefore.pod b/doc/man3/X509_get0_notBefore.pod index 1af2920a52bc..1d94729277b5 100644 --- a/doc/man3/X509_get0_notBefore.pod +++ b/doc/man3/X509_get0_notBefore.pod @@ -4,6 +4,8 @@ X509_get0_notBefore, X509_getm_notBefore, X509_get0_notAfter, X509_getm_notAfter, X509_set1_notBefore, X509_set1_notAfter, +X509_ACERT_get0_notBefore, X509_ACERT_get0_notAfter, +X509_ACERT_set1_notBefore, X509_ACERT_set1_notAfter, X509_CRL_get0_lastUpdate, X509_CRL_get0_nextUpdate, X509_CRL_set1_lastUpdate, X509_CRL_set1_nextUpdate - get or set certificate or CRL dates @@ -20,6 +22,12 @@ X509_CRL_set1_nextUpdate - get or set certificate or CRL dates int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); + const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notBefore(const X509 *x); + const ASN1_GENERALIZEDTIME *X509_ACERT_get0_notAfter(const X509 *x); + + int X509_ACERT_set1_notBefore(X509_ACERT *x, const ASN1_GENERALIZEDTIME *tm); + int X509_ACERT_set1_notAfter(X509_ACERT *x, const ASN1_GENERALIZEDTIME *tm); + const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); @@ -29,9 +37,9 @@ X509_CRL_set1_nextUpdate - get or set certificate or CRL dates =head1 DESCRIPTION X509_get0_notBefore() and X509_get0_notAfter() return the B -and B fields of certificate B respectively. The value +and B fields of certificate I respectively. The value returned is an internal pointer which must not be freed up after -the call. +the call. I B be NULL. X509_getm_notBefore() and X509_getm_notAfter() are similar to X509_get0_notBefore() and X509_get0_notAfter() except they return @@ -39,20 +47,32 @@ non-constant mutable references to the associated date field of the certificate. X509_set1_notBefore() and X509_set1_notAfter() set the B +and B fields of I to I. Ownership of the passed +parameter I is not transferred by these functions so it must +be freed up after the call. + +X509_ACERT_get0_notBefore() and X509_ACERT_get0_notAfter() return +the B and B fields of certificate B respectively. +returned is an internal pointer which must not be freed up after +the call. + +X509_ACERT_set1_notBefore() and X509_ACERT_set1_notAfter() set the B and B fields of B to B. Ownership of the passed parameter B is not transferred by these functions so it must be freed up after the call. X509_CRL_get0_lastUpdate() and X509_CRL_get0_nextUpdate() return the -B and B fields of B. The value +B and B fields of I. The value returned is an internal pointer which must not be freed up after -the call. If the B field is absent from B then -B is returned. +the call. If the B field is absent from I then +NULL is returned. X509_CRL_set1_lastUpdate() and X509_CRL_set1_nextUpdate() set the B -and B fields of B to B. Ownership of the passed parameter -B is not transferred by these functions so it must be freed up after the +and B fields of I to I. Ownership of the passed parameter +I is not transferred by these functions so it must be freed up after the call. +For X509_CRL_set1_nextUpdate() the I argument may be NULL, +which implies removal of the optional B field. =head1 RETURN VALUES @@ -65,9 +85,16 @@ or NULL if the B field is absent. X509_set1_notBefore(), X509_set1_notAfter(), X509_CRL_set1_lastUpdate() and X509_CRL_set1_nextUpdate() return 1 for success or 0 for failure. +=head1 NOTES + +Unlike the B and B routines, the B routines +use the ASN1_GENERALIZEDTIME format instead of ASN1_TIME for holding time +data. + =head1 SEE ALSO L, +L L, L, L, @@ -86,14 +113,16 @@ L =head1 HISTORY -These functions are available in all versions of OpenSSL. - X509_get_notBefore() and X509_get_notAfter() were deprecated in OpenSSL -1.1.0 +1.1.0. + +X509_ACERT_get0_notBefore(), X509_ACERT_get0_notAfter(), +X509_ACERT_set1_notBefore(), X509_ACERT_set1_notAfter() +were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get0_signature.pod b/doc/man3/X509_get0_signature.pod index e37a04fe8b27..18d9be6c45af 100644 --- a/doc/man3/X509_get0_signature.pod +++ b/doc/man3/X509_get0_signature.pod @@ -5,7 +5,9 @@ X509_get0_signature, X509_REQ_set0_signature, X509_REQ_set1_signature_algo, X509_get_signature_nid, X509_get0_tbs_sigalg, X509_REQ_get0_signature, X509_REQ_get_signature_nid, X509_CRL_get0_signature, X509_CRL_get_signature_nid, -X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature information +X509_ACERT_get0_signature, X509_ACERT_get0_info_sigalg, +X509_ACERT_get_signature_nid, X509_get_signature_info, +X509_SIG_INFO_get, X509_SIG_INFO_set - signature information =head1 SYNOPSIS @@ -24,6 +26,8 @@ X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature inform const X509_ALGOR **palg); int X509_REQ_get_signature_nid(const X509_REQ *crl); + const X509_ALGOR *X509_ACERT_get0_info_sigalg(const X509_ACERT *x); + void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, const X509_ALGOR **palg); @@ -37,6 +41,12 @@ X509_get_signature_info, X509_SIG_INFO_get, X509_SIG_INFO_set - signature inform void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid, int secbits, uint32_t flags); + #include + + void X509_ACERT_get0_signature(const X509_ACERT *x, + const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); + int X509_ACERT_get_signature_nid(const X509_ACERT *x); =head1 DESCRIPTION X509_get0_signature() sets B<*psig> to the signature of B and B<*palg> @@ -56,6 +66,10 @@ X509_REQ_get0_signature(), X509_REQ_get_signature_nid() X509_CRL_get0_signature() and X509_CRL_get_signature_nid() perform the same function for certificate requests and CRLs. +X509_ACERT_get0_signature(), X509_ACERT_get_signature_nid() and +X509_ACERT_get0_info_sigalg() perform the same function for attribute +certificates. + X509_get_signature_info() retrieves information about the signature of certificate B. The NID of the signing digest is written to B<*mdnid>, the public key algorithm to B<*pknid>, the effective security bits to @@ -130,9 +144,12 @@ added in OpenSSL 1.1.0. The X509_REQ_set0_signature() and X509_REQ_set1_signature_algo() were added in OpenSSL 1.1.1e. +The X509_ACERT_get0_signature(), X509_ACERT_get0_info_sigalg() and +X509_ACERT_get_signature_nid() functions were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get0_uids.pod b/doc/man3/X509_get0_uids.pod index 48ae5afc4243..6c03e0149dbc 100644 --- a/doc/man3/X509_get0_uids.pod +++ b/doc/man3/X509_get0_uids.pod @@ -2,7 +2,8 @@ =head1 NAME -X509_get0_uids - get certificate unique identifiers +X509_get0_uids, X509_ACERT_get0_issuerUID +- get certificate and attribute certificate unique identifiers =head1 SYNOPSIS @@ -11,11 +12,17 @@ X509_get0_uids - get certificate unique identifiers void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, const ASN1_BIT_STRING **psuid); + #include + + ASN1_BIT_STRING *X509_ACERT_get0_issuerUID(X509_ACERT *x); =head1 DESCRIPTION X509_get0_uids() sets B<*piuid> and B<*psuid> to the issuer and subject unique identifiers of certificate B or NULL if the fields are not present. +X509_ACERT_get0_issuerUID() returns the issuer unique identifier of the +attribute certificate B or NULL if the field is not present. + =head1 NOTES The issuer and subject unique identifier fields are very rarely encountered in @@ -25,6 +32,9 @@ practice outside test cases. X509_get0_uids() does not return a value. +X509_ACERT_get0_issuerUID() returns a unique identifier on success or NULL +on failure. + =head1 SEE ALSO L, @@ -45,9 +55,15 @@ L, L, L +=head1 HISTORY + +X509_get0_uids() was added in OpenSSL 1.1.0. + +X509_ACERT_get0_issuerUID() was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get_pubkey.pod b/doc/man3/X509_get_pubkey.pod index fea0064b9bb2..c292cd3d2b32 100644 --- a/doc/man3/X509_get_pubkey.pod +++ b/doc/man3/X509_get_pubkey.pod @@ -77,7 +77,7 @@ L =head1 COPYRIGHT -Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get_serialNumber.pod b/doc/man3/X509_get_serialNumber.pod index 5594c8a284b0..fc6c4e731b27 100644 --- a/doc/man3/X509_get_serialNumber.pod +++ b/doc/man3/X509_get_serialNumber.pod @@ -4,7 +4,9 @@ X509_get_serialNumber, X509_get0_serialNumber, -X509_set_serialNumber +X509_set_serialNumber, +X509_ACERT_get0_serialNumber, +X509_ACERT_set1_serialNumber - get or set certificate serial number =head1 SYNOPSIS @@ -15,6 +17,11 @@ X509_set_serialNumber const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x); int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); + #include + + ASN1_INTEGER *X509_ACERT_get0_serialNumber(X509_ACERT *x); + int X509_ACERT_set1_serialNumber(X509_ACERT *x, ASN1_INTEGER *serial); + =head1 DESCRIPTION X509_get_serialNumber() returns the serial number of certificate B as an @@ -28,12 +35,19 @@ X509_set_serialNumber() sets the serial number of certificate B to B. A copy of the serial number is used internally so B should be freed up after use. +X509_ACERT_get0_serialNumber() performs the same operation as +X509_get_serialNumber() for attribute certificates. + +X509_ACERT_set1_serialNumber() performs the same operation as +X509_set_serialNumber() for attribute certificates. + =head1 RETURN VALUES -X509_get_serialNumber() and X509_get0_serialNumber() return an B -structure. +X509_get_serialNumber(), X509_get0_serialNumber() and +X509_ACERT_get0_serialNumber() return a pointer to an B structure. -X509_set_serialNumber() returns 1 for success and 0 for failure. +X509_set_serialNumber() and X509_ACERT_set1_serialNumber() return 1 for success +and 0 for failure. =head1 SEE ALSO @@ -59,10 +73,12 @@ L The X509_get_serialNumber() and X509_set_serialNumber() functions are available in all versions of OpenSSL. The X509_get0_serialNumber() function was added in OpenSSL 1.1.0. +The X509_ACERT_get0_serialNumber() and X509_ACERT_set1_serialNumber() +functions were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get_subject_name.pod b/doc/man3/X509_get_subject_name.pod index 64659de6ab6a..56c5404a439d 100644 --- a/doc/man3/X509_get_subject_name.pod +++ b/doc/man3/X509_get_subject_name.pod @@ -6,6 +6,7 @@ X509_NAME_hash_ex, X509_NAME_hash, X509_get_subject_name, X509_set_subject_name, X509_subject_name_hash, X509_get_issuer_name, X509_set_issuer_name, X509_issuer_name_hash, X509_REQ_get_subject_name, X509_REQ_set_subject_name, +X509_ACERT_get0_issuerName, X509_ACERT_set1_issuerName, X509_CRL_get_issuer, X509_CRL_set_issuer_name - get X509_NAME hashes or get and set issuer or subject names @@ -30,6 +31,11 @@ get X509_NAME hashes or get and set issuer or subject names X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); int X509_CRL_set_issuer_name(X509_CRL *x, const X509_NAME *name); + #include + + X509_NAME *X509_ACERT_get0_issuerName(const X509_ACERT *x); + int X509_ACERT_set1_issuerName(X509_ACERT *x, const X509_NAME *name); + The following macro has been deprecated since OpenSSL 3.0, and can be hidden entirely by defining B with a suitable version value, see L: @@ -48,7 +54,7 @@ X509_NAME_hash() returns a hash value of name I or 0 on failure, using the default library context and default property query. X509_get_subject_name() returns the subject name of certificate I. The -returned value is an internal pointer which B be freed. +returned value is an internal pointer which B be freed. I B be NULL. X509_set_subject_name() sets the issuer name of certificate I to I. The I parameter is copied internally and should be freed @@ -63,13 +69,19 @@ X509_get_subject_name(), X509_set_subject_name(), and X509_subject_name_hash() except they relate to the issuer name of I. Similarly X509_REQ_get_subject_name(), X509_REQ_set_subject_name(), +X509_ACERT_get0_issuerName(), X509_ACERT_set1_issuerName(), X509_CRL_get_issuer() and X509_CRL_set_issuer_name() get or set the subject or issuer names of certificate requests of CRLs respectively. +Since attribute certificates do not have a subject name, only the issuer name +can be set. For details on setting X509_ACERT holder identities, see +L. + =head1 RETURN VALUES X509_get_subject_name(), X509_get_issuer_name(), X509_REQ_get_subject_name() -and X509_CRL_get_issuer() return an B pointer. +X509_ACERT_get0_issuerName() and X509_CRL_get_issuer() return +an B pointer. X509_NAME_hash_ex(), X509_NAME_hash(), X509_subject_name_hash() and X509_issuer_name_hash() @@ -77,8 +89,9 @@ return the first four bytes of the SHA1 hash value, converted to B in little endian order, or 0 on failure. -X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name() -and X509_CRL_set_issuer_name() return 1 for success and 0 for failure. +X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name(), +X509_ACERT_get0_issuerName() and X509_CRL_set_issuer_name() return 1 for +success and 0 for failure. =head1 BUGS @@ -114,9 +127,12 @@ added in OpenSSL 1.0.0 as a macro. X509_NAME_hash() was turned into a macro and deprecated in OpenSSL 3.0. +X509_ACERT_get0_issuerName(), X509_ACERT_set1_issuerName() +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_get_version.pod b/doc/man3/X509_get_version.pod index 082859e4f413..23e1f5a9623c 100644 --- a/doc/man3/X509_get_version.pod +++ b/doc/man3/X509_get_version.pod @@ -3,7 +3,8 @@ =head1 NAME X509_get_version, X509_set_version, X509_REQ_get_version, X509_REQ_set_version, -X509_CRL_get_version, X509_CRL_set_version - get or set certificate, +X509_ACERT_get_version, X509_ACERT_set_version, X509_CRL_get_version, +X509_CRL_set_version - get or set certificate, certificate request or CRL version =head1 SYNOPSIS @@ -19,21 +20,28 @@ certificate request or CRL version long X509_CRL_get_version(const X509_CRL *crl); int X509_CRL_set_version(X509_CRL *x, long version); + #include + + int X509_ACERT_set_version(X509_ACERT *x, long version); + long X509_ACERT_get_version(const X509_ACERT *x); + =head1 DESCRIPTION X509_get_version() returns the numerical value of the version field of -certificate B. These correspond to the constants B, +certificate I. These correspond to the constants B, B, and B. Note: the values of these constants are defined by standards (X.509 et al) to be one less than the certificate version. So B has value 2 and B has value 0. X509_set_version() sets the numerical value of the version field of certificate -B to B. +I to I. Similarly X509_REQ_get_version(), X509_REQ_set_version(), +X509_ACERT_get_version(), X509_ACERT_set_version(), X509_CRL_get_version() and X509_CRL_set_version() get and set the version number of certificate requests and CRLs. They use constants -B, B, and B. +B, B, B, +and B. =head1 NOTES @@ -73,9 +81,12 @@ L X509_get_version(), X509_REQ_get_version() and X509_CRL_get_version() are functions in OpenSSL 1.1.0, in previous versions they were macros. +X509_ACERT_get_version(), X509_ACERT_set_version() +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_new.pod b/doc/man3/X509_new.pod index 4b52972554de..264767e83414 100644 --- a/doc/man3/X509_new.pod +++ b/doc/man3/X509_new.pod @@ -4,7 +4,9 @@ X509_new, X509_new_ex, X509_free, X509_up_ref, -X509_chain_up_ref - X509 certificate ASN1 allocation functions +X509_chain_up_ref, +OSSL_STACK_OF_X509_free +- X509 certificate ASN1 allocation and deallocation functions =head1 SYNOPSIS @@ -15,6 +17,7 @@ X509_chain_up_ref - X509 certificate ASN1 allocation functions void X509_free(X509 *a); int X509_up_ref(X509 *a); STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *x); + void OSSL_STACK_OF_X509_free(STACK_OF(X509) *certs); =head1 DESCRIPTION @@ -41,6 +44,10 @@ X509_up_ref() increments the reference count of B. X509_chain_up_ref() increases the reference count of all certificates in chain B and returns a copy of the stack, or an empty stack if B is NULL. +OSSL_STACK_OF_X509_free() deallocates the given list of pointers to +certificates after calling X509_free() on all its elements. +If the argument is NULL, nothing is done. + =head1 NOTES The function X509_up_ref() if useful if a certificate structure is being @@ -62,6 +69,8 @@ X509_up_ref() returns 1 for success and 0 for failure. X509_chain_up_ref() returns a copy of the stack or NULL if an error occurred. +OSSL_STACK_OF_X509_free() has no return value. + =head1 SEE ALSO L, @@ -83,7 +92,9 @@ L =head1 HISTORY -The function X509_new_ex() was added in OpenSSL 3.0. +X509_new_ex() was added in OpenSSL 3.0. + +OSSL_STACK_OF_X509_free() was added in OpenSSL 3.2. =head1 COPYRIGHT diff --git a/doc/man3/X509_sign.pod b/doc/man3/X509_sign.pod index df66e3e5b748..92bd52b4843c 100644 --- a/doc/man3/X509_sign.pod +++ b/doc/man3/X509_sign.pod @@ -4,6 +4,7 @@ X509_sign, X509_sign_ctx, X509_REQ_sign, X509_REQ_sign_ctx, +X509_ACERT_sign, X509_ACERT_sign_ctx, X509_CRL_sign, X509_CRL_sign_ctx - sign certificate, certificate request, or CRL signature @@ -20,13 +21,21 @@ sign certificate, certificate request, or CRL signature int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); + #include + + int X509_ACERT_sign(X509_ACERT *x, EVP_PKEY *pkey, const EVP_MD *md); + int X509_ACERT_sign_ctx(X509_ACERT *x, EVP_MD_CTX *ctx); + =head1 DESCRIPTION X509_sign() signs certificate I using private key I and message digest I and sets the signature in I. X509_sign_ctx() also signs certificate I but uses the parameters contained in digest context I. +If the certificate information includes X.509 extensions, +these two functions make sure that the certificate bears X.509 version 3. X509_REQ_sign(), X509_REQ_sign_ctx(), +X509_ACERT_sign(), X509_ACERT_sign_ctx(), X509_CRL_sign(), and X509_CRL_sign_ctx() sign certificate requests and CRLs, respectively. @@ -66,9 +75,12 @@ available in all versions of OpenSSL. The X509_sign_ctx(), X509_REQ_sign_ctx() and X509_CRL_sign_ctx() functions were added in OpenSSL 1.0.1. +The X509_ACERT_sign() and X509_ACERT_sign_ctx() functions were added +in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_verify.pod b/doc/man3/X509_verify.pod index ad22721bd1ac..ad08a5fafae2 100644 --- a/doc/man3/X509_verify.pod +++ b/doc/man3/X509_verify.pod @@ -4,7 +4,7 @@ X509_verify, X509_self_signed, X509_REQ_verify_ex, X509_REQ_verify, -X509_CRL_verify - +X509_CRL_verify, X509_ACERT_verify - verify certificate, certificate request, or CRL signature =head1 SYNOPSIS @@ -19,6 +19,9 @@ verify certificate, certificate request, or CRL signature int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); + #include + int X509_ACERT_verify(X509_CRL *a, EVP_PKEY *r); + =head1 DESCRIPTION X509_verify() verifies the signature of certificate I using public key @@ -31,8 +34,9 @@ authority key identifier (if present) must match the subject key identifier etc. The signature itself is actually verified only if B is 1, as for explicitly trusted certificates this verification is not worth the effort. -X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify() -verify the signatures of certificate requests and CRLs, respectively. +X509_REQ_verify_ex(), X509_REQ_verify(), X509_CRL_verify() and X509_ACERT_verify() +verify the signatures of certificate requests, CRLs and attribute certificates +respectively. =head1 RETURN VALUES @@ -71,9 +75,11 @@ functions are available in all versions of OpenSSL. X509_REQ_verify_ex(), and X509_self_signed() were added in OpenSSL 3.0. +X509_ACERT_verify() was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/X509_verify_cert.pod b/doc/man3/X509_verify_cert.pod index d54acfdb0bd4..360e97481273 100644 --- a/doc/man3/X509_verify_cert.pod +++ b/doc/man3/X509_verify_cert.pod @@ -59,6 +59,14 @@ The X509_STORE_CTX_verify() behaves like X509_verify_cert() except that its target certificate is the first element of the list of untrusted certificates in I unless a target certificate is set explicitly. +When the verification target is a raw public key, rather than a certificate, +both functions validate the target raw public key. +In that case the number of possible checks is significantly reduced. +The raw public key can be authenticated only via DANE TLSA records, either +locally synthesised or obtained by the application from DNS. +Raw public key DANE TLSA records may be added via L or +L. + =head1 RETURN VALUES X509_build_chain() returns NULL on error, else a stack of certificates. @@ -80,7 +88,12 @@ X509_V_OK, likely because a verification callback function has waived the error. =head1 SEE ALSO -L, L, +L, +L, +L, +L, +L, +L, L =head1 HISTORY @@ -89,7 +102,7 @@ X509_build_chain() and X509_STORE_CTX_verify() were added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2009-2022 The OpenSSL Project Authors. All Rights Reserved. +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 diff --git a/doc/man3/X509v3_get_ext_by_NID.pod b/doc/man3/X509v3_get_ext_by_NID.pod index 4010a71c4371..38caf524a63a 100644 --- a/doc/man3/X509v3_get_ext_by_NID.pod +++ b/doc/man3/X509v3_get_ext_by_NID.pod @@ -4,7 +4,7 @@ X509v3_get_ext_count, X509v3_get_ext, X509v3_get_ext_by_NID, X509v3_get_ext_by_OBJ, X509v3_get_ext_by_critical, X509v3_delete_ext, -X509v3_add_ext, X509_get_ext_count, X509_get_ext, +X509v3_add_ext, X509v3_add_extensions, X509_get_ext_count, X509_get_ext, X509_get_ext_by_NID, X509_get_ext_by_OBJ, X509_get_ext_by_critical, X509_delete_ext, X509_add_ext, X509_CRL_get_ext_count, X509_CRL_get_ext, X509_CRL_get_ext_by_NID, X509_CRL_get_ext_by_OBJ, X509_CRL_get_ext_by_critical, @@ -29,6 +29,9 @@ X509_REVOKED_add_ext - extension stack utility functions X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, X509_EXTENSION *ex, int loc); + STACK_OF(X509_EXTENSION) + *X509v3_add_extensions(STACK_OF(X509_EXTENSION) **target, + const STACK_OF(X509_EXTENSION) *exts); int X509_get_ext_count(const X509 *x); X509_EXTENSION *X509_get_ext(const X509 *x, int loc); @@ -79,10 +82,16 @@ X509v3_delete_ext() deletes the extension with index I from I. The deleted extension is returned and must be freed by the caller. If I is an invalid index value, NULL is returned. -X509v3_add_ext() adds extension I to STACK I<*x> at position I. If -I is -1, the new extension is added to the end. If I<*x> is NULL, -a new STACK will be allocated. The passed extension I is duplicated -internally so it must be freed after use. +X509v3_add_ext() inserts extension I to STACK I<*x> at position I. +If I is -1, the new extension is added to the end. +A new STACK is allocated if I<*x> is NULL. +The passed extension I is duplicated so it must be freed after use. + +X509v3_add_extensions() adds the list of extensions I to STACK I<*target>. +The STACK I<*target> is returned unchanged if I is NULL or an empty list. +Otherwise a new stack is allocated if I<*target> is NULL. +An extension to be added +that has the same OID as a pre-existing one replaces this earlier one. X509_get_ext_count(), X509_get_ext(), X509_get_ext_by_NID(), X509_get_ext_by_OBJ(), X509_get_ext_by_critical(), X509_delete_ext() @@ -134,15 +143,22 @@ error occurs. X509v3_add_ext() returns a STACK of extensions or NULL on error. +X509v3_add_extensions() returns a STACK of extensions +or NULL on error or if I<*target> is NULL and I is NULL or an empty list. + X509_add_ext() returns 1 on success and 0 on error. =head1 SEE ALSO L +=head1 HISTORY + +X509v3_add_extensions() was added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/d2i_PKCS8PrivateKey_bio.pod b/doc/man3/d2i_PKCS8PrivateKey_bio.pod index 51d8aa8cfb47..55ec34657504 100644 --- a/doc/man3/d2i_PKCS8PrivateKey_bio.pod +++ b/doc/man3/d2i_PKCS8PrivateKey_bio.pod @@ -64,7 +64,7 @@ L =head1 COPYRIGHT -Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/d2i_SSL_SESSION.pod b/doc/man3/d2i_SSL_SESSION.pod index fe8308c2bf0b..1e7b7d915348 100644 --- a/doc/man3/d2i_SSL_SESSION.pod +++ b/doc/man3/d2i_SSL_SESSION.pod @@ -2,7 +2,7 @@ =head1 NAME -d2i_SSL_SESSION, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 representation +d2i_SSL_SESSION, d2i_SSL_SESSION_ex, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 representation =head1 SYNOPSIS @@ -10,6 +10,9 @@ d2i_SSL_SESSION, i2d_SSL_SESSION - convert SSL_SESSION object from/to ASN1 repre SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length); + SSL_SESSION *d2i_SSL_SESSION_ex(SSL_SESSION **a, const unsigned char **pp, + long length, OSSL_LIB_CTX *libctx, + const char *propq); int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); =head1 DESCRIPTION @@ -25,8 +28,9 @@ from this SSL_CTX object). =head1 RETURN VALUES -d2i_SSL_SESSION() returns a pointer to the newly allocated SSL_SESSION -object. In case of failure the NULL-pointer is returned and the error message +d2i_SSL_SESSION() and d2i_SSL_SESSION_ex() return a pointer to the newly +allocated SSL_SESSION object. +In case of failure the NULL-pointer is returned and the error message can be retrieved from the error stack. i2d_SSL_SESSION() returns the size of the ASN1 representation in bytes. @@ -38,9 +42,13 @@ L, L, L, L +=head1 HISTORY + +The function d2i_SSL_SESSION_ex() was added in OpenSSL 3.2. + =head1 COPYRIGHT -Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod index c4b589dd8957..df5ea65e596e 100644 --- a/doc/man3/d2i_X509.pod +++ b/doc/man3/d2i_X509.pod @@ -89,21 +89,62 @@ d2i_OCSP_REVOKEDINFO, d2i_OCSP_SERVICELOC, d2i_OCSP_SIGNATURE, d2i_OCSP_SINGLERESP, +d2i_OSSL_AA_DIST_POINT, +d2i_OSSL_ALLOWED_ATTRIBUTES_CHOICE, +d2i_OSSL_ALLOWED_ATTRIBUTES_ITEM, +d2i_OSSL_ALLOWED_ATTRIBUTES_SYNTAX, +d2i_OSSL_ATAV, +d2i_OSSL_ATTRIBUTE_DESCRIPTOR, +d2i_OSSL_ATTRIBUTE_MAPPING, +d2i_OSSL_ATTRIBUTE_MAPPINGS, +d2i_OSSL_ATTRIBUTE_TYPE_MAPPING, +d2i_OSSL_ATTRIBUTE_VALUE_MAPPING, +d2i_OSSL_ATTRIBUTES_SYNTAX, +d2i_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX, +d2i_OSSL_BASIC_ATTR_CONSTRAINTS, +d2i_OSSL_CMP_ATAVS, d2i_OSSL_CMP_MSG, d2i_OSSL_CMP_PKIHEADER, d2i_OSSL_CMP_PKISI, d2i_OSSL_CRMF_CERTID, d2i_OSSL_CRMF_CERTTEMPLATE, +d2i_OSSL_CRMF_ENCRYPTEDKEY, d2i_OSSL_CRMF_ENCRYPTEDVALUE, d2i_OSSL_CRMF_MSG, d2i_OSSL_CRMF_MSGS, d2i_OSSL_CRMF_PBMPARAMETER, d2i_OSSL_CRMF_PKIPUBLICATIONINFO, d2i_OSSL_CRMF_SINGLEPUBINFO, +d2i_OSSL_DAY_TIME, +d2i_OSSL_DAY_TIME_BAND, +d2i_OSSL_HASH, +d2i_OSSL_IETF_ATTR_SYNTAX, +d2i_OSSL_INFO_SYNTAX, +d2i_OSSL_INFO_SYNTAX_POINTER, +d2i_OSSL_ISSUER_SERIAL, +d2i_OSSL_NAMED_DAY, +d2i_OSSL_OBJECT_DIGEST_INFO, +d2i_OSSL_PRIVILEGE_POLICY_ID, +d2i_OSSL_ROLE_SPEC_CERT_ID, +d2i_OSSL_ROLE_SPEC_CERT_ID_SYNTAX, +d2i_OSSL_TARGET_CERT, +d2i_OSSL_TARGET, +d2i_OSSL_TARGETING_INFORMATION, +d2i_OSSL_TARGETS, +d2i_OSSL_TIME_PERIOD, +d2i_OSSL_TIME_SPEC, +d2i_OSSL_TIME_SPEC_ABSOLUTE, +d2i_OSSL_TIME_SPEC_DAY, +d2i_OSSL_TIME_SPEC_MONTH, +d2i_OSSL_TIME_SPEC_TIME, +d2i_OSSL_TIME_SPEC_WEEKS, +d2i_OSSL_TIME_SPEC_X_DAY_OF, +d2i_OSSL_USER_NOTICE_SYNTAX, d2i_OTHERNAME, d2i_PBE2PARAM, d2i_PBEPARAM, d2i_PBKDF2PARAM, +d2i_PBMAC1PARAM, d2i_PKCS12, d2i_PKCS12_BAGS, d2i_PKCS12_MAC_DATA, @@ -157,6 +198,9 @@ d2i_USERNOTICE, d2i_X509, d2i_X509_bio, d2i_X509_fp, +d2i_X509_ACERT, +d2i_X509_ACERT_bio, +d2i_X509_ACERT_fp, d2i_X509_ALGOR, d2i_X509_ALGORS, d2i_X509_ATTRIBUTE, @@ -260,21 +304,62 @@ i2d_OCSP_REVOKEDINFO, i2d_OCSP_SERVICELOC, i2d_OCSP_SIGNATURE, i2d_OCSP_SINGLERESP, +i2d_OSSL_AA_DIST_POINT, +i2d_OSSL_ALLOWED_ATTRIBUTES_CHOICE, +i2d_OSSL_ALLOWED_ATTRIBUTES_ITEM, +i2d_OSSL_ALLOWED_ATTRIBUTES_SYNTAX, +i2d_OSSL_ATAV, +i2d_OSSL_ATTRIBUTE_DESCRIPTOR, +i2d_OSSL_ATTRIBUTE_MAPPING, +i2d_OSSL_ATTRIBUTE_MAPPINGS, +i2d_OSSL_ATTRIBUTE_TYPE_MAPPING, +i2d_OSSL_ATTRIBUTE_VALUE_MAPPING, +i2d_OSSL_ATTRIBUTES_SYNTAX, +i2d_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX, +i2d_OSSL_BASIC_ATTR_CONSTRAINTS, +i2d_OSSL_CMP_ATAVS, i2d_OSSL_CMP_MSG, i2d_OSSL_CMP_PKIHEADER, i2d_OSSL_CMP_PKISI, i2d_OSSL_CRMF_CERTID, i2d_OSSL_CRMF_CERTTEMPLATE, +i2d_OSSL_CRMF_ENCRYPTEDKEY, i2d_OSSL_CRMF_ENCRYPTEDVALUE, i2d_OSSL_CRMF_MSG, i2d_OSSL_CRMF_MSGS, i2d_OSSL_CRMF_PBMPARAMETER, i2d_OSSL_CRMF_PKIPUBLICATIONINFO, i2d_OSSL_CRMF_SINGLEPUBINFO, +i2d_OSSL_HASH, +i2d_OSSL_DAY_TIME, +i2d_OSSL_DAY_TIME_BAND, +i2d_OSSL_IETF_ATTR_SYNTAX, +i2d_OSSL_INFO_SYNTAX, +i2d_OSSL_INFO_SYNTAX_POINTER, +i2d_OSSL_ISSUER_SERIAL, +i2d_OSSL_NAMED_DAY, +i2d_OSSL_OBJECT_DIGEST_INFO, +i2d_OSSL_PRIVILEGE_POLICY_ID, +i2d_OSSL_ROLE_SPEC_CERT_ID, +i2d_OSSL_ROLE_SPEC_CERT_ID_SYNTAX, +i2d_OSSL_TARGET_CERT, +i2d_OSSL_TARGET, +i2d_OSSL_TARGETING_INFORMATION, +i2d_OSSL_TARGETS, +i2d_OSSL_TIME_PERIOD, +i2d_OSSL_TIME_SPEC, +i2d_OSSL_TIME_SPEC_ABSOLUTE, +i2d_OSSL_TIME_SPEC_DAY, +i2d_OSSL_TIME_SPEC_MONTH, +i2d_OSSL_TIME_SPEC_TIME, +i2d_OSSL_TIME_SPEC_WEEKS, +i2d_OSSL_TIME_SPEC_X_DAY_OF, +i2d_OSSL_USER_NOTICE_SYNTAX, i2d_OTHERNAME, i2d_PBE2PARAM, i2d_PBEPARAM, i2d_PBKDF2PARAM, +i2d_PBMAC1PARAM, i2d_PKCS12, i2d_PKCS12_BAGS, i2d_PKCS12_MAC_DATA, @@ -331,6 +416,9 @@ i2d_USERNOTICE, i2d_X509, i2d_X509_bio, i2d_X509_fp, +i2d_X509_ACERT, +i2d_X509_ACERT_bio, +i2d_X509_ACERT_fp, i2d_X509_ALGOR, i2d_X509_ALGORS, i2d_X509_ATTRIBUTE, @@ -615,9 +703,56 @@ structure has been modified after deserialization or previous serialization. This is because some objects cache the encoding for efficiency reasons. +=head1 HISTORY + +d2i_OSSL_ATTRIBUTES_SYNTAX(), d2i_OSSL_BASIC_ATTR_CONSTRAINTS(), +d2i_OSSL_CMP_ATAVS(), d2i_OSSL_IETF_ATTR_SYNTAX(), +d2i_OSSL_TARGET(), d2i_OSSL_TARGETING_INFORMATION(), +d2i_OSSL_TARGETS(), d2i_OSSL_USER_NOTICE_SYNTAX(), +d2i_PBMAC1PARAM(), d2i_X509_ACERT(), d2i_X509_ACERT_bio(), +d2i_X509_ACERT_fp(), i2d_OSSL_ATTRIBUTES_SYNTAX(), +i2d_OSSL_BASIC_ATTR_CONSTRAINTS(), i2d_OSSL_CMP_ATAVS(), +i2d_OSSL_IETF_ATTR_SYNTAX(), i2d_OSSL_TARGET(), +i2d_OSSL_TARGETING_INFORMATION(), i2d_OSSL_TARGETS(), +i2d_OSSL_USER_NOTICE_SYNTAX(), i2d_PBMAC1PARAM(), i2d_X509_ACERT(), +i2d_X509_ACERT_bio(), i2d_X509_ACERT_fp() +were added in OpenSSL 3.4. + +d2i_OSSL_AA_DIST_POINT(), +d2i_OSSL_ALLOWED_ATTRIBUTES_CHOICE(), d2i_OSSL_ALLOWED_ATTRIBUTES_ITEM(), +d2i_OSSL_ALLOWED_ATTRIBUTES_SYNTAX(), +d2i_OSSL_ATAV(), d2i_OSSL_ATTRIBUTE_DESCRIPTOR(), d2i_OSSL_ATTRIBUTE_MAPPING(), +d2i_OSSL_ATTRIBUTE_MAPPINGS(), d2i_OSSL_ATTRIBUTE_TYPE_MAPPING(), +d2i_OSSL_ATTRIBUTE_VALUE_MAPPING(), d2i_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX(), +d2i_OSSL_HASH(), d2i_OSSL_INFO_SYNTAX(), +d2i_OSSL_INFO_SYNTAX_POINTER(), d2i_OSSL_PRIVILEGE_POLICY_ID(), +d2i_OSSL_ROLE_SPEC_CERT_ID(), d2i_OSSL_ROLE_SPEC_CERT_ID_SYNTAX(), +i2d_OSSL_AA_DIST_POINT(), +i2d_OSSL_ALLOWED_ATTRIBUTES_CHOICE(), i2d_OSSL_ALLOWED_ATTRIBUTES_ITEM(), +i2d_OSSL_ALLOWED_ATTRIBUTES_SYNTAX(), +i2d_OSSL_ATAV(), i2d_OSSL_ATTRIBUTE_DESCRIPTOR(), i2d_OSSL_ATTRIBUTE_MAPPING(), +i2d_OSSL_ATTRIBUTE_MAPPINGS(), i2d_OSSL_ATTRIBUTE_TYPE_MAPPING(), +i2d_OSSL_ATTRIBUTE_VALUE_MAPPING(), i2d_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX(), +i2d_OSSL_HASH(), i2d_OSSL_INFO_SYNTAX(), +i2d_OSSL_INFO_SYNTAX_POINTER(), i2d_OSSL_PRIVILEGE_POLICY_ID(), +i2d_OSSL_ROLE_SPEC_CERT_ID(), i2d_OSSL_ROLE_SPEC_CERT_ID_SYNTAX(), +d2i_OSSL_CRMF_ENCRYPTEDKEY(), i2d_OSSL_CRMF_ENCRYPTEDKEY(), +d2i_OSSL_DAY_TIME(), d2i_OSSL_DAY_TIME_BAND(), d2i_OSSL_NAMED_DAY(), +d2i_OSSL_TIME_PERIOD(), d2i_OSSL_TIME_SPEC(), +d2i_OSSL_TIME_SPEC_ABSOLUTE(), d2i_OSSL_TIME_SPEC_DAY(), +d2i_OSSL_TIME_SPEC_MONTH(), d2i_OSSL_TIME_SPEC_TIME(), +d2i_OSSL_TIME_SPEC_WEEKS(), d2i_OSSL_TIME_SPEC_X_DAY_OF(), +i2d_OSSL_DAY_TIME(), i2d_OSSL_DAY_TIME_BAND(), +i2d_OSSL_NAMED_DAY(), i2d_OSSL_TIME_PERIOD(), +i2d_OSSL_TIME_SPEC(), i2d_OSSL_TIME_SPEC_ABSOLUTE(), +i2d_OSSL_TIME_SPEC_DAY(), i2d_OSSL_TIME_SPEC_MONTH(), +i2d_OSSL_TIME_SPEC_TIME(), i2d_OSSL_TIME_SPEC_WEEKS(), +i2d_OSSL_TIME_SPEC_X_DAY_OF() +were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 1998-2024 The OpenSSL Project Authors. All Rights Reserved. +Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man3/i2d_re_X509_tbs.pod b/doc/man3/i2d_re_X509_tbs.pod index d9247794fc59..bdb9bff6d681 100644 --- a/doc/man3/i2d_re_X509_tbs.pod +++ b/doc/man3/i2d_re_X509_tbs.pod @@ -78,7 +78,7 @@ L =head1 COPYRIGHT -Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 8d312c661fa0..e24ea0c59541 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -265,8 +265,19 @@ Specifies the pathname of the module (typically a shared library) to load. =item B -If present, the module is activated. The value assigned to this name is not -significant. +If present and set to one of the values yes, on, true or 1, then the associated +provider will be activated. Conversely, setting this value to no, off, false, or +0 will prevent the provider from being activated. Settings can be given in lower +or uppercase. Setting activate to any other setting, or omitting a setting +value will result in an error. + += item B + +If enabled, informs the library to clear the error stack on failure to activate +requested provider. A value of 1, yes, true or on (in lower or uppercase) will +activate this setting, while a value of 0, no, false, or off (again in lower or +uppercase) will disable this setting. Any other value will produce an error. +Note this setting defaults to off if not provided =back @@ -467,6 +478,12 @@ to access the same randomness sources from outside the validated boundary. This sets the property query used when fetching the randomness source. +=item B + +This sets the provider to use for the L calls instead of the built-in +entropy sources. It defaults to "fips". If the named provider is not loaded, the +built-in entropy sources will be used. + =back =head1 EXAMPLES @@ -570,12 +587,13 @@ L, L, L, L, +L, L, and L. =head1 COPYRIGHT -Copyright 2000-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man5/fips_config.pod b/doc/man5/fips_config.pod index cd0012a73a10..a25ced338393 100644 --- a/doc/man5/fips_config.pod +++ b/doc/man5/fips_config.pod @@ -39,10 +39,6 @@ section, as described in L. If present, the module is activated. The value assigned to this name is not significant. -=item B - -A version number for the fips install process. Should be 1. - =item B The FIPS module normally enters an internal error mode if any self test fails. @@ -56,18 +52,14 @@ Regardless of the value, the operation (e.g., key generation) that called the continuous test will return an error code if its continuous test fails. The operation may then be retried if the error mode has not been triggered. -=item B - -This indicates if run-time checks related to enforcement of security parameters -such as minimum security strength of keys and approved curve names are used. -A value of '1' will perform the checks, otherwise if the value is '0' the checks -are not performed and FIPS compliance must be done by procedures documented in -the relevant Security Policy. - =item B The calculated MAC of the FIPS provider file. +=item B + +A version number for the fips install process. Should be 1. + =item B An indicator that the self-tests were successfully run. @@ -84,6 +76,134 @@ It is written-to at the same time as B is updated. =back +=head2 FIPS indicator options + +The following FIPS configuration options indicate if run-time checks related to +enforcement of FIPS security parameters such as minimum security strength of +keys and approved curve names are used. +A value of '1' will perform the checks, otherwise if the value is '0' the checks +are not performed and FIPS compliance must be done by procedures documented in +the relevant Security Policy. + +See L for further information related to these +options. + +=over 4 + +=item B + +See L B<-no_security_checks> + +=item B + +See L B<-ems_check> + +=item B + +See L B<-no_short_mac> + +=item B + +See L B<-no_drbg_truncated_digests> + +=item B + +See L B<-signature_digest_check> + +=item B + +See L B<-hkdf_digest_check> + +=item B + +See L B<-tls13_kdf_digest_check> + +=item B + +See L B<-tls1_prf_digest_check> + +=item B + +See L B<-sshkdf_digest_check> + +=item B + +See L B<-sskdf_digest_check> + +=item B + +See L B<-x963kdf_digest_check> + +=item B + +See L B<-dsa_sign_disabled> + +=item B + +See L B<-tdes_encrypt_disabled> + +=item B + +See L B<-rsa_pkcs15_pad_disabled> + +=item B + +See L B<-rsa_pss_saltlen_check> + +=item B + +See L B<-rsa_sign_x931_disabled> + +=item B + +See L B<-hkdf_key_check> + +=item B + +See L B<-kbkdf_key_check> + +=item B + +See L B<-tls13_kdf_key_check> + +=item B + +See L B<-tls1_prf_key_check> + +=item B + +See L B<-sshkdf_key_check> + +=item B + +See L B<-sskdf_key_check> + +=item B + +See L B<-x963kdf_key_check> + +=item B + +See L B<-x942kdf_key_check> + +=item B + +See L B<-no_pbkdf2_lower_bound_check> + +=item B + +See L B<-ecdh_cofactor_check> + +=item B + +See L B<-hmac_key_check> + +=item B + +See L B<-kmac_key_check> + +=back + For example: [fips_sect] @@ -113,7 +233,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man5/x509v3_config.pod b/doc/man5/x509v3_config.pod index 044904022d89..ab33b7e7afe0 100644 --- a/doc/man5/x509v3_config.pod +++ b/doc/man5/x509v3_config.pod @@ -173,14 +173,27 @@ Examples: =head2 Subject Key Identifier The SKID extension specification has a value with three choices. -If the value is the word B then no SKID extension will be included. -If the value is the word B, or by default for the B, B, and -B apps, the process specified in RFC 5280 section 4.2.1.2. (1) is followed: + +=over 4 + +=item B + +No SKID extension will be included. + +=item B + +The process specified in RFC 5280 section 4.2.1.2. (1) is followed: The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits). -Otherwise, the value must be a hex string (possibly with C<:> separating bytes) -to output directly, however, this is strongly discouraged. +=item A hex string (possibly with C<:> separating bytes) + +The provided value is output directly. +This choice is strongly discouraged. + +=back + +By default the B, B, and B apps behave as if B was given. Example: @@ -195,8 +208,9 @@ or both of them, separated by C<,>. Either or both can have the option B, indicated by putting a colon C<:> between the value and this option. For self-signed certificates the AKID is suppressed unless B is present. -By default the B, B, and B apps behave as if -"none" was given for self-signed certificates and "keyid, issuer" otherwise. + +By default the B, B, and B apps behave as if B was given +for self-signed certificates and BC<,> B otherwise. If B is present, an attempt is made to copy the subject key identifier (SKID) from the issuer certificate except if @@ -208,6 +222,7 @@ If B is present but no value can be obtained, an error is returned. If B is present, and in addition it has the option B specified or B is not present, then the issuer DN and serial number are copied from the issuer certificate. +If this fails, an error is returned. Examples: diff --git a/doc/man7/EVP_ASYM_CIPHER-RSA.pod b/doc/man7/EVP_ASYM_CIPHER-RSA.pod index c68cad6c42f9..171a3d130ec0 100644 --- a/doc/man7/EVP_ASYM_CIPHER-RSA.pod +++ b/doc/man7/EVP_ASYM_CIPHER-RSA.pod @@ -25,6 +25,10 @@ The default provider understands these RSA padding modes in string form: =item "pkcs1" (B) +This padding mode is no longer supported by the FIPS provider for key +agreement and key transport. +(This is a FIPS 140-3 requirement) + =item "x931" (B) =back @@ -37,6 +41,10 @@ The default provider understands these RSA padding modes in integer form: =item 1 (B) +This padding mode is no longer supported by the FIPS provider for key +agreement and key transport. +(This is a FIPS 140-3 requirement) + =item 3 (B) =item 4 (B) @@ -69,6 +77,27 @@ See L for more information =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +=item "key-check" (B) + +See L for more information. + +=item "pkcs15-pad-disabled" (B) + +The default value of 1 causes an error during encryption if the RSA padding +mode is set to "pkcs1". +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 SEE ALSO L, @@ -80,7 +109,7 @@ L =head1 COPYRIGHT -Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_CIPHER-AES.pod b/doc/man7/EVP_CIPHER-AES.pod index 3313245f9842..7bd3746c9ba2 100644 --- a/doc/man7/EVP_CIPHER-AES.pod +++ b/doc/man7/EVP_CIPHER-AES.pod @@ -54,6 +54,8 @@ FIPS provider: =item "AES-128-SIV", "AES-192-SIV" and "AES-256-SIV" +=item "AES-128-GCM-SIV", "AES-192-GCM-SIV" and "AES-256-GCM-SIV" + =back =head2 Parameters @@ -78,9 +80,13 @@ stealing (CTS) is used to fill the block. L, L, L +=head1 HISTORY + +The GCM-SIV mode ciphers were added in OpenSSL version 3.2. + =head1 COPYRIGHT -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 diff --git a/doc/man7/EVP_CIPHER-DES.pod b/doc/man7/EVP_CIPHER-DES.pod index 25603f6fc676..7ece7c5e0f6e 100644 --- a/doc/man7/EVP_CIPHER-DES.pod +++ b/doc/man7/EVP_CIPHER-DES.pod @@ -59,7 +59,7 @@ The following algorithms are available in the legacy provider: =head2 Parameters This implementation supports the parameters described in -L. +L including "encrypt-check" and "fips-indicator". =head1 SEE ALSO @@ -68,7 +68,7 @@ L, =head1 COPYRIGHT -Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_CIPHER-SM4.pod b/doc/man7/EVP_CIPHER-SM4.pod index 36a51d18a423..a446fafb6d4b 100644 --- a/doc/man7/EVP_CIPHER-SM4.pod +++ b/doc/man7/EVP_CIPHER-SM4.pod @@ -24,6 +24,12 @@ The following algorithms are available in the default provider: =item "SM4-CFB" or "SM4-CFB128" +=item "SM4-GCM" + +=item "SM4-CCM" + +=item "SM4-XTS" + =back =head2 Parameters @@ -31,6 +37,15 @@ The following algorithms are available in the default provider: This implementation supports the parameters described in L. +=head1 NOTES + +The SM4-XTS implementation allows streaming to be performed, but each +L or L call requires each input +to be a multiple of the blocksize. Only the final EVP_EncryptUpdate() or +EVP_DecryptUpdate() call can optionally have an input that is not a multiple +of the blocksize but is larger than one block. In that case ciphertext +stealing (CTS) is used to fill the block. + =head1 SEE ALSO L, L diff --git a/doc/man7/EVP_KDF-HKDF.pod b/doc/man7/EVP_KDF-HKDF.pod index b563efa5f5d7..a269fbeabeb9 100644 --- a/doc/man7/EVP_KDF-HKDF.pod +++ b/doc/man7/EVP_KDF-HKDF.pod @@ -84,6 +84,28 @@ an error will occur. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if "key-check" +is set to 0 and the check fails. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES A context for HKDF can be obtained by calling: @@ -148,7 +170,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-KB.pod b/doc/man7/EVP_KDF-KB.pod index 78b81673a5bd..0e63fb5b3355 100644 --- a/doc/man7/EVP_KDF-KB.pod +++ b/doc/man7/EVP_KDF-KB.pod @@ -31,7 +31,7 @@ used if unspecified. =item "mac" (B) -The value is either CMAC or HMAC. +The value is either CMAC, HMAC, KMAC128 or KMAC256. =item "digest" (B) @@ -60,10 +60,39 @@ Set to B<0> to disable use of the optional Fixed Input data 'zero separator' (see SP800-108) that is placed between the Label and Context. The default value of B<1> will be used if unspecified. +=item "r" (B) + +Set the fixed value 'r', indicating the length of the counter in bits. + +Supported values are B<8>, B<16>, B<24>, and B<32>. +The default value of B<32> will be used if unspecified. + +=back + +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if "key-check" +is set to 0 and the check fails. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + =back Depending on whether mac is CMAC or HMAC, either digest or cipher is required -(respectively) and the other is unused. +(respectively) and the other is unused. They are unused for KMAC128 and KMAC256. The parameters key, salt, info, and seed correspond to KI, Label, Context, and IV (respectively) in SP800-108. As in that document, salt, info, and seed are @@ -161,9 +190,11 @@ L This functionality was added in OpenSSL 3.0. +Support for KMAC was added in OpenSSL 3.1. + =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Copyright 2019 Red Hat, Inc. Licensed under the Apache License 2.0 (the "License"). You may not use diff --git a/doc/man7/EVP_KDF-PBKDF1.pod b/doc/man7/EVP_KDF-PBKDF1.pod index c73ad6a9ec38..4b68b2293de6 100644 --- a/doc/man7/EVP_KDF-PBKDF1.pod +++ b/doc/man7/EVP_KDF-PBKDF1.pod @@ -53,6 +53,8 @@ of candidate passwords. No assumption is made regarding the given password; it is simply treated as a byte sequence. +The legacy provider needs to be available in order to access this algorithm. + =head1 CONFORMING TO RFC 8018 @@ -64,7 +66,8 @@ L, L, L, L, -L +L, +L =head1 HISTORY diff --git a/doc/man7/EVP_KDF-PBKDF2.pod b/doc/man7/EVP_KDF-PBKDF2.pod index 9a90f7583abe..8af7fd78f17d 100644 --- a/doc/man7/EVP_KDF-PBKDF2.pod +++ b/doc/man7/EVP_KDF-PBKDF2.pod @@ -59,8 +59,17 @@ The checks performed are: The default provider uses a default mode of 1 for backwards compatibility, and the FIPS provider uses a default mode of 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. -The value string is expected to be a decimal number 0 or 1. +=item "fips-indicator" (B) + +This option is used by the OpenSSL FIPS provider. + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if "pkcs5" +is set to 1 and the derived key length, salt length or iteration count test +fails. =back @@ -96,7 +105,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-SS.pod b/doc/man7/EVP_KDF-SS.pod index 6640703eef1c..acd2df00b210 100644 --- a/doc/man7/EVP_KDF-SS.pod +++ b/doc/man7/EVP_KDF-SS.pod @@ -65,6 +65,28 @@ This parameter sets an optional value for fixedinfo, also known as otherinfo. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if "key-check" +is set to 0 and the check fails. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES A context for SSKDF can be obtained by calling: @@ -179,7 +201,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. Copyright +Copyright 2019-2024 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 diff --git a/doc/man7/EVP_KDF-SSHKDF.pod b/doc/man7/EVP_KDF-SSHKDF.pod index a5b153947558..e9531a8296e5 100644 --- a/doc/man7/EVP_KDF-SSHKDF.pod +++ b/doc/man7/EVP_KDF-SSHKDF.pod @@ -84,6 +84,40 @@ A single char of value 70 (ASCII char 'F'). =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if any "***-check" +related parameter is set to 0 and the check fails. + +=item "digest-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if +used digest is not approved. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +According to SP 800-135r1, the following are approved digest algorithms: SHA-1, +SHA2-224, SHA2-256, SHA2-384, SHA2-512. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES A context for SSHKDF can be obtained by calling: @@ -152,7 +186,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-TLS13_KDF.pod b/doc/man7/EVP_KDF-TLS13_KDF.pod index 7fad55ca61f1..d2805005913c 100644 --- a/doc/man7/EVP_KDF-TLS13_KDF.pod +++ b/doc/man7/EVP_KDF-TLS13_KDF.pod @@ -81,6 +81,40 @@ an error will occur. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if any "***-check" +related parameter is set to 0 and the check fails. + +=item "digest-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if +used digest is not approved. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +According to RFC 8446, the following are approved digest algorithms: SHA2-256, +SHA2-384. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES This KDF is intended for use by the TLS 1.3 implementation in libssl. @@ -124,7 +158,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-TLS1_PRF.pod b/doc/man7/EVP_KDF-TLS1_PRF.pod index 90b357e70f0b..a80915364a8f 100644 --- a/doc/man7/EVP_KDF-TLS1_PRF.pod +++ b/doc/man7/EVP_KDF-TLS1_PRF.pod @@ -48,6 +48,48 @@ this should be more than enough for any normal use of the TLS PRF. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if any "***-check" +related parameter is set to 0 and the check fails. + +=item "ems_check" (B) + +The default value of 1 causes an error during EVP_KDF_derive() if +"master secret" is used instead of "extended master secret" Setting this to zero +will ignore the error and set the approved "fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=item "digest-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if +used digest is not approved. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +According to SP 800-135r1, the following are approved digest algorithms: +SHA2-256, SHA2-384, SHA2-512. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES A context for the TLS PRF can be obtained by calling: @@ -106,7 +148,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-X942-ASN1.pod b/doc/man7/EVP_KDF-X942-ASN1.pod index 17464738b511..b4d27a107829 100644 --- a/doc/man7/EVP_KDF-X942-ASN1.pod +++ b/doc/man7/EVP_KDF-X942-ASN1.pod @@ -79,6 +79,28 @@ Valid values are "AES-128-WRAP", "AES-192-WRAP", "AES-256-WRAP" and "DES3-WRAP". =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if "key-check" +parameter is set to 0 and the check fails. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES A context for X942KDF can be obtained by calling: @@ -143,7 +165,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KDF-X963.pod b/doc/man7/EVP_KDF-X963.pod index ca2f7c1df0ef..2df67a728e47 100644 --- a/doc/man7/EVP_KDF-X963.pod +++ b/doc/man7/EVP_KDF-X963.pod @@ -40,6 +40,41 @@ This parameter specifies an optional value for shared info. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if any "***-check" +related parameter is set to 0 and the check fails. + +=item "digest-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if +used digest is not approved. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +According to ANSI X9.63-2001, the following are approved digest algorithms: +SHA2-224, SHA2-256, SHA2-384, SHA2-512, SHA2-512/224, SHA2-512/256, SHA3-224, +SHA3-256, SHA3-384, SHA3-512. + +=item "key-check" (B) + +The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the +length of used key-derivation key (B) is shorter than 112 +bits. +Setting this to zero will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 NOTES X963KDF is very similar to the SSKDF that uses a digest as the auxiliary function, @@ -100,7 +135,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KEM-RSA.pod b/doc/man7/EVP_KEM-RSA.pod index 3a89f5db39a3..af70fdc01700 100644 --- a/doc/man7/EVP_KEM-RSA.pod +++ b/doc/man7/EVP_KEM-RSA.pod @@ -17,7 +17,7 @@ See L and L for more info. =item "operation" (B) The OpenSSL RSA Key Encapsulation Mechanism only currently supports the -following operation +following default operation (operating mode): =over 4 @@ -31,8 +31,13 @@ The decapsulate function recovers the secret using the RSA private key. This can be set using EVP_PKEY_CTX_set_kem_op(). -=back +=item "fips-indicator" (B) +=item "key-check" (B) + +These parameters are described in L. + +=back =head1 CONFORMING TO @@ -58,9 +63,13 @@ L This functionality was added in OpenSSL 3.0. +The C (operating mode) was a required parameter prior to OpenSSL 3.5. +As of OpenSSL 3.5, C is the default operating mode, and no explicit +value need be specified. + =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KEYEXCH-DH.pod b/doc/man7/EVP_KEYEXCH-DH.pod index eaec67775ddb..a6bcc06ed81f 100644 --- a/doc/man7/EVP_KEYEXCH-DH.pod +++ b/doc/man7/EVP_KEYEXCH-DH.pod @@ -33,22 +33,20 @@ the KDF type is set to "X942KDF-ASN1" (B). =item "kdf-type" (B) -See L. - =item "kdf-digest" (B) -See L. - =item "kdf-digest-props" (B) -See L. - =item "kdf-outlen" (B) -See L. - =item "kdf-ukm" (B) +=item "fips-indicator" (B) + +=item "key-check" (B) + +=item "digest-check" (B) + See L. =item "cekalg" (B) diff --git a/doc/man7/EVP_KEYEXCH-ECDH.pod b/doc/man7/EVP_KEYEXCH-ECDH.pod index 3d630d91bf65..280338ee9233 100644 --- a/doc/man7/EVP_KEYEXCH-ECDH.pod +++ b/doc/man7/EVP_KEYEXCH-ECDH.pod @@ -33,28 +33,44 @@ per-key basis. =item "kdf-type" (B) -See L. - =item "kdf-digest" (B) -See L. - =item "kdf-digest-props" (B) -See L. - =item "kdf-outlen" (B) -See L. - =item "kdf-ukm" (B) +=back + +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +=item "key-check" (B) + +=item "digest-check" (B) + See L. +=item "ecdh-cofactor-check" (B) + +If required this parameter should before OSSL_FUNC_keyexch_derive(). +The default value of 1 causes an error during the OSSL_FUNC_keyexch_derive if +the EC curve has a cofactor that is not 1, and the cofactor is not used. +Setting this to 0 will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + =back =head1 EXAMPLES +Examples of key agreement can be found in demos/keyexch. + Keys for the host and peer must be generated as shown in L using the same curve name. @@ -107,7 +123,7 @@ L, =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_KEYEXCH-X25519.pod b/doc/man7/EVP_KEYEXCH-X25519.pod index 6140c56196e4..5b2745da7760 100644 --- a/doc/man7/EVP_KEYEXCH-X25519.pod +++ b/doc/man7/EVP_KEYEXCH-X25519.pod @@ -16,6 +16,11 @@ Key exchange support for the B and B key types. =item "pad" (B) +=item "fips-indicator" (B) + +B and B are not FIPS approved in FIPS 140-3. +So this getter will return 0. + See L. =back @@ -40,7 +45,7 @@ L, =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MAC-CMAC.pod b/doc/man7/EVP_MAC-CMAC.pod index 0b1dc79eb3de..6405530182b0 100644 --- a/doc/man7/EVP_MAC-CMAC.pod +++ b/doc/man7/EVP_MAC-CMAC.pod @@ -38,7 +38,8 @@ Setting this parameter is identical to passing a I to L. =item "cipher" (B) -Sets the name of the underlying cipher to be used. +Sets the name of the underlying cipher to be used. The mode of the cipher +must be CBC. =item "properties" (B) @@ -46,6 +47,18 @@ Sets the properties to be queried when trying to fetch the underlying cipher. This must be given together with the cipher naming parameter to be considered valid. +=item "encrypt-check" (B) + +This option is used by the OpenSSL FIPS provider. +If required this parameter should be set before EVP_MAC_init() + +The default value of 1 causes an error when a unapproved Triple-DES encryption +operation is triggered. +Setting this to 0 will ignore the error and set the approved +"fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + =back The following parameters can be retrieved with @@ -58,15 +71,20 @@ EVP_MAC_CTX_get_params(): The "size" parameter can also be retrieved with with EVP_MAC_CTX_get_mac_size(). The length of the "size" parameter is equal to that of an B. -=back - -=over 4 =item "block-size" (B) Gets the MAC block size. The "block-size" parameter can also be retrieved with EVP_MAC_CTX_get_block_size(). +=item "fips-indicator" (B) + +This option is used by the OpenSSL FIPS provider. + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_MAC_final(). +It may return 0 if the "encrypt-check" option is set to 0. + =back =head1 SEE ALSO @@ -76,7 +94,7 @@ L, L =head1 COPYRIGHT -Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MAC-HMAC.pod b/doc/man7/EVP_MAC-HMAC.pod index 0e401710fc92..fb601a1b917f 100644 --- a/doc/man7/EVP_MAC-HMAC.pod +++ b/doc/man7/EVP_MAC-HMAC.pod @@ -27,7 +27,7 @@ used with EVP_MAC_fetch(): The general description of these parameters can be found in L. -The following parameter can be set with EVP_MAC_CTX_set_params(): +The following parameters can be set with EVP_MAC_CTX_set_params(): =over 4 @@ -51,19 +51,27 @@ B) to be considered valid. A flag to set the MAC digest to not initialise the implementation specific data. The value 0 or 1 is expected. +This option is deprecated and will be removed in a future release. +It may be set but is currently ignored =item "digest-oneshot" (B) A flag to set the MAC digest to be a one-shot operation. The value 0 or 1 is expected. +This option is deprecated and will be removed in a future release. +It may be set but is currently ignored. =item "tls-data-size" (B) +=item "key-check" (B) + +See L. + =back =for comment The "flags" parameter is passed directly to HMAC_CTX_set_flags(). -The following parameter can be retrieved with EVP_MAC_CTX_get_params(): +The following parameters can be retrieved with EVP_MAC_CTX_get_params(): =over 4 @@ -72,15 +80,15 @@ The following parameter can be retrieved with EVP_MAC_CTX_get_params(): The "size" parameter can also be retrieved with EVP_MAC_CTX_get_mac_size(). The length of the "size" parameter is equal to that of an B. -=back - -=over 4 - =item "block-size" (B) Gets the MAC block size. The "block-size" parameter can also be retrieved with EVP_MAC_CTX_get_block_size(). +=item "fips-indicator" (B) + +See L. + =back =head1 SEE ALSO @@ -90,7 +98,7 @@ L, L, L =head1 COPYRIGHT -Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MAC-KMAC.pod b/doc/man7/EVP_MAC-KMAC.pod index 9c4fbc0b2ad9..2031715167c5 100644 --- a/doc/man7/EVP_MAC-KMAC.pod +++ b/doc/man7/EVP_MAC-KMAC.pod @@ -35,7 +35,6 @@ The length of the "size" parameter should not exceed that of a B. Likewise, the "block-size" parameter can be retrieved with EVP_MAC_CTX_get_params(), or with EVP_MAC_CTX_get_block_size(). - =over 4 =item "key" (B) @@ -65,9 +64,24 @@ It is 168 for C and 136 for C. The "xof" parameter value is expected to be 1 or 0. Use 1 to enable XOF mode. The default value is 0. +=item "fips-indicator" (B) + +This settable parameter is described in L. + +=item "no-short-mac" (B) + +This settable parameter is described in L. It is used by +the OpenSSL FIPS provider and the minimum length output for KMAC +is defined by NIST's SP 800-185 8.4.2. + +=item "key-check" (B) + +This settable parameter is described in L. + =back -The "custom" parameter must be set as part of or before the EVP_MAC_init() call. +The "custom" and "no-short-mac" parameters must be set as part of or before +the EVP_MAC_init() call. The "xof" and "size" parameters can be set at any time before EVP_MAC_final(). The "key" parameter is set as part of the EVP_MAC_init() call, but can be set before it instead. @@ -140,11 +154,12 @@ set before it instead. =head1 SEE ALSO L, L, -L, L +L, L, +L =head1 COPYRIGHT -Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MD-BLAKE2.pod b/doc/man7/EVP_MD-BLAKE2.pod index f72d3da1ce8e..62bb8a728a6e 100644 --- a/doc/man7/EVP_MD-BLAKE2.pod +++ b/doc/man7/EVP_MD-BLAKE2.pod @@ -25,18 +25,56 @@ Known names are "BLAKE2B-512" and "BLAKE2b512". =back +=head2 Settable Parameters + +"BLAKE2B-512" supports the following EVP_MD_CTX_set_params() key +described in L. + +=over 4 + +=item "size" (B) + +=back + =head2 Gettable Parameters This implementation supports the common gettable parameters described in L. +=head2 Settable Context Parameters + +The implementation supports the following L entries which +are settable for an B with L or +L: + +=over 4 + +=item "size" (B) + +Sets a different digest length for the L output. +The value of the "size" parameter must not exceed the default digest length +of the respective BLAKE2 algorithm variants, 64 for BLAKE2B-512 and +32 for BLAKE2S-256. The parameter must be set with the +L call to have an immediate effect. When set with +L it will have an effect only if the B +context is reinitialized. + +=back + =head1 SEE ALSO L, L +=head1 HISTORY + +This functionality was added in OpenSSL 3.0. + +The variable size support was added in OpenSSL 3.2 for BLAKE2B-512 and +in OpenSSL 3.3 for BLAKE2S-256. + =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MD-RIPEMD160.pod b/doc/man7/EVP_MD-RIPEMD160.pod index 0bf680d2d52c..2e3361b23a50 100644 --- a/doc/man7/EVP_MD-RIPEMD160.pod +++ b/doc/man7/EVP_MD-RIPEMD160.pod @@ -29,7 +29,7 @@ This digest was added to the default provider in OpenSSL 3.0.7. =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MD-SHA2.pod b/doc/man7/EVP_MD-SHA2.pod index 2a2e799d8954..6266bf659e75 100644 --- a/doc/man7/EVP_MD-SHA2.pod +++ b/doc/man7/EVP_MD-SHA2.pod @@ -44,6 +44,10 @@ Available with the default provider: =over 4 +=item SHA2-256/192 + +Known names are "SHA2-256/192", "SHA-256/192" and "SHA256-192". + =item SHA2-512/224 Known names are "SHA2-512/224", "SHA-512/224" and "SHA512-224". @@ -67,7 +71,7 @@ L, L, L =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 diff --git a/doc/man7/EVP_MD-SHAKE.pod b/doc/man7/EVP_MD-SHAKE.pod index fc1822f962a1..343349d92ee1 100644 --- a/doc/man7/EVP_MD-SHAKE.pod +++ b/doc/man7/EVP_MD-SHAKE.pod @@ -45,40 +45,53 @@ Known names are "SHAKE-256" and "SHAKE256". =back -=head2 Gettable Parameters +=head2 Parameters -This implementation supports the common gettable parameters described -in L. - -=head2 Settable Context Parameters - -These implementations support the following L entries, -settable for an B with L: +This implementation supports the following L entries: =over 4 =item "xoflen" (B) -Sets the digest length for extendable output functions. +Sets or Gets the digest length for extendable output functions. The length of the "xoflen" parameter should not exceed that of a B. -For backwards compatibility reasons the default xoflen length for SHAKE-128 is -16 (bytes) which results in a security strength of only 64 bits. To ensure the -maximum security strength of 128 bits, the xoflen should be set to at least 32. +The SHAKE-128 and SHAKE-256 implementations do not have any default digest +length. -For backwards compatibility reasons the default xoflen length for SHAKE-256 is -32 (bytes) which results in a security strength of only 128 bits. To ensure the -maximum security strength of 256 bits, the xoflen should be set to at least 64. +This parameter must be set before calling either EVP_DigestFinal_ex() or +EVP_DigestFinal(), since these functions were not designed to handle variable +length output. It is recommended to either use EVP_DigestSqueeze() or +EVP_DigestFinalXOF() instead. + +=item "size" (B) + +An alias of "xoflen". =back +See L for further information related to parameters + +=head1 NOTES + +For SHAKE-128, to ensure the maximum security strength of 128 bits, the output +length passed to EVP_DigestFinalXOF() should be at least 32. + +For SHAKE-256, to ensure the maximum security strength of 256 bits, the output +length passed to EVP_DigestFinalXOF() should be at least 64. + =head1 SEE ALSO L, L, L +=head1 HISTORY + +Since OpenSSL 3.4 the SHAKE-128 and SHAKE-256 implementations have no default +digest length. + =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_MD-common.pod b/doc/man7/EVP_MD-common.pod index afbb91ec07b2..5a6b5b94f79e 100644 --- a/doc/man7/EVP_MD-common.pod +++ b/doc/man7/EVP_MD-common.pod @@ -48,11 +48,11 @@ This value can also be retrieved with L. =head1 SEE ALSO -L, L +L, L, L =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-DSA.pod b/doc/man7/EVP_PKEY-DSA.pod index cdafc0edad5c..f3bed36f88a4 100644 --- a/doc/man7/EVP_PKEY-DSA.pod +++ b/doc/man7/EVP_PKEY-DSA.pod @@ -6,18 +6,33 @@ EVP_PKEY-DSA, EVP_KEYMGMT-DSA - EVP_PKEY DSA keytype and algorithm support =head1 DESCRIPTION -For B the FIPS186-4 standard specifies that the values used for FFC +For B the FIPS 186-4 standard specifies that the values used for FFC parameter generation are also required for parameter validation. This means that optional FFC domain parameter values for I, I and I may need to be stored for validation purposes. For B these fields are not stored in the ASN1 data so they need to be stored externally if validation is required. +As part of FIPS 140-3 DSA is not longer FIPS approved for key generation and +signature validation, but is still allowed for signature verification. + =head2 DSA parameters The B key type supports the FFC parameters (see L). +It also supports the following parameters: + +=over 4 + +=item "sign-check" (B) ) + +See L for more information. + +=back + =head2 DSA key generation parameters The B key type supports the FFC key generation parameters (see @@ -111,9 +126,14 @@ L, L, L +=head1 HISTORY + +DSA Key generation and signature generation are no longer FIPS approved in +OpenSSL 3.4. See L for more information. + =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-EC.pod b/doc/man7/EVP_PKEY-EC.pod index 3b14e256721b..25177aa2dae8 100644 --- a/doc/man7/EVP_PKEY-EC.pod +++ b/doc/man7/EVP_PKEY-EC.pod @@ -19,7 +19,7 @@ Explicit parameters are supported for backwards compatibility 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 +The following Key generation/Gettable/Import/Export types are available for the built-in EC algorithm: =over 4 @@ -147,6 +147,14 @@ Used for getting the EC public key Y component. Getter that returns the default digest name. (Currently returns "SHA256" as of OpenSSL 3.0). +=item "dhkem-ikm" (B) + +DHKEM requires the generation of a keypair using an input key material (seed). +Use this to specify the key material used for generation of the private key. +This value should not be reused for other purposes. It can only be used +for the curves "P-256", "P-384" and "P-521" and should have a length of at least +the size of the encoded private key (i.e. 32, 48 and 66 for the listed curves). + =back The following Gettable types are also available for the built-in EC algorithm: @@ -179,6 +187,28 @@ that m > k3 > k2 > k1 > 0 =back +The following key generation settable parameter is also available for the +OpenSSL FIPS provider's EC algorithm: + +=over 4 + +=item "key-check" (B) + +See L for further information. + +=back + +The following key generation Gettable parameter is available for the OpenSSL +FIPS provider's EC algorithm: + +=over 4 + +=item "fips-indicator" (B) + +See L for further information. + +=back + =head2 EC key validation For EC keys, L behaves in the following way: @@ -272,7 +302,7 @@ L =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-FFC.pod b/doc/man7/EVP_PKEY-FFC.pod index 0b96bc24a614..7c9848676b8c 100644 --- a/doc/man7/EVP_PKEY-FFC.pod +++ b/doc/man7/EVP_PKEY-FFC.pod @@ -222,7 +222,7 @@ L, =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-RSA.pod b/doc/man7/EVP_PKEY-RSA.pod index dcd38fcee85b..9c4a615b8401 100644 --- a/doc/man7/EVP_PKEY-RSA.pod +++ b/doc/man7/EVP_PKEY-RSA.pod @@ -132,6 +132,15 @@ The RSA "e" value. The value may be any odd number greater than or equal to 65537. The default value is 65537. For legacy reasons a value of 3 is currently accepted but is deprecated. +=item "rsa-derive-from-pq" (B) + +Indicate that missing parameters not passed in the parameter list should be +derived if not provided. Setting a nonzero value will cause all +needed exponents and coefficients to be derived if not available. Setting this +option requires at least OSSL_PARAM_RSA_FACTOR1, OSSL_PARAM_RSA_FACTOR2, +and OSSL_PARAM_RSA_N to be provided. This option is ignored if +OSSL_KEYMGMT_SELECT_PRIVATE_KEY is not set in the selection parameter. + =back =head2 RSA key generation parameters for FIPS module testing @@ -264,7 +273,7 @@ L, L, L, L =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-X25519.pod b/doc/man7/EVP_PKEY-X25519.pod index 9e13e15f7f4f..666b41975391 100644 --- a/doc/man7/EVP_PKEY-X25519.pod +++ b/doc/man7/EVP_PKEY-X25519.pod @@ -13,8 +13,28 @@ implemented in OpenSSL's default and FIPS providers. These implementations support the associated key, containing the public key I and the private key I. -No additional parameters can be set during key generation. +=head2 Keygen Parameters +=over 4 + +=item "dhkem-ikm" (B) + +DHKEM requires the generation of a keypair using an input key material (seed). +Use this to specify the key material used for generation of the private key. +This value should not be reused for other purposes. +It should have a length of at least 32 for X25519, and 56 for X448. +This is only supported by X25519 and X448. + +=item "fips-indicator" (B) + +This getter is only supported by X25519 and X448 for the FIPS provider. +Since X25519 and X448 are unapproved in FIPS 140-3 this getter return 0. + +See L for further information. + +=back + +Use EVP_PKEY_CTX_set_params() after calling EVP_PKEY_keygen_init(). =head2 Common X25519, X448, ED25519 and ED448 parameters @@ -96,7 +116,7 @@ L, L =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_RAND-CTR-DRBG.pod b/doc/man7/EVP_RAND-CTR-DRBG.pod index 1012494250fb..d090c5f4fae1 100644 --- a/doc/man7/EVP_RAND-CTR-DRBG.pod +++ b/doc/man7/EVP_RAND-CTR-DRBG.pod @@ -63,7 +63,13 @@ does not. A context for CTR DRBG can be obtained by calling: EVP_RAND *rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL); - EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand); + EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL); + +The default CTR-DRBG implementation attempts to fetch the required internal +algorithms from the provider they are built into (eg the default provider) +regardless of the properties provided. Should the provider not implement +the required algorithms then properties will be used to find a different +implementation. =head1 EXAMPLES @@ -97,7 +103,7 @@ L =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_RAND-HASH-DRBG.pod b/doc/man7/EVP_RAND-HASH-DRBG.pod index 62ded203ad09..37b253584cf9 100644 --- a/doc/man7/EVP_RAND-HASH-DRBG.pod +++ b/doc/man7/EVP_RAND-HASH-DRBG.pod @@ -50,14 +50,44 @@ The supported parameters are: These parameters work as described in L. +=item "fips-indicator" (B) + +=item "digest-check" (B) + +These parameters work as described in L. + =back =head1 NOTES +When the FIPS provider is installed using the B<-no_drbg_truncated_digests> +option to fipsinstall, only these digests are permitted (as per +L): + +The default HASH-DRBG implementation attempts to fetch the required internal +algorithms from the provider they are built into (eg the default provider) +regardless of the properties provided. Should the provider not implement +the required algorithms then properties will be used to find a different +implementation. + +=over 4 + +=item SHA-1 + +=item SHA2-256 + +=item SHA2-512 + +=item SHA3-256 + +=item SHA3-512 + +=back + A context for HASH DRBG can be obtained by calling: EVP_RAND *rand = EVP_RAND_fetch(NULL, "HASH-DRBG", NULL); - EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand); + EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL); =head1 EXAMPLES @@ -86,11 +116,19 @@ NIST SP 800-90A and SP 800-90B =head1 SEE ALSO L, -L +L, +L + +=head1 HISTORY + +OpenSSL 3.1.1 introduced the B<-no_drbg_truncated_digests> option to +fipsinstall which restricts the permitted digests when using the FIPS +provider in a complaint manner. For details refer to +L. =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_RAND-HMAC-DRBG.pod b/doc/man7/EVP_RAND-HMAC-DRBG.pod index 54ae61478d79..4a4ce9517c36 100644 --- a/doc/man7/EVP_RAND-HMAC-DRBG.pod +++ b/doc/man7/EVP_RAND-HMAC-DRBG.pod @@ -52,14 +52,43 @@ The supported parameters are: These parameters work as described in L. +=item "fips-indicator" (B) + +=item "digest-check" (B) + +These parameters work as described in L. + =back =head1 NOTES +When using the FIPS provider, only these digests are permitted (as per +L): + +The default HMAC-DRBG implementation attempts to fetch the required internal +algorithms from the provider they are built into (eg the default provider) +regardless of the properties provided. Should the provider not implement +the required algorithms then properties will be used to find a different +implementation. + +=over 4 + +=item SHA-1 + +=item SHA2-256 + +=item SHA2-512 + +=item SHA3-256 + +=item SHA3-512 + +=back + A context for HMAC DRBG can be obtained by calling: EVP_RAND *rand = EVP_RAND_fetch(NULL, "HMAC-DRBG", NULL); - EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand); + EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL); =head1 EXAMPLES @@ -89,11 +118,20 @@ NIST SP 800-90A and SP 800-90B =head1 SEE ALSO L, -L +L, +L + + +=head1 HISTORY + +OpenSSL 3.1.1 introduced the B<-no_drbg_truncated_digests> option to +fipsinstall which restricts the permitted digests when using the FIPS +provider in a complaint manner. For details refer to +L). =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_RAND-SEED-SRC.pod b/doc/man7/EVP_RAND-SEED-SRC.pod index 56f4acd2b897..a00ed328d529 100644 --- a/doc/man7/EVP_RAND-SEED-SRC.pod +++ b/doc/man7/EVP_RAND-SEED-SRC.pod @@ -39,7 +39,7 @@ These parameters work as described in L. A context for the seed source can be obtained by calling: EVP_RAND *rand = EVP_RAND_fetch(NULL, "SEED-SRC", NULL); - EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand); + EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL); =head1 EXAMPLES diff --git a/doc/man7/EVP_RAND-TEST-RAND.pod b/doc/man7/EVP_RAND-TEST-RAND.pod index a5527cee3f87..44f0981d96d5 100644 --- a/doc/man7/EVP_RAND-TEST-RAND.pod +++ b/doc/man7/EVP_RAND-TEST-RAND.pod @@ -22,6 +22,8 @@ The supported parameters are: =item "state" (B) +=item "fips-indicator" (B) + These parameter works as described in L. =item "strength" (B) @@ -60,6 +62,13 @@ If there are insufficient data present to satisfy a call, an error is returned. Sets the bytes returned when the test generator is sent a nonce request. Each nonce request will return all of the bytes. +=item "generate" (B) + +If this parameter is zero, it will only emit the nonce and entropy data +supplied via the aforementioned parameters. Otherwise, low quality +non-cryptographic pseudorandom output is produced. This parameter defaults +to zero. + =back =head1 NOTES @@ -67,7 +76,7 @@ Each nonce request will return all of the bytes. A context for a test generator can be obtained by calling: EVP_RAND *rand = EVP_RAND_fetch(NULL, "TEST-RAND", NULL); - EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand); + EVP_RAND_CTX *rctx = EVP_RAND_CTX_new(rand, NULL); =head1 EXAMPLES @@ -106,7 +115,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_RAND.pod b/doc/man7/EVP_RAND.pod index 08f48fdc451a..c78a0e7f1090 100644 --- a/doc/man7/EVP_RAND.pod +++ b/doc/man7/EVP_RAND.pod @@ -224,11 +224,17 @@ but also for every generate request. =head2 Configuring the Random Seed Source In most cases OpenSSL will automatically choose a suitable seed source -for automatically seeding and reseeding its DRBG. In some cases -however, it will be necessary to explicitly specify a seed source during -configuration, using the --with-rand-seed option. For more information, -see the INSTALL instructions. There are also operating systems where no -seed source is available and automatic reseeding is disabled by default. +for automatically seeding and reseeding its DRBG. The +default seed source can be configured when OpenSSL is compiled by +setting B<-DOPENSSL_DEFAULT_SEED_SRC=SEED-SRC>. If not set then +"SEED-SRC" is used. One can specify a third-party provider seed-source, +or B<-DOPENSSL_DEFAULT_SEED_SRC=JITTER> if available. + +In some cases however, it will be necessary to explicitly specify a +seed source used by "SEED-SRC" during configuration, using the +--with-rand-seed option. For more information, see the INSTALL +instructions. There are also operating systems where no seed source is +available and automatic reseeding is disabled by default. The following two sections describe the reseeding process of the primary DRBG, depending on whether automatic reseeding is available or not. @@ -296,7 +302,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_SIGNATURE-DSA.pod b/doc/man7/EVP_SIGNATURE-DSA.pod index 326a86ee0b42..2c0f0073a4fa 100644 --- a/doc/man7/EVP_SIGNATURE-DSA.pod +++ b/doc/man7/EVP_SIGNATURE-DSA.pod @@ -12,11 +12,57 @@ L is DER encoded ASN.1 in the form described in RFC 3279, section 2.2.2. See L for information related to DSA keys. +As part of FIPS 140-3 DSA is not longer FIPS approved for key generation and +signature validation, but is still allowed for signature verification. + +=head2 Algorithm Names + +In this list, names are grouped together to signify that they are the same +algorithm having multiple names. This also includes the OID in canonical +decimal form (which means that they are possible to fetch if the caller has a +mere OID which came out in this form after a call to L). + +=over 4 + +=item "DSA", "dsaEncryption", "1.2.840.10040.4.1" + +The base signature algorithm, supported explicitly fetched with +L, and implicitly fetched (through +L) with L and +L. + +It can't be used with L + +=item "DSA-SHA1", "DSA-SHA-1", "dsaWithSHA1", "1.2.840.10040.4.3" + +=item "DSA-SHA2-224", "DSA-SHA224", "dsa_with_SHA224", "2.16.840.1.101.3.4.3.1" + +=item "DSA-SHA2-256", "DSA-SHA256", "dsa_with_SHA256", "2.16.840.1.101.3.4.3.2" + +=item "DSA-SHA2-384", "DSA-SHA384", "dsa_with_SHA384", "id-dsa-with-sha384", "1.2.840.1.101.3.4.3.3" + +=item "DSA-SHA2-512", "DSA-SHA512", "dsa_with_SHA512", "id-dsa-with-sha512", "1.2.840.1.101.3.4.3.4" + +=item "DSA-SHA3-224", "dsa_with_SHA3-224", "id-dsa-with-sha3-224", "2.16.840.1.101.3.4.3.5" + +=item "DSA-SHA3-256", "dsa_with_SHA3-256", "id-dsa-with-sha3-256", "2.16.840.1.101.3.4.3.6" + +=item "DSA-SHA3-384", "dsa_with_SHA3-384", "id-dsa-with-sha3-384", "2.16.840.1.101.3.4.3.7" + +=item "DSA-SHA3-512", "dsa_with_SHA3-512", "id-dsa-with-sha3-512", "2.16.840.1.101.3.4.3.8" + +DSA signature schemes with diverse message digest algorithms. They are all +supported explicitly fetched with L and +L. + +=back + =head2 Signature Parameters The following signature parameters can be set using EVP_PKEY_CTX_set_params(). This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(), -and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). +and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). They may also be set +using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex(). =over 4 @@ -24,6 +70,17 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "properties" (B) +These two are not supported with the DSA signature schemes that already +include a message digest algorithm, See L above. + +=item "nonce-type" (B) + +=item "key-check" (B) + +=item "digest-check" (B) + +=item "sign-check" (B) + The settable parameters are described in L. =back @@ -37,6 +94,10 @@ EVP_PKEY_CTX_get_params(). =item "digest" (B) +=item "nonce-type" (B) + +=item "fips-indicator" (B) + The gettable parameters are described in L. =back @@ -48,9 +109,14 @@ L, L, L, +=head1 HISTORY + +DSA Key generation and signature generation are no longer FIPS approved in +OpenSSL 3.4. See L for more information. + =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_SIGNATURE-ECDSA.pod b/doc/man7/EVP_SIGNATURE-ECDSA.pod index 0f6aa13c4a2f..bc75ed140814 100644 --- a/doc/man7/EVP_SIGNATURE-ECDSA.pod +++ b/doc/man7/EVP_SIGNATURE-ECDSA.pod @@ -9,6 +9,48 @@ EVP_SIGNATURE-ECDSA - The EVP_PKEY ECDSA signature implementation. Support for computing ECDSA signatures. See L for information related to EC keys. +=head2 Algorithm Names + +In this list, names are grouped together to signify that they are the same +algorithm having multiple names. This also includes the OID in canonical +decimal form (which means that they are possible to fetch if the caller has a +mere OID which came out in this form after a call to L). + +=over 4 + +=item "ECDSA" + +The base signature algorithm, supported explicitly fetched with +L, and implicitly fetched (through +L) with L and +L. + +It can't be used with L + +=item "ECDSA-SHA1", "ECDSA-SHA-1", "ecdsa-with-SHA1", "1.2.840.10045.4.1" + +=item "ECDSA-SHA2-224", "ECDSA-SHA224", "ecdsa-with-SHA224", "1.2.840.10045.4.3.1" + +=item "ECDSA-SHA2-256", "ECDSA-SHA256", "ecdsa-with-SHA256", "1.2.840.10045.4.3.2" + +=item "ECDSA-SHA2-384", "ECDSA-SHA384", "ecdsa-with-SHA384", "1.2.840.10045.4.3.3" + +=item "ECDSA-SHA2-512", "ECDSA-SHA512", "ecdsa-with-SHA512", "1.2.840.10045.4.3.4" + +=item "ECDSA-SHA3-224", "ecdsa_with_SHA3-224", "id-ecdsa-with-sha3-224", "2.16.840.1.101.3.4.3.9" + +=item "ECDSA-SHA3-256", "ecdsa_with_SHA3-256", "id-ecdsa-with-sha3-256", "2.16.840.1.101.3.4.3.10" + +=item "ECDSA-SHA3-384", "ecdsa_with_SHA3-384", "id-ecdsa-with-sha3-384", "2.16.840.1.101.3.4.3.11" + +=item "ECDSA-SHA3-512", "ecdsa_with_SHA3-512", "id-ecdsa-with-sha3-512", "2.16.840.1.101.3.4.3.12" + +ECDSA signature schemes with diverse message digest algorithms. They are all +supported explicitly fetched with L and +L. + +=back + =head2 ECDSA Signature Parameters The following signature parameters can be set using EVP_PKEY_CTX_set_params(). @@ -21,6 +63,15 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "properties" (B) +These two are not supported with the ECDSA signature schemes that already +include a message digest algorithm, See L above. + +=item "nonce-type" (B) + +=item "key-check" (B) + +=item "digest-check" (B) + These parameters are described in L. =back @@ -34,6 +85,12 @@ EVP_PKEY_CTX_get_params(). =item "digest" (B) +=item "nonce-type" (B) + +=item "fips-indicator" (B) + +=item "verify-message" (B + The parameters are described in L. =back @@ -47,7 +104,7 @@ L, =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_SIGNATURE-ED25519.pod b/doc/man7/EVP_SIGNATURE-ED25519.pod index 2183d83c2eae..924f254aad0f 100644 --- a/doc/man7/EVP_SIGNATURE-ED25519.pod +++ b/doc/man7/EVP_SIGNATURE-ED25519.pod @@ -10,16 +10,81 @@ Ed448 =head1 DESCRIPTION -The B and B EVP_PKEY implementation supports key generation, -one-shot digest sign and digest verify using PureEdDSA and B or B -(see RFC8032). It has associated private and public key formats compatible with -RFC 8410. +The B and B EVP_PKEY implementation supports key +generation, one-shot digest-sign and digest-verify using the EdDSA +signature schemes described in RFC 8032. It has associated private and +public key formats compatible with RFC 8410. + +=head2 EdDSA Instances + +RFC 8032 describes five EdDSA instances: Ed25519, Ed25519ctx, +Ed25519ph, Ed448, Ed448ph. + +The instances Ed25519, Ed25519ctx, Ed448 are referred to as B +schemes. For these three instances, the sign and verify procedures +require access to the complete message (not a digest of the message). + +The instances Ed25519ph, Ed448ph are referred to as B +schemes. For these two instances, the sign and verify procedures do +not require access to the complete message; they operate on a hash of +the message. For Ed25519ph, the hash function is SHA512. For +Ed448ph, the hash function is SHAKE256 with an output length of 512 +bits. + +The instances Ed25519ctx, Ed25519ph, Ed448, Ed448ph accept an optional +B as input to sign and verify operations (and for +Ed25519ctx, the context-string must be nonempty). For the Ed25519 +instance, a nonempty context-string is not permitted. + +These instances can be specified as signature parameters when using +L and L, see +L below. + +These instances are also explicitly fetchable as algorithms using +L, which can be used with +L, L, +L and L. =head2 ED25519 and ED448 Signature Parameters -No additional parameters can be set during one-shot signing or verification. -In particular, because PureEdDSA is used, a digest must B be specified when -signing or verifying. +Two parameters can be set during signing or verification: the EdDSA +B and the B. They can be set by +passing an OSSL_PARAM array to EVP_DigestSignInit_ex(). + +=over 4 + +=item * "instance" (B) + +One of the five strings "Ed25519", "Ed25519ctx", "Ed25519ph", "Ed448", "Ed448ph". + +"Ed25519", "Ed25519ctx", "Ed25519ph" are valid only for an Ed25519 EVP_PKEY. + +"Ed448", "Ed448ph" are valid only for an Ed448 EVP_PKEY. + +=item * "context-string" (B) + +A string of octets with length at most 255. + +=back + +Both of these parameters are optional. + +When using L or L, the +signature algorithm is derived from the key type name. The key type name +("Ed25519" or "Ed448") is also the default for the instance, but this can be +changed with the "instance" parameter. + +Note that a message digest name must B be specified when signing +or verifying. + +When using L, L, +L or L, the +instance is the explicit signature algorithm name, and may not be changed +(trying to give one with the "instance" parameter is therefore an error). + +If a context-string is not specified, then an empty context-string is +used. + See L for information related to B and B keys. The following signature parameters can be retrieved using @@ -27,19 +92,26 @@ EVP_PKEY_CTX_get_params(). =over 4 -=item "algorithm-id" (B) +=item * "algorithm-id" (B) -The parameters are described in L. +=item * "instance" (B) + +=item * "context-string" (B) =back +The parameters are described in L. + =head1 NOTES -The PureEdDSA algorithm does not support the streaming mechanism -of other signature algorithms using, for example, EVP_DigestUpdate(). +The PureEdDSA instances do not support the streaming mechanism of +other signature algorithms using, for example, EVP_DigestUpdate(). The message to sign or verify must be passed using the one-shot EVP_DigestSign() and EVP_DigestVerify() functions. +The HashEdDSA instances do not yet support the streaming mechanisms +(so the one-shot functions must be used with HashEdDSA as well). + When calling EVP_DigestSignInit() or EVP_DigestVerifyInit(), the digest I parameter B be set to NULL. @@ -64,7 +136,7 @@ specified, then both Ed25519 and Ed448 are benchmarked. =head1 EXAMPLES -To sign a message using a ED25519 or ED448 key: +To sign a message using an ED25519 EVP_PKEY structure: void do_sign(EVP_PKEY *ed_key, unsigned char *msg, size_t msg_len) { @@ -72,8 +144,16 @@ To sign a message using a ED25519 or ED448 key: unsigned char *sig = NULL; EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); - EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, ed_key); - /* Calculate the requires size for the signature by passing a NULL buffer */ + const OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string ("instance", "Ed25519ctx", 10), + OSSL_PARAM_octet_string("context-string", (unsigned char *)"A protocol defined context string", 33), + OSSL_PARAM_END + }; + + /* The input "params" is not needed if default options are acceptable. + Use NULL in place of "params" in that case. */ + EVP_DigestSignInit_ex(md_ctx, NULL, NULL, NULL, NULL, ed_key, params); + /* Calculate the required size for the signature by passing a NULL buffer. */ EVP_DigestSign(md_ctx, NULL, &sig_len, msg, msg_len); sig = OPENSSL_zalloc(sig_len); @@ -92,7 +172,7 @@ L, =head1 COPYRIGHT -Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod index 1ce32cc44368..5dc27ac2838e 100644 --- a/doc/man7/EVP_SIGNATURE-RSA.pod +++ b/doc/man7/EVP_SIGNATURE-RSA.pod @@ -10,11 +10,61 @@ EVP_SIGNATURE-RSA Support for computing RSA signatures. See L for information related to RSA keys. +=head2 Algorithm Names + +In this list, names are grouped together to signify that they are the same +algorithm having multiple names. This also includes the OID in canonical +decimal form (which means that they are possible to fetch if the caller has a +mere OID which came out in this form after a call to L). + +=over 4 + +=item "RSA", "rsaEncryption", "1.2.840.113549.1.1.1" + +The base signature algorithm, supported explicitly fetched with +L, and implicitly fetched (through +L) with L and +L. + +It can't be used with L + +=item "RSA-RIPEMD160", "ripemd160WithRSA", "1.3.36.3.3.1.2" + +=item "RSA-SHA2-256", "RSA-SHA256", "sha256WithRSAEncryption", "1.2.840.113549.1.1.11" + +=item "RSA-SHA2-384", "RSA-SHA384", "sha384WithRSAEncryption", "1.2.840.113549.1.1.12" + +=item "RSA-SHA2-512", "RSA-SHA512", "sha512WithRSAEncryption", "1.2.840.113549.1.1.13" + +=item "RSA-SHA2-224", "RSA-SHA224", "sha224WithRSAEncryption", "1.2.840.113549.1.1.14" + +=item "RSA-SHA2-512/224", "RSA-SHA512-224", "sha512-224WithRSAEncryption", "1.2.840.113549.1.1.15" + +=item "RSA-SHA2-512/256", "RSA-SHA512-256", "sha512-256WithRSAEncryption", "1.2.840.113549.1.1.16" + +=item "RSA-SHA3-224", "id-rsassa-pkcs1-v1_5-with-sha3-224", "2.16.840.1.101.3.4.3.13" + +=item "RSA-SHA3-256", "id-rsassa-pkcs1-v1_5-with-sha3-256", "2.16.840.1.101.3.4.3.14" + +=item "RSA-SHA3-384", "id-rsassa-pkcs1-v1_5-with-sha3-384", "2.16.840.1.101.3.4.3.15" + +=item "RSA-SHA3-512", "id-rsassa-pkcs1-v1_5-with-sha3-512", "2.16.840.1.101.3.4.3.16" + +=item "RSA-SM3", "sm3WithRSAEncryption", "1.2.156.10197.1.504" + +PKCS#1 v1.5 RSA signature schemes with diverse message digest algorithms. They +are all supported explicitly fetched with L and +L. +They are all pre-set to use the pad mode "pkcs1". This cannot be changed. + +=back + =head2 Signature Parameters The following signature parameters can be set using EVP_PKEY_CTX_set_params(). This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(), -and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). +and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). They may also be set +using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex(). =over 4 @@ -22,6 +72,9 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "properties" (B) +These are not supported with the RSA signature schemes that already include a +message digest algorithm, See L above. + These common parameters are described in L. =item "pad-mode" (B) @@ -36,6 +89,10 @@ The type of padding to be used. Its value can be one of the following: =item "x931" (B) +This padding mode is no longer supported by the FIPS provider for signature +generation, but may be used for signature verification for legacy use cases. +(This is a FIPS 140-3 requirement) + =item "pss" (B) =back @@ -68,10 +125,39 @@ Use the maximum salt length. Auto detect the salt length. +=item "auto-digestmax" (B) + +Auto detect the salt length when verifying. Maximize the salt length up to the +digest size when signing to comply with FIPS 186-4 section 5.5. + =back =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "key-check" (B) + +=item "digest-check" (B) + +=item "sign-x931-pad-check" (B) + +These parameters are described in L. + +=item "rsa-pss-saltlen-check" (B) + +The default value of 1 causes an error during signature generation or +verification if salt length (B) is not between +zero and the output block size of the digest function (inclusive). +Setting this to zero will ignore the error and set the approved "fips-indicator" +to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + The following signature parameters can be retrieved using EVP_PKEY_CTX_get_params(). @@ -79,7 +165,11 @@ EVP_PKEY_CTX_get_params(). =item "algorithm-id" (B) -This common parameter is described in L. +=item "fips-indicator" (B) + +=item "verify-message" (B + +These common parameter are described in L. =item "digest" (B) @@ -102,7 +192,7 @@ L, =head1 COPYRIGHT -Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod index 66165bdb0cc3..20d35fada87f 100644 --- a/doc/man7/OSSL_PROVIDER-FIPS.pod +++ b/doc/man7/OSSL_PROVIDER-FIPS.pod @@ -7,7 +7,7 @@ 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' +Information Processing Standards (FIPS) specified in FIPS 140-3. This 'module' contains an approved set of cryptographic algorithms that is validated by an accredited testing laboratory. @@ -29,14 +29,32 @@ L or L, as well as with other functions that take a property query string, such as L. -It isn't mandatory to query for any of these properties, except to -make sure to get implementations of this provider and none other. +To be FIPS compliant, it is mandatory to include C as +part of all property queries. This ensures that only FIPS approved +implementations are used for cryptographic operations. The C +query may also include other non-crypto support operations that +are not in the FIPS provider, such as asymmetric key encoders, see +L. -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. +It is not mandatory to include C as part of your property +query. Including C in your property query guarantees +that the OpenSSL FIPS provider is used for cryptographic operations +rather than other FIPS capable providers. + +=head2 Provider parameters + +See L for a list of base parameters. +Additionally the OpenSSL FIPS provider also supports the following gettable +parameters: + +=over 4 + +=item "security-checks" (B) + +For further information refer to the L option +B<-no_security_checks>. + +=back =head1 OPERATIONS AND ALGORITHMS @@ -54,6 +72,8 @@ The OpenSSL FIPS provider supports these operations and algorithms: =item KECCAK-KMAC, see L +=item SHAKE, see L + =back =head2 Symmetric Ciphers @@ -62,7 +82,9 @@ The OpenSSL FIPS provider supports these operations and algorithms: =item AES, see L -=item DES-EDE3 (TripleDES), see L +=item 3DES, see L + +This is an unapproved algorithm. =back @@ -118,6 +140,12 @@ The OpenSSL FIPS provider supports these operations and algorithms: =item X448, see L +=item ML-KEM, see L + +=item TLS1-PRF + +=item HKDF + =back =head2 Asymmetric Signature @@ -126,9 +154,25 @@ The OpenSSL FIPS provider supports these operations and algorithms: =item RSA, see L -=item X25519, see L +The B padding mode "OSSL_PKEY_RSA_PAD_MODE_X931" is no longer supported +for signature generation, but may be used for verification for legacy use cases. +(This is a FIPS 140-3 requirement) -=item X448, see L +=item DSA, see L + +=item ED25519, see L + +=item ED448, see L + +=item ECDSA, see L + +=item ML-DSA-44, see L + +=item ML-DSA-65, see L + +=item ML-DSA-87, see L + +=item SLH-DSA, see L =item HMAC, see L @@ -164,18 +208,72 @@ The OpenSSL FIPS provider supports these operations and algorithms: =item RSA, see L +=item RSA-PSS + =item EC, see L =item X25519, see L +This is an unapproved algorithm. + =item X448, see L +This is an unapproved algorithm. + +=item ED25519, see L + +This is an unapproved algorithm. + +=item ED448, see L + +This is an unapproved algorithm. + +=item TLS1-PRF + +=item HKDF + +=item HMAC, see L + +=item CMAC, see L + +=item ML-DSA-44, see L + +=item ML-DSA-65, see L + +=item ML-DSA-87, see L + +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + =back =head2 Random Number Generation =over 4 +=item CRNG-TEST, see L + =item CTR-DRBG, see L =item HASH-DRBG, see L @@ -232,6 +330,10 @@ Known answer test for a asymmetric cipher. Known answer test for a digest. +=item "KAT_AsymmetricKeyGeneration" (B) + +Known answer test for asymmetric key generation. + =item "KAT_Signature" (B) Known answer test for a signature. @@ -248,13 +350,17 @@ Known answer test for a key derivation function. Known answer test for key agreement. +=item "KAT_KEM" (B) + +Known answer test for key encapsulation. + =item "DRBG" (B) Known answer test for a Deterministic Random Bit Generator. =item "Conditional_PCT" (B) -Conditional test that is run during the generation of key pairs. +Conditional test that is run during the generation or importing of key pairs. =item "Continuous_RNG_Test" (B) @@ -283,10 +389,20 @@ The FIPS module passes the following descriptions(s) to OSSL_SELF_TEST_onbegin() =item "RSA" (B) +=item "RSA" (B) + =item "ECDSA" (B) +=item "EDDSA" (B) + =item "DSA" (B) +=item "ML-DSA" (B) + +=item "ML-KEM" (B) + +=item "SLH-DSA" (B) + Key generation tests used with the "Pairwise_Consistency_Test" type. =item "RSA_Encrypt" (B) @@ -295,6 +411,14 @@ Key generation tests used with the "Pairwise_Consistency_Test" type. "KAT_AsymmetricCipher" uses this to indicate an encrypt or decrypt KAT. +=item "ML-DSA" (B) + +=item "ML-KEM" (B) + +=item "SLH-DSA" (B) + +"KAT_AsymmetricKeyGeneration" uses this to indicate a key generation KAT. + =item "AES_GCM" (B) =item "AES_ECB_Decrypt" (B) @@ -317,6 +441,12 @@ Digest tests used with the "KAT_Digest" type. =item "ECDSA" (B) +=item "EDDSA" (B) + +=item "ML-DSA" (B) + +=item "SLH-DSA" (B) + Signature tests used with the "KAT_Signature" type. =item "ECDH" (B) @@ -345,6 +475,14 @@ Key agreement tests used with the "KAT_KA" type. =item "KBKDF" (B) +Key Encapsulation Function tests used with the "KAT_KEM" type. + +=item "KEM_Encap" (B) + +=item "KEM_Decap" (B) + +=item "KEM_Decap_Reject" (B) + Key Derivation Function tests used with the "KAT_KDF" type. =item "CTR" (B) @@ -355,7 +493,7 @@ Key Derivation Function tests used with the "KAT_KDF" type. DRBG tests used with the "DRBG" type. -= item "RNG" (B) +=item "RNG" (B) "Continuous_RNG_Test" uses this. @@ -421,6 +559,20 @@ validated versions alongside F and F compiled from any release within the same major release series. This flexibility enables you to address bug fixes and CVEs that fall outside the FIPS boundary. +The FIPS provider in OpenSSL 3.1 includes some non-FIPS validated algorithms, +consequently the property query C is mandatory for applications that +want to operate in a FIPS approved manner. The algorithms are: + +=over 4 + +=item Triple DES ECB + +=item Triple DES CBC + +=item EdDSA + +=back + =head1 SEE ALSO L, @@ -439,7 +591,7 @@ This functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/OSSL_PROVIDER-base.pod b/doc/man7/OSSL_PROVIDER-base.pod index c51adbde1e97..fdc7d0e54ee7 100644 --- a/doc/man7/OSSL_PROVIDER-base.pod +++ b/doc/man7/OSSL_PROVIDER-base.pod @@ -57,28 +57,170 @@ currently permitted. The OpenSSL base provider supports these operations and algorithms: -=head2 Asymmetric Key Encoder - -In addition to "provider=base", some of these encoders define the -property "fips=yes", to allow them to be used together with the FIPS -provider. +=head2 Random Number Generation =over 4 -=item RSA, see L +=item SEED-SRC, see L -=item DH, see L - -=item DSA, see L - -=item EC, see L - -=item X25519, see L - -=item X448, see L +=item JITTER, see L =back +In addition to this provider, the "SEED-SRC" and "JITTER" algorithms +are also available in the default provider. + +=head2 Asymmetric Key Encoder + +=over 4 + +=item RSA + +=item RSA-PSS + +=item DH + +=item DHX + +=item DSA + +=item EC + +=item ED25519 + +=item ED448 + +=item X25519 + +=item X448 + +=item SM2 + +=item ML-DSA-44 + +=item ML-DSA-65 + +=item ML-DSA-87 + +=item ML-KEM-512 + +=item ML-KEM-768 + +=item ML-KEM-1024 + +=item SLH-DSA-SHA2-128s + +=item SLH-DSA-SHA2-128f + +=item SLH-DSA-SHA2-192s + +=item SLH-DSA-SHA2-192f + +=item SLH-DSA-SHA2-256s + +=item SLH-DSA-SHA2-256f + +=item SLH-DSA-SHAKE-128s + +=item SLH-DSA-SHAKE-128f + +=item SLH-DSA-SHAKE-192s + +=item SLH-DSA-SHAKE-192f + +=item SLH-DSA-SHAKE-256s + +=item SLH-DSA-SHAKE-256f + +=back + +In addition to this provider, all of these encoding algorithms are also +available in the default provider. Some of these algorithms may be used in +combination with the FIPS provider. + +=head2 Asymmetric Key Decoder + +=over 4 + +=item RSA + +=item RSA-PSS + +=item DH + +=item DHX + +=item DSA + +=item EC + +=item ED25519 + +=item ED448 + +=item X25519 + +=item X448 + +=item SM2 + +=item DER + +=item ML-DSA-44 + +=item ML-DSA-65 + +=item ML-DSA-87 + +=item ML-KEM-512 + +=item ML-KEM-768 + +=item ML-KEM-1024 + +=item SLH-DSA-SHA2-128s + +=item SLH-DSA-SHA2-128f + +=item SLH-DSA-SHA2-192s + +=item SLH-DSA-SHA2-192f + +=item SLH-DSA-SHA2-256s + +=item SLH-DSA-SHA2-256f + +=item SLH-DSA-SHAKE-128s + +=item SLH-DSA-SHAKE-128f + +=item SLH-DSA-SHAKE-192s + +=item SLH-DSA-SHAKE-192f + +=item SLH-DSA-SHAKE-256s + +=item SLH-DSA-SHAKE-256f + +=back + +In addition to this provider, all of these decoding algorithms are also +available in the default provider. Some of these algorithms may be used in +combination with the FIPS provider. + +=head2 Stores + +=over 4 + +=item file + +=item org.openssl.winstore, see L + +=back + +In addition to this provider, all of these store algorithms are also +available in the default provider. + =head1 SEE ALSO L, L, @@ -88,9 +230,11 @@ L, L This functionality was added in OpenSSL 3.0. +Support for B and was added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod index e39d76abdbb8..300aee3577a6 100644 --- a/doc/man7/OSSL_PROVIDER-default.pod +++ b/doc/man7/OSSL_PROVIDER-default.pod @@ -57,6 +57,8 @@ The OpenSSL default provider supports these operations and algorithms: =item SHA3, see L +=item KECCAK, see L + =item KECCAK-KMAC, see L =item SHAKE, see L @@ -87,8 +89,6 @@ The OpenSSL default provider supports these operations and algorithms: =item 3DES, see L -=item SEED, see L - =item SM4, see L =item ChaCha20, see L @@ -125,6 +125,8 @@ The OpenSSL default provider supports these operations and algorithms: =item HKDF, see L +=item TLS13-KDF, see L + =item SSKDF, see L =item PBKDF2, see L @@ -147,6 +149,9 @@ The OpenSSL default provider supports these operations and algorithms: =item KRB5KDF, see L +=item HMAC-DRBG, see L + +=item ARGON2, see L =back @@ -162,6 +167,18 @@ The OpenSSL default provider supports these operations and algorithms: =item X448, see L +=item ML-KEM-512, see L + +=item ML-KEM-768, see L + +=item ML-KEM-1024, see L + +=item TLS1-PRF + +=item HKDF + +=item SCRYPT + =back =head2 Asymmetric Signature @@ -172,6 +189,20 @@ The OpenSSL default provider supports these operations and algorithms: =item RSA, see L +=item ED25519, see L + +=item ED448, see L + +=item ECDSA, see L + +=item SM2 + +=item ML-DSA-44, see L + +=item ML-DSA-65, see L + +=item ML-DSA-87, see L + =item HMAC, see L =item SIPHASH, see L @@ -180,6 +211,30 @@ The OpenSSL default provider supports these operations and algorithms: =item CMAC, see L +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + =back =head2 Asymmetric Cipher @@ -198,26 +253,96 @@ The OpenSSL default provider supports these operations and algorithms: =item RSA, see L +=item X25519, see L + +=item X448, see L + +=item EC, see L + +=item ML-KEM-512, see L + +=item ML-KEM-768, see L + +=item ML-KEM-1024, see L + =back =head2 Asymmetric Key Management =over 4 -=item DH, see L - -=item DHX, see L - =item DSA, see L =item RSA, see L +=item RSA-PSS + =item EC, see L +=item ED25519, see L + +=item ED448, see L + +=item SM2, see L + +=item DH, see L + +=item DHX, see L + =item X25519, see L =item X448, see L +=item ML-DSA-44, see L + +=item ML-DSA-65, see L + +=item ML-DSA-87, see L + +=item MK-KEM-512, see L + +=item MK-KEM-768, see L + +=item MK-KEM-1024, see L + +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + +=item TLS1-PRF + +=item HKDF + +=item SCRYPT + +=item HMAC, see L + +=item SIPHASH, see L + +=item POLY1305, see L + +=item CMAC, see L + =back =head2 Random Number Generation @@ -232,32 +357,164 @@ The OpenSSL default provider supports these operations and algorithms: =item SEED-SRC, see L +=item JITTER, see L + =item TEST-RAND, see L =back -=head2 Asymmetric Key Encoder +In addition to this provider, the "SEED-SRC" and "JITTER" algorithms +are also available in the base provider. -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. +=head2 Asymmetric Key Encoder =over 4 -=item RSA, see L +=item RSA -=item DH, see L +=item RSA-PSS -=item DSA, see L +=item DH -=item EC, see L +=item DHX -=item X25519, see L +=item DSA -=item X448, see L +=item EC + +=item ED25519 + +=item ED448 + +=item X25519 + +=item X448 + +=item SM2 + +=item ML-DSA-44 + +=item ML-DSA-65 + +=item ML-DSA-87 + +=item ML-KEM-512 + +=item ML-KEM-768 + +=item ML-KEM-1024 + +=item SLH-DSA-SHA2-128s + +=item SLH-DSA-SHA2-128f + +=item SLH-DSA-SHA2-192s + +=item SLH-DSA-SHA2-192f + +=item SLH-DSA-SHA2-256s + +=item SLH-DSA-SHA2-256f + +=item SLH-DSA-SHAKE-128s + +=item SLH-DSA-SHAKE-128f + +=item SLH-DSA-SHAKE-192s + +=item SLH-DSA-SHAKE-192f + +=item SLH-DSA-SHAKE-256s + +=item SLH-DSA-SHAKE-256f =back +In addition to this provider, all of these encoding algorithms are also +available in the base provider. Some of these algorithms may be used in +combination with the FIPS provider. + +=head2 Asymmetric Key Decoder + +=over 4 + +=item RSA + +=item RSA-PSS + +=item DH + +=item DHX + +=item DSA + +=item EC + +=item ED25519 + +=item ED448 + +=item X25519 + +=item X448 + +=item SM2 + +=item ML-DSA-44 + +=item ML-DSA-65 + +=item ML-DSA-87 + +=item ML-KEM-512 + +=item ML-KEM-768 + +=item ML-KEM-1024 + +=item SLH-DSA-SHA2-128s + +=item SLH-DSA-SHA2-128f + +=item SLH-DSA-SHA2-192s + +=item SLH-DSA-SHA2-192f + +=item SLH-DSA-SHA2-256s + +=item SLH-DSA-SHA2-256f + +=item SLH-DSA-SHAKE-128s + +=item SLH-DSA-SHAKE-128f + +=item SLH-DSA-SHAKE-192s + +=item SLH-DSA-SHAKE-192f + +=item SLH-DSA-SHAKE-256s + +=item SLH-DSA-SHAKE-256f + +=back + +In addition to this provider, all of these decoding algorithms are also +available in the base provider. Some of these algorithms may be used in +combination with the FIPS provider. + +=head2 Stores + +=over 4 + +=item file + +=item org.openssl.winstore, see L + +=back + +In addition to this provider, all of these store algorithms are also +available in the base provider. + =head1 SEE ALSO L, L, L, @@ -271,7 +528,7 @@ All other functionality was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/OSSL_PROVIDER-legacy.pod b/doc/man7/OSSL_PROVIDER-legacy.pod index f10827de7baa..d70de3682f34 100644 --- a/doc/man7/OSSL_PROVIDER-legacy.pod +++ b/doc/man7/OSSL_PROVIDER-legacy.pod @@ -42,6 +42,8 @@ The OpenSSL legacy provider supports these operations and algorithms: =item MD2, see L +Disabled by default. Use I config option to enable. + =item MD4, see L =item MDC2, see L @@ -87,6 +89,8 @@ Disabled by default. Use I config option to enable. =item PBKDF1 +=item PVKKDF + =back =begin comment diff --git a/doc/man7/RAND.pod b/doc/man7/RAND.pod index c4a630856c58..ac46d16e9090 100644 --- a/doc/man7/RAND.pod +++ b/doc/man7/RAND.pod @@ -54,6 +54,13 @@ only in exceptional cases and is not recommended, unless you have a profound knowledge of cryptographic principles and understand the implications of your changes. +Finally, it is possible for a provider to bypass the default RAND setup for +L and associated functions. A provider can be specified as the +single randomness source via the L function or via +configuration using the B option in L. Once specified, +the nominated provider will be used directly when calling the L +family of functions. + =head1 DEFAULT SETUP The default OpenSSL RAND method is based on the EVP_RAND deterministic random @@ -68,11 +75,13 @@ L, L, L, L, -L +L, +L, +L. =head1 COPYRIGHT -Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2018-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/bio.pod b/doc/man7/bio.pod index 9b86e9493d1c..ca20e115cd22 100644 --- a/doc/man7/bio.pod +++ b/doc/man7/bio.pod @@ -36,7 +36,6 @@ BIO and one or more filter BIOs. Data read from or written to the first BIO then traverses the chain to the end (normally a source/sink BIO). - Some BIOs (such as memory BIOs) can be used immediately after calling BIO_new(). Others (such as file BIOs) need some additional initialization, and frequently a utility function exists to create and initialize such BIOs. @@ -52,6 +51,29 @@ pointer to a BIO_METHOD. There is a naming convention for such functions: a source/sink BIO typically starts with I and a filter BIO with I. +=head2 TCP Fast Open + +TCP Fast Open (RFC7413), abbreviated "TFO", is supported by the BIO +interface since OpenSSL 3.2. TFO is supported in the following operating systems: + +=over 4 + +=item * Linux kernel 3.13 and later, where TFO is enabled by default. + +=item * Linux kernel 4.11 and later, using TCP_FASTOPEN_CONNECT. + +=item * FreeBSD 10.3 to 11.4, supports server TFO only. + +=item * FreeBSD 12.0 and later, supports both client and server TFO. + +=item * macOS 10.14 and later. + +=back + +Each operating system has a slightly different API for TFO. Please +refer to the operating systems' API documentation when using +sockets directly. + =head1 EXAMPLES Create a memory BIO: @@ -65,7 +87,9 @@ L, L, L, L, L, L, L, -L, L, +L, +L, +L, L, L, L, L, L, @@ -73,11 +97,14 @@ L, L, L, L, L, L, L, +L, +L, +L, L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy @@ -85,4 +112,3 @@ in the file LICENSE in the source distribution or at L. =cut - diff --git a/doc/man7/crypto.pod b/doc/man7/crypto.pod deleted file mode 100644 index c31e10ac29a5..000000000000 --- a/doc/man7/crypto.pod +++ /dev/null @@ -1,580 +0,0 @@ -=pod - -=head1 NAME - -crypto - OpenSSL cryptographic library - -=head1 SYNOPSIS - -See the individual manual pages for details. - -=head1 DESCRIPTION - -The OpenSSL crypto library (C) 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 page. Or to -perform a digest operation using SHA256 then you would use the digesting -functions on the L 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 type. Many OpenSSL API -functions take a library context as a parameter. Applications can always pass -B 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 for more information about library contexts. -See also L. - -=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 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 are not thread-safe. For example -the L and L 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 object -since both of them may attempt to make changes to the same B 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 in -multiple threads. - -See L 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 or -L 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 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, where -C is the name of the operation. For example L can -be used to explicitly fetch a digest algorithm implementation. The user is -responsible for freeing the object returned from the C function -using C 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 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) 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). - -=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 function takes -as a parameter an B object which may have been returned from an earlier -call to L. - -=head2 Implicit fetching - -OpenSSL has a number of functions that return an algorithm object with no -associated implementation, such as L, L, -L or L. 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 or -L, 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 and L, such as -L and friends, all fetch the implementations -implicitly. Because these functions involve both an operation type (such as -L) and an L for the L, 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. - -If the provider of the operation type implementation is different from the -provider of the L's L implementation, try to -fetch a L implementation in the same provider as the operation -type implementation and export the L 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's L, still using the -property string from the B. - -=back - -=head2 Performance - -If you perform the same operation many times then it is recommended to use -L to prefetch an algorithm once initially, -and then pass this created object to any operations that are currently -using L. -See an example of Explicit fetching in L. - -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 - -=item L - -=item L - -=item L - -=item L - -=item L - -=item L - -=item L - -=back - -The following methods are used internally when performing operations: - -=over 4 - -=item L - -=item L - -=item L - -=item L - -=back - -See L, and -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 command can be used to list the -currently available algorithms. - -The names of the algorithms shown from L 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. - -=head2 Default provider - -The default provider is built in as part of the F 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. - -=head2 Base provider - -The base provider is built in as part of the F 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. - -=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). 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 and L. - -=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). 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. - -=head2 Null provider - -The null provider is built in as part of the F 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. - -=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 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, and for an -encryption/decryption operation you would use an B. The -operation is then initialised ready for use via an "init" function - optionally -passing in a set of parameters (using the L 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 - #include - #include - #include - - 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 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. - -=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). 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 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. For -information about decoders see L. - -=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 object is passed -to the I object. Therefore, after calling this function I should not -be freed directly. It will be freed implicitly when I 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 value where appropriate. - -=head1 SEE ALSO - -L, L, L, L, L, -L, L, L, -L, L, L, -L, L - -=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. - -=cut diff --git a/doc/man7/evp.pod b/doc/man7/evp.pod index 44d385655e5f..9e0dc58e851b 100644 --- a/doc/man7/evp.pod +++ b/doc/man7/evp.pod @@ -63,7 +63,7 @@ implementation. However, new applications should not typically use this (preferr PBKDF2 from PCKS#5). The LI|EVP_EncodeInit(3)> and -LI|EVP_EncodeInit(3)> functions implement base 64 encoding +LI|EVP_EncodeInit(3)> functions implement base64 encoding and decoding. All the symmetric algorithms (ciphers), digests and asymmetric algorithms @@ -106,7 +106,7 @@ L =head1 COPYRIGHT -Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/fips_module.pod b/doc/man7/fips_module.pod index d0861a9dcecc..f32c65081e12 100644 --- a/doc/man7/fips_module.pod +++ b/doc/man7/fips_module.pod @@ -42,7 +42,7 @@ EC_KEY_METHOD_new(), etc.) =back All of the above APIs are deprecated in OpenSSL 3.0 - so a simple rule is to -avoid using all deprecated functions. See L for a list of +avoid using all deprecated functions. See L for a list of deprecated functions. =head2 Making all applications use the FIPS module by default @@ -83,6 +83,7 @@ Edit the config file to add the following lines near the beginning: [openssl_init] providers = provider_sect + alg_section = algorithm_sect [provider_sect] fips = fips_sect @@ -91,6 +92,9 @@ Edit the config file to add the following lines near the beginning: [base_sect] activate = 1 + [algorithm_sect] + default_properties = fips=yes + Obviously the include file location above should match the path and name of the FIPS module config file that you installed earlier. See L. @@ -208,7 +212,7 @@ application. If any OpenSSL functions get called that require the use of cryptographic functions before this occurs then, if no provider has yet been loaded, then the default provider will be automatically loaded. If you then later explicitly load the FIPS provider then you will have both the FIPS and the -default provider loaded at the same time. It is undefined which implementation +default provider loaded at the same time. It is unspecified which implementation of an algorithm will be used if multiple implementations are available and you have not explicitly specified via a property query (see below) which one should be used. @@ -240,7 +244,7 @@ standards you can specify the property query C like this: sha256 = EVP_MD_fetch(NULL, "SHA2-256", "fips=yes"); If no property query is specified, or more than one implementation matches the -property query then it is undefined which implementation of a particular +property query then it is unspecified which implementation of a particular algorithm will be returned. This example shows an explicit request for an implementation of SHA256 from the @@ -333,6 +337,14 @@ base providers. The other library context will just use the default provider. if (!OSSL_LIB_CTX_load_config(fips_libctx, "openssl-fips.cnf")) goto err; + /* + * Set the default property query on the FIPS library context to + * ensure that only FIPS algorithms can be used. There are a few non-FIPS + * approved algorithms in the FIPS provider for backward compatibility reasons. + */ + if (!EVP_set_default_properties(fips_libctx, "fips=yes")) + goto err; + /* * We don't need to do anything special to load the default * provider into nonfips_libctx. This happens automatically if no @@ -381,7 +393,7 @@ explicitly loaded, the default provider will not automatically load. This means code using the default context by accident will fail because no algorithms will be available. -See L for additional information about the +See L for additional information about the Library Context. =head2 Using Encoders and Decoders with the FIPS module @@ -422,7 +434,7 @@ contexts. * We assume that a nondefault library context with the FIPS * provider loaded has been created called fips_libctx. */ - SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(fips_libctx, NULL, TLS_method()); + SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(fips_libctx, "fips=yes", TLS_method()); /* * We assume that a nondefault library context with the default * provider loaded has been created called non_fips_libctx. @@ -459,6 +471,119 @@ use L. To extract the name from the B, use L. +=head2 FIPS indicators + +FIPS indicators have been added to the FIPS provider in OpenSSL 3.4. +FIPS 140-3 requires indicators to be used if the FIPS provider allows non +approved algorithms. An algorithm is approved if it passes all required checks +such as minimum key size. By default an error will occur if any check fails. +For backwards compatibility individual algorithms may override the checks by +using either an option in the FIPS configuration (See +L) OR in code using an algorithm context +setter. Overriding the check means that the algorithm is not FIPS compliant. +L can be called to register a callback to log +unapproved algorithms. At the end of any algorithm operation the approved status +can be queried using an algorithm context getter to retrieve the indicator +(e.g. "fips-indicator"). +An example of an algorithm context setter is "key-check" +in L. + +The following algorithms use "fips-indicator" to query if the algorithm +is approved: + +=over 4 + +=item DSA Key generation + +DSA Key generation is no longer approved. +See L + +=item DSA Signatures + +DSA Signature generation is no longer approved. +See L + +=item ECDSA Signatures + +See L + +=item EC Key Generation + +See L + +=item RSA Encryption + +"pkcs1" padding is no longer approved. + +See L and +L + +=item RSA Signatures + +See L + +=item DRBGS + +See L and +EVP_RAND-HMAC-DRBG(7)/Supported parameters> + +=item DES + +Triple-DES is not longer approved for encryption. +See L + +=item DH + +See L + +=item ECDH + +See L + +=item KDFS + +See relevant KDF documentation e.g. L + +=item CMAC and KMAC + +See L and +L + +=back + +The following FIPS algorithms are unapproved and use the "fips-indicator". + +=over 4 + +=item RAND-TEST-RAND + +See L +The indicator callback is NOT triggered for this algorithm since it is used +internally for non security purposes. + +=item X25519 and X448 Key Generation and Key Exchange + +=back + +The unapproved (non FIPS validated) algorithms have a property query value of +"fips=no". + +The following algorithms use a unique indicator and do not trigger the +indicator callback. + +=over 4 + +=item AES-GCM ciphers support the indicator "iv-generated" + +See L for further information. + +=item ECDSA and RSA Signatures support the indicator "verify-message". + +See L and +L /for further information. + +=back + =head1 NOTES Some released versions of OpenSSL do not include a validated @@ -472,19 +597,24 @@ validated versions alongside F and F compiled from any release within the same major release series. This flexibility enables you to address bug fixes and CVEs that fall outside the FIPS boundary. +As the FIPS provider still supports non-FIPS validated algorithms, +The property query C is mandatory for applications that +want to operate in a FIPS approved manner. + =head1 SEE ALSO -L, L, L, +L, L, L, L =head1 HISTORY The FIPS module guide was created for use with the new FIPS provider in OpenSSL 3.0. +FIPS indicators were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/img/digest.png b/doc/man7/img/digest.png index 9f35deb5dcc8..8a9f78a26b39 100644 Binary files a/doc/man7/img/digest.png and b/doc/man7/img/digest.png differ diff --git a/doc/man7/life_cycle-digest.pod b/doc/man7/life_cycle-digest.pod index 709fd0d04ce7..672e61c7e4b8 100644 --- a/doc/man7/life_cycle-digest.pod +++ b/doc/man7/life_cycle-digest.pod @@ -32,6 +32,14 @@ additional input or generating output. =item finaled This state represents the MD when it has generated output. +For an XOF digest, this state represents the MD when it has generated a +single-shot output. + +=item squeezed + +For an XOF digest, this state represents the MD when it has generated output. +It can be called multiple times to generate more output. The output length is +variable for each call. =item freed @@ -46,39 +54,57 @@ The usual life-cycle of a MD is illustrated: =begin man - +-------------------+ - | start | - +-------------------+ - | - | EVP_MD_CTX_new - v - +-------------------+ EVP_MD_CTX_reset - | newed | <------------------------------+ - +-------------------+ | - | | - | EVP_DigestInit | - v | - +-------------------+ | - +--> | initialised | <+ EVP_DigestInit | - | +-------------------+ | | - | | | EVP_DigestUpdate | - | | EVP_DigestUpdate | +------------------+ | - | v | v | | - | +------------------------------------------------+ | - EVP_DigestInit | | updated | --+ - | +------------------------------------------------+ | - | | | | - | | EVP_DigestFinal | EVP_DigestFinalXOF | - | v v | - | +------------------------------------------------+ | - +--- | finaled | --+ - +------------------------------------------------+ - | - | EVP_MD_CTX_free - v - +-------------------+ - | freed | - +-------------------+ + +--------------------+ + | start | + +--------------------+ + | EVP_MD_CTX_reset + | EVP_MD_CTX_new +-------------------------------------------------+ + v v | + EVP_MD_CTX_reset + - - - - - - - - - - - - - - - - - - - - - - + EVP_MD_CTX_reset | + +-------------------> ' newed ' <--------------------+ | + | + - - - - - - - - - - - - - - - - - - - - - - + | | + | | | | + | | EVP_DigestInit | | + | v | | + | EVP_DigestInit + - - - - - - - - - - - - - - - - - - - - - - + | | + +----+-------------------> ' initialised ' <+ EVP_DigestInit | | + | | + - - - - - - - - - - - - - - - - - - - - - - + | | | + | | | ^ | | | + | | | EVP_DigestUpdate | EVP_DigestInit | | | + | | v | | | | + | | +---------------------------------------------+ | | | + | +-------------------- | | | | | + | | | | | | + | EVP_DigestUpdate | | | | | + | +-------------------- | | | | | + | | | updated | | | | + | +-------------------> | | | | | + | | | | | | + | | | | | | + +----+------------------------- | | -+-------------------+----+ | + | | +---------------------------------------------+ | | | | + | | | | | | | + | | | EVP_DigestSqueeze +-------------------+ | | | + | | v | | | | + | | EVP_DigestSqueeze +---------------------------------------------+ | | | + | | +-------------------- | | | | | + | | | | squeezed | | | | + | | +-------------------> | | ---------------------+ | | + | | +---------------------------------------------+ | | + | | | | | + | | +---------------------------------------+ | | + | | | | | + | | +---------------------------------------------+ EVP_DigestFinalXOF | | | + | +------------------------- | finaled | <--------------------+----+ | + | +---------------------------------------------+ | | + | EVP_DigestFinal ^ | | | | + +---------------------------------+ | | EVP_MD_CTX_free | | + | v | | + | +------------------+ EVP_MD_CTX_free | | + | | freed | <--------------------+ | + | +------------------+ | + | | + +------------------------------------------------------+ =end man @@ -91,19 +117,21 @@ This is the canonical list. =begin man - Function Call --------------------- Current State ---------------------- - start newed initialised updated finaled freed + Function Call --------------------- Current State ----------------------------------- + start newed initialised updated finaled squeezed freed EVP_MD_CTX_new newed - EVP_DigestInit initialised initialised initialised initialised + EVP_DigestInit initialised initialised initialised initialised initialised EVP_DigestUpdate updated updated EVP_DigestFinal finaled EVP_DigestFinalXOF finaled + EVP_DigestSqueeze squeezed squeezed EVP_MD_CTX_free freed freed freed freed freed EVP_MD_CTX_reset newed newed newed newed EVP_MD_CTX_get_params newed initialised updated EVP_MD_CTX_set_params newed initialised updated EVP_MD_CTX_gettable_params newed initialised updated EVP_MD_CTX_settable_params newed initialised updated + EVP_MD_CTX_copy_ex newed initialised updated squeezed =end man @@ -118,6 +146,7 @@ This is the canonical list. initialised updated finaled + squeezed freed EVP_MD_CTX_new newed @@ -125,6 +154,7 @@ This is the canonical list. + EVP_DigestInit @@ -132,6 +162,7 @@ This is the canonical list. initialised initialised initialised + initialised EVP_DigestUpdate @@ -139,6 +170,7 @@ This is the canonical list. updated updated + EVP_DigestFinal @@ -146,6 +178,15 @@ This is the canonical list. finaled + + +EVP_DigestSqueeze + + + + squeezed + + squeezed EVP_DigestFinalXOF @@ -153,6 +194,7 @@ This is the canonical list. finaled + EVP_MD_CTX_free freed @@ -160,6 +202,7 @@ This is the canonical list. freed freed freed + EVP_MD_CTX_reset @@ -167,6 +210,7 @@ This is the canonical list. newed newed newed + EVP_MD_CTX_get_params @@ -174,6 +218,7 @@ This is the canonical list. initialised updated + EVP_MD_CTX_set_params @@ -181,6 +226,7 @@ This is the canonical list. initialised updated + EVP_MD_CTX_gettable_params @@ -188,6 +234,7 @@ This is the canonical list. initialised updated + EVP_MD_CTX_settable_params @@ -195,6 +242,15 @@ This is the canonical list. initialised updated + + +EVP_MD_CTX_copy_ex + + newed + initialised + updated + + squeezed @@ -211,7 +267,7 @@ L, L =head1 COPYRIGHT -Copyright 2021 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 diff --git a/doc/man7/life_cycle-pkey.pod b/doc/man7/life_cycle-pkey.pod index a9dc06b934d5..8d3e0353481f 100644 --- a/doc/man7/life_cycle-pkey.pod +++ b/doc/man7/life_cycle-pkey.pod @@ -703,7 +703,7 @@ The provider PKEY interface was introduced in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/migration_guide.pod b/doc/man7/migration_guide.pod deleted file mode 100644 index e5ab29b95370..000000000000 --- a/doc/man7/migration_guide.pod +++ /dev/null @@ -1,2494 +0,0 @@ -=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. -For an overview of some of the key concepts introduced in OpenSSL 3.0 see -L. - -=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 -(both licenses apply). From OpenSSL 3.0 this is replaced by the -L. - -=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). They cannot -be accessed using the L. - -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 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 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, -L, and L functions. In case when -the requested algorithm is not available, these functions will fail. - -See also L for information on the legacy provider. - -See also L and -L. - -=head3 Low Level APIs - -OpenSSL has historically provided two sets of APIs for invoking cryptographic -algorithms: the "high level" APIs (such as the C 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, -L and L 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, -L, 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 - -=head3 Legacy Algorithms - -Some cryptographic algorithms such as B and B 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 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 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, -L, L, L, -L, 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 implementation. -In this case the B objects created via L -will be considered 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. - -Setting engine-based or application-based default low-level crypto method such -as B or B is still possible and keys inside the -default provider will use the engine-based implementation for the crypto -operations. However Bs created by decoding by using B, -B or B APIs will be provider-based. To create a fully legacy -Bs L, L or similar -functions must be used. - -=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. - -=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 and L 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 interface. -See also L and -L. - -=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 and L. - -All new applications should use the new L interface. -See also L -and L. - -=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, L and L. - -=head4 Support for Linux Kernel TLS - -In order to use KTLS, support for it must be compiled in using the -C configuration option. It must also be enabled at run time using -the B option. - -=head4 New Algorithms - -=over 4 - -=item * - -KDF algorithms "SINGLE STEP" and "SSH" - -See L and L - -=item * - -MAC Algorithms "GMAC" and "KMAC" - -See L and L. - -=item * - -KEM Algorithm "RSASVE" - -See L. - -=item * - -Cipher Algorithm "AES-SIV" - -See L. - -=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 and L 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 -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, L, L, -L, L, L, -L, L, -L, L, L, -L, L, L, -L, L, -L, L, L, -L, L, -L, L, L. - -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, L and L. - -=head4 PKCS#12 KDF versus FIPS - -Unlike in 1.x.y, the PKCS12KDF algorithm used when a PKCS#12 structure -is created with a MAC that does not work with the FIPS provider as the PKCS12KDF -is not a FIPS approvable mechanism. - -See L, L, L, -L. - -=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 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. - -=head4 Key validation updates - -L and L 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 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 and L. - -=head4 The RAND_DRBG subsystem has been removed - -The new L 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 and -L. - -=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 in -L. The parameter can be set using L. - -=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 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 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 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 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, -L, 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, L, L and -L 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, L, L -and L 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 rather than -during L. -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, -L, L, 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 and B applications. - -=head4 Interactive mode from the B program has been removed - -From now on, running it without arguments is equivalent to B. - -=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 for further details. This affects the -behaviour of L for DH parameter generation. - -=head4 EVP_CIPHER_CTX_set_flags() ordering change - -If using a cipher from a provider the B flag can only -be set B the cipher has been assigned to the cipher context. -See L 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, 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 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. - -=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. - -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 and L 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 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 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 for further info. - -If the user creates an B via L 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 such as EVP_sha256() should be replaced with a call to -L. See L. - -If a library context is needed then all EVP_* cipher functions that return a -B such as EVP_aes_128_cbc() should be replaced vith a call to -L. See L. - -Some functions can be passed an object that has already been set up with a library -context such as L, L, L and -L. If NULL is passed instead then the created object will be -set up with the default library context. Use L, -L, L and L if a -library context is required. - -All functions listed below with a I have a replacement function I -that takes B as an additional argument. Functions that have other -mappings are listed along with the respective name. - -=over 4 - -=item * - -L, L, L, -L, L and L - -=item * - -L - -=item * - -b2i_RSA_PVK_bio() and i2b_PVK_bio() - -=item * - -L and L - -=item * - -L, L, L, -L, L, L, -L, L and L - -=item * - -L - -=item * - -L, L and L - -=item * - -L - -=item * - -L, L and L - -=item * - -L and L - -Use L and L - -=item * - -L - -Use L or L. - -=item * - -L and L - -=item * - -L, L and L - -=item * - -L - -=item * - -L - -=item * - -L - -Use L - -=item * - -L, L -and L - -=item * - -L and L - -=item * - -L - -=item * - -L and L - -=item * - -L - -=item * - -L - -=item * - -L, L, L, -L and L - -=item * - -L, L, L -and L - -=item * - -L and L - -=item * - -L, L, L, -L, L, L, L, -L, L, L, -L, L, L, -L, L - -=item * - -L, L, L, -L and L - -=item * - -L, L and L - -=item * - -L, L and L - -=item * - -L and L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L - -=item * - -L and L - -=item * - -L, L, L, -L and L - -=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 - -=item * - -L and L - -=item * - -L and L - -=item * - -L and -L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L - -=item * - -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L and L - -=item * - -L, L and L - -=item * - -L, L, -L, L, -L and L - -=item * - -L and L - -=item * - -L - -=item * - -L and L - -=item * - -L, L, L, -L and L - -=back - -=head3 Providers - -Providers are described in detail here L. -See also L. - -=head3 Fetching algorithms and property queries - -Implicit and Explicit Fetching is described in detail here -L. - -=head3 Mapping EVP controls and flags to provider L parameters - -The existing functions for controls (such as L) and -manipulating flags (such as L)internally use -B to pass information to/from provider objects. -See L for additional information related to parameters. - -For ciphers see L, L and -L. - -For digests see L, L and -L. - -=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 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 overridden 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 and -L APIs to read and write files. -See L 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) or OSSL_DECODER (See L) -APIs, or alternatively use L or L. - -=head4 Deprecated low-level key parameter getters - -Functions that access low-level objects directly such as L are now -deprecated. Applications should use one of L, -L, l, -L, L or -L to access fields from an EVP_PKEY. -Gettable parameters are listed in L, -L, L, -L, L and -L. -Applications may also use L to return all fields. - -=head4 Deprecated low-level key parameter setters - -Functions that access low-level objects directly such as L -are now deprecated. Applications should use L 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, L, -and L to create a modified key. -See L for more information. -See L for information on -generating a key using parameters. - -=head4 Deprecated low-level object creation - -Low-level objects were created using methods such as L, -L and L. Applications should instead use the -high-level EVP_PKEY APIs, e.g. L, L and -L. -See also L and L. - -EVP_PKEYs may be created in a variety of ways: -See also L, -L and -L. - -=head4 Deprecated low-level encryption functions - -Low-level encryption functions such as L and L -have been informally discouraged from use for a long time. Applications should -instead use the high level EVP APIs L, -L, and L or -L, L and L. - -=head4 Deprecated low-level digest functions - -Use of low-level digest functions such as L have been -informally discouraged from use for a long time. Applications should instead -use the the high level EVP APIs L, L -and L, or the quick one-shot L. - -Note that the functions L, L, L, L -and L have changed to macros that use L. - -=head4 Deprecated low-level signing functions - -Use of low-level signing functions such as L have been -informally discouraged for a long time. Instead applications should use -L and L. -See also L, L, -L and L. - -=head4 Deprecated low-level MAC functions - -Low-level mac functions such as L are deprecated. -Applications should instead use the new L interface, using -L, L, L, -L and L or the single-shot MAC function -L. -See L, L, L, L, -L, L, L and -L 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 have been informally -discouraged from use for a long time. Applications should instead use the high-level -EVP_PKEY APIs such as L, L, -L, L, -L, L, -and L. - -=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. -See L, L and L. - -=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 and -L as described in L, L, -L, L and L. -The 'quick' one-shot function L and macros for the most -common cases: and L 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 and L. - -=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, -L, L, -L, L or -L. Note that internally these use -L and L. - -=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 - -=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 or L 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. -The Blowfish algorithm has been moved to the L. - -=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 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 and L. - -=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 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. - -=item * - -CAST_encrypt(), CAST_decrypt(), CAST_set_key(), CAST_cbc_encrypt(), -CAST_cfb64_encrypt(), CAST_ecb_encrypt(), CAST_ofb64_encrypt() - -See L. -The CAST algorithm has been moved to the L. - -=item * - -CMAC_CTX_new(), CMAC_CTX_cleanup(), CMAC_CTX_copy(), CMAC_CTX_free(), -CMAC_CTX_get0_cipher_ctx() - -See L. - -=item * - -CMAC_Init(), CMAC_Update(), CMAC_Final(), CMAC_resume() - -See L. - -=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. -See L 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(), 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 - -=item * - -o2i_ECPublicKey() - -Use L. -See L - -=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. -Algorithms for "DESX-CBC", "DES-ECB", "DES-CBC", "DES-OFB", "DES-CFB", -"DES-CFB1" and "DES-CFB8" have been moved to the L. - -=item * - -DH_bits(), DH_security_bits(), DH_size() - -Use L, L and -L. - -=item * - -DH_check(), DH_check_ex(), DH_check_params(), DH_check_params_ex(), -DH_check_pub_key(), DH_check_pub_key_ex() - -See L - -=item * - -DH_clear_flags(), DH_test_flags(), DH_set_flags() - -The B flag has been deprecated without replacement. -The B and B 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. - -=item * - -DH_new(), DH_new_by_nid(), DH_free(), DH_up_ref() - -See L - -=item * - -DH_generate_key(), DH_generate_parameters_ex() - -See L. - -=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 - -=item * - -DH_get_1024_160(), DH_get_2048_224(), DH_get_2048_256() - -Applications should instead set the B as specified in -L) 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 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 - -=item * - -DHparams_print(), DHparams_print_fp() - -See L - -=item * - -DH_set0_key(), DH_set0_pqg(), DH_set_length() - -See L - -=item * - -DSA_bits(), DSA_security_bits(), DSA_size() - -Use L, L and -L. - -=item * - -DHparams_dup(), DSA_dup_DH() - -There is no direct replacement. Applications may use L -and L instead. - -=item * - -DSA_generate_key(), DSA_generate_parameters_ex() - -See L. - -=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. - -=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. - -=item * - -DSA_new(), DSA_free(), DSA_up_ref() - -See L - -=item * - -DSAparams_dup() - -There is no direct replacement. Applications may use L -and L instead. - -=item * - -DSAparams_print(), DSAparams_print_fp(), DSA_print(), DSA_print_fp() - -See L - -=item * - -DSA_set0_key(), DSA_set0_pqg() - -See L - -=item * - -DSA_set_flags(), DSA_clear_flags(), DSA_test_flags() - -The B flag has been deprecated without replacement. - -=item * - -DSA_sign(), DSA_do_sign(), DSA_sign_setup(), DSA_verify(), DSA_do_verify() - -See L. - -=item * - -ECDH_compute_key() - -See L. - -=item * - -ECDH_KDF_X9_62() - -Applications may either set this using the helper function -L or by setting an L using the -"kdf-type" as shown in L - -=item * - -ECDSA_sign(), ECDSA_sign_ex(), ECDSA_sign_setup(), ECDSA_do_sign(), -ECDSA_do_sign_ex(), ECDSA_verify(), ECDSA_do_verify() - -See L. - -=item * - -ECDSA_size() - -Applications should use L. - -=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 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 and L. - -=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 instead. - -=item * - -EC_KEY_check_key() - -See L - -=item * - -EC_KEY_set_flags(), EC_KEY_get_flags(), EC_KEY_clear_flags() - -See L which handles flags as separate -parameters for B, -B, B, -B and -B. -See also L - -=item * - -EC_KEY_dup(), EC_KEY_copy() - -There is no direct replacement. Applications may use L -and L instead. - -=item * - -EC_KEY_decoded_from_explicit_params() - -There is no replacement. - -=item * - -EC_KEY_generate_key() - -See L. - -=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. - -=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 - -=item * - -EC_METHOD_get_field_type() - -Use L instead. -See L - -=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 - -=item * - -EC_KEY_print(), EC_KEY_print_fp() - -See L - -=item * - -EC_KEY_set_asn1_flag(), EC_KEY_set_conv_form(), EC_KEY_set_enc_flags() - -See L. - -=item * - -EC_KEY_set_group(), EC_KEY_set_private_key(), EC_KEY_set_public_key(), -EC_KEY_set_public_key_affine_coordinates() - -See L. - -=item * - -ECParameters_print(), ECParameters_print_fp(), ECPKParameters_print(), -ECPKParameters_print_fp() - -See L - -=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 and -L 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 and L -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 instead. - -=item * - -EC_POINTs_mul() - -This function is not widely used. Applications should instead use the -L function. - -=item * - -B - -All engine functions are deprecated. An engine should be rewritten as a provider. -See L. - -=item * - -B, 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, L, -L, L, L, -L and L. -Applications should use L, or pick information -with ERR_peek functions and finish off with getting the error code by using -L. - -=item * - -EVP_CIPHER_CTX_iv(), EVP_CIPHER_CTX_iv_noconst(), EVP_CIPHER_CTX_original_iv() - -Applications should instead use L, -L and L -respectively. -See L for further information. - -=item * - -B, EVP_MD_CTX_set_update_fn(), EVP_MD_CTX_update_fn(), -B - -See L. - -=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 and -L. -These functions are obsolete and should not be required. - -=item * - -EVP_PKEY_CTX_set_rsa_keygen_pubexp() - -Applications should use L instead. - -=item * - -EVP_PKEY_cmp(), EVP_PKEY_cmp_parameters() - -Applications should use L and L instead. -See L for further details. - -=item * - -EVP_PKEY_encrypt_old(), EVP_PKEY_decrypt_old(), - -Applications should use L and L or -L and L 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. - -=item * - -B - -See L. - -=item * - -EVP_PKEY_new_CMAC_key() - -See L. - -=item * - -EVP_PKEY_assign(), EVP_PKEY_set1_DH(), EVP_PKEY_set1_DSA(), -EVP_PKEY_set1_EC_KEY(), EVP_PKEY_set1_RSA() - -See L - -=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 and -L. -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. - -=item * - -EVP_PKEY_set_alias_type() - -This function has been removed. There is no replacement. -See L - -=item * - -HMAC_Init_ex(), HMAC_Update(), HMAC_Final(), HMAC_size() - -See L. - -=item * - -HMAC_CTX_new(), HMAC_CTX_free(), HMAC_CTX_copy(), HMAC_CTX_reset(), -HMAC_CTX_set_flags(), HMAC_CTX_get_md() - -See L. - -=item * - -i2d_DHparams(), i2d_DHxparams() - -See L -and L - -=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 -and L - -=item * - -i2d_ECParameters(), i2d_ECPrivateKey(), i2d_ECPrivateKey_bio(), -i2d_ECPrivateKey_fp(), i2d_EC_PUBKEY(), i2d_EC_PUBKEY_bio(), -i2d_EC_PUBKEY_fp() - -See L -and L - -=item * - -i2o_ECPublicKey() - -Use L. -See L - -=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 -and L - -=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. -IDEA has been moved to the L. - -=item * - -IDEA_options() - -There is no replacement. This function returned a constant string. - -=item * - -MD2(), MD2_Init(), MD2_Update(), MD2_Final() - -See L. -MD2 has been moved to the L. - -=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. -MD4 has been moved to the L. - -=item * - -MDC2(), MDC2_Init(), MDC2_Update(), MDC2_Final() - -See L. -MDC2 has been moved to the L. - -=item * - -MD5(), MD5_Init(), MD5_Update(), MD5_Final(), MD5_Transform() - -See L. - -=item * - -NCONF_WIN32() - -This undocumented function has no replacement. -See L for more details. - -=item * - -OCSP_parse_url() - -Use L instead. - -=item * - -B type and B 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, and the deprecated functions are replaced -with B. See L 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. - -=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 - -=item * - -PKCS1_MGF1() - -See L. - -=item * - -RAND_get_rand_method(), RAND_set_rand_method(), RAND_OpenSSL(), -RAND_set_rand_engine() - -Applications should instead use L, -L and L. -See L 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. -The Algorithms "RC2", "RC4" and "RC5" have been moved to the L. - -=item * - -RIPEMD160(), RIPEMD160_Init(), RIPEMD160_Update(), RIPEMD160_Final(), -RIPEMD160_Transform() - -See L. -The RIPE algorithm has been moved to the L. - -=item * - -RSA_bits(), RSA_security_bits(), RSA_size() - -Use L, L and -L. - -=item * - -RSA_check_key(), RSA_check_key_ex() - -See L - -=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, B, B, -B, B, B -B - -=item * - -RSA_generate_key_ex(), RSA_generate_multi_prime_key() - -See L. - -=item * - -RSA_get0_engine() - -See L - -=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 - -=item * - -RSA_new(), RSA_free(), RSA_up_ref() - -See L. - -=item * - -RSA_get_default_method(), RSA_get_ex_data and RSA_get_method() - -See L. - -=item * - -RSA_get_version() - -There is no replacement. - -=item * - -B, RSA_new_method(), RSA_null_method and RSA_PKCS1_OpenSSL() - -See L. - -=item * - -B, B - -See L and -L. - -=item * - -RSA_print(), RSA_print_fp() - -See L - -=item * - -RSA_public_encrypt(), RSA_private_decrypt() - -See L - -=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. - -=item * - -RSAPrivateKey_dup(), RSAPublicKey_dup() - -There is no direct replacement. Applications may use L. - -=item * - -RSAPublicKey_it(), RSAPrivateKey_it() - -See L - -=item * - -RSA_set0_crt_params(), RSA_set0_factors(), RSA_set0_key(), -RSA_set0_multi_prime_params() - -See L. - -=item * - -RSA_set_default_method(), RSA_set_method(), RSA_set_ex_data() - -See L - -=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. - -=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. -See B. - -=item * - -SEED_encrypt(), SEED_decrypt(), SEED_set_key(), SEED_cbc_encrypt(), -SEED_cfb128_encrypt(), SEED_ecb_encrypt(), SEED_ofb128_encrypt() - -See L. -The SEED algorithm has been moved to the L. - -=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. - -=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 -or L. If custom parameters are necessary then applications can -use the alternative functions L and -L. 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 function instead. - -=item * - -WHIRLPOOL(), WHIRLPOOL_Init(), WHIRLPOOL_Update(), WHIRLPOOL_Final(), -WHIRLPOOL_BitUpdate() - -See L. -The Whirlpool algorithm has been moved to the L. - -=item * - -X509_certificate_type() - -This was an undocumented function. Applications can use L -and L instead. - -=item * - -X509_http_nbio(), X509_CRL_http_nbio() - -Use L and L 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. With the introduction -of Ls EVP_PKEY_id() or its new equivalent -L might now also return the value -1 -(B) indicating the use of a provider to -implement the EVP_PKEY object. Therefore, the use of -L is recommended for retrieving -the name of the EVP_PKEY algorithm. - -=back - -=head2 Using the FIPS Module in applications - -See L and L for details. - -=head2 OpenSSL command line application changes - -=head3 New applications - -L|openssl-kdf(1)> uses the new L API. -L|openssl-mac(1)> uses the new L 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 app has many new options. See L for more -information. - -B<-crl_lastupdate> and B<-crl_nextupdate> used by B 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. -The B<-c> option used by B, B, -B, and B. - -=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 now lists 'P', -'Q', 'G' and 'pcounter' instead of 'prime', 'generator', 'subgroup order' and -'counter' respectively. - -The B 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 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, B, B, B, -B and B have been modified to use PKEY APIs. -B and B now write PKCS #8 keys by default. - -=head3 Default settings - -"SHA256" is now the default digest for TS query used by B. - -=head3 Deprecated apps - -B is deprecated, use B instead. -B, B, B, B, -B, B, B and B 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 macro values in preprocessor C<#if> conditions. -However it is still possible to test whether these macros are defined or not. - -See L, L, -L and L. - -=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). - -=item * - -Client-initiated renegotiation is disabled by default. - -To allow it, use the B<-client_renegotiation> option, -the B flag, or the C -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. 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. If the -leaf certificate is signed with SHA-1, a call to L -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 or using the B<-auth_level> -options of the commands. - -=back - -=head1 SEE ALSO - -L - -=head1 HISTORY - -The migration guide was created for OpenSSL 3.0. - -=head1 COPYRIGHT - -Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/doc/man7/openssl-env.pod b/doc/man7/openssl-env.pod index c7dbd2277dc6..78043d5bd68a 100644 --- a/doc/man7/openssl-env.pod +++ b/doc/man7/openssl-env.pod @@ -167,24 +167,44 @@ See L. Additional arguments for the L command. -=item B, B, B, B, B +=item B, B, B, B, B, B OpenSSL supports a number of different algorithm implementations for various machines and, by default, it determines which to use based on the processor capabilities and run time feature enquiry. These environment variables can be used to exert more control over this selection process. -See L, L. +See L, L and L. =item B, B, B Specify a proxy hostname. See L. +=item B + +Specifies a QUIC qlog output directory. See L. + +=item B + +Used to set a QUIC qlog filter specification. See L. + +=item B + +Used to produce the standard format output file for SSL key logging. Optionally +set this variable to a filename to log all secrets produced by SSL connections. +Note, use of the environment variable is predicated on configuring OpenSSL at +build time with the enable-sslkeylog feature. The file format standard can be +found at L. +Note: the use of B poses an explicit security risk. By recording +the exchanged keys during an SSL session, it allows any available party with +read access to the file to decrypt application traffic sent over that session. +Use of this feature should be restricted to test and debug environments only. + =back =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/openssl-glossary.pod b/doc/man7/openssl-glossary.pod index 54c8de93a058..994246fb8168 100644 --- a/doc/man7/openssl-glossary.pod +++ b/doc/man7/openssl-glossary.pod @@ -221,7 +221,7 @@ This glossary was added in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/openssl-threads.pod b/doc/man7/openssl-threads.pod index 56cc638e1b86..7f29a327ac6a 100644 --- a/doc/man7/openssl-threads.pod +++ b/doc/man7/openssl-threads.pod @@ -73,8 +73,8 @@ For implicit global state or singletons, thread-safety depends on the facility. The L and related API's have their own lock, while L assumes the underlying platform allocation will do any necessary locking. -Some API's, such as L and related, or L -do no locking at all; this can be considered a bug. +Some API's, such as L and related do no locking at all; +this can be considered a bug. A separate, although related, issue is modifying "factory" objects when other objects have been created from that. diff --git a/doc/man7/provider-asym_cipher.pod b/doc/man7/provider-asym_cipher.pod index 0976a263a883..9679c5c98526 100644 --- a/doc/man7/provider-asym_cipher.pod +++ b/doc/man7/provider-asym_cipher.pod @@ -234,6 +234,37 @@ The TLS protocol version first requested by the client. The negotiated TLS protocol version. +=item "implicit-rejection" (B) + +Gets or sets the use of the implicit rejection mechanism for RSA PKCS#1 v1.5 +decryption. When set (non zero value), the decryption API will return +a deterministically random value if the PKCS#1 v1.5 padding check fails. +This makes exploitation of the Bleichenbacher significantly harder, even +if the code using the RSA decryption API is not implemented in side-channel +free manner. Set by default in OpenSSL providers. + +=back + +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling either OSSL_FUNC_asym_cipher_encrypt() or +OSSL_FUNC_asym_cipher_decrypt(). It may return 0 if "key-check" is set to 0. + +=item "key-check" (B) + +If required this parameter should be set using either +OSSL_FUNC_asym_cipher_encrypt_init() or OSSL_FUNC_asym_cipher_decrypt_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + =back OSSL_FUNC_asym_cipher_gettable_ctx_params() and OSSL_FUNC_asym_cipher_settable_ctx_params() @@ -255,10 +286,12 @@ L =head1 HISTORY The provider ASYM_CIPHER interface was introduced in OpenSSL 3.0. +The Asymmetric Cipher Parameters "fips-indicator" and "key-check" +were added in OpenSSL 3.4. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod index 2fd803bb96b6..0302900a7314 100644 --- a/doc/man7/provider-base.pod +++ b/doc/man7/provider-base.pod @@ -76,13 +76,23 @@ provider-base size_t get_entropy(const OSSL_CORE_HANDLE *handle, unsigned char **pout, int entropy, size_t min_len, size_t max_len); + size_t get_user_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); + void cleanup_user_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); + size_t get_user_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); + void cleanup_user_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, @@ -171,9 +181,13 @@ provider): 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_get_user_entropy OSSL_FUNC_GET_USER_ENTROPY ossl_rand_cleanup_entropy OSSL_FUNC_CLEANUP_ENTROPY + ossl_rand_cleanup_user_entropy OSSL_FUNC_CLEANUP_USER_ENTROPY ossl_rand_get_nonce OSSL_FUNC_GET_NONCE + ossl_rand_get_user_nonce OSSL_FUNC_GET_USER_NONCE ossl_rand_cleanup_nonce OSSL_FUNC_CLEANUP_NONCE + ossl_rand_cleanup_user_nonce OSSL_FUNC_CLEANUP_USER_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 @@ -265,7 +279,6 @@ It will treat as success the case where the OID already exists (even if the short name I or long name I 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) consisting of an underlying signature algorithm (I) @@ -280,7 +293,6 @@ signature algorithm already exists (even if registered against a different underlying signature or digest algorithm). For I, 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(), @@ -304,9 +316,17 @@ output will have at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length is returned to the caller. On error, zero is returned. +get_user_entropy() is the same as get_entropy() except that it will +attempt to gather seed material via the seed source specified by a call to +L or via L. + 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 and its length in B. +get_entropy(). The entropy pointer returned by get_entropy() +is passed in B and its length in B. + +cleanup_user_entropy() is used to clean up and free the buffer returned by +get_user_entropy(). The entropy pointer returned by get_user_entropy() +is passed in B and its length in B. get_nonce() retrieves a nonce using the passed I parameter of length I and operating system specific information. @@ -316,9 +336,17 @@ The output is stored in a buffer which contains at least I and at most I bytes. The buffer address is stored in I<*pout> and the buffer length returned to the caller. On error, zero is returned. +get_user_nonce() is the same as get_nonce() except that it will attempt +to gather seed material via the seed source specified by a call to +L or via L. + 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 and its length in B. +get_nonce(). The nonce pointer returned by get_nonce() +is passed in B and its length in B. + +cleanup_user_nonce() is used to clean up and free the buffer returned by +get_user_nonce(). The nonce pointer returned by get_user_nonce() +is passed in B and its length in B. provider_register_child_cb() registers callbacks for being informed about the loading and unloading of providers in the application's library context. @@ -553,6 +581,11 @@ The name of the group as known by the provider. This could be the same as the The TLS group id value as given in the IANA TLS Supported Groups registry. +It is possible to register the same group id from within different +providers. Users should note that if no property query is specified, or +more than one implementation matches the property query then it is +unspecified which implementation for a particular group id will be used. + =item "tls-group-alg" (B) The name of a Key Management algorithm that the provider offers and that should @@ -609,6 +642,143 @@ or maximum. A -1 indicates that the group should not be used in that protocol. =back +=head3 "TLS-SIGALG" Capability + +The "TLS-SIGALG" capability can be queried by libssl to discover the list of +TLS signature algorithms that a provider can support. Each signature supported +can be used for client- or server-authentication in addition to the built-in +signature algorithms. +TLS1.3 clients can advertise the list of TLS signature algorithms they support +in the signature_algorithms extension, and TLS servers can select an algorithm +from the offered list that they also support. In this way a provider can add +to the list of signature algorithms that libssl already supports with +additional ones. + +Each TLS signature algorithm that a provider supports should be described via +the callback passed in through the provider_get_capabilities function. Each +algorithm can have the following details supplied: + +=over 4 + +=item "iana-name" (B) + +The name of the signature algorithm as given in the IANA TLS Signature Scheme +registry as "Description": +L. +This value must be supplied. + +=item "iana-code-point" (B) + +The TLS algorithm ID value as given in the IANA TLS SignatureScheme registry. +This value must be supplied. + +It is possible to register the same code point from within different +providers. Users should note that if no property query is specified, or +more than one implementation matches the property query then it is +unspecified which implementation for a particular code point will be used. + +=item "sigalg-name" (B) + +A name for the full (possibly composite hash-and-signature) signature +algorithm. +The provider may, but is not obligated to, provide a signature implementation +with this name; if it doesn't, this is assumed to be a composite of a pure +signature algorithm and a hash algorithm, which must be given with the +parameters "sig-name" and "hash-name". +This value must be supplied. + +=item "sigalg-oid" (B) + +The OID of the "sigalg-name" algorithm in canonical numeric text form. If +this parameter is given, OBJ_create() will be used to create an OBJ and +a NID for this OID, using the "sigalg-name" parameter for its (short) name. +Otherwise, it's assumed to already exist in the object database, possibly +done by the provider with the core_obj_create() upcall. +This value is optional. + +=item "sig-name" (B) + +The name of the pure signature algorithm that is part of a composite +"sigalg-name". If "sigalg-name" is implemented by the provider, this +parameter is redundant and must not be given. +This value is optional. + +=item "sig-oid" (B) + +The OID of the "sig-name" algorithm in canonical numeric text form. If +this parameter is given, OBJ_create() will be used to create an OBJ and +a NID for this OID, using the "sig-name" parameter for its (short) name. +Otherwise, it is assumed to already exist in the object database. This +can be done by the provider using the core_obj_create() upcall. +This value is optional. + +=item "hash-name" (B) + +The name of the hash algorithm that is part of a composite "sigalg-name". +If "sigalg-name" is implemented by the provider, this parameter is redundant +and must not be given. +This value is optional. + +=item "hash-oid" (B) + +The OID of the "hash-name" algorithm in canonical numeric text form. If +this parameter is given, OBJ_create() will be used to create an OBJ and +a NID for this OID, using the "hash-name" parameter for its (short) name. +Otherwise, it's assumed to already exist in the object database, possibly +done by the provider with the core_obj_create() upcall. +This value is optional. + +=item "key-type" (B) + +The key type of the public key of applicable certificates. If this parameter +isn't present, it's assumed to be the same as "sig-name" if that's present, +otherwise "sigalg-name". +This value is optional. + +=item "key-type-oid" (B) + +The OID of the "key-type" in canonical numeric text form. If +this parameter is given, OBJ_create() will be used to create an OBJ and +a NID for this OID, using the "key-type" parameter for its (short) name. +Otherwise, it's assumed to already exist in the object database, possibly +done by the provider with the core_obj_create() upcall. +This value is optional. + +=item "sec-bits" (B) + +The number of bits of security offered by keys of this algorithm. The number +of bits should be comparable with the ones given in table 2 and 3 of the NIST +SP800-57 document. This number is used to determine the security strength of +the algorithm if no digest algorithm has been registered that otherwise +defines the security strength. If the signature algorithm implements its own +digest internally, this value needs to be set to properly reflect the overall +security strength. +This value must be supplied. + +=item "tls-min-tls" (B) + +=item "tls-max-tls" (B) + +=item "tls-min-dtls" (B) + +=item "tls-max-dtls" (B) + +These parameters can be used to describe the minimum and maximum TLS and DTLS +versions supported by the signature algorithm. 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 in either the min or max field +indicates that the signature algorithm should not be used in that protocol. +Presently, provider signature algorithms are used only with TLS 1.3, if +that's enclosed in the specified range. + +=back + +=head1 NOTES + +The core_obj_create() and core_obj_add_sigid() functions were not thread safe +in OpenSSL 3.0. + =head1 EXAMPLES This is an example of a simple provider made available as a @@ -625,7 +795,7 @@ operation C. static const OSSL_ITEM reasons[] = { { E_MALLOC, "memory allocation failure" }. - { 0, NULL } /* Termination */ + OSSL_DISPATCH_END }; /* @@ -705,7 +875,7 @@ operation C. { 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 } + OSSL_DISPATCH_END }; static const OSSL_ALGORITHM bars[] = { @@ -737,7 +907,7 @@ operation C. { 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 } + OSSL_DISPATCH_END }; int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, @@ -807,9 +977,15 @@ L The concept of providers and everything surrounding them was introduced in OpenSSL 3.0. +Definitions for +B +and +B +were added in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-cipher.pod b/doc/man7/provider-cipher.pod index eaad3cf2ff02..93fdcfb1c0fa 100644 --- a/doc/man7/provider-cipher.pod +++ b/doc/man7/provider-cipher.pod @@ -29,6 +29,12 @@ provider-cipher - The cipher library E-E provider functions 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_encrypt_skey_init(void *cctx, void *skeydata, + const unsigned char *iv, size_t ivlen, + const OSSL_PARAM params[]); + int OSSL_FUNC_cipher_encrypt_skey_init(void *cctx, void *skeydata, + 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, @@ -36,6 +42,23 @@ provider-cipher - The cipher library E-E provider functions int OSSL_FUNC_cipher_cipher(void *cctx, unsigned char *out, size_t *outl, size_t outsize, const unsigned char *in, size_t inl); + /* Encryption/decryption using cipher pipeline */ + int OSSL_FUNC_cipher_pipeline_encrypt_init(void *cctx, const unsigned char *key, + size_t keylen, size_t numpipes, + const unsigned char **iv, size_t ivlen, + const OSSL_PARAM params[])) + int OSSL_FUNC_cipher_pipeline_decrypt_init(void *cctx, const unsigned char *key, + size_t keylen, size_t numpipes, + const unsigned char **iv, size_t ivlen, + const OSSL_PARAM params[])) + int OSSL_FUNC_cipher_pipeline_update(void *cctx, size_t numpipes, + unsigned char **out, size_t *outl, + const size_t *outsize, + const unsigned char **in, const size_t *inl)) + int OSSL_FUNC_cipher_pipeline_final(void *cctx, size_t numpipes, + unsigned char **out, size_t *outl, + const size_t *outsize)) + /* Cipher parameter descriptors */ const OSSL_PARAM *OSSL_FUNC_cipher_gettable_params(void *provctx); @@ -81,28 +104,36 @@ For example, the "function" OSSL_FUNC_cipher_newctx() has these: L arrays are indexed by numbers that are provided as macros in L, 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_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_encrypt_init OSSL_FUNC_CIPHER_ENCRYPT_INIT + OSSL_FUNC_cipher_decrypt_init OSSL_FUNC_CIPHER_DECRYPT_INIT + OSSL_FUNC_cipher_encrypt_skey_init OSSL_FUNC_CIPHER_ENCRYPT_SKEY_INIT + OSSL_FUNC_cipher_decrypt_skey_init OSSL_FUNC_CIPHER_DECRYPT_SKEY_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_pipeline_encrypt_init OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT + OSSL_FUNC_cipher_pipeline_decrypt_init OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT + OSSL_FUNC_cipher_pipeline_update OSSL_FUNC_CIPHER_PIPELINE_UPDATE + OSSL_FUNC_cipher_pipeline_final OSSL_FUNC_CIPHER_PIPELINE_FINAL - 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 + 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. +single "cipher" function. Similarly, there can be a complete set of pipeline +"encrypt" functions, and/or a complete set of pipeline "decrypt" functions. In all cases both the OSSL_FUNC_cipher_newctx and OSSL_FUNC_cipher_freectx functions must be present. All other functions are optional. @@ -132,8 +163,13 @@ The IV to be used is given in I which is I bytes long. The I, 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_decrypt_init() is the same as OSSL_FUNC_cipher_encrypt_init() +except that it initialises the context for a decryption operation. + +OSSL_FUNC_cipher_encrypt_skey_init() and +OSSL_FUNC_cipher_decrypt_skey_init() are variants of +OSSL_FUNC_cipher_encrypt_init() and OSSL_FUNC_cipher_decrypt_init() for working with +opaque objects containing provider-specific key handles instead of raw bytes. OSSL_FUNC_cipher_update() is called to supply data to be encrypted/decrypted as part of a previously initialised cipher operation. @@ -179,6 +215,16 @@ The output from the encryption/decryption should be stored in I and the amount of data stored should be put in I<*outl> which should be no more than I bytes. +OSSL_FUNC_cipher_pipeline_encrypt_init(), OSSL_FUNC_cipher_pipeline_decrypt_init() +OSSL_FUNC_cipher_pipeline_update(), and OSSL_FUNC_cipher_pipeline_final() are similar to +the non-pipeline variants, but are used when the application is using cipher pipelining. +The I parameter is the number of pipes in the pipeline. The I parameter +is an array of buffers with IVs, each I bytes long. The I and I are +arrays of buffer pointers. The I and I, I are arrays of size_t +representing corresponding buffer length as similar to the non-pipeline variants. +All arrays are of length I. See L for more +information. + =head2 Cipher Parameters See L for further details on the parameters structure used by @@ -216,8 +262,12 @@ OSSL_FUNC_cipher_newctx() and OSSL_FUNC_cipher_dupctx() should return the newly 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 +OSSL_FUNC_cipher_final(), OSSL_FUNC_cipher_cipher(), +OSSL_FUNC_cipher_encrypt_skey_init(), OSSL_FUNC_cipher_decrypt_skey_init(), +OSSL_FUNC_cipher_pipeline_encrypt_init(), OSSL_FUNC_cipher_pipeline_decrypt_init(), +OSSL_FUNC_cipher_pipeline_update(), OSSL_FUNC_cipher_pipeline_final(), +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 @@ -239,9 +289,12 @@ L, L The provider CIPHER interface was introduced in OpenSSL 3.0. +The OSSL_FUNC_cipher_encrypt_skey_init() and +OSSL_FUNC_cipher_decrypt_skey_init() were introduced in OpenSSL 3.5. + =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-decoder.pod b/doc/man7/provider-decoder.pod index e968e661f7cf..d19deec4af5b 100644 --- a/doc/man7/provider-decoder.pod +++ b/doc/man7/provider-decoder.pod @@ -110,7 +110,9 @@ 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: +Properties, as defined in the L array element of each +decoder implementation, can be used to further specify details about an +implementation: =over 4 @@ -302,7 +304,7 @@ The DECODER interface was introduced in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod index cac53ac291fe..c44de648dcdf 100644 --- a/doc/man7/provider-digest.pod +++ b/doc/man7/provider-digest.pod @@ -20,6 +20,7 @@ provider-digest - The digest library E-E provider functions void *OSSL_FUNC_digest_newctx(void *provctx); void OSSL_FUNC_digest_freectx(void *dctx); void *OSSL_FUNC_digest_dupctx(void *dctx); + void OSSL_FUNC_digest_copyctx(void *voutctx, void *vinctx); /* Digest generation */ int OSSL_FUNC_digest_init(void *dctx, const OSSL_PARAM params[]); @@ -76,6 +77,7 @@ macros in L, 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_copyctx OSSL_FUNC_DIGEST_COPYCTX OSSL_FUNC_digest_init OSSL_FUNC_DIGEST_INIT OSSL_FUNC_digest_update OSSL_FUNC_DIGEST_UPDATE @@ -92,7 +94,8 @@ macros in L, as follows: 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. +OSSL_FUNC_digest_init, OSSL_FUNC_digest_update, OSSL_FUNC_digest_final +and OSSL_FUNC_digest_get_params should be implemented. All other functions are optional. =head2 Context Management Functions @@ -111,6 +114,14 @@ This function should free any resources associated with that context. OSSL_FUNC_digest_dupctx() should duplicate the provider side digest context in the I parameter and return the duplicate copy. +OSSL_FUNC_digest_copyctx() should copy the provider side digest context in the +I parameter to the I parameter which is the another provider side +context. +The OSSL_FUNC_digest_copyctx function is used in the EVP_MD_CTX_copy_ex function to +speed up HMAC operations in the PBKDF2. +This function is optional, and dupctx will be used if there is no EVP_MD_CTX_copy_ex +function. + =head2 Digest Generation Functions OSSL_FUNC_digest_init() initialises a digest operation given a newly created @@ -198,8 +209,7 @@ This digest method can only handle one block of input. =item B -This digest method is an extensible-output function (XOF) and supports -setting the B parameter. +This digest method is an extensible-output function (XOF). =item B @@ -266,18 +276,19 @@ L, L, L, L, L, L, L, L, L, L, -L, L, L, -L, L, +L, L, L +L, L, L, L, L, L =head1 HISTORY The provider DIGEST interface was introduced in OpenSSL 3.0. +OSSL_FUNC_digest_copyctx() was added in 3.5 version. =head1 COPYRIGHT -Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-encoder.pod b/doc/man7/provider-encoder.pod index f3e9ce5b1632..dadd33f9b0f6 100644 --- a/doc/man7/provider-encoder.pod +++ b/doc/man7/provider-encoder.pod @@ -127,7 +127,9 @@ The name of an implementation should match the type of object it handles. For example, an implementation that encodes an RSA key should be named "RSA". Likewise, an implementation that further encodes DER should be named "DER". -Properties can be used to further specify details about an implementation: +Properties, as defined in the L array element of each +decoder implementation, can be used to further specify details about an +implementation: =over 4 @@ -321,7 +323,7 @@ The ENCODER interface was introduced in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-kdf.pod b/doc/man7/provider-kdf.pod index 51362a7cccdc..4221f9a0f401 100644 --- a/doc/man7/provider-kdf.pod +++ b/doc/man7/provider-kdf.pod @@ -349,7 +349,7 @@ The provider KDF interface was introduced in OpenSSL 3.0. =head1 COPYRIGHT -Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-kem.pod b/doc/man7/provider-kem.pod index 8436a7f25e3f..85b8f1a6b80a 100644 --- a/doc/man7/provider-kem.pod +++ b/doc/man7/provider-kem.pod @@ -23,13 +23,19 @@ provider-kem - The kem library E-E provider functions void *OSSL_FUNC_kem_dupctx(void *ctx); /* Encapsulation */ - int OSSL_FUNC_kem_encapsulate_init(void *ctx, void *provkey, const char *name, + int OSSL_FUNC_kem_encapsulate_init(void *ctx, void *provkey, const OSSL_PARAM params[]); + int OSSL_FUNC_kem_auth_encapsulate_init(void *ctx, void *provkey, + void *provauthkey, + const OSSL_PARAM params[]); int OSSL_FUNC_kem_encapsulate(void *ctx, unsigned char *out, size_t *outlen, unsigned char *secret, size_t *secretlen); /* Decapsulation */ - int OSSL_FUNC_kem_decapsulate_init(void *ctx, void *provkey, const char *name); + int OSSL_FUNC_kem_decapsulate_init(void *ctx, void *provkey); + int OSSL_FUNC_kem_auth_decapsulate_init(void *ctx, void *provkey, + void *provauthkey, + const OSSL_PARAM params[]); int OSSL_FUNC_kem_decapsulate(void *ctx, unsigned char *out, size_t *outlen, const unsigned char *in, size_t inlen); @@ -68,20 +74,22 @@ For example, the "function" OSSL_FUNC_kem_newctx() has these: L arrays are indexed by numbers that are provided as macros in L, as follows: - OSSL_FUNC_kem_newctx OSSL_FUNC_KEM_NEWCTX - OSSL_FUNC_kem_freectx OSSL_FUNC_KEM_FREECTX - OSSL_FUNC_kem_dupctx OSSL_FUNC_KEM_DUPCTX + OSSL_FUNC_kem_newctx OSSL_FUNC_KEM_NEWCTX + OSSL_FUNC_kem_freectx OSSL_FUNC_KEM_FREECTX + OSSL_FUNC_kem_dupctx OSSL_FUNC_KEM_DUPCTX - OSSL_FUNC_kem_encapsulate_init OSSL_FUNC_KEM_ENCAPSULATE_INIT - OSSL_FUNC_kem_encapsulate OSSL_FUNC_KEM_ENCAPSULATE + OSSL_FUNC_kem_encapsulate_init OSSL_FUNC_KEM_ENCAPSULATE_INIT + OSSL_FUNC_kem_auth_encapsulate_init OSSL_FUNC_KEM_AUTH_ENCAPSULATE_INIT + OSSL_FUNC_kem_encapsulate OSSL_FUNC_KEM_ENCAPSULATE - OSSL_FUNC_kem_decapsulate_init OSSL_FUNC_KEM_DECAPSULATE_INIT - OSSL_FUNC_kem_decapsulate OSSL_FUNC_KEM_DECAPSULATE + OSSL_FUNC_kem_decapsulate_init OSSL_FUNC_KEM_DECAPSULATE_INIT + OSSL_FUNC_kem_auth_decapsulate_init OSSL_FUNC_KEM_AUTH_DECAPSULATE_INIT + OSSL_FUNC_kem_decapsulate OSSL_FUNC_KEM_DECAPSULATE - OSSL_FUNC_kem_get_ctx_params OSSL_FUNC_KEM_GET_CTX_PARAMS - OSSL_FUNC_kem_gettable_ctx_params OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS - OSSL_FUNC_kem_set_ctx_params OSSL_FUNC_KEM_SET_CTX_PARAMS - OSSL_FUNC_kem_settable_ctx_params OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS + OSSL_FUNC_kem_get_ctx_params OSSL_FUNC_KEM_GET_CTX_PARAMS + OSSL_FUNC_kem_gettable_ctx_params OSSL_FUNC_KEM_GETTABLE_CTX_PARAMS + OSSL_FUNC_kem_set_ctx_params OSSL_FUNC_KEM_SET_CTX_PARAMS + OSSL_FUNC_kem_settable_ctx_params OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS An asymmetric kem algorithm implementation may not implement all of these functions. @@ -90,10 +98,12 @@ OSSL_FUNC_kem_newctx and OSSL_FUNC_kem_freectx. It must also implement both of OSSL_FUNC_kem_encapsulate_init and OSSL_FUNC_kem_encapsulate, or both of OSSL_FUNC_kem_decapsulate_init and OSSL_FUNC_kem_decapsulate. +OSSL_FUNC_kem_auth_encapsulate_init is optional but if it is present then so +must OSSL_FUNC_kem_auth_decapsulate_init. OSSL_FUNC_kem_get_ctx_params is optional but if it is present then so must OSSL_FUNC_kem_gettable_ctx_params. Similarly, OSSL_FUNC_kem_set_ctx_params is optional but if it is present then -so must OSSL_FUNC_kem_settable_ctx_params. +OSSL_FUNC_kem_settable_ctx_params must also be present. An asymmetric kem algorithm must also implement some mechanism for generating, loading or importing keys via the key management (OSSL_OP_KEYMGMT) operation. @@ -127,6 +137,10 @@ 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_kem_auth_encapsulate_init() is similar to +OSSL_FUNC_kem_encapsulate_init(), but also passes an additional authentication +key I which cannot be NULL. + OSSL_FUNC_kem_encapsulate() performs the actual encapsulation itself. A previously initialised asymmetric kem context is passed in the I parameter. @@ -151,6 +165,10 @@ 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_kem_auth_decapsulate_init() is similar to +OSSL_FUNC_kem_decapsulate_init(), but also passes an additional authentication +key I which cannot be NULL. + OSSL_FUNC_kem_decapsulate() performs the actual decapsulation itself. A previously initialised asymmetric kem context is passed in the I parameter. @@ -168,12 +186,36 @@ See L for further details on the parameters structure used by the OSSL_FUNC_kem_get_ctx_params() and OSSL_FUNC_kem_set_ctx_params() functions. -OSSL_FUNC_kem_get_ctx_params() gets asymmetric kem parameters associated +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling either OSSL_FUNC_kem_encapsulate() or +OSSL_FUNC_kem_decapsulate(). It may return 0 if the "key-check" is set to 0. + +=item "key-check" (B) + +If required this parameter should be set using OSSL_FUNC_kem_encapsulate_init() +or OSSL_FUNC_kem_decapsulate_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + +=head2 Asymmetric Key Encapsulation Parameter Functions + +OSSL_FUNC_kem_get_ctx_params() gets asymmetric KEM parameters associated with the given provider side asymmetric kem context I and stores them in I. Passing NULL for I should return true. -OSSL_FUNC_kem_set_ctx_params() sets the asymmetric kem parameters associated +OSSL_FUNC_kem_set_ctx_params() sets the asymmetric KEM parameters associated with the given provider side asymmetric kem context I to I. Any parameter settings are additional to any that were previously set. Passing NULL for I should return true. @@ -200,9 +242,15 @@ L The provider KEM interface was introduced in OpenSSL 3.0. +OSSL_FUNC_kem_auth_encapsulate_init() and OSSL_FUNC_kem_auth_decapsulate_init() +were added in OpenSSL 3.2. + +The Asymmetric Key Encapsulation Parameters "fips-indicator" and "key-check" +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-keyexch.pod b/doc/man7/provider-keyexch.pod index 9e146d31c719..1d3604e783a3 100644 --- a/doc/man7/provider-keyexch.pod +++ b/doc/man7/provider-keyexch.pod @@ -206,6 +206,36 @@ and EVP_PKEY_CTX_get0_dh_kdf_ukm() functions. =back +The OpenSSL FIPS provider also supports the following parameters: + +=over 4 + +=item "fips-indicator" (B) + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling OSSL_FUNC_keyexch_derive(). It may +return 0 if either the "digest-check" or the "key-check" are set to 0. + +=item "key-check" (B) + +If required this parameter should be set using OSSL_FUNC_keyexch_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=item "digest-check" (B) + +If required this parameter should be set before any optional digest is set. +The default value of 1 causes an error when the digest is set if the digest is +not FIPS approved. Setting this to 0 will ignore the error and set the +approved "fips-indicator" to 0. +This option breaks FIPS compliance if it causes the approved "fips-indicator" +to return 0. + +=back + =head1 RETURN VALUES OSSL_FUNC_keyexch_newctx() and OSSL_FUNC_keyexch_dupctx() should return the newly created @@ -226,9 +256,12 @@ L The provider KEYEXCH interface was introduced in OpenSSL 3.0. +The Key Exchange Parameters "fips-indicator", "key-check" and "digest-check" +were added in OpenSSL 3.4. + =head1 COPYRIGHT -Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/provider-keymgmt.pod b/doc/man7/provider-keymgmt.pod index 498ad9c4e107..f8235ac8a0af 100644 --- a/doc/man7/provider-keymgmt.pod +++ b/doc/man7/provider-keymgmt.pod @@ -22,7 +22,10 @@ provider-keymgmt - The KEYMGMT library E-E provider functions 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_get_params(void *genctx, OSSL_PARAM params[]); int OSSL_FUNC_keymgmt_gen_set_params(void *genctx, const OSSL_PARAM params[]); + const OSSL_PARAM *OSSL_FUNC_keymgmt_gen_gettable_params(void *genctx, + void *provctx); 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); @@ -48,9 +51,11 @@ provider-keymgmt - The KEYMGMT library E-E provider functions /* 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); + const OSSL_PARAM *OSSL_FUNC_keymgmt_import_types_ex(void *provctx, 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); + const OSSL_PARAM *OSSL_FUNC_keymgmt_export_types_ex(void *provctx, int selection); /* Key object duplication, a constructor */ void *OSSL_FUNC_keymgmt_dup(const void *keydata_from, int selection); @@ -95,6 +100,8 @@ macros in L, as follows: 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_get_params OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS + OSSL_FUNC_keymgmt_gen_gettable_params OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS 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 @@ -115,8 +122,10 @@ macros in L, as follows: OSSL_FUNC_keymgmt_import OSSL_FUNC_KEYMGMT_IMPORT OSSL_FUNC_keymgmt_import_types OSSL_FUNC_KEYMGMT_IMPORT_TYPES + OSSL_FUNC_keymgmt_import_types_ex OSSL_FUNC_KEYMGMT_IMPORT_TYPES_EX OSSL_FUNC_keymgmt_export OSSL_FUNC_KEYMGMT_EXPORT OSSL_FUNC_keymgmt_export_types OSSL_FUNC_KEYMGMT_EXPORT_TYPES + OSSL_FUNC_keymgmt_export_types_ex OSSL_FUNC_KEYMGMT_EXPORT_TYPES_EX OSSL_FUNC_keymgmt_dup OSSL_FUNC_KEYMGMT_DUP @@ -215,6 +224,7 @@ key object, but that is not mandatory. OSSL_FUNC_keymgmt_free() should free the passed I. OSSL_FUNC_keymgmt_gen_init(), OSSL_FUNC_keymgmt_gen_set_template(), +OSSL_FUNC_keymgmt_gen_get_params(), OSSL_FUNC_keymgmt_gen_gettable_params(), 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. @@ -232,6 +242,13 @@ 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