Browse Source

OpenSSL 3.5.4

Source commit: 3e9d97cebbb2e97f8f7c4bc406ebfe7062715032
Martin Prikryl 2 weeks ago
parent
commit
c1b9277a66
100 changed files with 6980 additions and 947 deletions
  1. 2 0
      libs/openssl/AUTHORS.md
  2. 548 27
      libs/openssl/CHANGES.md
  3. 21 0
      libs/openssl/Configurations/00-base-templates.conf
  4. 59 0
      libs/openssl/Configurations/50-cppbuilder.conf
  5. 19 13
      libs/openssl/Configurations/50-nonstop.conf
  6. 12 7
      libs/openssl/Configurations/unix-Makefile.tmpl
  7. 65 7
      libs/openssl/Configure
  8. 67 20
      libs/openssl/HACKING.md
  9. 122 8
      libs/openssl/INSTALL.md
  10. 171 10
      libs/openssl/NEWS.md
  11. 33 0
      libs/openssl/NOTES-ANSI.md
  12. 9 11
      libs/openssl/NOTES-NONSTOP.md
  13. 20 0
      libs/openssl/NOTES-POSIX.md
  14. 8 8
      libs/openssl/NOTES-VALGRIND.md
  15. 32 20
      libs/openssl/NOTES-WINDOWS.md
  16. 30 0
      libs/openssl/README-FIPS.md
  17. 29 1
      libs/openssl/README-QUIC.md
  18. 6 4
      libs/openssl/README.md
  19. 2 2
      libs/openssl/VERSION.dat
  20. 3 0
      libs/openssl/apps/asn1parse.c
  21. 1 1
      libs/openssl/apps/build.info
  22. 16 20
      libs/openssl/apps/ca.c
  23. 461 30
      libs/openssl/apps/cmp.c
  24. 13 12
      libs/openssl/apps/cms.c
  25. 8 3
      libs/openssl/apps/crl2pkcs7.c
  26. 2 2
      libs/openssl/apps/demoSRP/srp_verifier.txt
  27. 154 68
      libs/openssl/apps/dgst.c
  28. 4 4
      libs/openssl/apps/dhparam.c
  29. 4 4
      libs/openssl/apps/dsaparam.c
  30. 14 14
      libs/openssl/apps/ecparam.c
  31. 76 15
      libs/openssl/apps/enc.c
  32. 6 3
      libs/openssl/apps/engine.c
  33. 332 27
      libs/openssl/apps/fipsinstall.c
  34. 34 19
      libs/openssl/apps/genpkey.c
  35. 6 3
      libs/openssl/apps/include/apps.h
  36. 3 1
      libs/openssl/apps/include/cmp_mock_srv.h
  37. 4 1
      libs/openssl/apps/include/opt.h
  38. 2 2
      libs/openssl/apps/include/platform.h
  39. 10 3
      libs/openssl/apps/info.c
  40. 76 1
      libs/openssl/apps/lib/app_provider.c
  41. 1 0
      libs/openssl/apps/lib/app_rand.c
  42. 145 45
      libs/openssl/apps/lib/apps.c
  43. 152 5
      libs/openssl/apps/lib/cmp_mock_srv.c
  44. 1 0
      libs/openssl/apps/lib/engine_loader.c
  45. 3 1
      libs/openssl/apps/lib/http_server.c
  46. 3 2
      libs/openssl/apps/lib/names.c
  47. 25 13
      libs/openssl/apps/lib/s_cb.c
  48. 2 1
      libs/openssl/apps/lib/s_socket.c
  49. 3 3
      libs/openssl/apps/lib/tlssrp_depr.c
  50. 263 33
      libs/openssl/apps/list.c
  51. 4 4
      libs/openssl/apps/ocsp.c
  52. 2 2
      libs/openssl/apps/openssl-vms.cnf
  53. 2 0
      libs/openssl/apps/openssl.c
  54. 2 2
      libs/openssl/apps/openssl.cnf
  55. 7 9
      libs/openssl/apps/passwd.c
  56. 80 22
      libs/openssl/apps/pkcs12.c
  57. 5 3
      libs/openssl/apps/pkcs8.c
  58. 4 4
      libs/openssl/apps/pkey.c
  59. 3 3
      libs/openssl/apps/pkeyparam.c
  60. 203 79
      libs/openssl/apps/pkeyutl.c
  61. 6 2
      libs/openssl/apps/prime.c
  62. 6 2
      libs/openssl/apps/rehash.c
  63. 39 15
      libs/openssl/apps/req.c
  64. 54 18
      libs/openssl/apps/s_client.c
  65. 47 7
      libs/openssl/apps/s_server.c
  66. 135 0
      libs/openssl/apps/skeyutl.c
  67. 6 9
      libs/openssl/apps/smime.c
  68. 165 112
      libs/openssl/apps/speed.c
  69. 13 9
      libs/openssl/apps/storeutl.c
  70. 6 7
      libs/openssl/apps/ts.c
  71. 19 1
      libs/openssl/apps/version.c
  72. 30 7
      libs/openssl/apps/x509.c
  73. 7 0
      libs/openssl/build.info
  74. 3 1
      libs/openssl/crypto/aes/asm/aes-x86_64.pl
  75. 3 1
      libs/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
  76. 3 1
      libs/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl
  77. 3 1
      libs/openssl/crypto/aes/asm/aesni-x86_64.pl
  78. 2872 0
      libs/openssl/crypto/aes/asm/aesni-xts-avx512.pl
  79. 16 0
      libs/openssl/crypto/aes/asm/aesv8-armx.pl
  80. 18 10
      libs/openssl/crypto/aes/asm/bsaes-armv8.pl
  81. 5 2
      libs/openssl/crypto/aes/asm/bsaes-x86_64.pl
  82. 37 18
      libs/openssl/crypto/aes/asm/vpaes-armv8.pl
  83. 3 2
      libs/openssl/crypto/aes/asm/vpaes-x86_64.pl
  84. 4 1
      libs/openssl/crypto/aes/build.info
  85. 1 0
      libs/openssl/crypto/arm_arch.h
  86. 9 5
      libs/openssl/crypto/armcap.c
  87. 2 2
      libs/openssl/crypto/asn1/a_dup.c
  88. 2 2
      libs/openssl/crypto/asn1/a_i2d_fp.c
  89. 14 8
      libs/openssl/crypto/asn1/a_int.c
  90. 3 2
      libs/openssl/crypto/asn1/a_object.c
  91. 2 3
      libs/openssl/crypto/asn1/a_strex.c
  92. 0 75
      libs/openssl/crypto/asn1/a_time.c
  93. 2 1
      libs/openssl/crypto/asn1/asn1_item_list.c
  94. 2 1
      libs/openssl/crypto/asn1/asn1_item_list.h
  95. 12 1
      libs/openssl/crypto/asn1/d2i_pr.c
  96. 3 6
      libs/openssl/crypto/asn1/f_int.c
  97. 2 4
      libs/openssl/crypto/asn1/f_string.c
  98. 8 1
      libs/openssl/crypto/asn1/p5_pbev2.c
  99. 23 5
      libs/openssl/crypto/asn1/p8_pkey.c
  100. 1 3
      libs/openssl/crypto/asn1/standard_methods.h

+ 2 - 0
libs/openssl/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

+ 548 - 27
libs/openssl/CHANGES.md

@@ -12,6 +12,8 @@ appropriate release branch.
 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)
@@ -23,10 +25,10 @@ OpenSSL Releases
  - [OpenSSL 1.0.0](#openssl-100)
  - [OpenSSL 0.9.x](#openssl-09x)
 
-OpenSSL 3.3
+OpenSSL 3.5
 -----------
 
-### Changes between 3.3.4 and 3.3.5 [30 Sep 2025]
+### Changes between 3.5.3 and 3.5.4 [30 Sep 2025]
 
  * Fix Out-of-bounds read & write in RFC 3211 KEK Unwrap
 
@@ -75,13 +77,38 @@ OpenSSL 3.3
 
    *Stanislav Fort*
 
- * Avoided a potential race condition introduced in 3.3.4, where
+ * The FIPS provider no longer performs a PCT on key import for ECX keys
+   (that was introduced in 3.5.2), following the latest update
+   on that requirement in FIPS 140-3 IG 10.3.A additional comment 1.
+
+   *Eugene Syromiatnikov*
+
+ * Fixed the length of the ASN.1 sequence for the SM3 digests of RSA-encrypted
+   signatures.
+
+   *Xiao Lou Dong Feng*
+
+ * Reverted the synthesised `OPENSSL_VERSION_NUMBER` change for the release
+   builds, as it broke some exiting applications that relied on the previous
+   3.x semantics, as documented in `OpenSSL_version(3)`.
+
+   *Richard Levitte*
+
+### Changes between 3.5.2 and 3.5.3 [16 Sep 2025]
+
+ * Avoided a potential race condition introduced in 3.5.1, where
    `OSSL_STORE_CTX` kept open during lookup while potentially being used
    by multiple threads simultaneously, that could lead to potential crashes
    when multiple concurrent TLS connections are served.
 
    *Matt Caswell*
 
+ * The FIPS provider no longer performs a PCT on key import for RSA, DH,
+   and EC keys (that was introduced in 3.5.2), following the latest update
+   on that requirement in FIPS 140-3 IG 10.3.A additional comment 1.
+
+   *Dr Paul Dale*
+
  * Secure memory allocation calls are no longer used for HMAC keys.
 
    *Dr Paul Dale*
@@ -109,7 +136,34 @@ OpenSSL 3.3
 
    *Viktor Dukhovni*
 
-### Changes between 3.3.3 and 3.3.4 [1 Jul 2025]
+ * Added FIPS 140-3 PCT on DH key generation.
+
+   *Nikola Pajkovsky*
+
+ * Fixed the synthesised `OPENSSL_VERSION_NUMBER`.
+
+   *Richard Levitte*
+
+### Changes between 3.5.1 and 3.5.2 [5 Aug 2025]
+
+ * The FIPS provider now performs a PCT on key import for RSA, EC and ECX.
+   This is mandated by FIPS 140-3 IG 10.3.A additional comment 1.
+
+   *Dr Paul Dale*
+
+### Changes between 3.5.0 and 3.5.1 [1 Jul 2025]
+
+ * Fix x509 application adds trusted use instead of rejected use.
+
+   Issue summary: Use of -addreject option with the openssl x509 application adds
+   a trusted use instead of a rejected use for a certificate.
+
+   Impact summary: If a user intends to make a trusted certificate rejected for
+   a particular use it will be instead marked as trusted for that use.
+
+   ([CVE-2025-4575])
+
+   *Tomas Mraz*
 
  * Aligned the behaviour of TLS and DTLS in the event of a no_renegotiation
    alert being received. Older versions of OpenSSL failed with DTLS if a
@@ -120,12 +174,291 @@ OpenSSL 3.3
 
    *Matt Caswell*
 
+### Changes between 3.4 and 3.5.0 [8 Apr 2025]
+
+ * Added server side support for QUIC
+
+   *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<RAND_bytes(3)> 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.3.2 and 3.3.3 [11 Feb 2025]
+### Changes between 3.4.0 and 3.4.1 [11 Feb 2025]
 
  * Fixed RFC7250 handshakes with unauthenticated servers don't abort as expected.
 
@@ -151,6 +484,191 @@ OpenSSL 3.3
 
    *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.
 
@@ -315,6 +833,8 @@ OpenSSL 3.3
    - `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
@@ -406,7 +926,7 @@ OpenSSL 3.3
 
    *Fisher Yu*
 
- * Enable AES and SHA3 optimisations on Applie Silicon M3-based MacOS systems
+ * Enable AES and SHA3 optimisations on Apple Silicon M3-based MacOS systems
    similar to M1/M2.
 
    *Tom Cosgrove*
@@ -620,11 +1140,6 @@ OpenSSL 3.2
 
    *Fergus Dall*
 
- * Added support for securely getting root CA certificate update in
-   CMP.
-
-   *David von Oheimb*
-
  * Improved contention on global write locks by using more read locks where
    appropriate.
 
@@ -877,21 +1392,24 @@ OpenSSL 3.2
 
    * Lutz Jänicke*
 
- * The `x509`, `ca`, and `req` apps now produce X.509 v3 certificates.
+ * 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 apps `x509`, `verify` etc.
+ * 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 requests for central key generation, generalized
-   polling, and various types of genm/genp exchanges defined in CMP Updates.
+   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*
 
@@ -1190,7 +1708,7 @@ OpenSSL 3.1
 
  * 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
+   The option '-ems_check' can optionally be supplied to
    'openssl fipsinstall'.
 
    *Shane Lontis*
@@ -1213,7 +1731,7 @@ OpenSSL 3.1
 
    *Orr Toledano*
 
- * s_client and s_server apps now explicitly say when the TLS version
+ * `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.
@@ -2264,7 +2782,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.
 
@@ -3180,7 +3699,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*
 
@@ -4514,7 +5033,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*
 
@@ -8509,7 +9028,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])
@@ -9574,7 +10093,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])
@@ -15705,7 +16224,7 @@ s-cbc           3624.96k     5258.21k     5530.91k     5624.30k     5628.26k
 
    *[email protected] 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
@@ -16254,7 +16773,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 <[email protected]>:
    PRNG state recovery was possible based on the output of
    one PRNG request appropriately sized to gain knowledge on
@@ -16639,7 +17158,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.)
 
@@ -18855,7 +19374,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*
@@ -20834,8 +21353,8 @@ ndif
 [CVE-2025-9232]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9232
 [CVE-2025-9231]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9231
 [CVE-2025-9230]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9230
+[CVE-2025-4575]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-4575
 [CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
-[CVE-2024-12797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-12797
 [CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
 [CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
 [CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
@@ -21030,3 +21549,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

+ 21 - 0
libs/openssl/Configurations/00-base-templates.conf

@@ -59,6 +59,8 @@ my %targets=(
         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}
@@ -76,9 +78,27 @@ 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 {
                 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};
@@ -87,6 +107,7 @@ my %targets=(
         ex_libs         =>
             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");

+ 59 - 0
libs/openssl/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',
     }
 );

+ 19 - 13
libs/openssl/Configurations/50-nonstop.conf

@@ -173,6 +173,15 @@
         ex_libs          => '-lput',
     },
 
+    ######################################################################
+    # Build models
+    'nonstop-model-klt' => {
+        template         => 1,
+        defines          => ['_KLT_MODEL_',
+                             '_REENTRANT', '_THREAD_SUPPORT_FUNCTIONS'],
+        ex_libs          => '-lklt',
+    },
+
     ######################################################################
     # Now for the entries themselves, let's combine things!
     'nonstop-nsx' => {
@@ -211,6 +220,16 @@
         multibin         => '64-put',
         disable          => ['atexit'],
     },
+    'nonstop-nsx_64_klt' => {
+        inherit_from     => [ 'nonstop-common',
+                              'nonstop-archenv-x86_64-oss',
+                              'nonstop-lp64-x86_64',
+                              'nonstop-efloat-x86_64',
+                              'nonstop-model-klt' ],
+        multilib         => '64-klt',
+        multibin         => '64-klt',
+        disable          => ['atexit'],
+    },
     'nonstop-nsx_g' => {
         inherit_from     => [ 'nonstop-common',
                               'nonstop-archenv-x86_64-guardian',
@@ -262,16 +281,3 @@
         multibin         => '64-put',
         disable          => ['atexit'],
     },
-    'nonstop-nse_g' => {
-        inherit_from     => [ 'nonstop-common',
-                              'nonstop-archenv-itanium-guardian',
-                              'nonstop-ilp32', 'nonstop-nfloat-itanium' ],
-        disable          => ['threads','atexit'],
-    },
-
-    'nonstop-nse_g_tandem' => {
-        inherit_from     => [ 'nonstop-common',
-                              'nonstop-archenv-itanium-guardian',
-                              'nonstop-ilp32', 'nonstop-tfloat-itanium' ],
-        disable          => ['threads','atexit'],
-    },

+ 12 - 7
libs/openssl/Configurations/unix-Makefile.tmpl

@@ -146,7 +146,7 @@ GENERATED_PODS={- # common0.tmpl provides @generated
                        fill_lines(" ", $COLUMNS - 15,
                                   map { my $x = $_;
                                         (
-                                          grep { 
+                                          grep {
                                                  $unified_info{attributes}->{depends}
                                                  ->{$x}->{$_}->{pod} // 0
                                                }
@@ -384,6 +384,7 @@ CFLAGS={- join(' ', @{$config{CFLAGS}}) -}
 CXXFLAGS={- join(' ', @{$config{CXXFLAGS}}) -}
 LDFLAGS= {- join(' ', @{$config{LDFLAGS}}) -}
 EX_LIBS= {- join(' ', @{$config{LDLIBS}}) -}
+OBJCOPY={- $config{OBJCOPY} -}
 
 MAKEDEPEND={- $config{makedepcmd} -}
 
@@ -544,6 +545,11 @@ LANG=C
 {- 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)
@@ -814,12 +820,12 @@ install_dev: install_runtime_libs
 		cp $$e "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
 		chmod 644 "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
 	done
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(CMAKECONFIGDIR)
+	@$(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; \
+		cp $$e "$(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \
+		chmod 644 "$(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \
 	done
 
 uninstall_dev: uninstall_runtime_libs
@@ -1178,7 +1184,7 @@ generate_buildinfo: generate_doc_buildinfo
 
 .PHONY: doc-nits md-nits
 doc-nits: build_generated_pods ## Evaluate OpenSSL documentation
-	$(PERL) $(SRCDIR)/util/find-doc-nits -c -n -l -e
+	$(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
@@ -1343,8 +1349,7 @@ errors:
            include/internal/asn1.h
            include/internal/sslconf.h );
    my @cryptoskipheaders = ( @sslheaders_tmpl,
-       qw( include/openssl/asn1_mac.h
-           include/openssl/conf_api.h
+       qw( include/openssl/conf_api.h
            include/openssl/ebcdic.h
            include/openssl/opensslconf.h
            include/openssl/symhacks.h ) );

+ 65 - 7
libs/openssl/Configure

@@ -77,6 +77,15 @@ 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
@@ -443,6 +452,9 @@ my @disablables = (
     "crypto-mdebug",
     "ct",
     "default-thread-pool",
+    "demos",
+    "h3demo",
+    "hqinterop",
     "deprecated",
     "des",
     "devcryptoeng",
@@ -466,11 +478,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",
@@ -478,6 +494,8 @@ my @disablables = (
     "md2",
     "md4",
     "mdc2",
+    "ml-dsa",
+    "ml-kem",
     "module",
     "msan",
     "multiblock",
@@ -486,6 +504,7 @@ my @disablables = (
     "ocsp",
     "padlockeng",
     "pic",
+    "pie",
     "pinshared",
     "poly1305",
     "posix-io",
@@ -505,6 +524,7 @@ my @disablables = (
     "shared",
     "siphash",
     "siv",
+    "slh-dsa",
     "sm2",
     "sm2-precomp",
     "sm3",
@@ -517,11 +537,13 @@ my @disablables = (
     "ssl-trace",
     "static-engine",
     "stdio",
+    "sslkeylog",
     "tests",
     "tfo",
     "thread-pool",
     "threads",
     "tls",
+    "tls-deprecated-ec",
     "trace",
     "ts",
     "ubsan",
@@ -564,18 +586,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",
@@ -583,6 +611,7 @@ our %disabled = ( # "what"         => "comment"
                   "sctp"                => "default",
                   "ssl3"                => "default",
                   "ssl3-method"         => "default",
+                  "sslkeylog"           => "default",
                   "tfo"                 => "default",
                   "trace"               => "default",
                   "ubsan"               => "default",
@@ -605,8 +634,8 @@ my @disable_cascades = (
                              "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",
@@ -622,7 +651,8 @@ my @disable_cascades = (
     "brotli"            => [ "brotli-dynamic" ],
     "zstd"              => [ "zstd-dynamic" ],
     "des"               => [ "mdc2" ],
-    "ec"                => [ "ec2m", "ecdsa", "ecdh", "sm2", "gost", "ecx" ],
+    "deprecated"        => [ "tls-deprecated-ec" ],
+    "ec"                => [ qw(ec2m ecdsa ecdh sm2 gost ecx tls-deprecated-ec) ],
     "dgram"             => [ "dtls", "quic", "sctp" ],
     "sock"              => [ "dgram", "tfo" ],
     "dtls"              => [ @dtls ],
@@ -676,7 +706,8 @@ my @disable_cascades = (
 
     "cmp"               => [ "crmf" ],
 
-    "fips"              => [ "fips-securitychecks", "acvp-tests" ],
+    "fips"              => [ "fips-securitychecks", "fips-post", "acvp-tests",
+                             "fips-jitter" ],
 
     "threads"           => [ "thread-pool" ],
     "thread-pool"       => [ "default-thread-pool" ],
@@ -745,6 +776,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
@@ -805,7 +837,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)
         {
@@ -935,10 +967,19 @@ while (@argvcopy)
                         {
                         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};
 
@@ -1005,6 +1046,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;
@@ -1297,11 +1346,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.
@@ -1313,6 +1366,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;
@@ -1883,7 +1941,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';
     }
 }
 

+ 67 - 20
libs/openssl/HACKING.md

@@ -1,33 +1,80 @@
 MODIFYING OPENSSL SOURCE
 ========================
 
-This document describes the way to add custom modifications to OpenSSL sources.
+This document describes the way to add custom modifications to OpenSSL
+sources.
 
- If you are adding new public functions to the custom library build, you need to
- either add a prototype in one of the existing OpenSSL header files;
- or provide a new header file and edit
- [Configurations/unix-Makefile.tmpl](Configurations/unix-Makefile.tmpl)
- to pick up that file.
+If you are adding new C source files
+------------------------------------
 
- After that, perform the following steps:
+Please update the `build.info` files in the directories where you placed the
+C source files, to include a line like this for each new C source file:
+
+-   In `crypto/` or any of its subdirectories (intended for `libcrypto`):
+
+        SOURCE[../libcrypto]={name-of-C-source-file}
+
+-   In `ssl/` or any of its subdirectories (intended for `libssl`):
+
+        SOURCE[../libssl]={name-of-C-source-file}
+
+Do note that the path given as the `SOURCE` attribute must be adapted
+appropriately for the location of the `build.info` file, as it's a relative
+path to where the library itself is built, for example:
+
+-   For `crypto/build.info`, the library path should be `../libcrypto`
+-   For `crypto/evp/build.info`, the library path should be
+    `../../libcrypto`
+-   For `ssl/build.info`, the library path should be `../libssl`
+-   For `ssl/quic/build.info`, the library path should be `../../libssl`
+
+To know more about `build.info` files, please read [doc/internal/man7/build.info.pod].
+For better viewing, consider converting it to HTML or PDF using `pod2html`
+or `pod2pdf`.
+
+Adding new public functions
+---------------------------
+
+If you are adding new public functions to the custom library build, you need to
+either add a prototype in one of the existing OpenSSL header files, or
+provide a new header file and edit.
+
+Only headers in the `include/openssl` subdirectory are considered for public
+functions.  If you're creating a new header file, it must be located in that
+directory.
+
+Functions declared in `include/openssl` header files are assumed to be part
+of the `libcrypto` library unless specified otherwise.  *If your new
+functions are meant for the `libssl` library*, you will need to edit
+[Configurations/unix-Makefile.tmpl] and add the header file name in the
+array `my @sslheaders_tmpl`.
+
+Updating OpenSSL's bookkeeping files
+------------------------------------
+
+OpenSSL has a few bookkeeping files to keep track of exposed functions, most
+importantly `util/libcrypto.num` and `util/libssl.num`.  Any time a new
+public function - as defined above - is added, these files must be updated.
+
+To make such an update, please do the following:
 
     ./Configure -Werror --strict-warnings [your-options]
     make update
-    make
-    make test
 
- `make update` ensures that your functions declarations are added to
- `util/libcrypto.num` or `util/libssl.num`.
- If you plan to submit the changes you made to OpenSSL
- (see [CONTRIBUTING.md](CONTRIBUTING.md)), it's worth running:
+If you plan to submit the changes you made to OpenSSL (see
+[CONTRIBUTING.md]), it's also worth running the following after running
+`make update`, to ensure that documentation has correct format.
 
     make doc-nits
 
- after running `make update` to ensure that documentation has correct format.
+Do note that `make update` also generates files related to OIDs (in the
+`crypto/objects/`  folder) and errors messages.
+
+If a git 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
+so they can be removed easily by reverting that commit.
 
- `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
- generated files need to be removed and regenerated using `make update`.
- To aid in this process, the generated files can be committed separately
- so they can be removed easily.
+[doc/internal/man7/build.info.pod]: ./doc/internal/man7/build.info.pod
+[Configurations/unix-Makefile.tmpl]: ./Configurations/unix-Makefile.tmpl
+[CONTRIBUTING.md]: ./CONTRIBUTING.md

+ 122 - 8
libs/openssl/INSTALL.md

@@ -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
@@ -65,6 +67,7 @@ issues and other details, please read one of these:
  * [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)
 
@@ -507,11 +510,6 @@ 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.
 
-### librandom
-
-Use librandom (not implemented yet).
-This source is ignored by the FIPS provider.
-
 ### none
 
 Disable automatic seeding.  This is the default on some operating systems where
@@ -523,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
 -------------------------
 
@@ -754,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<secp160r1>, B<secp160r2>, B<secp192r1>, B<secp224r1>, and the
+binary Elliptic curves that would also be disabled by C<no-ec2m>.
+
 ### enable-ec_nistp_64_gcc_128
 
 Enable support for optimised implementations of some commonly used NIST
@@ -807,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.
@@ -838,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.
@@ -870,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.
@@ -923,6 +990,11 @@ 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.
@@ -1027,6 +1099,17 @@ 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.
@@ -1113,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
@@ -1134,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.
 
@@ -1634,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.
@@ -1958,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]:
+    <https://csrc.nist.gov/projects/cryptographic-module-validation-program>
+
+[ESV]:
+    <https://csrc.nist.gov/Projects/cryptographic-module-validation-program/entropy-validations>
+
+[FIPS 203]:
+    <https://csrc.nist.gov/pubs/fips/203/final>
+
+[FIPS 204]:
+    <https://csrc.nist.gov/pubs/fips/204/final>
+
+[SP 800-90B]:
+    <https://csrc.nist.gov/pubs/sp/800/90/b/final>
+
+[jitterentropy-library]:
+    <https://github.com/smuellerDD/jitterentropy-library>
+
+[FIPS 205]:
+    <https://csrc.nist.gov/pubs/fips/205/final>

+ 171 - 10
libs/openssl/NEWS.md

@@ -7,6 +7,8 @@ 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)
@@ -18,12 +20,12 @@ OpenSSL Releases
  - [OpenSSL 1.0.0](#openssl-100)
  - [OpenSSL 0.9.x](#openssl-09x)
 
-OpenSSL 3.3
+OpenSSL 3.5
 -----------
 
-### Major changes between OpenSSL 3.3.4 and OpenSSL 3.3.5 [30 Sep 2025]
+### Major changes between OpenSSL 3.5.3 and OpenSSL 3.5.4 [30 Sep 2025]
 
-OpenSSL 3.3.5 is a security patch release. The most severe CVE fixed in this
+OpenSSL 3.5.4 is a security patch release. The most severe CVE fixed in this
 release is Moderate.
 
 This release incorporates the following bug fixes and mitigations:
@@ -37,17 +39,99 @@ This release incorporates the following bug fixes and mitigations:
   * Fix Out-of-bounds read in HTTP client no_proxy handling.
     ([CVE-2025-9232])
 
-### Major changes between OpenSSL 3.3.3 and OpenSSL 3.3.4 [1 Jul 2025]
+  * Reverted the synthesised `OPENSSL_VERSION_NUMBER` change for the release
+    builds, as it broke some exiting applications that relied on the previous
+    3.x semantics, as documented in `OpenSSL_version(3)`.
+
+### Major changes between OpenSSL 3.5.2 and OpenSSL 3.5.3 [16 Sep 2025]
 
-OpenSSL 3.3.4 is a bug fix release.
+OpenSSL 3.5.3 is a bug fix release.
 
 This release incorporates the following bug fixes and mitigations:
 
-  * Miscellaneous minor bug fixes.
+  * Added FIPS 140-3 PCT on DH key generation.
 
-### Major changes between OpenSSL 3.3.2 and OpenSSL 3.3.3 [11 Feb 2025]
+  * Fixed the synthesised `OPENSSL_VERSION_NUMBER`.
 
-OpenSSL 3.3.3 is a security patch release. The most severe CVE fixed in this
+  * Removed PCT on key import in the FIPS provider as it is not required by
+    the standard.
+
+### Major changes between OpenSSL 3.5.1 and OpenSSL 3.5.2 [5 Aug 2025]
+
+OpenSSL 3.5.2 is a bug fix release.
+
+This release incorporates the following bug fixes and mitigations:
+
+  * The FIPS provider now performs a PCT on key import for RSA, EC and ECX.
+
+### Major changes between OpenSSL 3.5.0 and OpenSSL 3.5.1 [1 Jul 2025]
+
+OpenSSL 3.5.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:
+
+  * Fix x509 application adds trusted use instead of rejected use.
+    ([CVE-2025-4575])
+
+### Major changes between OpenSSL 3.4 and OpenSSL 3.5.0 [8 Apr 2025]
+
+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
+
+  * <https://github.com/openssl/openssl/issues/27282>
+    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:
@@ -58,6 +142,78 @@ This release incorporates the following bug fixes and mitigations:
   * 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])
@@ -151,6 +307,8 @@ This release adds the following new features:
   * 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:
 
@@ -158,7 +316,7 @@ changes:
 
   * Optimized AES-CTR for ARM Neoverse V1 and V2
 
-  * Enable AES and SHA3 optimisations on Applie Silicon M3-based MacOS systems
+  * 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
@@ -1785,8 +1943,8 @@ OpenSSL 0.9.x
 [CVE-2025-9232]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9232
 [CVE-2025-9231]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9231
 [CVE-2025-9230]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-9230
+[CVE-2025-4575]: https://www.openssl.org/news/vulnerabilities.html#CVE-2025-4575
 [CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
-[CVE-2024-12797]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-12797
 [CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
 [CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
 [CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
@@ -1965,3 +2123,6 @@ OpenSSL 0.9.x
 [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

+ 33 - 0
libs/openssl/NOTES-ANSI.md

@@ -0,0 +1,33 @@
+Notes on ANSI C
+===============
+
+When building for pure ANSI C (C89/C90), you must configure with at least
+the following configuration settings:
+
+-   `no-asm`
+
+    There are cases of `asm()` calls in our C source, which isn't supported
+    in pure ANSI C.
+
+-   `no-secure-memory`
+
+    The secure memory calls aren't supported with ANSI C.
+
+-   `-D_XOPEN_SOURCE=1`
+
+    This macro enables the use of the following types, functions and global
+    variables:
+
+    -   `timezone`
+
+-   `-D_POSIX_C_SOURCE=200809L`
+
+    This macro enables the use of the following types, functions and global
+    variables:
+
+    -   `ssize_t`
+    -   `strdup()`
+
+It's arguable that with gcc and clang, all of these issues are removed when
+defining the macro `_DEFAULT_SOURCE`.  However, that effectively sets the C
+language level to C99, which isn't ANSI C.

+ 9 - 11
libs/openssl/NOTES-NONSTOP.md

@@ -30,9 +30,16 @@ for each on the TNS/X (L-Series) platform:
 
  * `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 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
@@ -214,15 +221,12 @@ 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}
@@ -232,9 +236,6 @@ assumes that your PWD is set according to your installation standards.
     ./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 \
@@ -251,6 +252,3 @@ assumes that your PWD is set according to your installation standards.
     ./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}

+ 20 - 0
libs/openssl/NOTES-POSIX.md

@@ -0,0 +1,20 @@
+Notes on POSIX
+==============
+
+There are few instances where OpenSSL requires a POSIX C library, at least
+version 1-2008, or compatible enough functionality.
+
+There are exceptions, though, for platforms that do not have a POSIX
+library, or where there are quirks that need working around.  A notable
+platform is Windows, where POSIX functionality may be available, but where
+the function names are prefixed with an underscore, and where some POSIX
+types are not present (such as `ssize_t`).
+
+Platforms that do have a POSIX library may still not have them accessible
+unless the following macros are defined:
+
+    _POSIX_C_SOURCE=200809L
+    _XOPEN_SOURCE=1
+
+This is, for example, the case when building with gcc or clang and using the
+flag `-ansi`.

+ 8 - 8
libs/openssl/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 <http://valgrind.org/info/platforms.html>
+   - See [Valgrind Supported Platforms](http://valgrind.org/info/platforms.html)
 2. Valgrind installed on the platform
-   See <http://valgrind.org/downloads/current.html>
+   - 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"

+ 32 - 20
libs/openssl/NOTES-WINDOWS.md

@@ -104,31 +104,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-<version>-<ctx>\OPENSSLDIR`
+    `\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL-<version>-<ctx>\ENGINESDIR`
+    `\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\OpenSSL-<version>-<ctx>\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=<string>`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-<version>-<ctx>`
 
-Should those environment variables not exist (on a pure Win32
-installation for examples), these fallbacks are used:
+Where `<version>` is the major.minor version of the library being
+built, and `<ctx>` is the value specified by `-DOSSL_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 <https://github.com/openssl/installer> 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`
 -------------------------------------------------------------------
@@ -143,8 +153,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.
 <https://www.embarcadero.com/products/cbuilder/starter>
 
  1. Install Perl.
@@ -153,6 +163,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`
 

+ 30 - 0
libs/openssl/README-FIPS.md

@@ -169,3 +169,33 @@ Documentation about using the FIPS module is available on the [fips_module(7)]
 manual page.
 
  [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.

+ 29 - 1
libs/openssl/README-QUIC.md

@@ -2,7 +2,7 @@ Using OpenSSL with QUIC
 =======================
 
 From OpenSSL 3.2, OpenSSL features support for making QUIC connections as a
-client.
+client. Starting with OpenSSL 3.5, server-side QUIC support has also been added.
 
 Users interested in using the new QUIC functionality are encouraged to look at
 some of the following resources:
@@ -70,6 +70,34 @@ using simple TCP/TLS-like usage. Note that OpenSSL has no direct support for
 HTTP/3 so connecting to an HTTP/3 server should be possible but sending an
 HTTP/3 request or receiving any response data is not.
 
+### How can I create a QUIC server with OpenSSL?
+
+Starting with OpenSSL 3.5, you can create a QUIC server. OpenSSL provides a server
+implementation example that you can use as a reference:
+
+The example QUIC server implementation can be found in the source tree under
+[`demos/quic/server`](./demos/quic/server/). This demonstrates how to implement a
+basic QUIC server using the OpenSSL API.
+
+To run the example QUIC server:
+
+```shell
+$ ./demos/quic/server/server <port-number> <certificate-file> <key-file>
+```
+
+For example:
+
+```shell
+$ ./demos/quic/server/server 4433 server.pem server.key
+```
+
+Replace `server.pem` and `server.key` with your certificate and private key files.
+Note that the standard `openssl s_server` command does NOT support QUIC - you must
+use this dedicated server example instead.
+
+For more information about implementing QUIC servers with OpenSSL, refer to the
+[OpenSSL Guide] and the [openssl-quic(7) manual page].
+
 [openssl-quic(7) manual page]: https://www.openssl.org/docs/manmaster/man7/openssl-quic.html
 [OpenSSL Guide]: https://www.openssl.org/docs/manmaster/man7/ossl-guide-introduction.html
 [DDD]: https://github.com/openssl/openssl/tree/master/doc/designs/ddd

+ 6 - 4
libs/openssl/README.md

@@ -4,11 +4,13 @@ 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 TLS (formerly SSL), DTLS and QUIC (currently client side only)
-protocols.
+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
@@ -39,7 +41,7 @@ The OpenSSL toolkit includes:
 - **libssl**
   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 (currently client side only) version 1 protocol ([RFC 9000]).
+  the QUIC version 1 protocol ([RFC 9000]).
 
 - **libcrypto**
   a full-strength general purpose cryptographic library. It constitutes the

+ 2 - 2
libs/openssl/VERSION.dat

@@ -1,6 +1,6 @@
 MAJOR=3
-MINOR=3
-PATCH=5
+MINOR=5
+PATCH=4
 PRE_RELEASE_TAG=
 BUILD_METADATA=
 RELEASE_DATE="30 Sep 2025"

+ 3 - 0
libs/openssl/apps/asn1parse.c

@@ -217,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;
             }
         }

+ 1 - 1
libs/openssl/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'} -}]

+ 16 - 20
libs/openssl/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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -150,7 +152,7 @@ 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_QUIET,
@@ -199,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, '<',
@@ -359,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:
@@ -874,22 +881,8 @@ end_of_options:
         if (startdate == NULL)
             startdate =
                 app_conf_try_string(conf, section, ENV_DEFAULT_STARTDATE);
-        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 = app_conf_try_string(conf, section, ENV_DEFAULT_ENDDATE);
-        if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) {
-            BIO_printf(bio_err,
-                       "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
-            goto end;
-        }
-
         if (days == 0) {
             if (!app_conf_try_number(conf, section, ENV_DEFAULT_DAYS, &days))
                 days = 0;
@@ -898,6 +891,9 @@ end_of_options:
             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)) {
@@ -1671,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) {

+ 461 - 30
libs/openssl/apps/cmp.c

@@ -10,6 +10,7 @@
  */
 
 /* This app is disabled when OPENSSL_NO_CMP is defined. */
+#include "internal/e_os.h"
 
 #include <string.h>
 #include <ctype.h>
@@ -94,6 +95,11 @@ 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;
@@ -118,6 +124,8 @@ 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 int opt_days = 0;
 static char *opt_reqexts = NULL;
@@ -143,6 +151,12 @@ 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;
@@ -187,6 +201,9 @@ 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;
@@ -215,8 +232,10 @@ typedef enum OPTION_choice {
     OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
 
     OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO,
+    OPT_TEMPLATE, OPT_KEYSPEC,
 
-    OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT,
+    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,
@@ -237,12 +256,13 @@ typedef enum OPTION_choice {
     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,
@@ -267,7 +287,8 @@ typedef enum OPTION_choice {
     OPT_SRV_REF, OPT_SRV_SECRET,
     OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
     OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
-    OPT_REF_CERT, 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,
@@ -302,11 +323,19 @@ const OPTIONS cmp_options[] = {
      "Comma-separated list of OID and value to place in generalInfo PKIHeader"},
     {OPT_MORE_STR, 0, 0,
      "of form <OID>:int:<n> or <OID>:str:<s>, 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,
@@ -428,6 +457,12 @@ const OPTIONS cmp_options[] = {
       "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',
@@ -459,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',
@@ -544,6 +581,14 @@ const OPTIONS cmp_options[] = {
      "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',
@@ -599,9 +644,10 @@ 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_profile}, {&opt_geninfo},
+    {&opt_template}, {&opt_keyspec},
 
-    {&opt_newkey}, {&opt_newkeypass}, {&opt_subject},
-    {(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},
@@ -623,13 +669,14 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {(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},
@@ -652,7 +699,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_srv_ref}, {&opt_srv_secret},
     {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
     {&opt_srv_trusted}, {&opt_srv_untrusted},
-    {&opt_ref_cert}, {&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},
@@ -1010,6 +1058,19 @@ static int setup_certs(char *files, const char *desc, void *ctx,
     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
@@ -1057,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;
 }
@@ -1147,11 +1213,28 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (opt_rsp_cert == NULL) {
         CMP_warn("no -rsp_cert given for mock server");
     } else {
-        if (!setup_cert(srv_ctx, opt_rsp_cert, opt_keypass,
+        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;
     }
+    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;
+        }
+        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))
@@ -1619,11 +1702,27 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     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_reqin == NULL && 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, -cert, or -reqin option given, which could provide 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) {
@@ -1671,6 +1770,12 @@ 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);
@@ -1775,13 +1880,14 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             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_key == NULL && opt_csr == NULL && opt_oldcert == NULL
+               && !opt_centralkeygen) {
         if (!set_fallback_pubkey(ctx))
             return 0;
     }
@@ -1915,20 +2021,20 @@ static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name)
 
     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;
-   }
-   /* 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;
+    if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
+        goto err;
+    if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) {
+        ASN1_STRING_free(utf8string);
+        goto err;
+    }
+    /* 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;
 
  err:
     sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free);
@@ -1973,7 +2079,7 @@ static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
             if (*ptr != '\0') {
                 if (*ptr != ',') {
                     CMP_err1("Missing ',' or end of -geninfo arg after int at %.40s",
-                        ptr);
+                             ptr);
                     goto err;
                 }
                 ptr++;
@@ -2132,6 +2238,17 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         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;
@@ -2248,6 +2365,18 @@ 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 file != NULL writes out a stack of certs to the given file.
  * If certs is NULL, the file is emptied.
@@ -2295,6 +2424,35 @@ static int save_free_certs(STACK_OF(X509) *certs,
     return n;
 }
 
+static int save_crl(X509_CRL *crl,
+                    const char *file, const char *desc)
+{
+    BIO *bio = NULL;
+    int res = 0;
+
+    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;
+    }
+
+    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)
@@ -2328,6 +2486,66 @@ static int save_cert_or_delete(X509 *cert, const char *file, const char *desc)
     }
 }
 
+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);
+        BIO_free(bio);
+        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);
+        BIO_free(bio);
+        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 = "<unknown OID>";
+    return name;
+}
+
 static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
 {
     int i, ret = 1;
@@ -2727,6 +2945,15 @@ static int get_opts(int argc, char **argv)
         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))
@@ -2744,13 +2971,24 @@ static int get_opts(int argc, char **argv)
         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;
@@ -2822,6 +3060,9 @@ static int get_opts(int argc, char **argv)
         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;
@@ -2905,6 +3146,15 @@ static int get_opts(int argc, char **argv)
         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;
@@ -3047,6 +3297,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, &paramtype, &param, 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 */
@@ -3141,6 +3456,94 @@ static int do_genm(OSSL_CMP_CTX *ctx)
     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;
@@ -3358,10 +3761,10 @@ int cmp_main(int argc, char **argv)
     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 !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
         if (opt_server != NULL)
             CMP_warn1("-server %s", msg);
-#endif
+# endif
         if (opt_use_mock_srv)
             CMP_warn1("-use_mock_srv %s", msg);
         if (opt_reqout != NULL)
@@ -3456,6 +3859,34 @@ int cmp_main(int argc, char **argv)
             if (save_free_certs(OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
                                 opt_cacertsout, "CA") < 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;

+ 13 - 12
libs/openssl/apps/cms.c

@@ -69,7 +69,8 @@ typedef enum OPTION_choice {
     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,
@@ -175,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"},
@@ -183,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, '-',
@@ -426,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;
@@ -721,7 +730,6 @@ int cms_main(int argc, char **argv)
     }
 
     /* Remaining args are files to process. */
-    argc = opt_num_rest();
     argv = opt_rest();
 
     if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) {
@@ -828,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;

+ 8 - 3
libs/openssl/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
@@ -138,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 */
     }
 
@@ -216,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++;
         }

+ 2 - 2
libs/openssl/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 an 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.

+ 154 - 68
libs/openssl/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,6 +114,8 @@ 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]);
@@ -278,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
@@ -290,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;
         }
     }
 
@@ -342,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;
         }
@@ -379,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;
@@ -407,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;
         }
@@ -436,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;
 
@@ -452,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);
         }
@@ -468,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);
@@ -544,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,
@@ -551,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)) {
@@ -567,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) {
@@ -617,43 +683,63 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout, int xoflen
         if ((int)len < 0)
             goto end;
     }
+    print_out(out, buf, len, sep, binout, sig_name, md_name, file);
+    ret = EXIT_SUCCESS;
+ end:
+    if (allocated_buf != NULL)
+        OPENSSL_clear_free(allocated_buf, len);
 
-    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]);
+    return ret;
+}
 
-        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);
+/*
+ * 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;
         }
-        for (i = 0; i < (int)len; i++) {
-            if (sep && (i != 0))
-                BIO_printf(out, ":");
-            BIO_printf(out, "%02x", buf[i]);
+        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;
         }
-        BIO_printf(out, "\n");
+        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;
     }
 
-    ret = EXIT_SUCCESS;
  end:
-    if (allocated_buf != NULL)
-        OPENSSL_clear_free(allocated_buf, len);
+    OPENSSL_free(sig);
+    OPENSSL_clear_free(buf, buflen);
 
     return ret;
 }

+ 4 - 4
libs/openssl/apps/dhparam.c

@@ -179,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;
@@ -322,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);
 

+ 4 - 4
libs/openssl/apps/dsaparam.c

@@ -150,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,
@@ -200,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);
     }

+ 14 - 14
libs/openssl/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)
@@ -192,18 +188,18 @@ int ecparam_main(int argc, char **argv)
     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;
@@ -276,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;
     }

+ 76 - 15
libs/openssl/apps/enc.c

@@ -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_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM
+    OPT_SALTLEN, OPT_R_ENUM, OPT_PROV_ENUM,
+    OPT_SKEYOPT, OPT_SKEYMGMT
 } OPTION_CHOICE;
 
 const OPTIONS enc_options[] = {
@@ -105,6 +106,8 @@ const OPTIONS enc_options[] = {
 #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,
@@ -134,6 +137,7 @@ 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];
+    int rawkey_set = 0;
     unsigned char *buff = NULL, salt[EVP_MAX_IV_LENGTH];
     int saltlen = 0;
     int pbkdf2 = 0;
@@ -150,6 +154,10 @@ int enc_main(int argc, char **argv)
     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)
@@ -312,6 +320,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;
@@ -393,7 +412,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 (;;) {
@@ -573,6 +592,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"
@@ -583,6 +603,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
@@ -620,6 +641,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)
@@ -635,24 +666,51 @@ int enc_main(int argc, char **argv)
         if (wrap == 1)
             EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
 
-        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 (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,
-                               (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;
-        }
-
         if (debug) {
             BIO_set_callback_ex(benc, BIO_debug_callback_ex);
             BIO_set_callback_arg(benc, (char *)bio_err);
@@ -718,6 +776,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);

+ 6 - 3
libs/openssl/apps/engine.c

@@ -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++;
     }
@@ -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;
         }
     }
 

+ 332 - 27
libs/openssl/apps/fipsinstall.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
@@ -38,8 +38,30 @@ typedef enum OPTION_choice {
     OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG,
     OPT_NO_CONDITIONAL_ERRORS,
     OPT_NO_SECURITY_CHECKS,
-    OPT_TLS_PRF_EMS_CHECK,
+    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;
 
@@ -48,7 +70,7 @@ const OPTIONS fipsinstall_options[] = {
     {"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',
@@ -64,8 +86,55 @@ const OPTIONS fipsinstall_options[] = {
      "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"},
 
@@ -86,8 +155,33 @@ 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 */
@@ -95,8 +189,33 @@ 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 */
@@ -104,8 +223,33 @@ 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)
@@ -140,7 +284,8 @@ 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;
@@ -170,7 +315,16 @@ static int load_fips_prov_and_run_self_test(const char *prov_name)
             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);
@@ -223,22 +377,83 @@ static int write_config_fips_section(BIO *out, const char *section,
                       VERSION_VAL) <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
                       opts->conditional_errors ? "1" : "0") <= 0
-        || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+        || 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_FIPS_PARAM_TLS1_PRF_EMS_CHECK,
+        || 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:
@@ -255,12 +470,12 @@ static CONF *generate_config_and_load(const char *prov_name,
     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,
-                                       opts, 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);
@@ -356,6 +571,7 @@ end:
 int fipsinstall_main(int argc, char **argv)
 {
     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";
@@ -382,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:
@@ -409,12 +625,89 @@ opthelp:
                 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;
             /* FALLTHROUGH */
@@ -454,11 +747,13 @@ opthelp:
             verify = 1;
             break;
         case OPT_SELF_TEST_ONLOAD:
+            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;
         }
@@ -478,7 +773,7 @@ opthelp:
             ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1;
             if (!quiet) {
                 BIO_printf(bio_err, "FIPS provider is %s\n",
-                           ret == 0 ? "available" : " not available");
+                           ret == 0 ? "available" : "not available");
             }
         }
         goto end;
@@ -556,34 +851,43 @@ opthelp:
     if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
         goto end;
 
-    if (fips_opts.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, &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);
@@ -591,6 +895,7 @@ 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, &fips_opts,
                                        install_mac, install_mac_len))

+ 34 - 19
libs/openssl/apps/genpkey.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
@@ -106,7 +106,7 @@ cleanup:
 int genpkey_main(int argc, char **argv)
 {
     CONF *conf = NULL;
-    BIO *in = NULL, *out = NULL, *outpubkey = NULL;
+    BIO *mem_out = NULL, *mem_outpubkey = NULL;
     ENGINE *e = NULL;
     EVP_PKEY *pkey = NULL;
     EVP_PKEY_CTX *ctx = NULL;
@@ -237,14 +237,16 @@ 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);
 
     if (outpubkeyfile != NULL) {
-        outpubkey = bio_open_owner(outpubkeyfile, outformat, private);
-        if (outpubkey == NULL)
+        mem_outpubkey = BIO_new(BIO_s_mem());
+        if (mem_outpubkey == NULL)
             goto end;
+        BIO_set_mem_eof_return(mem_outpubkey, 0);
     }
 
     if (verbose)
@@ -257,17 +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);
-        if (rv > 0 && outpubkey != NULL)
-           rv = PEM_write_bio_PUBKEY(outpubkey, pkey);
+        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);
-        if (rv > 0 && outpubkey != NULL)
-           rv = i2d_PUBKEY_bio(outpubkey, 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;
@@ -282,9 +284,9 @@ int genpkey_main(int argc, char **argv)
 
     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");
@@ -294,14 +296,27 @@ 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",
+                           outfile, strerror(errno));
+        }
+    }
     EVP_PKEY_free(pkey);
     EVP_PKEY_CTX_free(ctx);
     EVP_CIPHER_free(cipher);
-    BIO_free_all(out);
-    BIO_free_all(outpubkey);
-    BIO_free(in);
+    BIO_free_all(mem_out);
+    BIO_free_all(mem_outpubkey);
     release_engine(e);
     OPENSSL_free(pass);
     NCONF_free(conf);

+ 6 - 3
libs/openssl/apps/include/apps.h

@@ -10,10 +10,8 @@
 #ifndef OSSL_APPS_H
 # define OSSL_APPS_H
 
-# include "internal/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 <assert.h>
 
 # include <stdarg.h>
@@ -65,6 +63,7 @@ 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);
@@ -82,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);

+ 3 - 1
libs/openssl/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
@@ -22,6 +22,8 @@ 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,

+ 4 - 1
libs/openssl/apps/include/opt.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.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -295,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 \
@@ -304,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
 
 /*

+ 2 - 2
libs/openssl/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

+ 10 - 3
libs/openssl/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,6 +86,10 @@ opthelp:
             type = OPENSSL_INFO_CPU_SETTINGS;
             dirty++;
             break;
+        case OPT_WINDOWSCONTEXT:
+            type = OPENSSL_INFO_WINDOWS_CONTEXT;
+            dirty++;
+            break;
         }
     }
     if (!opt_check_rest_arg(NULL))
@@ -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;

+ 76 - 1
libs/openssl/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 <ctype.h>
 #include <string.h>
 #include <openssl/err.h>
 #include <openssl/provider.h>
@@ -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());
     }

+ 1 - 0
libs/openssl/apps/lib/app_rand.c

@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include "internal/e_os.h" /* LIST_SEPARATOR_CHAR */
 #include "apps.h"
 #include <openssl/bio.h>
 #include <openssl/err.h>

+ 145 - 45
libs/openssl/apps/lib/apps.c

@@ -48,6 +48,9 @@
 #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))
@@ -850,11 +853,15 @@ static const char *format2string(int format)
         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. */
+/* 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) \
@@ -862,6 +869,7 @@ static const char *format2string(int format)
         *(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" :                              \
@@ -869,7 +877,9 @@ static const char *format2string(int format)
      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
@@ -897,24 +907,38 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     OSSL_PARAM itp[2];
     const OSSL_PARAM *params = NULL;
 
+    /* 'failed' describes type of credential to load for potential error msg */
     if (failed == NULL) {
         if (!quiet)
-            BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
+            BIO_printf(bio_err, "Internal error: nothing was requested to load from %s\n",
                        uri != NULL ? uri : "<stdin>");
         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) {
             if (!quiet)
                 BIO_printf(bio_err, "Out of memory loading");
             goto end;
         }
+        /*
+         * 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);
@@ -924,6 +948,11 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
                 BIO_printf(bio_err, "Out of memory loading");
             goto end;
         }
+        /*
+         * 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);
     }
 
@@ -963,6 +992,7 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
             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)) {
         if (!quiet)
             BIO_printf(bio_err, "Internal error trying to load");
@@ -970,6 +1000,8 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
     }
 
     failed = NULL;
+    /* 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)) {
@@ -1039,7 +1071,7 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
             ncrls += ok;
             break;
         default:
-            /* skip any other type */
+            /* skip any other type; ok stays == 1 */
             break;
         }
         OSSL_STORE_INFO_free(info);
@@ -1053,18 +1085,22 @@ int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
 
  end:
     OSSL_STORE_close(ctx);
-    if (ncerts > 0)
-        pcerts = NULL;
-    if (ncrls > 0)
-        pcrls = NULL;
+
+    /* 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 (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 {
@@ -1525,9 +1561,9 @@ int save_serial(const char *serialfile, const char *suffix,
         OPENSSL_strlcpy(buf[0], serialfile, BSIZE);
     } 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");
@@ -1569,11 +1605,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
@@ -1728,13 +1764,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) {
@@ -1778,17 +1814,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
@@ -2142,7 +2178,7 @@ int check_cert_attributes(BIO *bio, X509 *x, const char *checkhost,
         if (print)
             BIO_printf(bio, "Hostname %s does%s match certificate\n",
                        checkhost, valid_host == 1 ? "" : " NOT");
-        ret = ret && valid_host;
+        ret = ret && valid_host > 0;
     }
 
     if (checkemail != NULL) {
@@ -2150,7 +2186,7 @@ int check_cert_attributes(BIO *bio, X509 *x, const char *checkhost,
         if (print)
             BIO_printf(bio, "Email %s does%s match certificate\n",
                        checkemail, valid_mail ? "" : " NOT");
-        ret = ret && valid_mail;
+        ret = ret && valid_mail > 0;
     }
 
     if (checkip != NULL) {
@@ -2158,7 +2194,7 @@ int check_cert_attributes(BIO *bio, X509 *x, const char *checkhost,
         if (print)
             BIO_printf(bio, "IP %s does%s match certificate\n",
                        checkip, valid_ip ? "" : " NOT");
-        ret = ret && valid_ip;
+        ret = ret && valid_ip > 0;
     }
 
     return ret;
@@ -2441,18 +2477,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)
@@ -3151,6 +3193,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  */
@@ -3218,23 +3286,54 @@ void corrupt_signature(const ASN1_STRING *signature)
     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;
 }
 
@@ -3391,6 +3490,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.

+ 152 - 5
libs/openssl/apps/lib/cmp_mock_srv.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-2024 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,10 +16,11 @@
 #include <openssl/cmperr.h>
 
 /* 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; /* used in caPubs of ip and in caCerts of genp */
     X509 *newWithNew;          /* to return in newWithNew of rootKeyUpdate */
@@ -87,6 +88,37 @@ static mock_srv_ctx *mock_srv_ctx_new(void)
 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);
+
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    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;
+    }
+    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,
                                     STACK_OF(X509) *chain)
 {
@@ -257,8 +289,9 @@ 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;
+    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) {
@@ -342,6 +375,23 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
             && (*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;
@@ -391,10 +441,50 @@ 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;
+    OSSL_CMP_ITAV *rsp = NULL;
 
     switch (req_nid) {
     case NID_id_it_caCerts:
@@ -418,6 +508,63 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
                                                         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);
     }

+ 1 - 0
libs/openssl/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

+ 3 - 1
libs/openssl/apps/lib/http_server.c

@@ -18,8 +18,10 @@
 #endif
 
 #include <ctype.h>
+#include "internal/e_os.h"
 #include "http_server.h"
-#include "internal/sockets.h"
+#include "internal/sockets.h" /* for openssl_fdset() */
+
 #include <openssl/err.h>
 #include <openssl/trace.h>
 #include <openssl/rand.h>

+ 3 - 2
libs/openssl/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
@@ -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)

+ 25 - 13
libs/openssl/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
@@ -328,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))
@@ -336,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;
 }
@@ -416,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;
@@ -1294,6 +1309,7 @@ void print_verify_detail(SSL *s, BIO *bio)
 
 void print_ssl_summary(SSL *s)
 {
+    const char *sigalg;
     const SSL_CIPHER *c;
     X509 *peer = SSL_get0_peer_certificate(s);
     EVP_PKEY *peer_rpk = SSL_get0_peer_rpk(s);
@@ -1311,13 +1327,13 @@ void print_ssl_summary(SSL *s)
         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_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 {
         BIO_puts(bio_err, "No peer certificate or raw public key\n");
@@ -1326,12 +1342,8 @@ void print_ssl_summary(SSL *s)
     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,

+ 2 - 1
libs/openssl/apps/lib/s_socket.c

@@ -37,9 +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"
+# include "internal/sockets.h" /* for openssl_fdset() */
 
 # include <openssl/bio.h>
 # include <openssl/err.h>

+ 3 - 3
libs/openssl/apps/lib/tlssrp_depr.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.
  * Copyright 2005 Nokia. All rights reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -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 =

+ 263 - 33
libs/openssl/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 <string.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
@@ -21,6 +23,9 @@
 #include <openssl/store.h>
 #include <openssl/core_names.h>
 #include <openssl/rand.h>
+#include <openssl/safestack.h>
+#include <openssl/ssl.h>
+#include <openssl/tls1.h>
 #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,8 +104,9 @@ 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(const char *prefix)
@@ -182,8 +189,9 @@ 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(const char *prefix)
@@ -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
@@ -1459,11 +1617,22 @@ typedef enum HELPLIST_CHOICE {
     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;
@@ -1495,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, '-',
@@ -1517,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
@@ -1539,6 +1725,14 @@ int list_main(int argc, char **argv)
     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;
@@ -1553,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;
@@ -1624,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;
@@ -1686,7 +1908,7 @@ opthelp:
             BIO_printf(bio_out, "\n"); \
         } \
         cmd; \
-    } while(0)
+    } while (0)
 
     if (todo.commands)
         MAYBE_ADD_NL(list_type(FT_general, one));
@@ -1742,14 +1964,22 @@ opthelp:
         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)

+ 4 - 4
libs/openssl/apps/ocsp.c

@@ -553,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;
 
@@ -710,6 +706,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);
 

+ 2 - 2
libs/openssl/apps/openssl-vms.cnf

@@ -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

+ 2 - 0
libs/openssl/apps/openssl.c

@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include "internal/e_os.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include "internal/common.h"

+ 2 - 2
libs/openssl/apps/openssl.cnf

@@ -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

+ 7 - 9
libs/openssl/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
@@ -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]) {

+ 80 - 22
libs/openssl/apps/pkcs12.c

@@ -70,7 +70,7 @@ typedef enum OPTION_choice {
     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_JDKTRUST,
+    OPT_R_ENUM, OPT_PROV_ENUM, OPT_JDKTRUST, OPT_PBMAC1_PBKDF2, OPT_PBMAC1_PBKDF2_MD,
 #ifndef OPENSSL_NO_DES
     OPT_LEGACY_ALG
 #endif
@@ -147,6 +147,8 @@ 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)"},
@@ -170,14 +172,14 @@ int pkcs12_main(int argc, char **argv)
     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;
@@ -283,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;
@@ -701,10 +709,20 @@ int pkcs12_main(int argc, char **argv)
         }
 
         if (maciter != -1) {
-            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 if MAC not required and PKCS12KDF support not available.\n");
-                goto export_end;
+            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);
@@ -775,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 (OBJ_obj2nid(macobj) == NID_pbmac1) {
+            PBKDF2PARAM *pbkdf2_param = PBMAC1_get1_pbkdf2_param(macalgid);
+
+            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);
+        }
     }
+
     if (macver) {
-        EVP_KDF *pkcs12kdf;
+        const X509_ALGOR *macalgid;
+        const ASN1_OBJECT *macobj;
 
-        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;
+        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);
         }
-        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 */
@@ -1258,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);
             }

+ 5 - 3
libs/openssl/apps/pkcs8.c

@@ -227,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");
@@ -240,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) {
@@ -361,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,

+ 4 - 4
libs/openssl/apps/pkey.c

@@ -208,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
@@ -219,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;

+ 3 - 3
libs/openssl/apps/pkeyparam.c

@@ -97,9 +97,6 @@ int pkeyparam_main(int argc, char **argv)
     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) {
@@ -107,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)

+ 203 - 79
libs/openssl/apps/pkeyutl.c

@@ -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,12 +79,13 @@ 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"},
     {"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"},
@@ -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;
@@ -260,25 +294,8 @@ int pkeyutl_main(int argc, char **argv)
     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) {
@@ -292,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;
     }
 
@@ -302,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;
@@ -357,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 +445,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 +456,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 <file>' 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 +511,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 +522,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 +557,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 +590,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 +654,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 +682,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 +691,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 +743,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 +763,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 +781,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 +796,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 +822,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,8 +847,7 @@ 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");

+ 6 - 2
libs/openssl/apps/prime.c

@@ -145,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");
         }
     }
 

+ 6 - 2
libs/openssl/apps/rehash.c

@@ -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;
 }
@@ -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);

+ 39 - 15
libs/openssl/apps/req.c

@@ -30,6 +30,7 @@
 #ifndef OPENSSL_NO_DSA
 # include <openssl/dsa.h>
 #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
 
@@ -80,6 +81,7 @@ 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,
@@ -87,7 +89,7 @@ typedef enum OPTION_choice {
     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_X509V1, OPT_CA, OPT_CAKEY,
-    OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL,
+    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,
@@ -97,6 +99,7 @@ typedef 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',
@@ -127,7 +130,11 @@ 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"},
@@ -245,7 +252,7 @@ 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;
+    const EVP_CIPHER *cipher = NULL;
     int ext_copy = EXT_COPY_UNSET;
     BIO *addext_bio = NULL;
     char *extsect = NULL;
@@ -259,6 +266,7 @@ int req_main(int argc, char **argv)
     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, progress = 1;
     int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF;
@@ -267,9 +275,7 @@ int req_main(int argc, char **argv)
     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);
@@ -423,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;
@@ -470,7 +482,7 @@ int req_main(int argc, char **argv)
             }
             i = duplicated(addexts, p);
             if (i == 1)
-                goto opthelp;
+                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)
@@ -479,6 +491,13 @@ int req_main(int argc, char **argv)
         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;
@@ -494,14 +513,18 @@ 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)
+        else if (!newreq && isatty(fileno_stdin()))
             BIO_printf(bio_err,
                        "Warning: Will read cert request from stdin since no -in option is given\n");
     }
@@ -802,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;

+ 54 - 18
libs/openssl/apps/s_client.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 2005 Nokia. All rights reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -16,6 +16,7 @@
 #include <errno.h>
 #include <openssl/e_os2.h>
 #include "internal/nelem.h"
+#include "internal/sockets.h" /* for openssl_fdset() */
 
 #ifndef OPENSSL_NO_SOCK
 
@@ -55,7 +56,7 @@ 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
@@ -207,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;
@@ -3175,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:
@@ -3359,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
@@ -3384,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);
             }
         }
 
@@ -3486,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;
 

+ 47 - 7
libs/openssl/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 <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,6 +24,7 @@
 #include <openssl/async.h>
 #include <openssl/ssl.h>
 #include <openssl/decoder.h>
+#include "internal/sockets.h" /* for openssl_fdset() */
 
 #ifndef OPENSSL_NO_SOCK
 
@@ -206,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;
     }
@@ -1754,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;
     }
 
@@ -3153,7 +3158,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     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
@@ -3175,7 +3180,8 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     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) {
@@ -3235,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) {
@@ -3251,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)
@@ -3592,6 +3631,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
     OPENSSL_free(buf);
     BIO_free(ssl_bio);
     BIO_free_all(io);
+    BIO_free_all(edio);
     return ret;
 }
 

+ 135 - 0
libs/openssl/apps/skeyutl.c

@@ -0,0 +1,135 @@
+/*
+ * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "apps.h"
+#include "progs.h"
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+typedef enum OPTION_choice {
+    OPT_COMMON,
+    OPT_PROV_ENUM,
+    OPT_CIPHER,
+    OPT_SKEYOPT, OPT_SKEYMGMT, OPT_GENKEY
+} OPTION_CHOICE;
+
+const OPTIONS skeyutl_options[] = {
+    OPT_SECTION("General"),
+    {"help", OPT_HELP, '-', "Display this summary"},
+    {"skeyopt", OPT_SKEYOPT, 's', "Key options as opt:value for opaque keys handling"},
+    {"skeymgmt", OPT_SKEYMGMT, 's', "Symmetric key management name for opaque keys handling"},
+    {"genkey", OPT_GENKEY, '-', "Generate an opaque symmetric key"},
+    {"cipher", OPT_CIPHER, 's', "The cipher to generate key for"},
+    OPT_PROV_OPTIONS,
+    {NULL}
+};
+
+int skeyutl_main(int argc, char **argv)
+{
+    EVP_CIPHER *cipher = NULL;
+    int ret = 1;
+    OPTION_CHOICE o;
+    int genkey = 0;
+    char *prog, *ciphername = NULL;
+    STACK_OF(OPENSSL_STRING) *skeyopts = NULL;
+    const char *skeymgmt = NULL;
+    EVP_SKEY *skey = NULL;
+    EVP_SKEYMGMT *mgmt = NULL;
+
+    prog = opt_init(argc, argv, skeyutl_options);
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_EOF:
+        case OPT_ERR:
+ opthelp:
+            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
+            goto end;
+        case OPT_HELP:
+            opt_help(skeyutl_options);
+            ret = 0;
+            goto end;
+        case OPT_GENKEY:
+            genkey = 1;
+            break;
+        case OPT_CIPHER:
+            ciphername = opt_arg();
+            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_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
+        }
+    }
+
+    /* Get the cipher name, either from progname (if set) or flag. */
+    if (!opt_cipher_any(ciphername, &cipher))
+        goto opthelp;
+
+    if (cipher == NULL && skeymgmt == NULL) {
+        BIO_printf(bio_err, "Either -skeymgmt -or -cipher option should be specified\n");
+        goto end;
+    }
+
+    if (genkey) {
+        OSSL_PARAM *params = NULL;
+
+        mgmt = EVP_SKEYMGMT_fetch(app_get0_libctx(),
+                                  skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher),
+                                  app_get0_propq());
+        if (mgmt == NULL)
+            goto end;
+        params = app_params_new_from_opts(skeyopts,
+                                          EVP_SKEYMGMT_get0_gen_settable_params(mgmt));
+
+        skey = EVP_SKEY_generate(app_get0_libctx(),
+                                 skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher),
+                                 app_get0_propq(), params);
+        OSSL_PARAM_free(params);
+        if (skey == NULL) {
+            BIO_printf(bio_err, "Error creating opaque key for skeymgmt %s\n",
+                       skeymgmt ? skeymgmt : EVP_CIPHER_name(cipher));
+            ERR_print_errors(bio_err);
+        } else {
+            const char *key_name = EVP_SKEY_get0_key_id(skey);
+
+            BIO_printf(bio_out, "An opaque key identified by %s is created\n",
+                       key_name ? key_name : "<unknown>");
+            BIO_printf(bio_out, "Provider: %s\n", EVP_SKEY_get0_provider_name(skey));
+            BIO_printf(bio_out, "Key management: %s\n", EVP_SKEY_get0_skeymgmt_name(skey));
+            ret = 0;
+        }
+        goto end;
+    } else {
+        BIO_printf(bio_err, "Key generation is the only supported operation as of now\n");
+    }
+
+ end:
+    ERR_print_errors(bio_err);
+    sk_OPENSSL_STRING_free(skeyopts);
+    EVP_SKEYMGMT_free(mgmt);
+    EVP_SKEY_free(skey);
+    EVP_CIPHER_free(cipher);
+    return ret;
+}

+ 6 - 9
libs/openssl/apps/smime.c

@@ -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"),
@@ -474,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;

File diff suppressed because it is too large
+ 165 - 112
libs/openssl/apps/speed.c


+ 13 - 9
libs/openssl/apps/storeutl.c

@@ -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,7 +73,6 @@ 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;
@@ -309,13 +310,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);
@@ -354,7 +351,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;
@@ -433,6 +430,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
@@ -444,7 +448,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;

+ 6 - 7
libs/openssl/apps/ts.c

@@ -513,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) {
@@ -920,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;
             }
@@ -928,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;
             }
@@ -949,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;

+ 19 - 1
libs/openssl/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
@@ -131,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;

+ 30 - 7
libs/openssl/apps/x509.c

@@ -29,8 +29,8 @@
 
 #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);
@@ -54,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;
 
@@ -135,6 +136,10 @@ 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, '-',
@@ -279,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;
@@ -376,9 +381,15 @@ 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 err;
@@ -442,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 err;
             trustout = 1;
             break;
         case OPT_ADDREJECT:
@@ -453,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(reject, objtmp))
+                goto err;
             trustout = 1;
             break;
         case OPT_SETALIAS:
@@ -610,12 +623,22 @@ int x509_main(int argc, char **argv)
     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 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");
@@ -837,7 +860,7 @@ int x509_main(int argc, char **argv)
         goto err;
 
     if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
-        if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
+        if (!preserve_dates && !set_cert_times(x, not_before, not_after, days, 1))
             goto err;
         if (fissu != NULL) {
             if (!X509_set_issuer_name(x, fissu))

+ 7 - 0
libs/openssl/build.info

@@ -5,6 +5,9 @@ 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
@@ -23,6 +26,7 @@ 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 \
@@ -41,6 +45,7 @@ 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/internal/param_names.h crypto/params_idx.c
@@ -51,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.
@@ -72,6 +78,7 @@ 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

+ 3 - 1
libs/openssl/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 <appro\@openssl.org>"
 .align	64
+.previous
 ___
 
 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,

+ 3 - 1
libs/openssl/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 <appro\@openssl.org>"
 .align	64
+.previous
 ___
 						if ($shaext) {{{
 ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");

+ 3 - 1
libs/openssl/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 <appro\@openssl.org>"
 .align	64
+.previous
 ___
 
 ######################################################################

+ 3 - 1
libs/openssl/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 <appro\@openssl.org>"
 .align	64
+.previous
 ___
 
 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,

+ 2872 - 0
libs/openssl/crypto/aes/asm/aesni-xts-avx512.pl

@@ -0,0 +1,2872 @@
+#! /usr/bin/env perl
+# Copyright (C) 2023 Intel Corporation
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# This implementation is based on the AES-XTS code (AVX512VAES + VPCLMULQDQ)
+# from Intel(R) Intelligent Storage Acceleration Library Crypto Version
+# (https://github.com/intel/isa-l_crypto).
+#
+######################################################################
+# The main building block of the loop is code that encrypts/decrypts
+# 8/16 blocks of data stitching with generation of tweak for the next
+# 8/16 blocks, utilizing VAES and VPCLMULQDQ instructions with full width
+# of ZMM registers. The main loop is selected based on the input length.
+# main_loop_run_16 encrypts/decrypts 16 blocks in parallel and it's selected
+# when input length >= 256 bytes (16 blocks)
+# main_loop_run_8 encrypts/decrypts 8 blocks in parallel and it's selected
+# when 128 bytes <= input length < 256 bytes (8-15 blocks)
+# Input length < 128 bytes (8 blocks) is handled by do_n_blocks.
+#
+# This implementation mainly uses vpshrdq from AVX-512-VBMI2 family and vaesenc,
+# vaesdec, vpclmulqdq from AVX-512F family.
+$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$/);
+$avx512vaes=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]+)/) {
+    $avx512vaes = ($1>=2.30);
+}
+
+if (!$avx512vaes && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+       `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)(?:\.([0-9]+))?/) {
+    $avx512vaes = ($1==2.11 && $2>=8) + ($1>=2.12);
+}
+
+if (!$avx512vaes && `$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
+        $avx512vaes = ($ver>=10.0001)
+    } else {
+        $avx512vaes = ($ver>=7.0);
+    }
+}
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""
+    or die "can't call $xlate: $!";
+*STDOUT=*OUT;
+
+#======================================================================
+
+if ($avx512vaes) {
+
+  my $GP_STORAGE  = $win64 ? (16 * 18)  : (16 * 8);    # store rbx
+  my $XMM_STORAGE = $win64 ? (16 * 8) : 0;     # store xmm6:xmm15
+  my $VARIABLE_OFFSET = $win64 ? (16*8 + 16*10 + 8*3) :
+                                 (16*8 + 8*1);
+
+  # right now, >= 0x80 (128) is used for expanded keys. all usages of
+  # rsp should be invoked via $TW, not shadowed by any other name or
+  # used directly.
+  my $TW = "%rsp";
+  my $TEMPHIGH = "%rbx";
+  my $TEMPLOW = "%rax";
+  my $ZPOLY = "%zmm25";
+
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  # ;;; Function arguments abstraction
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  my ($key2, $key1, $tweak, $length, $input, $output);
+
+ 
+$input    = "%rdi";
+$output   = "%rsi";
+$length   = "%rdx";
+$key1     = "%rcx";
+$key2     = "%r8";
+$tweak    = "%r9";
+
+  # arguments for temp parameters
+  my ($tmp1, $gf_poly_8b, $gf_poly_8b_temp);
+    $tmp1                = "%r8";
+    $gf_poly_8b       = "%r10";
+    $gf_poly_8b_temp  = "%r11";
+
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  # ;;; Helper functions
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+  # Generates "random" local labels
+  sub random_string() {
+    my @chars  = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '_');
+    my $length = 15;
+    my $str;
+    map { $str .= $chars[rand(33)] } 1 .. $length;
+    return $str;
+  }
+
+  # ; Seed the RNG so the labels are generated deterministically
+  srand(12345);
+
+  sub encrypt_tweak {
+    my $state_tweak = $_[0];
+    my $is_128 = $_[1];
+
+    $code.=<<___;
+    vpxor	($key2), $state_tweak, $state_tweak
+    vaesenc	0x10($key2), $state_tweak, $state_tweak
+    vaesenc	0x20($key2), $state_tweak, $state_tweak
+    vaesenc	0x30($key2), $state_tweak, $state_tweak
+    vaesenc	0x40($key2), $state_tweak, $state_tweak
+    vaesenc	0x50($key2), $state_tweak, $state_tweak
+    vaesenc	0x60($key2), $state_tweak, $state_tweak
+    vaesenc	0x70($key2), $state_tweak, $state_tweak
+    vaesenc	0x80($key2), $state_tweak, $state_tweak
+    vaesenc	0x90($key2), $state_tweak, $state_tweak
+___
+
+    if ($is_128) {
+      $code .= "vaesenclast	0xa0($key2), $state_tweak, $state_tweak\n";
+    } else {
+      $code .= "vaesenc	0xa0($key2), $state_tweak, $state_tweak\n";
+      $code .= "vaesenc	0xb0($key2), $state_tweak, $state_tweak\n";
+      $code .= "vaesenc	0xc0($key2), $state_tweak, $state_tweak\n";
+      $code .= "vaesenc	0xd0($key2), $state_tweak, $state_tweak\n";
+      $code .= "vaesenclast	0xe0($key2), $state_tweak, $state_tweak\n";
+    }
+    $code .= "vmovdqa	$state_tweak, ($TW)\n";
+  }
+
+  sub encrypt_final {
+    my $st = $_[0];
+    my $tw = $_[1];
+    my $is_128 = $_[2];
+
+    # xor Tweak value
+	$code .= "vpxor	$tw, $st, $st\n";
+    $code .= "vpxor	($key1), $st, $st\n";
+
+    my $rounds = $is_128 ? 10 : 14;
+    for (my $i = 1; $i < $rounds; $i++) {
+      $code .= "vaesenc	16*$i($key1), $st, $st\n";
+    }
+
+    $code .=<<___;
+    vaesenclast 16*$rounds($key1), $st, $st
+    vpxor	$tw, $st, $st
+___
+  }
+
+  # decrypt initial blocks of AES
+  # 1, 2, 3, 4, 5, 6 or 7 blocks are encrypted
+  # next 8 Tweak values are generated
+  sub decrypt_initial {
+    my @st;
+    $st[0] = $_[0];
+    $st[1] = $_[1];
+    $st[2] = $_[2];
+    $st[3] = $_[3];
+    $st[4] = $_[4];
+    $st[5] = $_[5];
+    $st[6] = $_[6];
+    $st[7] = $_[7];
+
+    my @tw;
+    $tw[0] = $_[8];
+    $tw[1] = $_[9];
+    $tw[2] = $_[10];
+    $tw[3] = $_[11];
+    $tw[4] = $_[12];
+    $tw[5] = $_[13];
+    $tw[6] = $_[14];
+    my $t0 = $_[15];
+    my $num_blocks = $_[16];
+    my $lt128 = $_[17];
+    my $is_128 = $_[18];
+
+    # num_blocks blocks encrypted
+    # num_blocks can be 1, 2, 3, 4, 5, 6, 7
+
+    #  xor Tweak value
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vpxor $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    $code .= "vmovdqu  ($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vpxor $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+___
+    }
+    # round 1
+    $code .= "vmovdqu 0x10($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+    $code .= <<___;
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, ($TW)     # next Tweak1 generated
+      mov     $TEMPLOW, 0x08($TW)
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+___
+    }
+
+    # round 2
+    $code .= "vmovdqu 0x20($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x10($TW) # next Tweak2 generated
+___
+    }
+
+    # round 3
+    $code .= "vmovdqu 0x30($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      mov     $TEMPHIGH, 0x18($TW)
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+___
+    }
+
+    # round 4
+    $code .= "vmovdqu 0x40($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+    $code .= <<___;
+    xor     $gf_poly_8b_temp, $TEMPLOW
+    mov     $TEMPLOW, 0x20($TW) # next Tweak3 generated
+    mov     $TEMPHIGH, 0x28($TW)
+    xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+    shl     \$1, $TEMPLOW
+___
+    }
+
+    # round 5
+    $code .= "vmovdqu 0x50($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+    $code .= <<___;
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x30($TW) # next Tweak4 generated
+      mov     $TEMPHIGH, 0x38($TW)
+___
+    }
+
+    # round 6
+    $code .= "vmovdqu 0x60($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x40($TW) # next Tweak5 generated
+      mov     $TEMPHIGH, 0x48($TW)
+___
+    }
+
+    # round 7
+    $code .= "vmovdqu 0x70($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x50($TW) # next Tweak6 generated
+      mov     $TEMPHIGH, 0x58($TW)
+___
+    }
+
+    # round 8
+    $code .= "vmovdqu 0x80($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x60($TW) # next Tweak7 generated
+      mov     $TEMPHIGH, 0x68($TW)
+___
+    }
+
+    # round 9
+    $code .= "vmovdqu 0x90($key1), $t0\n";
+
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      $code .= <<___;
+      xor     $gf_poly_8b_temp, $gf_poly_8b_temp
+      shl     \$1, $TEMPLOW
+      adc     $TEMPHIGH, $TEMPHIGH
+      cmovc   $gf_poly_8b, $gf_poly_8b_temp
+      xor     $gf_poly_8b_temp, $TEMPLOW
+      mov     $TEMPLOW, 0x70($TW) # next Tweak8 generated
+      mov     $TEMPHIGH, 0x78($TW)
+___
+    }
+
+    if ($is_128) {
+      # round 10
+      $code .= "vmovdqu 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdeclast $t0, $st[$i], $st[$i]\n";
+      }
+    } else {
+      # round 10
+      $code .= "vmovdqu 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 11
+      $code .= "vmovdqu 0xb0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 12
+      $code .= "vmovdqu 0xc0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 13
+      $code .= "vmovdqu 0xd0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 14
+      $code .= "vmovdqu 0xe0($key1), $t0\n";
+      for (my $i = 0; $i < $num_blocks; $i++) {
+        $code .= "vaesdeclast $t0, $st[$i], $st[$i]\n";
+      }
+    }
+
+    # xor Tweak values
+    for (my $i = 0; $i < $num_blocks; $i++) {
+      $code .= "vpxor $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $lt128) {
+      # load next Tweak values
+      $code .= <<___;
+      vmovdqa  ($TW), $tw1
+      vmovdqa  0x10($TW), $tw2
+      vmovdqa  0x20($TW), $tw3
+      vmovdqa  0x30($TW), $tw4
+      vmovdqa  0x40($TW), $tw5
+      vmovdqa  0x50($TW), $tw6
+      vmovdqa  0x60($TW), $tw7
+___
+    }
+  }
+
+  sub initialize {
+    my @st;
+    $st[0] = $_[0];
+    $st[1] = $_[1];
+    $st[2] = $_[2];
+    $st[3] = $_[3];
+    $st[4] = $_[4];
+    $st[5] = $_[5];
+    $st[6] = $_[6];
+    $st[7] = $_[7];
+
+    my @tw;
+    $tw[0] = $_[8];
+    $tw[1] = $_[9];
+    $tw[2] = $_[10];
+    $tw[3] = $_[11];
+    $tw[4] = $_[12];
+    $tw[5] = $_[13];
+    $tw[6] = $_[14];
+    my $num_initial_blocks = $_[15];
+
+    $code .= <<___;
+    vmovdqa  0x0($TW), $tw[0]
+    mov      0x0($TW), $TEMPLOW
+    mov      0x08($TW), $TEMPHIGH
+    vmovdqu  0x0($input), $st[0]
+___
+
+    if ($num_initial_blocks >= 2) {
+      for (my $i = 1; $i < $num_initial_blocks; $i++) {
+        $code .= "xor      $gf_poly_8b_temp, $gf_poly_8b_temp\n";
+        $code .= "shl      \$1, $TEMPLOW\n";
+        $code .= "adc      $TEMPHIGH, $TEMPHIGH\n";
+        $code .= "cmovc    $gf_poly_8b, $gf_poly_8b_temp\n";
+        $code .= "xor      $gf_poly_8b_temp, $TEMPLOW\n";
+        my $offset = $i * 16;
+        $code .= "mov      $TEMPLOW, $offset($TW)\n";
+        $code .= "mov      $TEMPHIGH, $offset + 8($TW)\n";
+        $code .= "vmovdqa  $offset($TW), $tw[$i]\n";
+        $code .= "vmovdqu  $offset($input), $st[$i]\n";
+      }
+    }
+  }
+
+  # Encrypt 4 blocks in parallel
+  sub encrypt_by_four {
+    my $st1 = $_[0]; # state 1
+    my $tw1 = $_[1]; # tweak 1
+    my $tmp = $_[2];
+    my $is_128 = $_[3];
+
+    $code .= "vbroadcasti32x4 ($key1), $tmp\n";
+    $code .= "vpternlogq      \$0x96, $tmp, $tw1, $st1\n";
+
+    my $rounds = $is_128 ? 10 : 14;
+    for (my $i = 1; $i < $rounds; $i++) {
+      $code .= "vbroadcasti32x4 16*$i($key1), $tmp\n";
+      $code .= "vaesenc  $tmp, $st1, $st1\n";
+    }
+
+    $code .= "vbroadcasti32x4 16*$rounds($key1), $tmp\n";
+    $code .= "vaesenclast  $tmp, $st1, $st1\n";
+
+    $code .= "vpxorq $tw1, $st1, $st1\n";
+  }
+
+  # Encrypt 8 blocks in parallel
+  # generate next 8 tweak values
+  sub encrypt_by_eight_zmm {
+    my $st1 = $_[0];
+    my $st2 = $_[1];
+    my $tw1 = $_[2];
+    my $tw2 = $_[3];
+    my $t0 = $_[4];
+    my $last_eight = $_[5];
+    my $is_128 = $_[6];
+
+    $code .= <<___;
+	vbroadcasti32x4 ($key1), $t0
+	vpternlogq    \$0x96, $t0, $tw1, $st1
+	vpternlogq    \$0x96, $t0, $tw2, $st2
+___
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw1, %zmm13
+      vpclmulqdq	\$0x0, $ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw1, %zmm15
+      vpxord		%zmm14, %zmm15, %zmm15
+___
+    }
+    # round 1
+    $code .= <<___;
+    vbroadcasti32x4 0x10($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 2
+    vbroadcasti32x4 0x20($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 3
+    vbroadcasti32x4 0x30($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+___
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw2, %zmm13
+      vpclmulqdq	\$0x0, $ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw2, %zmm16
+      vpxord		%zmm14, %zmm16, %zmm16
+___
+    }
+
+    $code .= <<___;
+    # round 4
+    vbroadcasti32x4 0x40($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 5
+    vbroadcasti32x4 0x50($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 6
+    vbroadcasti32x4 0x60($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 7
+    vbroadcasti32x4 0x70($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 8
+    vbroadcasti32x4 0x80($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+
+    # round 9
+    vbroadcasti32x4 0x90($key1), $t0
+    vaesenc  $t0, $st1, $st1
+    vaesenc  $t0, $st2, $st2
+___
+
+    if ($is_128) {
+      $code .= <<___;
+      # round 10
+      vbroadcasti32x4 0xa0($key1), $t0
+      vaesenclast  $t0, $st1, $st1
+      vaesenclast  $t0, $st2, $st2
+___
+    } else {
+      $code .= <<___;
+      # round 10
+      vbroadcasti32x4 0xa0($key1), $t0
+      vaesenc  $t0, $st1, $st1
+      vaesenc  $t0, $st2, $st2
+
+      # round 11
+      vbroadcasti32x4 0xb0($key1), $t0
+      vaesenc  $t0, $st1, $st1
+      vaesenc  $t0, $st2, $st2
+
+      # round 12
+      vbroadcasti32x4 0xc0($key1), $t0
+      vaesenc  $t0, $st1, $st1
+      vaesenc  $t0, $st2, $st2
+
+      # round 13
+      vbroadcasti32x4 0xd0($key1), $t0
+      vaesenc  $t0, $st1, $st1
+      vaesenc  $t0, $st2, $st2
+
+      # round 14
+      vbroadcasti32x4 0xe0($key1), $t0
+      vaesenclast  $t0, $st1, $st1
+      vaesenclast  $t0, $st2, $st2
+___
+    }
+	
+    # xor Tweak values
+    $code .= "vpxorq    $tw1, $st1, $st1\n";
+    $code .= "vpxorq    $tw2, $st2, $st2\n";
+
+    if (0 == $last_eight) {
+      # load next Tweak values
+      $code .= <<___;
+      vmovdqa32  %zmm15, $tw1
+      vmovdqa32  %zmm16, $tw2
+___
+    }
+  }
+
+  # Decrypt 8 blocks in parallel
+  # generate next 8 tweak values
+  sub decrypt_by_eight_zmm {
+    my $st1 = $_[0];
+    my $st2 = $_[1];
+    my $tw1 = $_[2];
+    my $tw2 = $_[3];
+    my $t0 = $_[4];
+    my $last_eight = $_[5];
+    my $is_128 = $_[6];
+
+    $code .= <<___;
+    # xor Tweak values
+    vpxorq    $tw1, $st1, $st1
+    vpxorq    $tw2, $st2, $st2
+
+    # ARK
+    vbroadcasti32x4 ($key1), $t0
+    vpxorq    $t0, $st1, $st1
+    vpxorq    $t0, $st2, $st2
+___
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw1, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw1, %zmm15
+      vpxord		%zmm14, %zmm15, %zmm15
+___
+    }
+    # round 1
+    $code .= <<___;
+    vbroadcasti32x4 0x10($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 2
+    vbroadcasti32x4 0x20($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 3
+    vbroadcasti32x4 0x30($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+___
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw2, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw2, %zmm16
+      vpxord		%zmm14, %zmm16, %zmm16
+___
+    }
+
+    $code .= <<___;
+    # round 4
+    vbroadcasti32x4 0x40($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 5
+    vbroadcasti32x4 0x50($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 6
+    vbroadcasti32x4 0x60($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 7
+    vbroadcasti32x4 0x70($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 8
+    vbroadcasti32x4 0x80($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+    # round 9
+    vbroadcasti32x4 0x90($key1), $t0
+    vaesdec  $t0, $st1, $st1
+    vaesdec  $t0, $st2, $st2
+
+___
+    if ($is_128) {
+      $code .= <<___;
+      # round 10
+      vbroadcasti32x4 0xa0($key1), $t0
+      vaesdeclast  $t0, $st1, $st1
+      vaesdeclast  $t0, $st2, $st2
+___
+    } else {
+      $code .= <<___;
+      # round 10
+      vbroadcasti32x4 0xa0($key1), $t0
+      vaesdec  $t0, $st1, $st1
+      vaesdec  $t0, $st2, $st2
+
+      # round 11
+      vbroadcasti32x4 0xb0($key1), $t0
+      vaesdec  $t0, $st1, $st1
+      vaesdec  $t0, $st2, $st2
+
+      # round 12
+      vbroadcasti32x4 0xc0($key1), $t0
+      vaesdec  $t0, $st1, $st1
+      vaesdec  $t0, $st2, $st2
+
+      # round 13
+      vbroadcasti32x4 0xd0($key1), $t0
+      vaesdec  $t0, $st1, $st1
+      vaesdec  $t0, $st2, $st2
+
+      # round 14
+      vbroadcasti32x4 0xe0($key1), $t0
+      vaesdeclast  $t0, $st1, $st1
+      vaesdeclast  $t0, $st2, $st2
+___
+    }
+
+    $code .= <<___;
+    # xor Tweak values
+    vpxorq    $tw1, $st1, $st1
+    vpxorq    $tw2, $st2, $st2
+
+    # load next Tweak values
+    vmovdqa32  %zmm15, $tw1
+    vmovdqa32  %zmm16, $tw2
+___
+  }
+
+  # Encrypt 16 blocks in parallel
+  # generate next 16 tweak values
+  sub encrypt_by_16_zmm {
+    my @st;
+    $st[0] = $_[0];
+    $st[1] = $_[1];
+    $st[2] = $_[2];
+    $st[3] = $_[3];
+
+    my @tw;
+    $tw[0] = $_[4];
+    $tw[1] = $_[5];
+    $tw[2] = $_[6];
+    $tw[3] = $_[7];
+
+    my $t0 = $_[8];
+    my $last_eight = $_[9];
+    my $is_128 = $_[10];
+
+    # xor Tweak values
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq    $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    # ARK
+    $code .= "vbroadcasti32x4 ($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw[2], %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw[2], %zmm15
+      vpxord		%zmm14, %zmm15, %zmm15
+___
+    }
+
+    # round 1
+    $code .= "vbroadcasti32x4 0x10($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 2
+    $code .= "vbroadcasti32x4 0x20($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 3
+    $code .= "vbroadcasti32x4 0x30($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw[3], %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw[3], %zmm16
+      vpxord		%zmm14, %zmm16, %zmm16
+___
+    }
+    # round 4
+    $code .= "vbroadcasti32x4 0x40($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 5
+    $code .= "vbroadcasti32x4 0x50($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 6
+    $code .= "vbroadcasti32x4 0x60($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, %zmm15, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, %zmm15, %zmm17
+      vpxord		%zmm14, %zmm17, %zmm17
+___
+    }
+    # round 7
+    $code .= "vbroadcasti32x4 0x70($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 8
+    $code .= "vbroadcasti32x4 0x80($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 9
+    $code .= "vbroadcasti32x4 0x90($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, %zmm16, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, %zmm16, %zmm18
+      vpxord		%zmm14, %zmm18, %zmm18
+___
+    }
+    if ($is_128) {
+      # round 10
+      $code .= "vbroadcasti32x4 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenclast $t0, $st[$i], $st[$i]\n";
+      }
+    } else {
+      # round 10
+      $code .= "vbroadcasti32x4 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+      }
+      # round 11
+      $code .= "vbroadcasti32x4 0xb0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+      }
+      # round 12
+      $code .= "vbroadcasti32x4 0xc0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+      }
+      # round 13
+      $code .= "vbroadcasti32x4 0xd0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenc $t0, $st[$i], $st[$i]\n";
+      }
+      # round 14
+      $code .= "vbroadcasti32x4 0xe0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesenclast $t0, $st[$i], $st[$i]\n";
+      }
+    }
+
+    # xor Tweak values
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq    $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    $code .= <<___;
+    # load next Tweak values
+    vmovdqa32  %zmm15, $tw[0]
+    vmovdqa32  %zmm16, $tw[1]
+    vmovdqa32  %zmm17, $tw[2]
+    vmovdqa32  %zmm18, $tw[3]
+___
+  }
+
+  # Decrypt 16 blocks in parallel
+  # generate next 8 tweak values
+  sub decrypt_by_16_zmm {
+    my @st;
+    $st[0] = $_[0];
+    $st[1] = $_[1];
+    $st[2] = $_[2];
+    $st[3] = $_[3];
+
+    my @tw;
+    $tw[0] = $_[4];
+    $tw[1] = $_[5];
+    $tw[2] = $_[6];
+    $tw[3] = $_[7];
+
+    my $t0 = $_[8];
+    my $last_eight = $_[9];
+    my $is_128 = $_[10];
+
+    # xor Tweak values
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq    $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    # ARK
+    $code .= "vbroadcasti32x4 ($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw[2], %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw[2], %zmm15
+      vpxord		%zmm14, %zmm15, %zmm15
+___
+    }
+
+    # round 1
+    $code .= "vbroadcasti32x4 0x10($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 2
+    $code .= "vbroadcasti32x4 0x20($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 3
+    $code .= "vbroadcasti32x4 0x30($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, $tw[3], %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, $tw[3], %zmm16
+      vpxord		%zmm14, %zmm16, %zmm16
+___
+    }
+    # round 4
+    $code .= "vbroadcasti32x4 0x40($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 5
+    $code .= "vbroadcasti32x4 0x50($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 6
+    $code .= "vbroadcasti32x4 0x60($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, %zmm15, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, %zmm15, %zmm17
+      vpxord		%zmm14, %zmm17, %zmm17
+___
+    }
+    # round 7
+    $code .= "vbroadcasti32x4 0x70($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 8
+    $code .= "vbroadcasti32x4 0x80($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    # round 9
+    $code .= "vbroadcasti32x4 0x90($key1), $t0\n";
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+    }
+
+    if (0 == $last_eight) {
+      $code .= <<___;
+      vpsrldq		\$0xf, %zmm16, %zmm13
+      vpclmulqdq	\$0x0,$ZPOLY, %zmm13, %zmm14
+      vpslldq		\$0x1, %zmm16, %zmm18
+      vpxord		%zmm14, %zmm18, %zmm18
+___
+    }
+    if ($is_128) {
+      # round 10
+      $code .= "vbroadcasti32x4 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdeclast $t0, $st[$i], $st[$i]\n";
+      }
+    } else {
+      # round 10
+      $code .= "vbroadcasti32x4 0xa0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 11
+      $code .= "vbroadcasti32x4 0xb0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 12
+      $code .= "vbroadcasti32x4 0xc0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 13
+      $code .= "vbroadcasti32x4 0xd0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdec $t0, $st[$i], $st[$i]\n";
+      }
+
+      # round 14
+      $code .= "vbroadcasti32x4 0xe0($key1), $t0\n";
+      for (my $i = 0; $i < 4; $i++) {
+        $code .= "vaesdeclast $t0, $st[$i], $st[$i]\n";
+      }
+    }
+
+    # xor Tweak values
+    for (my $i = 0; $i < 4; $i++) {
+      $code .= "vpxorq    $tw[$i], $st[$i], $st[$i]\n";
+    }
+
+    $code .= <<___;
+    # load next Tweak values
+    vmovdqa32  %zmm15, $tw[0]
+    vmovdqa32  %zmm16, $tw[1]
+    vmovdqa32  %zmm17, $tw[2]
+    vmovdqa32  %zmm18, $tw[3]
+___
+  }
+
+  $code .= ".text\n";
+
+  {
+    $code.=<<"___";
+    .extern	OPENSSL_ia32cap_P
+    .globl	aesni_xts_avx512_eligible
+    .type	aesni_xts_avx512_eligible,\@abi-omnipotent
+    .align	32
+    aesni_xts_avx512_eligible:
+        mov	OPENSSL_ia32cap_P+8(%rip), %ecx
+        xor	%eax,%eax
+    	# 1<<31|1<<30|1<<17|1<<16 avx512vl + avx512bw + avx512dq + avx512f
+        and	\$0xc0030000, %ecx
+        cmp	\$0xc0030000, %ecx
+        jne	.L_done
+        mov	OPENSSL_ia32cap_P+12(%rip), %ecx
+    	# 1<<10|1<<9|1<<6 vaes + vpclmulqdq + vbmi2
+        and	\$0x640, %ecx
+        cmp	\$0x640, %ecx
+        cmove	%ecx,%eax
+        .L_done:
+        ret
+    .size   aesni_xts_avx512_eligible, .-aesni_xts_avx512_eligible
+___
+  }
+
+
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  # ;void aesni_xts_[128|256]_encrypt_avx512(
+  # ;               const uint8_t *in,        // input data
+  # ;               uint8_t *out,             // output data
+  # ;               size_t length,            // sector size, in bytes
+  # ;               const AES_KEY *key1,      // key used for "ECB" encryption
+  # ;               const AES_KEY *key2,      // key used for tweaking
+  # ;               const uint8_t iv[16])     // initial tweak value, 16 bytes
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  sub enc {
+    my $is_128 = $_[0];
+    my $rndsuffix = &random_string();
+
+    if ($is_128) {
+      $code.=<<___;
+      .globl	aesni_xts_128_encrypt_avx512
+      .hidden	aesni_xts_128_encrypt_avx512
+      .type	aesni_xts_128_encrypt_avx512,\@function,6
+      .align	32
+      aesni_xts_128_encrypt_avx512:
+      .cfi_startproc
+      endbranch
+___
+    } else {
+      $code.=<<___;
+      .globl	aesni_xts_256_encrypt_avx512
+      .hidden	aesni_xts_256_encrypt_avx512
+      .type	aesni_xts_256_encrypt_avx512,\@function,6
+      .align	32
+      aesni_xts_256_encrypt_avx512:
+      .cfi_startproc
+      endbranch
+___
+    }
+    $code .= "push 	 %rbp\n";
+    $code .= "mov 	 $TW,%rbp\n";
+    $code .= "sub 	 \$$VARIABLE_OFFSET,$TW\n";
+    $code .= "and 	 \$0xffffffffffffffc0,$TW\n";
+    $code .= "mov 	 %rbx,$GP_STORAGE($TW)\n";
+
+    if ($win64) {
+      $code .= "mov 	 %rdi,$GP_STORAGE + 8*1($TW)\n";
+      $code .= "mov 	 %rsi,$GP_STORAGE + 8*2($TW)\n";
+      $code .= "vmovdqa      %xmm6, $XMM_STORAGE + 16*0($TW)\n";
+      $code .= "vmovdqa      %xmm7, $XMM_STORAGE + 16*1($TW)\n";
+      $code .= "vmovdqa      %xmm8, $XMM_STORAGE + 16*2($TW)\n";
+      $code .= "vmovdqa      %xmm9, $XMM_STORAGE + 16*3($TW)\n";
+      $code .= "vmovdqa      %xmm10, $XMM_STORAGE + 16*4($TW)\n";
+      $code .= "vmovdqa      %xmm11, $XMM_STORAGE + 16*5($TW)\n";
+      $code .= "vmovdqa      %xmm12, $XMM_STORAGE + 16*6($TW)\n";
+      $code .= "vmovdqa      %xmm13, $XMM_STORAGE + 16*7($TW)\n";
+      $code .= "vmovdqa      %xmm14, $XMM_STORAGE + 16*8($TW)\n";
+      $code .= "vmovdqa      %xmm15, $XMM_STORAGE + 16*9($TW)\n";
+    }
+
+    $code .= "mov 	 \$0x87, $gf_poly_8b\n";
+    $code .= "vmovdqu 	 ($tweak),%xmm1\n";      # read initial tweak values
+
+    encrypt_tweak("%xmm1", $is_128);
+
+    if ($win64) {
+      $code .= "mov	 $input, 8 + 8*5(%rbp)\n";  # ciphertext pointer
+      $code .= "mov        $output, 8 + 8*6(%rbp)\n"; # plaintext pointer
+    }
+
+    {
+    $code.=<<___;
+
+    cmp 	 \$0x80,$length
+    jl 	 .L_less_than_128_bytes_${rndsuffix}
+    vpbroadcastq 	 $gf_poly_8b,$ZPOLY
+    cmp 	 \$0x100,$length
+    jge 	 .L_start_by16_${rndsuffix}
+    cmp 	 \$0x80,$length
+    jge 	 .L_start_by8_${rndsuffix}
+
+    .L_do_n_blocks_${rndsuffix}:
+    cmp 	 \$0x0,$length
+    je 	 .L_ret_${rndsuffix}
+    cmp 	 \$0x70,$length
+    jge 	 .L_remaining_num_blocks_is_7_${rndsuffix}
+    cmp 	 \$0x60,$length
+    jge 	 .L_remaining_num_blocks_is_6_${rndsuffix}
+    cmp 	 \$0x50,$length
+    jge 	 .L_remaining_num_blocks_is_5_${rndsuffix}
+    cmp 	 \$0x40,$length
+    jge 	 .L_remaining_num_blocks_is_4_${rndsuffix}
+    cmp 	 \$0x30,$length
+    jge 	 .L_remaining_num_blocks_is_3_${rndsuffix}
+    cmp 	 \$0x20,$length
+    jge 	 .L_remaining_num_blocks_is_2_${rndsuffix}
+    cmp 	 \$0x10,$length
+    jge 	 .L_remaining_num_blocks_is_1_${rndsuffix}
+    vmovdqa 	 %xmm0,%xmm8
+    vmovdqa 	 %xmm9,%xmm0
+    jmp 	 .L_steal_cipher_${rndsuffix}
+
+    .L_remaining_num_blocks_is_7_${rndsuffix}:
+    mov 	 \$0x0000ffffffffffff,$tmp1
+    kmovq 	 $tmp1,%k1
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2{%k1}
+    add 	 \$0x70,$input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %zmm2,0x40($output){%k1}
+    add 	 \$0x70,$output
+    vextracti32x4 	 \$0x2,%zmm2,%xmm8
+    vextracti32x4 	 \$0x3,%zmm10,%xmm0
+    and 	 \$0xf,$length
+    je 	 .L_ret_${rndsuffix}
+    jmp 	 .L_steal_cipher_${rndsuffix}
+
+    .L_remaining_num_blocks_is_6_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%ymm2
+    add 	 \$0x60,$input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %ymm2,0x40($output)
+    add 	 \$0x60,$output
+    vextracti32x4 	 \$0x1,%zmm2,%xmm8
+    vextracti32x4 	 \$0x2,%zmm10,%xmm0
+    and 	 \$0xf,$length
+    je 	 .L_ret_${rndsuffix}
+    jmp 	 .L_steal_cipher_${rndsuffix}
+
+    .L_remaining_num_blocks_is_5_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu 	 0x40($input),%xmm2
+    add 	 \$0x50,$input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu 	 %xmm2,0x40($output)
+    add 	 \$0x50,$output
+    vmovdqa 	 %xmm2,%xmm8
+    vextracti32x4 	 \$0x1,%zmm10,%xmm0
+    and 	 \$0xf,$length
+    je 	 .L_ret_${rndsuffix}
+    jmp 	 .L_steal_cipher_${rndsuffix}
+
+    .L_remaining_num_blocks_is_4_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    add 	 \$0x40,$input
+___
+    }
+
+    encrypt_by_four("%zmm1", "%zmm9", "%zmm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1,($output)
+    add	\$0x40,$output
+    vextracti32x4	\$0x3,%zmm1,%xmm8
+    vmovdqa64	%xmm10, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_remaining_num_blocks_is_3_${rndsuffix}:
+    mov	\$-1, $tmp1
+    shr	\$0x10, $tmp1
+    kmovq	$tmp1, %k1
+    vmovdqu8	($input), %zmm1{%k1}
+    add	\$0x30, $input
+___
+    }
+
+    encrypt_by_four("%zmm1", "%zmm9", "%zmm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, ($output){%k1}
+    add	\$0x30, $output
+    vextracti32x4	\$0x2, %zmm1, %xmm8
+    vextracti32x4	\$0x3, %zmm9, %xmm0
+    and	\$0xf, $length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_remaining_num_blocks_is_2_${rndsuffix}:
+    vmovdqu8	($input), %ymm1
+    add	\$0x20, $input
+___
+    }
+
+    encrypt_by_four("%ymm1", "%ymm9", "%ymm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %ymm1,($output)
+    add 	 \$0x20,$output
+    vextracti32x4	\$0x1, %zmm1, %xmm8
+    vextracti32x4	\$0x2,%zmm9,%xmm0
+    and 	 \$0xf,$length
+    je 	 .L_ret_${rndsuffix}
+    jmp 	 .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_remaining_num_blocks_is_1_${rndsuffix}:
+    vmovdqu 	 ($input),%xmm1
+    add 	 \$0x10,$input
+___
+    }
+
+    encrypt_final("%xmm1", "%xmm9", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    add 	 \$0x10,$output
+    vmovdqa 	 %xmm1,%xmm8
+    vextracti32x4 	 \$0x1,%zmm9,%xmm0
+    and 	 \$0xf,$length
+    je 	 .L_ret_${rndsuffix}
+    jmp 	 .L_steal_cipher_${rndsuffix}
+
+
+    .L_start_by16_${rndsuffix}:
+    vbroadcasti32x4 	 ($TW),%zmm0
+    vbroadcasti32x4 shufb_15_7(%rip),%zmm8
+    mov 	 \$0xaa,$tmp1
+    kmovq 	 $tmp1,%k2
+    vpshufb 	 %zmm8,%zmm0,%zmm1
+    vpsllvq const_dq3210(%rip),%zmm0,%zmm4
+    vpsrlvq const_dq5678(%rip),%zmm1,%zmm2
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm2,%zmm3
+    vpxorq 	 %zmm2,%zmm4,%zmm4{%k2}
+    vpxord 	 %zmm4,%zmm3,%zmm9
+    vpsllvq const_dq7654(%rip),%zmm0,%zmm5
+    vpsrlvq const_dq1234(%rip),%zmm1,%zmm6
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm6,%zmm7
+    vpxorq 	 %zmm6,%zmm5,%zmm5{%k2}
+    vpxord 	 %zmm5,%zmm7,%zmm10
+    vpsrldq 	 \$0xf,%zmm9,%zmm13
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm13,%zmm14
+    vpslldq 	 \$0x1,%zmm9,%zmm11
+    vpxord 	 %zmm14,%zmm11,%zmm11
+    vpsrldq 	 \$0xf,%zmm10,%zmm15
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm15,%zmm16
+    vpslldq 	 \$0x1,%zmm10,%zmm12
+    vpxord 	 %zmm16,%zmm12,%zmm12
+
+    .L_main_loop_run_16_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2
+    vmovdqu8 	 0x80($input),%zmm3
+    vmovdqu8 	 0xc0($input),%zmm4
+    add 	 \$0x100,$input
+___
+    }
+
+    encrypt_by_16_zmm("%zmm1", "%zmm2", "%zmm3", "%zmm4", "%zmm9",
+                      "%zmm10", "%zmm11", "%zmm12", "%zmm0", 0, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %zmm2,0x40($output)
+    vmovdqu8 	 %zmm3,0x80($output)
+    vmovdqu8 	 %zmm4,0xc0($output)
+    add 	 \$0x100,$output
+    sub 	 \$0x100,$length
+    cmp 	 \$0x100,$length
+    jae 	 .L_main_loop_run_16_${rndsuffix}
+    cmp 	 \$0x80,$length
+    jae 	 .L_main_loop_run_8_${rndsuffix}
+    vextracti32x4 	 \$0x3,%zmm4,%xmm0
+    jmp 	 .L_do_n_blocks_${rndsuffix}
+
+    .L_start_by8_${rndsuffix}:
+    vbroadcasti32x4 	 ($TW),%zmm0
+    vbroadcasti32x4 shufb_15_7(%rip),%zmm8
+    mov 	 \$0xaa,$tmp1
+    kmovq 	 $tmp1,%k2
+    vpshufb 	 %zmm8,%zmm0,%zmm1
+    vpsllvq const_dq3210(%rip),%zmm0,%zmm4
+    vpsrlvq const_dq5678(%rip),%zmm1,%zmm2
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm2,%zmm3
+    vpxorq 	 %zmm2,%zmm4,%zmm4{%k2}
+    vpxord 	 %zmm4,%zmm3,%zmm9
+    vpsllvq const_dq7654(%rip),%zmm0,%zmm5
+    vpsrlvq const_dq1234(%rip),%zmm1,%zmm6
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm6,%zmm7
+    vpxorq 	 %zmm6,%zmm5,%zmm5{%k2}
+    vpxord 	 %zmm5,%zmm7,%zmm10
+
+    .L_main_loop_run_8_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2
+    add 	 \$0x80,$input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 0, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %zmm2,0x40($output)
+    add 	 \$0x80,$output
+    sub 	 \$0x80,$length
+    cmp 	 \$0x80,$length
+    jae 	 .L_main_loop_run_8_${rndsuffix}
+    vextracti32x4 	 \$0x3,%zmm2,%xmm0
+    jmp 	 .L_do_n_blocks_${rndsuffix}
+
+    .L_steal_cipher_${rndsuffix}:
+    vmovdqa	%xmm8,%xmm2
+    lea	vpshufb_shf_table(%rip),$TEMPLOW
+    vmovdqu	($TEMPLOW,$length,1),%xmm10
+    vpshufb	%xmm10,%xmm8,%xmm8
+    vmovdqu	-0x10($input,$length,1),%xmm3
+    vmovdqu	%xmm8,-0x10($output,$length,1)
+    lea	vpshufb_shf_table(%rip),$TEMPLOW
+    add	\$16, $TEMPLOW
+    sub	$length,$TEMPLOW
+    vmovdqu	($TEMPLOW),%xmm10
+    vpxor	mask1(%rip),%xmm10,%xmm10
+    vpshufb	%xmm10,%xmm3,%xmm3
+    vpblendvb	%xmm10,%xmm2,%xmm3,%xmm3
+    vpxor	%xmm0,%xmm3,%xmm8
+    vpxor	($key1),%xmm8,%xmm8
+    vaesenc	0x10($key1),%xmm8,%xmm8
+    vaesenc	0x20($key1),%xmm8,%xmm8
+    vaesenc	0x30($key1),%xmm8,%xmm8
+    vaesenc	0x40($key1),%xmm8,%xmm8
+    vaesenc	0x50($key1),%xmm8,%xmm8
+    vaesenc	0x60($key1),%xmm8,%xmm8
+    vaesenc	0x70($key1),%xmm8,%xmm8
+    vaesenc	0x80($key1),%xmm8,%xmm8
+    vaesenc	0x90($key1),%xmm8,%xmm8
+___
+    if ($is_128) {
+      $code .= "vaesenclast	0xa0($key1),%xmm8,%xmm8\n";
+    } else {
+      $code .= <<___
+      vaesenc	0xa0($key1),%xmm8,%xmm8
+      vaesenc	0xb0($key1),%xmm8,%xmm8
+      vaesenc	0xc0($key1),%xmm8,%xmm8
+      vaesenc	0xd0($key1),%xmm8,%xmm8
+      vaesenclast	0xe0($key1),%xmm8,%xmm8
+___
+    }
+    $code .= "vpxor	%xmm0,%xmm8,%xmm8\n";
+    $code .= "vmovdqu	%xmm8,-0x10($output)\n";
+    }
+
+    {
+    $code .= <<___;
+    .L_ret_${rndsuffix}:
+    mov 	 $GP_STORAGE($TW),%rbx
+    xor    $tmp1,$tmp1
+    mov    $tmp1,$GP_STORAGE($TW)
+    # Zero-out the whole of `%zmm0`.
+    vpxorq %zmm0,%zmm0,%zmm0
+___
+    }
+
+    if ($win64) {
+      $code .= <<___;
+      mov $GP_STORAGE + 8*1($TW),%rdi
+      mov $tmp1,$GP_STORAGE + 8*1($TW)
+      mov $GP_STORAGE + 8*2($TW),%rsi
+      mov $tmp1,$GP_STORAGE + 8*2($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 0($TW), %xmm6
+      vmovdqa $XMM_STORAGE + 16 * 1($TW), %xmm7
+      vmovdqa $XMM_STORAGE + 16 * 2($TW), %xmm8
+      vmovdqa $XMM_STORAGE + 16 * 3($TW), %xmm9
+
+      # Zero the 64 bytes we just restored to the xmm registers.
+      vmovdqa64 %zmm0,$XMM_STORAGE($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 4($TW), %xmm10
+      vmovdqa $XMM_STORAGE + 16 * 5($TW), %xmm11
+      vmovdqa $XMM_STORAGE + 16 * 6($TW), %xmm12
+      vmovdqa $XMM_STORAGE + 16 * 7($TW), %xmm13
+
+      # And again.
+      vmovdqa64 %zmm0,$XMM_STORAGE + 16 * 4($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 8($TW), %xmm14
+      vmovdqa $XMM_STORAGE + 16 * 9($TW), %xmm15
+
+      # Last round is only 32 bytes (256-bits), so we use `%ymm` as the
+      # source operand.
+      vmovdqa %ymm0,$XMM_STORAGE + 16 * 8($TW)
+___
+    }
+
+    {
+    $code .= <<___;
+    mov %rbp,$TW
+    pop %rbp
+    vzeroupper
+    ret
+
+    .L_less_than_128_bytes_${rndsuffix}:
+    vpbroadcastq	$gf_poly_8b, $ZPOLY
+    cmp 	 \$0x10,$length
+    jb 	 .L_ret_${rndsuffix}
+    vbroadcasti32x4	($TW), %zmm0
+    vbroadcasti32x4	shufb_15_7(%rip), %zmm8
+    movl    \$0xaa, %r8d
+    kmovq	%r8, %k2
+    mov	$length,$tmp1
+    and	\$0x70,$tmp1
+    cmp	\$0x60,$tmp1
+    je	.L_num_blocks_is_6_${rndsuffix}
+    cmp	\$0x50,$tmp1
+    je	.L_num_blocks_is_5_${rndsuffix}
+    cmp	\$0x40,$tmp1
+    je	.L_num_blocks_is_4_${rndsuffix}
+    cmp	\$0x30,$tmp1
+    je	.L_num_blocks_is_3_${rndsuffix}
+    cmp	\$0x20,$tmp1
+    je	.L_num_blocks_is_2_${rndsuffix}
+    cmp	\$0x10,$tmp1
+    je	.L_num_blocks_is_1_${rndsuffix}
+
+    .L_num_blocks_is_7_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+    vpsllvq	const_dq7654(%rip), %zmm0, %zmm5
+    vpsrlvq	const_dq1234(%rip), %zmm1, %zmm6
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm6, %zmm7
+    vpxorq	%zmm6, %zmm5, %zmm5{%k2}
+    vpxord	%zmm5, %zmm7, %zmm10
+    mov	\$0x0000ffffffffffff, $tmp1
+    kmovq	$tmp1, %k1
+    vmovdqu8	16*0($input), %zmm1
+    vmovdqu8	16*4($input), %zmm2{%k1}
+
+    add	\$0x70,$input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, 16*0($output)
+    vmovdqu8	%zmm2, 16*4($output){%k1}
+    add	\$0x70,$output
+    vextracti32x4	\$0x2, %zmm2, %xmm8
+    vextracti32x4	\$0x3, %zmm10, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_6_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+    vpsllvq	const_dq7654(%rip), %zmm0, %zmm5
+    vpsrlvq	const_dq1234(%rip), %zmm1, %zmm6
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm6, %zmm7
+    vpxorq	%zmm6, %zmm5, %zmm5{%k2}
+    vpxord	%zmm5, %zmm7, %zmm10
+    vmovdqu8	16*0($input), %zmm1
+    vmovdqu8	16*4($input), %ymm2
+    add	\$96, $input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, 16*0($output)
+    vmovdqu8	%ymm2, 16*4($output)
+    add	\$96, $output
+
+    vextracti32x4	\$0x1, %ymm2, %xmm8
+    vextracti32x4	\$0x2, %zmm10, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_5_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+    vpsllvq	const_dq7654(%rip), %zmm0, %zmm5
+    vpsrlvq	const_dq1234(%rip), %zmm1, %zmm6
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm6, %zmm7
+    vpxorq	%zmm6, %zmm5, %zmm5{%k2}
+    vpxord	%zmm5, %zmm7, %zmm10
+    vmovdqu8	16*0($input), %zmm1
+    vmovdqu8	16*4($input), %xmm2
+    add	\$80, $input
+___
+    }
+
+    encrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, 16*0($output)
+    vmovdqu8	%xmm2, 16*4($output)
+    add	\$80, $output
+
+    vmovdqa	%xmm2, %xmm8
+    vextracti32x4	\$0x1, %zmm10, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_4_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+    vpsllvq	const_dq7654(%rip), %zmm0, %zmm5
+    vpsrlvq	const_dq1234(%rip), %zmm1, %zmm6
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm6, %zmm7
+    vpxorq	%zmm6, %zmm5, %zmm5{%k2}
+    vpxord	%zmm5, %zmm7, %zmm10
+    vmovdqu8	16*0($input), %zmm1
+    add	\$64, $input
+___
+    }
+
+    encrypt_by_four("%zmm1", "%zmm9", "%zmm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, 16*0($output)
+    add	\$64, $output
+    vextracti32x4	\$0x3, %zmm1, %xmm8
+    vmovdqa	%xmm10, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_3_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+    mov	\$0x0000ffffffffffff, $tmp1
+    kmovq	$tmp1, %k1
+    vmovdqu8	16*0($input), %zmm1{%k1}
+    add	\$48, $input
+___
+    }
+
+    encrypt_by_four("%zmm1", "%zmm9", "%zmm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%zmm1, 16*0($output){%k1}
+    add	\$48, $output
+    vextracti32x4	\$2, %zmm1, %xmm8
+    vextracti32x4	\$3, %zmm9, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_2_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+
+    vmovdqu8	16*0($input), %ymm1
+    add	\$32, $input
+___
+    }
+
+    encrypt_by_four("%ymm1", "%ymm9", "%ymm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%ymm1, 16*0($output)
+    add	\$32, $output
+
+    vextracti32x4	\$1, %ymm1, %xmm8
+    vextracti32x4	\$2, %zmm9, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_num_blocks_is_1_${rndsuffix}:
+    vpshufb	%zmm8, %zmm0, %zmm1
+    vpsllvq	const_dq3210(%rip), %zmm0, %zmm4
+    vpsrlvq	const_dq5678(%rip), %zmm1, %zmm2
+    vpclmulqdq	\$0x00, $ZPOLY, %zmm2, %zmm3
+    vpxorq	%zmm2, %zmm4, %zmm4{%k2}
+    vpxord	%zmm4, %zmm3, %zmm9
+
+    vmovdqu8	16*0($input), %xmm1
+    add	\$16, $input
+___
+    }
+
+    encrypt_by_four("%ymm1", "%ymm9", "%ymm0", $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8	%xmm1, 16*0($output)
+    add	\$16, $output
+
+    vmovdqa	%xmm1, %xmm8
+    vextracti32x4	\$1, %zmm9, %xmm0
+    and	\$0xf,$length
+    je	.L_ret_${rndsuffix}
+    jmp	.L_steal_cipher_${rndsuffix}
+    .cfi_endproc
+___
+    }
+  }
+
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  # ;void aesni_xts_[128|256]_decrypt_avx512(
+  # ;               const uint8_t *in,        // input data
+  # ;               uint8_t *out,             // output data
+  # ;               size_t length,            // sector size, in bytes
+  # ;               const AES_KEY *key1,      // key used for "ECB" encryption, 16*2 bytes
+  # ;               const AES_KEY *key2,      // key used for tweaking, 16*2 bytes
+  # ;               const uint8_t iv[16])      // initial tweak value, 16 bytes
+  # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+  sub dec {
+    my $is_128 = $_[0];
+    my $rndsuffix = &random_string();
+
+    if ($is_128) {
+      $code.=<<___;
+      .globl	aesni_xts_128_decrypt_avx512
+      .hidden	aesni_xts_128_decrypt_avx512
+      .type	aesni_xts_128_decrypt_avx512,\@function,6
+      .align	32
+      aesni_xts_128_decrypt_avx512:
+      .cfi_startproc
+      endbranch
+___
+    } else {
+      $code.=<<___;
+      .globl	aesni_xts_256_decrypt_avx512
+      .hidden	aesni_xts_256_decrypt_avx512
+      .type	aesni_xts_256_decrypt_avx512,\@function,6
+      .align	32
+      aesni_xts_256_decrypt_avx512:
+      .cfi_startproc
+      endbranch
+___
+    }
+    $code .= "push 	 %rbp\n";
+    $code .= "mov 	 $TW,%rbp\n";
+    $code .= "sub 	 \$$VARIABLE_OFFSET,$TW\n";
+    $code .= "and 	 \$0xffffffffffffffc0,$TW\n";
+    $code .= "mov 	 %rbx,$GP_STORAGE($TW)\n";
+
+    if ($win64) {
+      $code .= "mov 	 %rdi,$GP_STORAGE + 8*1($TW)\n";
+      $code .= "mov 	 %rsi,$GP_STORAGE + 8*2($TW)\n";
+      $code .= "vmovdqa      %xmm6, $XMM_STORAGE + 16*0($TW)\n";
+      $code .= "vmovdqa      %xmm7, $XMM_STORAGE + 16*1($TW)\n";
+      $code .= "vmovdqa      %xmm8, $XMM_STORAGE + 16*2($TW)\n";
+      $code .= "vmovdqa      %xmm9, $XMM_STORAGE + 16*3($TW)\n";
+      $code .= "vmovdqa      %xmm10, $XMM_STORAGE + 16*4($TW)\n";
+      $code .= "vmovdqa      %xmm11, $XMM_STORAGE + 16*5($TW)\n";
+      $code .= "vmovdqa      %xmm12, $XMM_STORAGE + 16*6($TW)\n";
+      $code .= "vmovdqa      %xmm13, $XMM_STORAGE + 16*7($TW)\n";
+      $code .= "vmovdqa      %xmm14, $XMM_STORAGE + 16*8($TW)\n";
+      $code .= "vmovdqa      %xmm15, $XMM_STORAGE + 16*9($TW)\n";
+    }
+
+    $code .= "mov 	 \$0x87, $gf_poly_8b\n";
+    $code .= "vmovdqu 	 ($tweak),%xmm1\n";      # read initial tweak values
+
+    encrypt_tweak("%xmm1", $is_128);
+
+    if ($win64) {
+      $code .= "mov	 $input, 8 + 8*5(%rbp)\n"; # ciphertext pointer
+      $code .= "mov        $output, 8 + 8*6(%rbp)\n"; # plaintext pointer
+    }
+
+    {
+    $code.=<<___;
+
+    cmp 	 \$0x80,$length
+    jb 	 .L_less_than_128_bytes_${rndsuffix}
+    vpbroadcastq 	 $gf_poly_8b,$ZPOLY
+    cmp 	 \$0x100,$length
+    jge 	 .L_start_by16_${rndsuffix}
+    jmp 	 .L_start_by8_${rndsuffix}
+
+    .L_do_n_blocks_${rndsuffix}:
+    cmp 	 \$0x0,$length
+    je 	 .L_ret_${rndsuffix}
+    cmp 	 \$0x70,$length
+    jge 	 .L_remaining_num_blocks_is_7_${rndsuffix}
+    cmp 	 \$0x60,$length
+    jge 	 .L_remaining_num_blocks_is_6_${rndsuffix}
+    cmp 	 \$0x50,$length
+    jge 	 .L_remaining_num_blocks_is_5_${rndsuffix}
+    cmp 	 \$0x40,$length
+    jge 	 .L_remaining_num_blocks_is_4_${rndsuffix}
+    cmp 	 \$0x30,$length
+    jge 	 .L_remaining_num_blocks_is_3_${rndsuffix}
+    cmp 	 \$0x20,$length
+    jge 	 .L_remaining_num_blocks_is_2_${rndsuffix}
+    cmp 	 \$0x10,$length
+    jge 	 .L_remaining_num_blocks_is_1_${rndsuffix}
+
+    # _remaining_num_blocks_is_0:
+    vmovdqu		%xmm5, %xmm1
+    # xmm5 contains last full block to decrypt with next teawk
+___
+    }
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 1, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu %xmm1, -0x10($output)
+    vmovdqa %xmm1, %xmm8
+
+    # Calc previous tweak
+    mov		\$0x1,$tmp1
+    kmovq		$tmp1, %k1
+    vpsllq	\$0x3f,%xmm9,%xmm13
+    vpsraq	\$0x3f,%xmm13,%xmm14
+    vpandq	%xmm25,%xmm14,%xmm5
+    vpxorq        %xmm5,%xmm9,%xmm9{%k1}
+    vpsrldq       \$0x8,%xmm9,%xmm10
+    .byte 98, 211, 181, 8, 115, 194, 1 #vpshrdq \$0x1,%xmm10,%xmm9,%xmm0
+    vpslldq       \$0x8,%xmm13,%xmm13
+    vpxorq        %xmm13,%xmm0,%xmm0
+    jmp           .L_steal_cipher_${rndsuffix}
+
+    .L_remaining_num_blocks_is_7_${rndsuffix}:
+    mov 	 \$0xffffffffffffffff,$tmp1
+    shr 	 \$0x10,$tmp1
+    kmovq 	 $tmp1,%k1
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2{%k1}
+    add 	         \$0x70,$input
+    and            \$0xf,$length
+    je             .L_done_7_remain_${rndsuffix}
+    vextracti32x4   \$0x2,%zmm10,%xmm12
+    vextracti32x4   \$0x3,%zmm10,%xmm13
+    vinserti32x4    \$0x2,%xmm13,%zmm10,%zmm10
+___
+    }
+
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1, ($output)
+    vmovdqu8 	 %zmm2, 0x40($output){%k1}
+    add 	         \$0x70, $output
+    vextracti32x4  \$0x2,%zmm2,%xmm8
+    vmovdqa        %xmm12,%xmm0
+    jmp            .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_7_remain_${rndsuffix}:\n";
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8        %zmm1, ($output)
+    vmovdqu8        %zmm2, 0x40($output){%k1}
+    jmp     .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_6_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%ymm2
+    add 	         \$0x60,$input
+    and            \$0xf, $length
+    je             .L_done_6_remain_${rndsuffix}
+    vextracti32x4   \$0x1,%zmm10,%xmm12
+    vextracti32x4   \$0x2,%zmm10,%xmm13
+    vinserti32x4    \$0x1,%xmm13,%zmm10,%zmm10
+___
+    }
+
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1, ($output)
+    vmovdqu8 	 %ymm2, 0x40($output)
+    add 	         \$0x60,$output
+    vextracti32x4  \$0x1,%zmm2,%xmm8
+    vmovdqa        %xmm12,%xmm0
+    jmp            .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_6_remain_${rndsuffix}:\n";
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8        %zmm1, ($output)
+    vmovdqu8        %ymm2,0x40($output)
+    jmp             .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_5_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu 	 0x40($input),%xmm2
+    add 	         \$0x50,$input
+    and            \$0xf,$length
+    je             .L_done_5_remain_${rndsuffix}
+    vmovdqa        %xmm10,%xmm12
+    vextracti32x4  \$0x1,%zmm10,%xmm10
+___
+    }
+
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8         %zmm1, ($output)
+    vmovdqu          %xmm2, 0x40($output)
+    add              \$0x50, $output
+    vmovdqa          %xmm2,%xmm8
+    vmovdqa          %xmm12,%xmm0
+    jmp              .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_5_remain_${rndsuffix}:\n";
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8        %zmm1, ($output)
+    vmovdqu8        %xmm2, 0x40($output)
+    jmp             .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_4_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    add 	         \$0x40,$input
+    and            \$0xf, $length
+    je             .L_done_4_remain_${rndsuffix}
+    vextracti32x4   \$0x3,%zmm9,%xmm12
+    vinserti32x4    \$0x3,%xmm10,%zmm9,%zmm9
+___
+    }
+
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8        %zmm1,($output)
+    add             \$0x40,$output
+    vextracti32x4   \$0x3,%zmm1,%xmm8
+    vmovdqa         %xmm12,%xmm0
+    jmp             .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_4_remain_${rndsuffix}:\n";
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8        %zmm1, ($output)
+    jmp             .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_3_${rndsuffix}:
+    vmovdqu         ($input),%xmm1
+    vmovdqu         0x10($input),%xmm2
+    vmovdqu         0x20($input),%xmm3
+    add             \$0x30,$input
+    and             \$0xf,$length
+    je              .L_done_3_remain_${rndsuffix}
+    vextracti32x4   \$0x2,%zmm9,%xmm13
+    vextracti32x4   \$0x1,%zmm9,%xmm10
+    vextracti32x4   \$0x3,%zmm9,%xmm11
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 3, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    add 	         \$0x30,$output
+    vmovdqa 	 %xmm3,%xmm8
+    vmovdqa        %xmm13,%xmm0
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+    $code .= "\n.L_done_3_remain_${rndsuffix}:\n";
+    $code .= "vextracti32x4   \$0x1,%zmm9,%xmm10\n";
+    $code .= "vextracti32x4   \$0x2,%zmm9,%xmm11\n";
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 3, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu %xmm1,($output)
+    vmovdqu %xmm2,0x10($output)
+    vmovdqu %xmm3,0x20($output)
+    jmp     .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_2_${rndsuffix}:
+    vmovdqu         ($input),%xmm1
+    vmovdqu         0x10($input),%xmm2
+    add             \$0x20,$input
+    and             \$0xf,$length
+    je              .L_done_2_remain_${rndsuffix}
+    vextracti32x4   \$0x2,%zmm9,%xmm10
+    vextracti32x4   \$0x1,%zmm9,%xmm12
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 2, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    add 	         \$0x20,$output
+    vmovdqa 	 %xmm2,%xmm8
+    vmovdqa 	 %xmm12,%xmm0
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+    $code .= "\n.L_done_2_remain_${rndsuffix}:\n";
+    $code .= "vextracti32x4   \$0x1,%zmm9,%xmm10\n";
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 2, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu   %xmm1,($output)
+    vmovdqu   %xmm2,0x10($output)
+    jmp       .L_ret_${rndsuffix}
+
+    .L_remaining_num_blocks_is_1_${rndsuffix}:
+    vmovdqu 	 ($input),%xmm1
+    add 	         \$0x10,$input
+    and            \$0xf,$length
+    je             .L_done_1_remain_${rndsuffix}
+    vextracti32x4  \$0x1,%zmm9,%xmm11
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm11", "%xmm10", "%xmm9", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 1, 1, $is_128);
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    add 	         \$0x10,$output
+    vmovdqa 	 %xmm1,%xmm8
+    vmovdqa 	 %xmm9,%xmm0
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_1_remain_${rndsuffix}:\n";
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 1, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu   %xmm1, ($output)
+    jmp       .L_ret_${rndsuffix}
+
+    .L_start_by16_${rndsuffix}:
+    vbroadcasti32x4 	 ($TW),%zmm0
+    vbroadcasti32x4 shufb_15_7(%rip),%zmm8
+    mov 	 \$0xaa,$tmp1
+    kmovq 	 $tmp1,%k2
+
+    # Mult tweak by 2^{3, 2, 1, 0}
+    vpshufb 	 %zmm8,%zmm0,%zmm1
+    vpsllvq const_dq3210(%rip),%zmm0,%zmm4
+    vpsrlvq const_dq5678(%rip),%zmm1,%zmm2
+    vpclmulqdq 	 \$0x0,$ZPOLY,%zmm2,%zmm3
+    vpxorq 	 %zmm2,%zmm4,%zmm4{%k2}
+    vpxord 	 %zmm4,%zmm3,%zmm9
+
+    # Mult tweak by 2^{7, 6, 5, 4}
+    vpsllvq const_dq7654(%rip),%zmm0,%zmm5
+    vpsrlvq const_dq1234(%rip),%zmm1,%zmm6
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm6,%zmm7
+    vpxorq 	 %zmm6,%zmm5,%zmm5{%k2}
+    vpxord 	 %zmm5,%zmm7,%zmm10
+
+    # Make next 8 tweek values by all x 2^8
+    vpsrldq 	 \$0xf,%zmm9,%zmm13
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm13,%zmm14
+    vpslldq 	 \$0x1,%zmm9,%zmm11
+    vpxord 	 %zmm14,%zmm11,%zmm11
+
+    vpsrldq 	 \$0xf,%zmm10,%zmm15
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm15,%zmm16
+    vpslldq 	 \$0x1,%zmm10,%zmm12
+    vpxord 	 %zmm16,%zmm12,%zmm12
+
+    .L_main_loop_run_16_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2
+    vmovdqu8 	 0x80($input),%zmm3
+    vmovdqu8 	 0xc0($input),%zmm4
+    vmovdqu8 	 0xf0($input),%xmm5
+    add 	 \$0x100,$input
+___
+    }
+
+    decrypt_by_16_zmm("%zmm1", "%zmm2", "%zmm3", "%zmm4", "%zmm9",
+                      "%zmm10", "%zmm11", "%zmm12", "%zmm0", 0, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %zmm2,0x40($output)
+    vmovdqu8 	 %zmm3,0x80($output)
+    vmovdqu8 	 %zmm4,0xc0($output)
+    add 	 \$0x100,$output
+    sub 	 \$0x100,$length
+    cmp 	 \$0x100,$length
+    jge 	 .L_main_loop_run_16_${rndsuffix}
+
+    cmp 	 \$0x80,$length
+    jge 	 .L_main_loop_run_8_${rndsuffix}
+    jmp 	 .L_do_n_blocks_${rndsuffix}
+
+    .L_start_by8_${rndsuffix}:
+    # Make first 7 tweek values
+    vbroadcasti32x4 	 ($TW),%zmm0
+    vbroadcasti32x4 shufb_15_7(%rip),%zmm8
+    mov 	 \$0xaa,$tmp1
+    kmovq 	 $tmp1,%k2
+
+    # Mult tweak by 2^{3, 2, 1, 0}
+    vpshufb 	 %zmm8,%zmm0,%zmm1
+    vpsllvq const_dq3210(%rip),%zmm0,%zmm4
+    vpsrlvq const_dq5678(%rip),%zmm1,%zmm2
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm2,%zmm3
+    vpxorq 	 %zmm2,%zmm4,%zmm4{%k2}
+    vpxord 	 %zmm4,%zmm3,%zmm9
+
+    # Mult tweak by 2^{7, 6, 5, 4}
+    vpsllvq const_dq7654(%rip),%zmm0,%zmm5
+    vpsrlvq const_dq1234(%rip),%zmm1,%zmm6
+    vpclmulqdq 	 \$0x0,%zmm25,%zmm6,%zmm7
+    vpxorq 	 %zmm6,%zmm5,%zmm5{%k2}
+    vpxord 	 %zmm5,%zmm7,%zmm10
+
+    .L_main_loop_run_8_${rndsuffix}:
+    vmovdqu8 	 ($input),%zmm1
+    vmovdqu8 	 0x40($input),%zmm2
+    vmovdqu8 	 0x70($input),%xmm5
+    add 	         \$0x80,$input
+___
+    }
+
+
+    decrypt_by_eight_zmm("%zmm1", "%zmm2", "%zmm9", "%zmm10", "%zmm0", 0, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu8 	 %zmm1,($output)
+    vmovdqu8 	 %zmm2,0x40($output)
+    add 	 \$0x80,$output
+    sub 	 \$0x80,$length
+    cmp 	 \$0x80,$length
+    jge 	 .L_main_loop_run_8_${rndsuffix}
+    jmp 	 .L_do_n_blocks_${rndsuffix}
+
+    .L_steal_cipher_${rndsuffix}:
+    # start cipher stealing simplified: xmm8-last cipher block, xmm0-next tweak
+    vmovdqa 	 %xmm8,%xmm2
+
+    # shift xmm8 to the left by 16-N_val bytes
+    lea vpshufb_shf_table(%rip),$TEMPLOW
+    vmovdqu 	 ($TEMPLOW,$length,1),%xmm10
+    vpshufb 	 %xmm10,%xmm8,%xmm8
+
+
+    vmovdqu 	 -0x10($input,$length,1),%xmm3
+    vmovdqu 	 %xmm8,-0x10($output,$length,1)
+
+    # shift xmm3 to the right by 16-N_val bytes
+    lea vpshufb_shf_table(%rip), $TEMPLOW
+    add \$16, $TEMPLOW
+    sub 	 $length,$TEMPLOW
+    vmovdqu 	 ($TEMPLOW),%xmm10
+    vpxor mask1(%rip),%xmm10,%xmm10
+    vpshufb 	 %xmm10,%xmm3,%xmm3
+
+    vpblendvb 	 %xmm10,%xmm2,%xmm3,%xmm3
+
+    # xor Tweak value
+    vpxor 	 %xmm0,%xmm3,%xmm8
+
+    # decrypt last block with cipher stealing
+    vpxor	($key1),%xmm8,%xmm8
+    vaesdec	0x10($key1),%xmm8,%xmm8
+    vaesdec	0x20($key1),%xmm8,%xmm8
+    vaesdec	0x30($key1),%xmm8,%xmm8
+    vaesdec	0x40($key1),%xmm8,%xmm8
+    vaesdec	0x50($key1),%xmm8,%xmm8
+    vaesdec	0x60($key1),%xmm8,%xmm8
+    vaesdec	0x70($key1),%xmm8,%xmm8
+    vaesdec	0x80($key1),%xmm8,%xmm8
+    vaesdec	0x90($key1),%xmm8,%xmm8
+___
+    if ($is_128) {
+      $code .= "vaesdeclast	0xa0($key1),%xmm8,%xmm8\n";
+    } else {
+      $code .= <<___;
+      vaesdec	0xa0($key1),%xmm8,%xmm8
+      vaesdec	0xb0($key1),%xmm8,%xmm8
+      vaesdec	0xc0($key1),%xmm8,%xmm8
+      vaesdec	0xd0($key1),%xmm8,%xmm8
+      vaesdeclast	0xe0($key1),%xmm8,%xmm8
+___
+    }
+    $code .= <<___
+    # xor Tweak value
+    vpxor 	 %xmm0,%xmm8,%xmm8
+
+    .L_done_${rndsuffix}:
+    # store last ciphertext value
+    vmovdqu 	 %xmm8,-0x10($output)
+___
+    }
+
+    {
+    $code .= <<___;
+    .L_ret_${rndsuffix}:
+    mov 	 $GP_STORAGE($TW),%rbx
+    xor    $tmp1,$tmp1
+    mov    $tmp1,$GP_STORAGE($TW)
+    # Zero-out the whole of `%zmm0`.
+    vpxorq %zmm0,%zmm0,%zmm0
+___
+    }
+
+    if ($win64) {
+      $code .= <<___;
+      mov $GP_STORAGE + 8*1($TW),%rdi
+      mov $tmp1,$GP_STORAGE + 8*1($TW)
+      mov $GP_STORAGE + 8*2($TW),%rsi
+      mov $tmp1,$GP_STORAGE + 8*2($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 0($TW), %xmm6
+      vmovdqa $XMM_STORAGE + 16 * 1($TW), %xmm7
+      vmovdqa $XMM_STORAGE + 16 * 2($TW), %xmm8
+      vmovdqa $XMM_STORAGE + 16 * 3($TW), %xmm9
+
+      # Zero the 64 bytes we just restored to the xmm registers.
+      vmovdqa64 %zmm0,$XMM_STORAGE($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 4($TW), %xmm10
+      vmovdqa $XMM_STORAGE + 16 * 5($TW), %xmm11
+      vmovdqa $XMM_STORAGE + 16 * 6($TW), %xmm12
+      vmovdqa $XMM_STORAGE + 16 * 7($TW), %xmm13
+
+      # And again.
+      vmovdqa64 %zmm0,$XMM_STORAGE + 16 * 4($TW)
+
+      vmovdqa $XMM_STORAGE + 16 * 8($TW), %xmm14
+      vmovdqa $XMM_STORAGE + 16 * 9($TW), %xmm15
+
+      # Last round is only 32 bytes (256-bits), so we use `%ymm` as the
+      # source operand.
+      vmovdqa %ymm0,$XMM_STORAGE + 16 * 8($TW)
+___
+    }
+
+    {
+    $code .= <<___;
+    mov %rbp,$TW
+    pop %rbp
+    vzeroupper
+    ret
+
+    .L_less_than_128_bytes_${rndsuffix}:
+    cmp 	 \$0x10,$length
+    jb 	 .L_ret_${rndsuffix}
+
+    mov 	 $length,$tmp1
+    and 	 \$0x70,$tmp1
+    cmp 	 \$0x60,$tmp1
+    je 	 .L_num_blocks_is_6_${rndsuffix}
+    cmp 	 \$0x50,$tmp1
+    je 	 .L_num_blocks_is_5_${rndsuffix}
+    cmp 	 \$0x40,$tmp1
+    je 	 .L_num_blocks_is_4_${rndsuffix}
+    cmp 	 \$0x30,$tmp1
+    je 	 .L_num_blocks_is_3_${rndsuffix}
+    cmp 	 \$0x20,$tmp1
+    je 	 .L_num_blocks_is_2_${rndsuffix}
+    cmp 	 \$0x10,$tmp1
+    je 	 .L_num_blocks_is_1_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_7_${rndsuffix}:\n";
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 7);
+
+    {
+    $code .= <<___;
+    add    \$0x70,$input
+    and    \$0xf,$length
+    je      .L_done_7_${rndsuffix}
+
+    .L_steal_cipher_7_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm15,%xmm16
+     vmovdqa     0x10($TW),%xmm15
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 7, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    vmovdqu 	 %xmm5,0x40($output)
+    vmovdqu 	 %xmm6,0x50($output)
+    add 	         \$0x70,$output
+    vmovdqa64 	 %xmm16,%xmm0
+    vmovdqa 	 %xmm7,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_7_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 7, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    vmovdqu 	 %xmm5,0x40($output)
+    vmovdqu 	 %xmm6,0x50($output)
+    add 	         \$0x70,$output
+    vmovdqa 	 %xmm7,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_6_${rndsuffix}:\n";
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 6);
+
+    {
+    $code .= <<___;
+    add    \$0x60,$input
+    and    \$0xf,$length
+    je      .L_done_6_${rndsuffix}
+
+    .L_steal_cipher_6_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm14,%xmm15
+     vmovdqa     0x10($TW),%xmm14
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 6, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    vmovdqu 	 %xmm5,0x40($output)
+    add 	         \$0x60,$output
+    vmovdqa 	 %xmm15,%xmm0
+    vmovdqa 	 %xmm6,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+    $code .= "\n.L_done_6_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 6, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    vmovdqu 	 %xmm5,0x40($output)
+    add 	         \$0x60,$output
+    vmovdqa 	 %xmm6,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_5_${rndsuffix}:\n";
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 5);
+
+    {
+    $code .= <<___;
+    add    \$0x50,$input
+    and    \$0xf,$length
+    je      .L_done_5_${rndsuffix}
+
+    .L_steal_cipher_5_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm13,%xmm14
+     vmovdqa     0x10($TW),%xmm13
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 5, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    add 	         \$0x50,$output
+    vmovdqa 	 %xmm14,%xmm0
+    vmovdqa 	 %xmm5,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_5_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 5, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    vmovdqu 	 %xmm4,0x30($output)
+    add 	         \$0x50,$output
+    vmovdqa 	 %xmm5,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_4_${rndsuffix}:\n";
+
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 4);
+
+    {
+    $code .= <<___;
+    add    \$0x40,$input
+    and    \$0xf,$length
+    je      .L_done_4_${rndsuffix}
+
+    .L_steal_cipher_4_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm12,%xmm13
+     vmovdqa     0x10($TW),%xmm12
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 4, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    add 	         \$0x40,$output
+    vmovdqa 	 %xmm13,%xmm0
+    vmovdqa 	 %xmm4,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_4_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 4, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    vmovdqu 	 %xmm3,0x20($output)
+    add 	         \$0x40,$output
+    vmovdqa 	 %xmm4,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_3_${rndsuffix}:\n";
+
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 3);
+
+    {
+    $code .= <<___;
+    add    \$0x30,$input
+    and    \$0xf,$length
+    je      .L_done_3_${rndsuffix}
+
+    .L_steal_cipher_3_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm11,%xmm12
+     vmovdqa     0x10($TW),%xmm11
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 3, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    add 	         \$0x30,$output
+    vmovdqa 	 %xmm12,%xmm0
+    vmovdqa 	 %xmm3,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+    $code .= "\n.L_done_3_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 3, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    vmovdqu 	 %xmm2,0x10($output)
+    add 	         \$0x30,$output
+    vmovdqa 	 %xmm3,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_2_${rndsuffix}:\n";
+
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 2);
+
+    {
+    $code .= <<___;
+    add    \$0x20,$input
+    and    \$0xf,$length
+    je      .L_done_2_${rndsuffix}
+
+    .L_steal_cipher_2_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm10,%xmm11
+     vmovdqa     0x10($TW),%xmm10
+___
+    }
+
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 2, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    add 	         \$0x20,$output
+    vmovdqa 	 %xmm11,%xmm0
+    vmovdqa 	 %xmm2,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_done_2_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 2, 1, $is_128);
+
+    {
+    $code .= <<___;
+    vmovdqu 	 %xmm1,($output)
+    add 	         \$0x20,$output
+    vmovdqa 	 %xmm2,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+___
+    }
+
+    $code .= "\n.L_num_blocks_is_1_${rndsuffix}:\n";
+
+    initialize("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+               "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+               "%xmm13", "%xmm14", "%xmm15", 1);
+
+    {
+    $code .= <<___;
+    add    \$0x10,$input
+    and    \$0xf,$length
+    je      .L_done_1_${rndsuffix}
+
+    .L_steal_cipher_1_${rndsuffix}:
+     xor         $gf_poly_8b_temp, $gf_poly_8b_temp
+     shl         \$1, $TEMPLOW
+     adc         $TEMPHIGH, $TEMPHIGH
+     cmovc       $gf_poly_8b, $gf_poly_8b_temp
+     xor         $gf_poly_8b_temp, $TEMPLOW
+     mov         $TEMPLOW,0x10($TW)
+     mov         $TEMPHIGH,0x18($TW)
+     vmovdqa64   %xmm9,%xmm10
+     vmovdqa     0x10($TW),%xmm9
+___
+    }
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 1, 1, $is_128);
+
+    {
+    $code .= <<___;
+    add 	         \$0x10,$output
+    vmovdqa 	 %xmm10,%xmm0
+    vmovdqa 	 %xmm1,%xmm8
+    jmp 	         .L_steal_cipher_${rndsuffix}
+___
+    }
+    $code .= "\n.L_done_1_${rndsuffix}:\n";
+    decrypt_initial("%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+                    "%xmm7", "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12",
+                    "%xmm13", "%xmm14", "%xmm15", "%xmm0", 1, 1, $is_128);
+
+    {
+    $code .= <<___;
+    add 	         \$0x10,$output
+    vmovdqa 	 %xmm1,%xmm8
+    jmp 	         .L_done_${rndsuffix}
+    .cfi_endproc
+___
+    }
+
+  }
+
+  # The only difference between AES-XTS-128 and -256 is the number of rounds,
+  # so we generate from the same perlasm base, extending to 14 rounds when
+  # `$is_128' is 0.
+
+  enc(1);
+  dec(1);
+
+  enc(0);
+  dec(0);
+
+  $code .= <<___;
+  .section .rodata
+  .align 16
+
+  vpshufb_shf_table:
+    .quad 0x8786858483828100, 0x8f8e8d8c8b8a8988
+    .quad 0x0706050403020100, 0x000e0d0c0b0a0908
+
+  mask1:
+    .quad 0x8080808080808080, 0x8080808080808080
+
+  const_dq3210:
+    .quad 0, 0, 1, 1, 2, 2, 3, 3
+  const_dq5678:
+    .quad 8, 8, 7, 7, 6, 6, 5, 5
+  const_dq7654:
+    .quad 4, 4, 5, 5, 6, 6, 7, 7
+  const_dq1234:
+    .quad 4, 4, 3, 3, 2, 2, 1, 1
+
+  shufb_15_7:
+    .byte  15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7, 0xff, 0xff
+    .byte  0xff, 0xff, 0xff, 0xff, 0xff
+
+.text
+___
+
+} else {
+    $code .= <<___;
+    .text
+    .globl  aesni_xts_128_encrypt_avx512
+    .globl  aesni_xts_128_decrypt_avx512
+
+    aesni_xts_128_encrypt_avx512:
+    aesni_xts_128_decrypt_avx512:
+    .byte   0x0f,0x0b    # ud2
+    ret
+
+    .globl  aesni_xts_256_encrypt_avx512
+    .globl  aesni_xts_256_decrypt_avx512
+
+    aesni_xts_256_encrypt_avx512:
+    aesni_xts_256_decrypt_avx512:
+    .byte   0x0f,0x0b    # ud2
+    ret
+
+    .globl  aesni_xts_avx512_eligible
+    .type   aesni_xts_avx512_eligible,\@abi-omnipotent
+    aesni_xts_avx512_eligible:
+    xor	%eax,%eax
+    ret
+    .size   aesni_xts_avx512_eligible, .-aesni_xts_avx512_eligible
+
+___
+}
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";

+ 16 - 0
libs/openssl/crypto/aes/asm/aesv8-armx.pl

@@ -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
@@ -139,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 !~ /64/);
 	adr	$ptr,.Lrcon
+___
+$code.=<<___;
 	cmp	$bits,#192
 
 	veor	$zero,$zero,$zero

+ 18 - 10
libs/openssl/crypto/aes/asm/bsaes-armv8.pl

@@ -1,5 +1,5 @@
 #!/usr/bin/env perl
-# 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
@@ -32,7 +32,7 @@ sub data
 }
 
 __END__
-// Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
+// Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved.
 //
 // Licensed under the OpenSSL license (the "License").  You may not use
 // this file except in compliance with the License.  You can obtain a copy
@@ -78,7 +78,8 @@ __END__
 //   other SIMD registers corrupted
 _bsaes_decrypt8:
         ldr     q8, [x9], #16
-        adr     x11, .LM0ISR
+        adrp    x11, .LM0ISR
+        add     x11, x11, #:lo12:.LM0ISR
         movi    v9.16b, #0x55
         ldr     q10, [x11], #16
         movi    v16.16b, #0x33
@@ -494,9 +495,10 @@ _bsaes_decrypt8:
         ret
 .size   _bsaes_decrypt8,.-_bsaes_decrypt8
 
-.type   _bsaes_const,%object
+.rodata
+.type   _bsaes_consts,%object
 .align  6
-_bsaes_const:
+_bsaes_consts:
 // InvShiftRows constants
 // Used in _bsaes_decrypt8, which assumes contiguity
 // .LM0ISR used with round 0 key
@@ -532,7 +534,9 @@ _bsaes_const:
 .quad   0x090d01050c000408, 0x03070b0f060a0e02
 
 .align  6
-.size   _bsaes_const,.-_bsaes_const
+.size   _bsaes_consts,.-_bsaes_consts
+
+.previous
 
 .type   _bsaes_encrypt8,%function
 .align  4
@@ -548,7 +552,8 @@ _bsaes_const:
 //   other SIMD registers corrupted
 _bsaes_encrypt8:
         ldr     q8, [x9], #16
-        adr     x11, .LM0SR
+        adrp    x11, .LM0SR
+        add     x11, x11, #:lo12:.LM0SR
         ldr     q9, [x11], #16
 _bsaes_encrypt8_alt:
         eor     v0.16b, v0.16b, v8.16b
@@ -952,9 +957,11 @@ _bsaes_encrypt8_alt:
 //   other SIMD registers corrupted
 _bsaes_key_convert:
 #ifdef __AARCH64EL__
-        adr     x11, .LM0_littleendian
+        adrp    x11, .LM0_littleendian
+        add     x11, x11, #:lo12:.LM0_littleendian
 #else
-        adr     x11, .LM0_bigendian
+        adrp    x11, .LM0_bigendian
+        add     x11, x11, #:lo12:.LM0_bigendian
 #endif
         ldr     q0, [x9], #16               // load round 0 key
         ldr     q1, [x11]                   // .LM0
@@ -998,7 +1005,8 @@ _bsaes_key_convert:
         // don't save last round key
 #ifdef __AARCH64EL__
         rev32   v15.16b, v15.16b
-        adr     x11, .LM0_bigendian
+        adrp    x11, .LM0_bigendian
+        add     x11, x11, #:lo12:.LM0_bigendian
 #endif
         ret
 .size   _bsaes_key_convert,.-_bsaes_key_convert

+ 5 - 2
libs/openssl/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,

+ 37 - 18
libs/openssl/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
@@ -55,7 +55,7 @@ open OUT,"| \"$^X\" $xlate $flavour \"$output\""
 $code.=<<___;
 #include "arm_arch.h"
 
-.text
+.rodata
 
 .type	_vpaes_consts,%object
 .align	7	// totally strategic alignment
@@ -146,6 +146,9 @@ _vpaes_consts:
 .asciz  "Vector Permutation AES for ARMv8, Mike Hamburg (Stanford University)"
 .size	_vpaes_consts,.-_vpaes_consts
 .align	6
+
+.text
+
 ___
 
 {
@@ -165,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
@@ -193,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
@@ -280,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
@@ -383,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
@@ -407,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
@@ -518,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
@@ -657,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
@@ -688,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
 
@@ -814,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
 

+ 3 - 2
libs/openssl/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) {

+ 4 - 1
libs/openssl/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
@@ -145,6 +146,8 @@ 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

+ 1 - 0
libs/openssl/crypto/arm_arch.h

@@ -104,6 +104,7 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
 # 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

+ 9 - 5
libs/openssl/crypto/armcap.c

@@ -78,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 <sys/param.h>
-#  if __FreeBSD_version >= 1200000
+#  if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
+    (defined(__OpenBSD__) && OpenBSD >= 202409)
 #   include <sys/auxv.h>
 #   define OSSL_IMPLEMENT_GETAUXVAL
 
@@ -299,7 +300,8 @@ void OPENSSL_cpuid_setup(void)
             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 M3", 8) == 0) ||
+                (strncmp(uarch, "Apple M4", 8) == 0))) {
                 OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3;
                 OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING;
             }
@@ -419,11 +421,13 @@ void OPENSSL_cpuid_setup(void)
     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_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_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)     ||

+ 2 - 2
libs/openssl/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
@@ -75,7 +75,7 @@ void *ASN1_item_dup(const ASN1_ITEM *it, const void *x)
     }
 
     i = ASN1_item_i2d(x, &b, it);
-    if (b == NULL) {
+    if (i < 0 || b == NULL) {
         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
         return NULL;
     }

+ 2 - 2
libs/openssl/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
@@ -88,7 +88,7 @@ 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) {
+    if (n < 0 || b == NULL) {
         ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
         return 0;
     }

+ 14 - 8
libs/openssl/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);
@@ -345,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 {

+ 3 - 2
libs/openssl/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
@@ -198,7 +198,8 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
     }
     if (i <= 0) {
         i = BIO_write(bp, "<INVALID>", 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);

+ 2 - 3
libs/openssl/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++;

+ 0 - 75
libs/openssl/crypto/asn1/a_time.c

@@ -586,78 +586,3 @@ int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)
         return -1;
     return 0;
 }
-
-/*
- * tweak for Windows
- */
-#ifdef WIN32
-# define timezone _timezone
-#endif
-
-#if defined(__FreeBSD__) || defined(__wasi__)
-# define USE_TIMEGM
-#endif
-
-time_t ossl_asn1_string_to_time_t(const char *asn1_string)
-{
-    ASN1_TIME *timestamp_asn1 = NULL;
-    struct tm *timestamp_tm = NULL;
-#if defined(__DJGPP__)
-    char *tz = NULL;
-#elif !defined(USE_TIMEGM)
-    time_t timestamp_local;
-#endif
-    time_t timestamp_utc;
-
-    timestamp_asn1 = ASN1_TIME_new();
-    if (!ASN1_TIME_set_string(timestamp_asn1, asn1_string))
-    {
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
-
-    timestamp_tm = OPENSSL_malloc(sizeof(*timestamp_tm));
-    if (timestamp_tm == NULL) {
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
-    if (!(ASN1_TIME_to_tm(timestamp_asn1, timestamp_tm))) {
-        OPENSSL_free(timestamp_tm);
-        ASN1_TIME_free(timestamp_asn1);
-        return -1;
-    }
-    ASN1_TIME_free(timestamp_asn1);
-
-#if defined(__DJGPP__)
-    /*
-     * This is NOT thread-safe.  Do not use this method for platforms other
-     * than djgpp.
-     */
-    tz = getenv("TZ");
-    if (tz != NULL) {
-        tz = OPENSSL_strdup(tz);
-        if (tz == NULL) {
-            OPENSSL_free(timestamp_tm);
-            return -1;
-        }
-    }
-    setenv("TZ", "UTC", 1);
-
-    timestamp_utc = mktime(timestamp_tm);
-
-    if (tz != NULL) {
-        setenv("TZ", tz, 1);
-        OPENSSL_free(tz);
-    } else {
-        unsetenv("TZ");
-    }
-#elif defined(USE_TIMEGM)
-    timestamp_utc = timegm(timestamp_tm);
-#else
-    timestamp_local = mktime(timestamp_tm);
-    timestamp_utc = timestamp_local - timezone;
-#endif
-    OPENSSL_free(timestamp_tm);
-
-    return timestamp_utc;
-}

+ 2 - 1
libs/openssl/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 <openssl/pkcs12.h>
 #include <openssl/rsa.h>
 #include <openssl/x509v3.h>
+#include <openssl/x509_acert.h>
 
 #include "asn1_item_list.h"
 

+ 2 - 1
libs/openssl/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
@@ -150,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),

+ 12 - 1
libs/openssl/crypto/asn1/d2i_pr.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
@@ -21,6 +21,7 @@
 #include <openssl/asn1.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/x509.h"
 #include "internal/asn1.h"
 #include "internal/sizes.h"
 
@@ -51,6 +52,16 @@ d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
     p8info = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, len);
     ERR_pop_to_mark();
     if (p8info != NULL) {
+        int64_t v;
+
+        /* ascertain version is 0 or 1 as per RFC5958 */
+        if (!ASN1_INTEGER_get_int64(&v, p8info->version)
+            || (v != 0 && v != 1)) {
+            *pp = p;
+            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))

+ 3 - 6
libs/openssl/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;
             }

+ 2 - 4
libs/openssl/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;

+ 8 - 1
libs/openssl/crypto/asn1/p5_pbev2.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
@@ -35,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

+ 23 - 5
libs/openssl/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;
     }

+ 1 - 3
libs/openssl/crypto/asn1/standard_methods.h

@@ -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
@@ -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,
@@ -42,4 +41,3 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
     &ossl_sm2_asn1_meth,
 #endif
 };
-

Some files were not shown because too many files changed in this diff