1
0
Эх сурвалжийг харах

OpenSSL 3.3.1

Source commit: 96fe61bb0db2d2509837764686191422b7caa46a
Martin Prikryl 1 жил өмнө
parent
commit
c4c4ebb56d
100 өөрчлөгдсөн 6218 нэмэгдсэн , 721 устгасан
  1. 198 8
      libs/openssl/CHANGES.md
  2. 18 0
      libs/openssl/Configurations/10-main.conf
  3. 7 0
      libs/openssl/Configurations/15-android.conf
  4. 5 5
      libs/openssl/Configurations/15-ios.conf
  5. 14 8
      libs/openssl/Configurations/50-nonstop.conf
  6. 1 1
      libs/openssl/Configurations/descrip.mms.tmpl
  7. 20 2
      libs/openssl/Configurations/platform/AIX.pm
  8. 3 1
      libs/openssl/Configurations/platform/Unix.pm
  9. 61 74
      libs/openssl/Configurations/unix-Makefile.tmpl
  10. 9 0
      libs/openssl/Configurations/windows-makefile.tmpl
  11. 13 1
      libs/openssl/Configure
  12. 12 2
      libs/openssl/INSTALL.md
  13. 132 3
      libs/openssl/NEWS.md
  14. 2 2
      libs/openssl/NOTES-ANDROID.md
  15. 8 7
      libs/openssl/NOTES-NONSTOP.md
  16. 2 2
      libs/openssl/NOTES-WINDOWS.md
  17. 2 2
      libs/openssl/VERSION.dat
  18. 269 93
      libs/openssl/apps/cmp.c
  19. 4 3
      libs/openssl/apps/crl.c
  20. 2 1
      libs/openssl/apps/enc.c
  21. 5 2
      libs/openssl/apps/engine.c
  22. 10 2
      libs/openssl/apps/genpkey.c
  23. 5 1
      libs/openssl/apps/include/opt.h
  24. 1 16
      libs/openssl/apps/lib/apps.c
  25. 101 19
      libs/openssl/apps/lib/cmp_mock_srv.c
  26. 2 8
      libs/openssl/apps/lib/http_server.c
  27. 1 7
      libs/openssl/apps/lib/s_socket.c
  28. 1 7
      libs/openssl/apps/ocsp.c
  29. 86 7
      libs/openssl/apps/rand.c
  30. 2 2
      libs/openssl/apps/rehash.c
  31. 3 2
      libs/openssl/apps/req.c
  32. 30 14
      libs/openssl/apps/s_server.c
  33. 2 3
      libs/openssl/apps/s_time.c
  34. 120 58
      libs/openssl/apps/speed.c
  35. 20 6
      libs/openssl/apps/x509.c
  36. 25 0
      libs/openssl/build.info
  37. 0 3
      libs/openssl/crypto/aes/aes_x86core.c
  38. 710 0
      libs/openssl/crypto/aes/asm/aes-riscv64-zvbb-zvkg-zvkned.pl
  39. 376 0
      libs/openssl/crypto/aes/asm/aes-riscv64-zvkb-zvkned.pl
  40. 1376 0
      libs/openssl/crypto/aes/asm/aes-riscv64-zvkned.pl
  41. 1 1
      libs/openssl/crypto/aes/asm/aesp8-ppc.pl
  42. 765 3
      libs/openssl/crypto/aes/asm/aesv8-armx.pl
  43. 4 1
      libs/openssl/crypto/aes/build.info
  44. 5 1
      libs/openssl/crypto/arm_arch.h
  45. 8 2
      libs/openssl/crypto/armcap.c
  46. 3 5
      libs/openssl/crypto/asn1/a_time.c
  47. 5 1
      libs/openssl/crypto/asn1/asn1_err.c
  48. 9 1
      libs/openssl/crypto/asn1/tasn_dec.c
  49. 3 2
      libs/openssl/crypto/bio/bio_dump.c
  50. 1 1
      libs/openssl/crypto/bio/bio_lib.c
  51. 3 1
      libs/openssl/crypto/bio/bio_meth.c
  52. 0 3
      libs/openssl/crypto/bio/bio_sock.c
  53. 1 1
      libs/openssl/crypto/bio/bss_dgram.c
  54. 1 1
      libs/openssl/crypto/bn/bn_gcd.c
  55. 1 1
      libs/openssl/crypto/bn/bn_mod.c
  56. 476 0
      libs/openssl/crypto/chacha/asm/chacha-riscv64-zbb-zvkb.pl
  57. 6 0
      libs/openssl/crypto/chacha/build.info
  58. 7 3
      libs/openssl/crypto/chacha/chacha_enc.c
  59. 56 0
      libs/openssl/crypto/chacha/chacha_riscv.c
  60. 9 5
      libs/openssl/crypto/cmac/cmac.c
  61. 36 18
      libs/openssl/crypto/cmp/cmp_asn.c
  62. 162 34
      libs/openssl/crypto/cmp/cmp_client.c
  63. 13 1
      libs/openssl/crypto/cmp/cmp_ctx.c
  64. 8 1
      libs/openssl/crypto/cmp/cmp_err.c
  65. 10 0
      libs/openssl/crypto/cmp/cmp_hdr.c
  66. 10 1
      libs/openssl/crypto/cmp/cmp_local.h
  67. 41 5
      libs/openssl/crypto/cmp/cmp_msg.c
  68. 165 63
      libs/openssl/crypto/cmp/cmp_server.c
  69. 89 60
      libs/openssl/crypto/cmp/cmp_vfy.c
  70. 1 1
      libs/openssl/crypto/cms/cms_enc.c
  71. 9 1
      libs/openssl/crypto/cms/cms_pwri.c
  72. 1 1
      libs/openssl/crypto/conf/conf_lib.c
  73. 92 47
      libs/openssl/crypto/conf/conf_mod.c
  74. 1 1
      libs/openssl/crypto/conf/conf_sap.c
  75. 2 2
      libs/openssl/crypto/dh/dh_check.c
  76. 1 1
      libs/openssl/crypto/dsa/dsa_check.c
  77. 2 2
      libs/openssl/crypto/dso/dso_dl.c
  78. 2 2
      libs/openssl/crypto/dso/dso_dlfcn.c
  79. 1 1
      libs/openssl/crypto/ec/curve448/ed448.h
  80. 13 0
      libs/openssl/crypto/err/err_mark.c
  81. 15 0
      libs/openssl/crypto/err/openssl.txt
  82. 5 1
      libs/openssl/crypto/evp/bio_enc.c
  83. 35 2
      libs/openssl/crypto/evp/digest.c
  84. 13 13
      libs/openssl/crypto/evp/evp_enc.c
  85. 1 1
      libs/openssl/crypto/evp/evp_fetch.c
  86. 2 2
      libs/openssl/crypto/evp/evp_key.c
  87. 27 9
      libs/openssl/crypto/evp/evp_lib.c
  88. 3 1
      libs/openssl/crypto/evp/evp_local.h
  89. 30 1
      libs/openssl/crypto/evp/keymgmt_meth.c
  90. 3 2
      libs/openssl/crypto/evp/legacy_sha.c
  91. 1 19
      libs/openssl/crypto/evp/pmeth_lib.c
  92. 24 1
      libs/openssl/crypto/http/http_client.c
  93. 12 5
      libs/openssl/crypto/http/http_err.c
  94. 1 1
      libs/openssl/crypto/initthread.c
  95. 1 1
      libs/openssl/crypto/lhash/lh_stats.c
  96. 56 12
      libs/openssl/crypto/lhash/lhash.c
  97. 5 1
      libs/openssl/crypto/lhash/lhash_local.h
  98. 2 2
      libs/openssl/crypto/loongarch64cpuid.pl
  99. 297 0
      libs/openssl/crypto/md5/asm/md5-loongarch64.pl
  100. 4 0
      libs/openssl/crypto/md5/build.info

+ 198 - 8
libs/openssl/CHANGES.md

@@ -12,6 +12,7 @@ appropriate release branch.
 OpenSSL Releases
 ----------------
 
+ - [OpenSSL 3.3](#openssl-33)
  - [OpenSSL 3.2](#openssl-32)
  - [OpenSSL 3.1](#openssl-31)
  - [OpenSSL 3.0](#openssl-30)
@@ -22,10 +23,10 @@ OpenSSL Releases
  - [OpenSSL 1.0.0](#openssl-100)
  - [OpenSSL 0.9.x](#openssl-09x)
 
-OpenSSL 3.2
+OpenSSL 3.3
 -----------
 
-### Changes between 3.2.1 and 3.2.2 [4 Jun 2024]
+### Changes between 3.3.0 and 3.3.1 [4 Jun 2024]
 
  * Fixed potential use after free after SSL_free_buffers() is called.
 
@@ -67,6 +68,201 @@ OpenSSL 3.2
 
    *Tomáš Mráz*
 
+### Changes between 3.2 and 3.3.0 [9 Apr 2024]
+
+ * The `-verify` option to the `openssl crl` and `openssl req` will make
+   the program exit with 1 on failure.
+
+   *Vladimír Kotal*
+
+ * The BIO_get_new_index() function can only be called 127 times before it
+   reaches its upper bound of BIO_TYPE_MASK. It will now correctly return an
+   error of -1 once it is exhausted. Users may need to reserve using this
+   function for cases where BIO_find_type() is required. Either BIO_TYPE_NONE
+   or BIO_get_new_index() can be used to supply a type to BIO_meth_new().
+
+   *Shane Lontis*
+
+ * Added API functions SSL_SESSION_get_time_ex(), SSL_SESSION_set_time_ex()
+   using time_t which is Y2038 safe on 32 bit systems when 64 bit time
+   is enabled (e.g via setting glibc macro _TIME_BITS=64).
+
+   *Ijtaba Hussain*
+
+ * The d2i_ASN1_GENERALIZEDTIME(), d2i_ASN1_UTCTIME(), ASN1_TIME_check(), and
+   related functions have been augmented to check for a minimum length of
+   the input string, in accordance with ITU-T X.690 section 11.7 and 11.8.
+
+   *Job Snijders*
+
+ * Unknown entries in TLS SignatureAlgorithms, ClientSignatureAlgorithms
+   config options and the respective calls to SSL[_CTX]_set1_sigalgs() and
+   SSL[_CTX]_set1_client_sigalgs() that start with `?` character are
+   ignored and the configuration will still be used.
+
+   Similarly unknown entries that start with `?` character in a TLS
+   Groups config option or set with SSL[_CTX]_set1_groups_list() are ignored
+   and the configuration will still be used.
+
+   In both cases if the resulting list is empty, an error is returned.
+
+   *Tomáš Mráz*
+
+ * The EVP_PKEY_fromdata function has been augmented to allow for the derivation
+   of CRT (Chinese Remainder Theorem) parameters when requested.  See the
+   OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ param in the EVP_PKEY-RSA documentation.
+
+   *Neil Horman*
+
+ * The activate and soft_load configuration settings for providers in
+   openssl.cnf have been updated to require a value of [1|yes|true|on]
+   (in lower or UPPER case) to enable the setting. Conversely a value
+   of [0|no|false|off] will disable the setting. All other values, or the
+   omission of a value for these settings will result in an error.
+
+    *Neil Horman*
+
+ * Added `-set_issuer` and `-set_subject` options to `openssl x509` to
+   override the Issuer and Subject when creating a certificate. The `-subj`
+   option now is an alias for `-set_subject`.
+
+    *Job Snijders, George Michaelson*
+
+ * OPENSSL_sk_push() and sk_<TYPE>_push() functions now return 0 instead of -1
+   if called with a NULL stack argument.
+
+   *Tomáš Mráz*
+
+ * In `openssl speed`, changed the default hash function used with `hmac` from
+   `md5` to `sha256`.
+
+   *James Muir*
+
+ * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483:
+   - `certProfile` request message header and respective `-profile` CLI option
+   - support for delayed delivery of all types of response messages
+
+   *David von Oheimb*
+
+ * The build of exporters (such as `.pc` files for pkg-config) cleaned up to
+   be less hard coded in the build file templates, and to allow easier
+   addition of more exporters.  With that, an exporter for CMake is also
+   added.
+
+   *Richard Levitte*
+
+ * The BLAKE2s hash algorithm matches BLAKE2b's support
+   for configurable output length.
+
+   *Ahelenia Ziemiańska*
+
+ * New option `SSL_OP_PREFER_NO_DHE_KEX`, which allows configuring a TLS1.3
+   server to prefer session resumption using PSK-only key exchange over PSK
+   with DHE, if both are available.
+
+   *Markus Minichmayr, Tapkey GmbH*
+
+ * New API `SSL_write_ex2`, which can be used to send an end-of-stream (FIN)
+   condition in an optimised way when using QUIC.
+
+   *Hugo Landau*
+
+ * New atexit configuration switch, which controls whether the OPENSSL_cleanup
+   is registered when libcrypto is unloaded. This is turned off on NonStop
+   configurations because of loader differences on that platform compared to
+   Linux.
+
+   *Randall S. Becker*
+
+ * Support for qlog for tracing QUIC connections has been added.
+
+   The qlog output from OpenSSL currently uses a pre-standard draft version of
+   qlog. The output from OpenSSL will change in incompatible ways in future
+   releases, and is not subject to any format stability or compatibility
+   guarantees at this time. This functionality can be
+   disabled with the build-time option `no-unstable-qlog`. See the
+   openssl-qlog(7) manpage for details.
+
+   *Hugo Landau*
+
+ * Added APIs to allow configuring the negotiated idle timeout for QUIC
+   connections, and to allow determining the number of additional streams
+   that can currently be created for a QUIC connection.
+
+   *Hugo Landau*
+
+ * Added APIs to allow disabling implicit QUIC event processing for
+   QUIC SSL objects, allowing applications to control when event handling
+   occurs. Refer to the SSL_get_value_uint(3) manpage for details.
+
+   *Hugo Landau*
+
+ * Limited support for polling of QUIC connection and stream objects in a
+   non-blocking manner. Refer to the SSL_poll(3) manpage for details.
+
+   *Hugo Landau*
+
+ * Added APIs to allow querying the size and utilisation of a QUIC stream's
+   write buffer. Refer to the SSL_get_value_uint(3) manpage for details.
+
+   *Hugo Landau*
+
+ * New limit on HTTP response headers is introduced to HTTP client. The
+   default limit is set to 256 header lines. If limit is exceeded the
+   response processing stops with error HTTP_R_RESPONSE_TOO_MANY_HDRLINES.
+   Application may call OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(3)
+   to change the default. Setting the value to 0 disables the limit.
+
+   *Alexandr Nedvedicky*
+
+ * Applied AES-GCM unroll8 optimisation to Microsoft Azure Cobalt 100
+
+   *Tom Cosgrove*
+
+ * Added X509_STORE_get1_objects to avoid issues with the existing
+   X509_STORE_get0_objects API in multi-threaded applications. Refer to the
+   documentation for details.
+
+   *David Benjamin*
+
+ * Added assembly implementation for md5 on loongarch64
+
+   *Min Zhou*
+
+ * Optimized AES-CTR for ARM Neoverse V1 and V2
+
+   *Fisher Yu*
+
+ * Enable AES and SHA3 optimisations on Applie Silicon M3-based MacOS systems
+   similar to M1/M2.
+
+   *Tom Cosgrove*
+
+ * Added a new EVP_DigestSqueeze() API. This allows SHAKE to squeeze multiple
+   times with different output sizes.
+
+   *Shane Lontis, Holger Dengler*
+
+ * Various optimizations for cryptographic routines using RISC-V vector crypto
+   extensions
+
+   *Christoph Müllner, Charalampos Mitrodimas, Ard Biesheuvel, Phoebe Chen,
+    Jerry Shih*
+
+ * Accept longer context for TLS 1.2 exporters
+
+   While RFC 5705 implies that the maximum length of a context for exporters is
+   65535 bytes as the length is embedded in uint16, the previous implementation
+   enforced a much smaller limit, which is less than 1024 bytes. This
+   restriction has been removed.
+
+   *Daiki Ueno*
+
+OpenSSL 3.2
+-----------
+
+### Changes between 3.2.1 and 3.2.2 [xx XXX xxxx]
+
  * Fixed an issue where some non-default TLS server configurations can cause
    unbounded memory growth when processing TLSv1.3 sessions. An attacker may
    exploit certain server configurations to trigger unbounded memory growth that
@@ -85,12 +281,6 @@ OpenSSL 3.2
 
    *Matt Caswell*
 
- * New atexit configuration switch, which controls whether the OPENSSL_cleanup
-   is registered when libcrypto is unloaded. This can be used on platforms
-   where using atexit() from shared libraries causes crashes on exit.
-
-   *Randall S. Becker*
-
  * Fixed bug where SSL_export_keying_material() could not be used with QUIC
    connections. (#23560)
 

+ 18 - 0
libs/openssl/Configurations/10-main.conf

@@ -1414,6 +1414,19 @@ my %targets = (
         AR               => add("-X32"),
         RANLIB           => add("-X32"),
     },
+    # shared_target of "aix-solib" builds shared libraries packaged
+    # without archives.  This improves the behavior of inter-library
+    # references (libssl depending on libcrypto) when building with
+    # shlib_variant.
+    # You'll get:  libxxx.so (import library, used when linking applications)
+    #              libxxx.so.ver (shared object)
+    #              libxxx.a (static library archive)
+    # and for runtime, you only need libxxx.so.ver.  libxxx.so and libxxx.a
+    # can be installed along with include files to make an SDK
+    "aix-cc-solib" => {
+        inherit_from     => [ "aix-cc" ],
+        shared_target    => "aix-solib",
+    },
     "aix64-cc" => {
         inherit_from     => [ "aix-common" ],
         CC               => "cc",
@@ -1432,6 +1445,10 @@ my %targets = (
         AR               => add("-X64"),
         RANLIB           => add("-X64"),
     },
+    "aix64-cc-solib" => {
+        inherit_from     => [ "aix64-cc" ],
+        shared_target    => "aix-solib",
+    },
 
 # SIEMENS BS2000/OSD: an EBCDIC-based mainframe
     "BS2000-OSD" => {
@@ -2045,6 +2062,7 @@ my %targets = (
         cflag_incfirst   => '/FIRST_INCLUDE=',
         lib_defines      =>
             add("OPENSSL_USE_NODELETE",
+                "_XOPEN_SOURCE", "_XOPEN_SOURCE_EXTENDED=1",
                 sub {
                     return vms_info()->{def_zlib}
                         ? "LIBZ=\"\"\"".vms_info()->{def_zlib}."\"\"\"" : ();

+ 7 - 0
libs/openssl/Configurations/15-android.conf

@@ -12,6 +12,7 @@
         arm64  => "aarch64-linux-android",
         mips   => "mipsel-linux-android",
         mips64 => "mips64el-linux-android",
+        riscv64 => "riscv64-linux-android",
         x86    => "i686-linux-android",
         x86_64 => "x86_64-linux-android",
     );
@@ -270,6 +271,12 @@ my %targets = (
         perlasm_scheme   => "elf",
     },
 
+    "android-riscv64" => {
+        inherit_from     => [ "android" ],
+        asm_arch         => 'riscv64',
+        perlasm_scheme   => "linux64",
+    },
+
     ####################################################################
     # Backward compatible targets, (might) require $CROSS_SYSROOT
     #

+ 5 - 5
libs/openssl/Configurations/15-ios.conf

@@ -19,14 +19,14 @@ my %targets = (
         # thus targeting iPhone pre-3GS, but it's assumed to be irrelevant
         # at this point.
         CC               => "xcrun -sdk iphoneos cc",
-        cflags           => add("-arch armv7 -mios-version-min=6.0.0 -fno-common"),
+        cflags           => add("-arch armv7 -fno-common"),
         asm_arch         => 'armv4',
         perlasm_scheme   => "ios32",
     },
     "ios64-xcrun" => {
         inherit_from     => [ "ios-common" ],
         CC               => "xcrun -sdk iphoneos cc",
-        cflags           => add("-arch arm64 -mios-version-min=7.0.0 -fno-common"),
+        cflags           => add("-arch arm64 -fno-common"),
         bn_ops           => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
         asm_arch         => 'aarch64',
         perlasm_scheme   => "ios64",
@@ -38,7 +38,7 @@ my %targets = (
     "iossimulator-arm64-xcrun" => {
         inherit_from     => [ "ios-common" ],
         CC               => "xcrun -sdk iphonesimulator cc",
-        cflags           => add("-arch arm64 -mios-simulator-version-min=7.0.0 -fno-common"),
+        cflags           => add("-arch arm64 -fno-common"),
         bn_ops           => "SIXTY_FOUR_BIT_LONG",
         asm_arch         => 'aarch64',
         perlasm_scheme   => "ios64",
@@ -46,7 +46,7 @@ my %targets = (
     "iossimulator-i386-xcrun" => {
         inherit_from     => [ "ios-common" ],
         CC               => "xcrun -sdk iphonesimulator cc",
-        cflags           => add("-arch i386 -mios-simulator-version-min=7.0.0 -fno-common"),
+        cflags           => add("-arch i386 -fno-common"),
         bn_ops           => "BN_LLONG",
         asm_arch         => 'x86',
         perlasm_scheme   => "macosx",
@@ -54,7 +54,7 @@ my %targets = (
     "iossimulator-x86_64-xcrun" => {
         inherit_from     => [ "ios-common" ],
         CC               => "xcrun -sdk iphonesimulator cc",
-        cflags           => add("-arch x86_64 -mios-simulator-version-min=7.0.0 -fno-common"),
+        cflags           => add("-arch x86_64 -fno-common"),
         bn_ops           => "SIXTY_FOUR_BIT_LONG",
         asm_arch         => 'x86_64',
         perlasm_scheme   => "macosx",

+ 14 - 8
libs/openssl/Configurations/50-nonstop.conf

@@ -21,6 +21,8 @@
         shared_extension => ".so",
         ex_libs          => add('-lrld'),
         enable           => ['egd'],
+	# Not currently inherited
+        disable          => ['atexit'],
         dso_scheme       => 'DLFCN',
         sys_id           => 'TANDEM',
     },
@@ -178,7 +180,7 @@
                               'nonstop-archenv-x86_64-oss',
                               'nonstop-ilp32',
                               'nonstop-efloat-x86_64' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nsx_put' => {
         inherit_from     => [ 'nonstop-common',
@@ -188,6 +190,7 @@
                               'nonstop-model-put' ],
         multilib         => '-put',
         multibin         => '-put',
+        disable          => ['atexit'],
     },
     'nonstop-nsx_64' => {
         inherit_from     => [ 'nonstop-common',
@@ -196,7 +199,7 @@
                               'nonstop-efloat-x86_64' ],
         multilib         => '64',
         multibin         => '64',
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nsx_64_put' => {
         inherit_from     => [ 'nonstop-common',
@@ -206,18 +209,19 @@
                               'nonstop-model-put' ],
         multilib         => '64-put',
         multibin         => '64-put',
+        disable          => ['atexit'],
     },
     'nonstop-nsx_g' => {
         inherit_from     => [ 'nonstop-common',
                               'nonstop-archenv-x86_64-guardian',
                               'nonstop-ilp32', 'nonstop-nfloat-x86_64' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nsx_g_tandem' => {
         inherit_from     => [ 'nonstop-common',
                               'nonstop-archenv-x86_64-guardian',
                               'nonstop-ilp32', 'nonstop-tfloat-x86_64' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nsv' => {
         inherit_from     => [ 'nonstop-nsx' ],
@@ -227,7 +231,7 @@
                               'nonstop-archenv-itanium-oss',
                               'nonstop-ilp32',
                               'nonstop-efloat-itanium' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nse_put' => {
         inherit_from     => [ 'nonstop-common',
@@ -237,6 +241,7 @@
                               'nonstop-model-put' ],
         multilib         => '-put',
         multibin         => '-put',
+        disable          => ['atexit'],
     },
     'nonstop-nse_64' => {
         inherit_from     => [ 'nonstop-common',
@@ -245,7 +250,7 @@
                               'nonstop-efloat-itanium' ],
         multilib         => '64',
         multibin         => '64',
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
     'nonstop-nse_64_put' => {
         inherit_from     => [ 'nonstop-common',
@@ -255,17 +260,18 @@
                               'nonstop-model-put' ],
         multilib         => '64-put',
         multibin         => '64-put',
+        disable          => ['atexit'],
     },
     'nonstop-nse_g' => {
         inherit_from     => [ 'nonstop-common',
                               'nonstop-archenv-itanium-guardian',
                               'nonstop-ilp32', 'nonstop-nfloat-itanium' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },
 
     'nonstop-nse_g_tandem' => {
         inherit_from     => [ 'nonstop-common',
                               'nonstop-archenv-itanium-guardian',
                               'nonstop-ilp32', 'nonstop-tfloat-itanium' ],
-        disable          => ['threads'],
+        disable          => ['threads','atexit'],
     },

+ 1 - 1
libs/openssl/Configurations/descrip.mms.tmpl

@@ -239,7 +239,7 @@
       # from these directories.
       push @{$unified_info{includes_extra}->{$obj}}, qw(./quic);
   }
-  foreach (grep /\[\.ssl\.(?:quic|record|statem)\].*?\.o$/, keys %{$unified_info{sources}}) {
+  foreach (grep /\[\.ssl\.(?:quic|record|statem|rio)\].*?\.o$/, keys %{$unified_info{sources}}) {
       my $obj = platform->obj($_);
       # Most of the files in [.ssl.record] and [.ssl.statem] include
       # "../ssl_local.h", which includes things like "record/record.h".

+ 20 - 2
libs/openssl/Configurations/platform/AIX.pm

@@ -13,12 +13,16 @@ require platform::Unix;
 use configdata;
 
 sub dsoext              { '.so' }
-sub shlibextsimple      { '.a' }
+sub shlibextsimple      { return '.so' if $target{shared_target} eq "aix-solib";
+			  '.a'}
 
 # In shared mode, the default static library names clashes with the final
 # "simple" full shared library name, so we add '_a' to the basename of the
-# static libraries in that case.
+# static libraries in that case, unless in solib mode (using only .so
+# files for shared libraries, and not packaging them inside archives)
 sub staticname {
+    return platform::Unix->staticname($_[1]) if $target{shared_target} eq "aix-solib";
+
     # Non-installed libraries are *always* static, and their names remain
     # the same, except for the mandatory extension
     my $in_libname = platform::BASE->staticname($_[1]);
@@ -27,3 +31,17 @@ sub staticname {
 
     return platform::BASE->staticname($_[1]) . ($disabled{shared} ? '' : '_a');
 }
+
+# In solib mode, we do not install the simple symlink (we install the import
+# library).  In regular mode, we install the symlink.
+sub sharedlib_simple {
+    return undef if $target{shared_target} eq "aix-solib";
+    return platform::Unix->sharedlib_simple($_[1], $_[0]->shlibextsimple());
+}
+
+# In solib mode, we install the import library.  In regular mode, we have
+# no import library.
+sub sharedlib_import {
+    return platform::Unix->sharedlib_simple($_[1]) if $target{shared_target} eq "aix-solib";
+    return undef;
+}

+ 3 - 1
libs/openssl/Configurations/platform/Unix.pm

@@ -73,7 +73,9 @@ sub sharedlib_simple {
     my $name = $_[0]->sharedname($_[1]);
     my $simplename = $_[0]->sharedname_simple($_[1]);
     my $ext = $_[0]->shlibext();
-    my $simpleext = $_[0]->shlibextsimple();
+    # Allow override of the extension passed in as parameter
+    my $simpleext = $_[2];
+    $simpleext = $_[0]->shlibextsimple() unless defined $simpleext;
 
     return undef unless defined $simplename && defined $name;
     return undef if ($name eq $simplename && $ext eq $simpleext);

+ 61 - 74
libs/openssl/Configurations/unix-Makefile.tmpl

@@ -11,8 +11,13 @@
      sub windowsdll { $config{target} =~ /^(?:Cygwin|mingw)/ }
 
      # Shared AIX support is special. We put libcrypto[64].so.ver into
-     # libcrypto.a and use libcrypto_a.a as static one.
-     sub sharedaix  { !$disabled{shared} && $config{target} =~ /^aix/ }
+     # libcrypto.a and use libcrypto_a.a as static one, unless using
+     # shared_target style aix-solib.  In that mode, create
+     # libcrypto.so as a link-import library that inserts runtime
+     # dependencies on libcrypto.so.ver, and the static library is
+     # named libcrypto.a.
+     sub sharedaix  { !$disabled{shared} && $target{shared_target} =~ /^aix(?!-solib$)/ }
+     sub sharedaix_solib  { !$disabled{shared} && $target{shared_target} =~ /^aix-solib$/ }
 
      our $sover_dirname = platform->shlib_version_as_filename();
 
@@ -199,6 +204,18 @@ INSTALL_PROGRAMS={-
                         grep { !$unified_info{attributes}->{programs}->{$_}->{noinst} }
                         @{$unified_info{programs}}))
 -}
+INSTALL_EXPORTERS_PKGCONFIG={-
+        join(" \\\n" . ' ' x 28,
+             fill_lines(" ", $COLUMNS - 28,
+                        grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'pkg-config'}
+                        sort keys %{$unified_info{generate}}))
+-}
+INSTALL_EXPORTERS_CMAKE={-
+        join(" \\\n" . ' ' x 24,
+             fill_lines(" ", $COLUMNS - 24,
+                        grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'cmake'}
+                        sort keys %{$unified_info{generate}}))
+-}
 BIN_SCRIPTS={-
         join(" \\\n" . ' ' x 12,
              fill_lines(" ", $COLUMNS - 12,
@@ -320,6 +337,9 @@ BINDIR={- our $bindir = $config{bindir};
 bindir={- file_name_is_absolute($bindir)
           ? $bindir : '$(INSTALLTOP)/$(BINDIR)' -}
 
+PKGCONFIGDIR=$(libdir)/pkgconfig
+CMAKECONFIGDIR=$(libdir)/cmake/OpenSSL
+
 MANDIR=$(INSTALLTOP)/share/man
 DOCDIR=$(INSTALLTOP)/share/doc/$(BASENAME)
 HTMLDIR=$(DOCDIR)/html
@@ -521,7 +541,7 @@ build_man_docs: $(MANDOCS1) $(MANDOCS3) $(MANDOCS5) $(MANDOCS7) ## Create manpag
 build_html_docs: $(HTMLDOCS1) $(HTMLDOCS3) $(HTMLDOCS5) $(HTMLDOCS7) ## Create HTML documentation
 
 build_generated: $(GENERATED_MANDATORY)
-build_libs_nodep: libcrypto.pc libssl.pc openssl.pc
+build_libs_nodep: $(LIBS) {- join(" ",map { platform->sharedlib_simple($_) // platform->sharedlib_import($_) // platform->sharedlib($_) // () } @{$unified_info{libraries}}) -}
 build_modules_nodep: $(MODULES)
 build_programs_nodep: $(PROGRAMS) $(SCRIPTS)
 
@@ -607,7 +627,6 @@ clean: libclean ## Clean the workspace, keep the configuration
 	$(RM) tags TAGS doc-nits md-nits
 	$(RM) -r test/test-runs
 	$(RM) providers/fips*.new
-	$(RM) openssl.pc libcrypto.pc libssl.pc
 	-find . -type l \! -name '.*' -exec $(RM) {} \;
 
 distclean: clean ## Clean and remove the configuration
@@ -746,12 +765,12 @@ install_dev: install_runtime_libs
 		fn1=`basename "$$s1"`; \
 		fn2=`basename "$$s2"`; \
 		fn3=`basename "$$s3"`; \
-		: {- output_off(); output_on() unless windowsdll() or sharedaix(); "" -}; \
+		: {- output_off(); output_on() unless windowsdll() or sharedaix() or sharedaix_solib(); "" -}; \
 		if [ "$$fn2" != "" ]; then \
 			$(ECHO) "link $(DESTDIR)$(libdir)/$$fn2 -> $(DESTDIR)$(libdir)/$$fn1"; \
 			ln -sf $$fn1 "$(DESTDIR)$(libdir)/$$fn2"; \
 		fi; \
-		: {- output_off() unless windowsdll() or sharedaix(); output_on() if windowsdll(); "" -}; \
+		: {- output_off() unless windowsdll() or sharedaix() or sharedaix_solib(); output_on() if windowsdll() or sharedaix_solib(); "" -}; \
 		if [ "$$fn3" != "" ]; then \
 			$(ECHO) "install $$s3 -> $(DESTDIR)$(libdir)/$$fn3"; \
 			cp $$s3 "$(DESTDIR)$(libdir)/$$fn3.new"; \
@@ -759,7 +778,7 @@ install_dev: install_runtime_libs
 			mv -f "$(DESTDIR)$(libdir)/$$fn3.new" \
 			      "$(DESTDIR)$(libdir)/$$fn3"; \
 		fi; \
-		: {- output_off() if windowsdll(); output_on() if sharedaix(); "" -}; \
+		: {- output_off() if windowsdll() or sharedaix_solib(); output_on() if sharedaix(); "" -}; \
 		a="$(DESTDIR)$(libdir)/$$fn2"; \
 		$(ECHO) "install $$s1 -> $$a"; \
 		if [ -f $$a ]; then ( trap "rm -rf /tmp/ar.$$$$" INT 0; \
@@ -777,16 +796,20 @@ install_dev: install_runtime_libs
 		: {- output_off() if sharedaix(); output_on(); "" -}; \
 	done
 	@ : {- output_on() if $disabled{shared}; "" -}
-	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(libdir)/pkgconfig"
-	@$(ECHO) "install libcrypto.pc -> $(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
-	@cp libcrypto.pc "$(DESTDIR)$(libdir)/pkgconfig"
-	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
-	@$(ECHO) "install libssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
-	@cp libssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
-	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
-	@$(ECHO) "install openssl.pc -> $(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
-	@cp openssl.pc "$(DESTDIR)$(libdir)/pkgconfig"
-	@chmod 644 "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl "$(DESTDIR)$(PKGCONFIGDIR)"
+	@for e in $(INSTALL_EXPORTERS_PKGCONFIG); do \
+		fn=`basename $$e`; \
+		$(ECHO) "install $$e -> $(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
+		cp $$e "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
+		chmod 644 "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
+	done
+	@$(PERL) $(SRCDIR)/util/mkdir-p.pl $(DESTDIR)$(CMAKECONFIGDIR)
+	@for e in $(INSTALL_EXPORTERS_CMAKE); do \
+		fn=`basename $$e`; \
+		$(ECHO) "install $$e -> $(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \
+		cp $$e $(DESTDIR)$(CMAKECONFIGDIR)/$$fn; \
+		chmod 644 $(DESTDIR)$(CMAKECONFIGDIR)/$$fn; \
+	done
 
 uninstall_dev: uninstall_runtime_libs
 	@$(ECHO) "*** Uninstalling development files"
@@ -830,10 +853,16 @@ uninstall_dev: uninstall_runtime_libs
 		: {- output_on() unless windowsdll(); "" -}; \
 	done
 	@ : {- output_on() if $disabled{shared}; "" -}
-	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libcrypto.pc"
-	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/libssl.pc"
-	$(RM) "$(DESTDIR)$(libdir)/pkgconfig/openssl.pc"
-	-$(RMDIR) "$(DESTDIR)$(libdir)/pkgconfig"
+	@for e in $(INSTALL_EXPORTERS_PKGCONFIG); do \
+		fn=`basename "$$e"`; \
+		$(RM) "$(DESTDIR)$(PKGCONFIGDIR)/$$fn"; \
+	done
+	@for e in $(INSTALL_EXPORTERS_CMAKE); do \
+		fn=`basename "$$e"`; \
+		$(RM) "$(DESTDIR)$(CMAKECONFIGDIR)/$$fn"; \
+	done
+	-$(RMDIR) "$(DESTDIR)$(PKGCONFIGDIR)"
+	-$(RMDIR) "$(DESTDIR)$(CMAKECONFIGDIR)"
 	-$(RMDIR) "$(DESTDIR)$(libdir)"
 
 _install_modules_deps: install_runtime_libs build_modules
@@ -1434,59 +1463,6 @@ FORCE:
 
 # Building targets ###################################################
 
-libcrypto.pc libssl.pc openssl.pc: Makefile $(LIBS) {- join(" ",map { platform->sharedlib_simple($_) // platform->sharedlib_import($_) // platform->sharedlib($_) // () } @{$unified_info{libraries}}) -}
-
-libcrypto.pc:
-	@ ( echo 'prefix=$(INSTALLTOP)'; \
-	    echo 'exec_prefix=$${prefix}'; \
-	    if [ -n "$(LIBDIR)" ]; then \
-	        echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
-	    else \
-	        echo 'libdir=$(libdir)'; \
-	    fi; \
-	    echo 'includedir=$${prefix}/include'; \
-	    echo 'enginesdir=$${libdir}/engines-{- $sover_dirname -}'; \
-	    echo 'modulesdir=$${libdir}/ossl-modules'; \
-	    echo ''; \
-	    echo 'Name: OpenSSL-libcrypto'; \
-	    echo 'Description: OpenSSL cryptography library'; \
-	    echo 'Version: '$(VERSION); \
-	    echo 'Libs: -L$${libdir} -lcrypto'; \
-	    echo 'Libs.private: $(LIB_EX_LIBS)'; \
-	    echo 'Cflags: -I$${includedir}' ) > libcrypto.pc
-
-libssl.pc:
-	@ ( echo 'prefix=$(INSTALLTOP)'; \
-	    echo 'exec_prefix=$${prefix}'; \
-	    if [ -n "$(LIBDIR)" ]; then \
-	        echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
-	    else \
-	        echo 'libdir=$(libdir)'; \
-	    fi; \
-	    echo 'includedir=$${prefix}/include'; \
-	    echo ''; \
-	    echo 'Name: OpenSSL-libssl'; \
-	    echo 'Description: Secure Sockets Layer and cryptography libraries'; \
-	    echo 'Version: '$(VERSION); \
-	    echo 'Requires.private: libcrypto'; \
-	    echo 'Libs: -L$${libdir} -lssl'; \
-	    echo 'Cflags: -I$${includedir}' ) > libssl.pc
-
-openssl.pc:
-	@ ( echo 'prefix=$(INSTALLTOP)'; \
-	    echo 'exec_prefix=$${prefix}'; \
-	    if [ -n "$(LIBDIR)" ]; then \
-	        echo 'libdir=$${exec_prefix}/$(LIBDIR)'; \
-	    else \
-	        echo 'libdir=$(libdir)'; \
-	    fi; \
-	    echo 'includedir=$${prefix}/include'; \
-	    echo ''; \
-	    echo 'Name: OpenSSL'; \
-	    echo 'Description: Secure Sockets Layer and cryptography libraries and tools'; \
-	    echo 'Version: '$(VERSION); \
-	    echo 'Requires: libssl libcrypto' ) > openssl.pc
-
 Makefile: configdata.pm \
           {- join(" \\\n" . ' ' x 10,
                   fill_lines(" ", $COLUMNS - 10,
@@ -1819,6 +1795,8 @@ EOF
       # libraries for DLLs are a thing.  On platforms that have this mechanism,
       # $import has the name of this import library.  On platforms that don't
       # have this mechanism, $import will be |undef|.
+      # It's also used on AIX in solib mode, which creates import libraries
+      # for the shared libraries.
       my $import = platform->sharedlib_import($args{lib});
       # $simple is for platforms where full shared library names include the
       # shared library version, and there's a simpler name that doesn't include
@@ -1879,9 +1857,18 @@ EOF
           }
       }
       if (defined $import) {
+          if (sharedaix_solib()) {
+              $recipe .= <<"EOF";
+$import: $full $defs[0]
+	rm -f $import && \\
+	echo \\#!$full > $import && \\
+        cat $defs[0] >>$import
+EOF
+          } else {
       $recipe .= <<"EOF";
 $import: $full
 EOF
+          }
       }
       $recipe .= <<"EOF";
 $full: $fulldeps

+ 9 - 0
libs/openssl/Configurations/windows-makefile.tmpl

@@ -155,6 +155,11 @@ MISC_SCRIPTS={-
                          && $unified_info{attributes}->{scripts}->{$_}->{misc} }
                   @{$unified_info{scripts}})
 -}
+INSTALL_EXPORTERS_CMAKE={-
+        join(" ", map { quotify1($_) }
+                  grep { $unified_info{attributes}->{generate}->{$_}->{exporter} eq 'cmake'}
+                  sort keys %{$unified_info{generate}})
+-}
 IMAGEDOCS1={- our @IMAGEDOCS1 = @{$unified_info{imagedocs}->{man1}};
              join(" ", @IMAGEDOCS1) -}
 IMAGEDOCS3={- our @IMAGEDOCS3 = @{$unified_info{imagedocs}->{man3}};
@@ -249,6 +254,8 @@ MODULESDIR=$(MODULESDIR_dev)$(MODULESDIR_dir)
 libdir={- file_name_is_absolute($libdir)
           ? $libdir : '$(INSTALLTOP)\$(LIBDIR)' -}
 
+CMAKECONFIGDIR=$(libdir)\cmake\OpenSSL
+
 ##### User defined commands and flags ################################
 
 CC="{- $config{CC} -}"
@@ -559,6 +566,8 @@ install_dev: install_runtime_libs
 	@"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_LIBS) "$(libdir)"
 	@if "$(SHLIBS)"=="" \
 	 "$(PERL)" "$(SRCDIR)\util\copy.pl" ossl_static.pdb "$(libdir)"
+	@"$(PERL)" "$(SRCDIR)\util\mkdir-p.pl" "$(CMAKECONFIGDIR)"
+	@"$(PERL)" "$(SRCDIR)\util\copy.pl" $(INSTALL_EXPORTERS_CMAKE) "$(CMAKECONFIGDIR)"
 
 uninstall_dev:
 

+ 13 - 1
libs/openssl/Configure

@@ -385,6 +385,12 @@ if (defined env($local_config_envname)) {
     }
 }
 
+# Fail if no configuration is apparent
+if (!%table) {
+    print "Failed to find any os/compiler configurations. Please make sure the Configurations directory is included.\n";
+    &usage;
+}
+
 # Save away perl command information
 $config{perl_cmd} = $^X;
 $config{perl_version} = $Config{version};
@@ -485,6 +491,7 @@ my @disablables = (
     "posix-io",
     "psk",
     "quic",
+    "unstable-qlog",
     "rc2",
     "rc4",
     "rc5",
@@ -591,7 +598,7 @@ our %disabled = ( # "what"         => "comment"
 my @disable_cascades = (
     # "what"            => [ "cascade", ... ]
     "bulk"              => [ "shared", "dso",
-                             "aria", "async", "autoload-config",
+                             "aria", "async", "atexit", "autoload-config",
                              "blake2", "bf", "camellia", "cast", "chacha",
                              "cmac", "cms", "cmp", "comp", "ct",
                              "des", "dgram", "dh", "dsa",
@@ -626,6 +633,7 @@ my @disable_cascades = (
     sub { 0 == scalar grep { !$disabled{$_} } @tls }
                         => [ "tls" ],
     "tls1_3"            => [ "quic" ],
+    "quic"              => [ "unstable-qlog" ],
 
     "crypto-mdebug"     => [ "crypto-mdebug-backtrace" ],
 
@@ -1547,6 +1555,10 @@ unless($disabled{threads}) {
     push @{$config{openssl_feature_defines}}, "OPENSSL_THREADS";
 }
 
+if ($disabled{"unstable-qlog"}) {
+    $disabled{"qlog"} = 1;
+}
+
 my $no_shared_warn=0;
 if (($target{shared_target} // '') eq "")
         {

+ 12 - 2
libs/openssl/INSTALL.md

@@ -64,6 +64,7 @@ issues and other details, please read one of these:
  * [Notes for Windows platforms](NOTES-WINDOWS.md)
  * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md)
  * [Notes for the OpenVMS platform](NOTES-VMS.md)
+ * [Notes for the HPE NonStop platform](NOTES-NONSTOP.md)
  * [Notes on Perl](NOTES-PERL.md)
  * [Notes on Valgrind](NOTES-VALGRIND.md)
 
@@ -141,7 +142,7 @@ Use the following commands to configure, build and test OpenSSL.
 The testing is optional, but recommended if you intend to install
 OpenSSL for production use.
 
-### Unix / Linux / macOS
+### Unix / Linux / macOS / NonStop
 
     $ ./Configure
     $ make
@@ -198,7 +199,7 @@ the global search path for system libraries.
 Finally, if you plan on using the FIPS module, you need to read the
 [Post-installation Notes](#post-installation-notes) further down.
 
-### Unix / Linux / macOS
+### Unix / Linux / macOS / NonStop
 
 Depending on your distribution, you need to run the following command as
 root user or prepend `sudo` to the command:
@@ -606,6 +607,7 @@ Do not use `atexit()` in libcrypto builds.
 
 `atexit()` has varied semantics between platforms and can cause SIGSEGV in some
 circumstances. This option disables the atexit registration of OPENSSL_cleanup.
+By default, NonStop configurations use `no-atexit`.
 
 ### no-autoalginit
 
@@ -1082,6 +1084,14 @@ when needed.
 
 This is only supported on systems where loading of shared libraries is supported.
 
+### enable-unstable-qlog
+
+Enables qlog output support for the QUIC protocol. This functionality is
+unstable and implements a draft version of the qlog specification. The qlog
+output from OpenSSL will change in incompatible ways in future, and is not
+subject to any format stability or compatibility guarantees at this time. See
+the manpage openssl-qlog(7) for details.
+
 ### 386
 
 In 32-bit x86 builds, use the 80386 instruction set only in assembly modules

+ 132 - 3
libs/openssl/NEWS.md

@@ -7,6 +7,7 @@ release. For more details please read the CHANGES file.
 OpenSSL Releases
 ----------------
 
+ - [OpenSSL 3.3](#openssl-33)
  - [OpenSSL 3.2](#openssl-32)
  - [OpenSSL 3.1](#openssl-31)
  - [OpenSSL 3.0](#openssl-30)
@@ -17,12 +18,12 @@ OpenSSL Releases
  - [OpenSSL 1.0.0](#openssl-100)
  - [OpenSSL 0.9.x](#openssl-09x)
 
-OpenSSL 3.2
+OpenSSL 3.3
 -----------
 
-### Major changes between OpenSSL 3.2.1 and OpenSSL 3.2.2 [4 Jun 2024]
+### Major changes between OpenSSL 3.3.0 and OpenSSL 3.3.1 [4 Jun 2024]
 
-OpenSSL 3.2.2 is a security patch release. The most severe CVE fixed in this
+OpenSSL 3.3.1 is a security patch release. The most severe CVE fixed in this
 release is Low.
 
 This release incorporates the following bug fixes and mitigations:
@@ -34,6 +35,132 @@ This release incorporates the following bug fixes and mitigations:
     be very slow
     ([CVE-2024-4603])
 
+### Major changes between OpenSSL 3.2 and OpenSSL 3.3.0 [9 Apr 2024]
+
+OpenSSL 3.3.0 is a feature release adding significant new functionality to
+OpenSSL.
+
+This release adds the following new features:
+
+  * Support for qlog for tracing QUIC connections has been added
+
+  * Added APIs to allow configuring the negotiated idle timeout for QUIC
+    connections, and to allow determining the number of additional streams
+    that can currently be created for a QUIC connection.
+
+  * Added APIs to allow disabling implicit QUIC event processing for QUIC SSL
+    objects
+
+  * Added APIs to allow querying the size and utilisation of a QUIC stream's
+    write buffer
+
+  * New API `SSL_write_ex2`, which can be used to send an end-of-stream (FIN)
+    condition in an optimised way when using QUIC.
+
+  * Limited support for polling of QUIC connection and stream objects in a
+    non-blocking manner.
+
+  * Added a new EVP_DigestSqueeze() API. This allows SHAKE to squeeze multiple
+    times with different output sizes.
+
+  * Added exporter for CMake on Unix and Windows, alongside the pkg-config
+    exporter.
+
+  * The BLAKE2s hash algorithm matches BLAKE2b's support for configurable
+    output length.
+
+  * The EVP_PKEY_fromdata function has been augmented to allow for the
+    derivation of CRT (Chinese Remainder Theorem) parameters when requested
+
+  * Added API functions SSL_SESSION_get_time_ex(), SSL_SESSION_set_time_ex()
+    using time_t which is Y2038 safe on 32 bit systems when 64 bit time
+    is enabled
+
+  * Unknown entries in TLS SignatureAlgorithms, ClientSignatureAlgorithms
+    config options and the respective calls to SSL[_CTX]_set1_sigalgs() and
+    SSL[_CTX]_set1_client_sigalgs() that start with `?` character are
+    ignored and the configuration will still be used.
+
+  * Added `-set_issuer` and `-set_subject` options to `openssl x509` to
+    override the Issuer and Subject when creating a certificate. The `-subj`
+    option now is an alias for `-set_subject`.
+
+  * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483
+
+  * New option `SSL_OP_PREFER_NO_DHE_KEX`, which allows configuring a TLS1.3
+    server to prefer session resumption using PSK-only key exchange over PSK
+    with DHE, if both are available.
+
+  * New atexit configuration switch, which controls whether the OPENSSL_cleanup
+    is registered when libcrypto is unloaded.
+
+  * Added X509_STORE_get1_objects to avoid issues with the existing
+    X509_STORE_get0_objects API in multi-threaded applications.
+
+This release incorporates the following potentially significant or incompatible
+changes:
+
+  * Applied AES-GCM unroll8 optimisation to Microsoft Azure Cobalt 100
+
+  * Optimized AES-CTR for ARM Neoverse V1 and V2
+
+  * Enable AES and SHA3 optimisations on Applie Silicon M3-based MacOS systems
+    similar to M1/M2.
+
+  * Various optimizations for cryptographic routines using RISC-V vector crypto
+    extensions
+
+  * Added assembly implementation for md5 on loongarch64
+
+  * Accept longer context for TLS 1.2 exporters
+
+  * The activate and soft_load configuration settings for providers in
+    openssl.cnf have been updated to require a value of [1|yes|true|on]
+    (in lower or UPPER case) to enable the setting. Conversely a value
+    of [0|no|false|off] will disable the setting.
+
+  * In `openssl speed`, changed the default hash function used with `hmac` from
+    `md5` to `sha256`.
+
+  * The `-verify` option to the `openssl crl` and `openssl req` will make the
+    program exit with 1 on failure.
+
+  * The d2i_ASN1_GENERALIZEDTIME(), d2i_ASN1_UTCTIME(), ASN1_TIME_check(), and
+    related functions have been augmented to check for a minimum length of
+    the input string, in accordance with ITU-T X.690 section 11.7 and 11.8.
+
+  * OPENSSL_sk_push() and sk_<TYPE>_push() functions now return 0 instead of -1
+    if called with a NULL stack argument.
+
+  * New limit on HTTP response headers is introduced to HTTP client. The
+    default limit is set to 256 header lines.
+
+This release incorporates the following bug fixes and mitigations:
+
+  * The BIO_get_new_index() function can only be called 127 times before it
+    reaches its upper bound of BIO_TYPE_MASK and will now return -1 once its
+    exhausted.
+
+A more detailed list of changes in this release can be found in the
+[CHANGES.md] file.
+
+Users interested in using the new QUIC functionality are encouraged to read the
+[README file for QUIC][README-QUIC.md], which provides links to relevant
+documentation and example code.
+
+As always, bug reports and issues relating to OpenSSL can be [filed on our issue
+tracker][issue tracker].
+
+OpenSSL 3.2
+-----------
+
+### Major changes between OpenSSL 3.2.1 and OpenSSL 3.2.2 [under development]
+
+OpenSSL 3.2.2 is a security patch release. The most severe CVE fixed in this
+release is Low.
+
+This release incorporates the following bug fixes and mitigations:
+
   * Fixed unbounded memory growth with session handling in TLSv1.3
     ([CVE-2024-2511])
 
@@ -46,8 +173,10 @@ This release incorporates the following bug fixes and mitigations:
 
   * Fixed PKCS12 Decoding crashes
     ([CVE-2024-0727])
+
   * Fixed excessive time spent checking invalid RSA public keys
     ([CVE-2023-6237])
+
   * Fixed POLY1305 MAC implementation corrupting vector registers on PowerPC
     CPUs which support PowerISA 2.07
     ([CVE-2023-6129])

+ 2 - 2
libs/openssl/NOTES-ANDROID.md

@@ -17,8 +17,8 @@ Notes for Android platforms
  Android is a cross-compiled target and you can't rely on `./Configure`
  to find out the configuration target for you.  You have to name your
  target explicitly; there are `android-arm`, `android-arm64`, `android-mips`,
- `android-mip64`, `android-x86` and `android-x86_64` (`*MIPS` targets are no
- longer supported with NDK R20+).
+ `android-mip64`, `android-x86`, `android-x86_64` and `android-riscv64`
+ (`*MIPS` targets are no longer supported with NDK R20+).
 
  Do not pass --cross-compile-prefix (as you might be tempted), as it
  will be "calculated" automatically based on chosen platform. However,

+ 8 - 7
libs/openssl/NOTES-NONSTOP.md

@@ -19,9 +19,7 @@ About c99 compiler
 
 The c99 compiler is required for building OpenSSL from source. While c11
 may work, it has not been broadly tested. c99 is the only compiler
-prerequisite needed to build OpenSSL 3.0 on this platform. You should also
-have the FLOSS package installed on your system. The ITUGLIB FLOSS package
-is the only FLOSS variant that has been broadly tested.
+prerequisite needed to build OpenSSL 3.0 on this platform.
 
 Threading Models
 ----------------
@@ -60,10 +58,13 @@ relating to `atexit()` processing when a shared library is unloaded and when
 the program terminates. This limitation applies to all OpenSSL shared library
 components.
 
-It is possible to configure the build with `no-atexit` to avoid the SIGSEGV.
-Preferably, you can explicitly call `OPENSSL_cleanup()` from your application.
-It is not mandatory as it just deallocates various global data structures
-OpenSSL allocated.
+A control has been added as of 3.3.x to disable calls to `atexit()` within the
+`libcrypto` builds (specifically in `crypto/init.c`). This switch can be
+controlled using `disable-atexit` or `enable-atexit`, and is disabled by default
+for NonStop builds. If you need to have `atexit()` functionality, set
+`enabled-atexit` when configuring OpenSSL to enable the `atexit()` call to
+register `OPENSSL_cleanup()` automatically. Preferably, you can explicitly call
+`OPENSSL_cleanup()` from your application.
 
 About Prefix and OpenSSLDir
 ---------------------------

+ 2 - 2
libs/openssl/NOTES-WINDOWS.md

@@ -1,9 +1,9 @@
 Notes for Windows platforms
 ===========================
 
- - [Native builds using Visual C++](#native-builds-using-visual-c++)
+ - [Native builds using Visual C++](#native-builds-using-visual-c)
  - [Native builds using Embarcadero C++Builder](
-   #native-builds-using-embarcadero-c++-builder)
+   #native-builds-using-embarcadero-cbuilder)
  - [Native builds using MinGW](#native-builds-using-mingw)
  - [Linking native applications](#linking-native-applications)
  - [Hosted builds using Cygwin](#hosted-builds-using-cygwin)

+ 2 - 2
libs/openssl/VERSION.dat

@@ -1,6 +1,6 @@
 MAJOR=3
-MINOR=2
-PATCH=2
+MINOR=3
+PATCH=1
 PRE_RELEASE_TAG=
 BUILD_METADATA=
 RELEASE_DATE="4 Jun 2024"

+ 269 - 93
libs/openssl/apps/cmp.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -86,6 +86,7 @@ static char *opt_srvcert = NULL;
 static char *opt_expect_sender = NULL;
 static int opt_ignore_keyusage = 0;
 static int opt_unprotected_errors = 0;
+static int opt_no_cache_extracerts = 0;
 static char *opt_srvcertout = NULL;
 static char *opt_extracertsout = NULL;
 static char *opt_cacertsout = NULL;
@@ -112,6 +113,7 @@ static int opt_cmd = -1;
 static char *opt_geninfo = NULL;
 static char *opt_infotype_s = NULL;
 static int opt_infotype = NID_undef;
+static char *opt_profile = NULL;
 
 /* certificate enrollment */
 static char *opt_newkey = NULL;
@@ -163,6 +165,8 @@ static int opt_repeat = 1;
 static char *opt_reqin = NULL;
 static int opt_reqin_new_tid = 0;
 static char *opt_reqout = NULL;
+static char *opt_reqout_only = NULL;
+static int reqout_only_done = 0;
 static char *opt_rspin = NULL;
 static int rspin_in_use = 0;
 static char *opt_rspout = NULL;
@@ -210,7 +214,7 @@ typedef enum OPTION_choice {
     OPT_COMMON,
     OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
 
-    OPT_CMD, OPT_INFOTYPE, OPT_GENINFO,
+    OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO,
 
     OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT,
     OPT_DAYS, OPT_REQEXTS,
@@ -230,7 +234,7 @@ typedef enum OPTION_choice {
 
     OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT,
     OPT_EXPECT_SENDER,
-    OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS,
+    OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS,
     OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
     OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW,
 
@@ -253,7 +257,8 @@ typedef enum OPTION_choice {
 #endif
 
     OPT_BATCH, OPT_REPEAT,
-    OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_RSPIN, OPT_RSPOUT,
+    OPT_REQIN, OPT_REQIN_NEW_TID, OPT_REQOUT, OPT_REQOUT_ONLY,
+    OPT_RSPIN, OPT_RSPOUT,
     OPT_USE_MOCK_SRV,
 
 #if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
@@ -291,10 +296,12 @@ const OPTIONS cmp_options[] = {
      "InfoType name for requesting specific info in genm, with specific support"},
     {OPT_MORE_STR, 0, 0,
      "for 'caCerts' and 'rootCaCert'"},
+    {"profile", OPT_PROFILE, 's',
+     "Certificate profile name to place in generalInfo field of request PKIHeader"},
     {"geninfo", OPT_GENINFO, 's',
-     "generalInfo integer values to place in request PKIHeader with given OID"},
+     "Comma-separated list of OID and value to place in generalInfo PKIHeader"},
     {OPT_MORE_STR, 0, 0,
-     "specified in the form <OID>:int:<n>, e.g. \"1.2.3.4:int:56789\""},
+     "of form <OID>:int:<n> or <OID>:str:<s>, e.g. \'1.2.3.4:int:56789, id-kp:str:name'"},
 
     OPT_SECTION("Certificate enrollment"),
     {"newkey", OPT_NEWKEY, 's',
@@ -405,6 +412,8 @@ const OPTIONS cmp_options[] = {
      "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"},
     {OPT_MORE_STR, 0, 0,
      "WARNING: This setting leads to behavior allowing violation of RFC 4210"},
+    {"no_cache_extracerts", OPT_NO_CACHE_EXTRACERTS, '-',
+     "Do not keep certificates received in the extraCerts CMP message field"},
     { "srvcertout", OPT_SRVCERTOUT, 's',
       "File to save the server cert used and validated for CMP response protection"},
     {"extracertsout", OPT_EXTRACERTSOUT, 's',
@@ -496,6 +505,8 @@ const OPTIONS cmp_options[] = {
      "Use fresh transactionID for CMP requests read from -reqin"},
     {"reqout", OPT_REQOUT, 's',
      "Save sequence of CMP requests created by the client to file(s)"},
+    {"reqout_only", OPT_REQOUT_ONLY, 's',
+     "Save first CMP request created by the client to file and exit"},
     {"rspin", OPT_RSPIN, 's',
      "Process sequence of CMP responses provided in file(s), skipping server"},
     {"rspout", OPT_RSPOUT, 's',
@@ -587,7 +598,7 @@ typedef union {
 static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_config}, {&opt_section}, {(char **)&opt_verbosity},
 
-    {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo},
+    {&opt_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo},
 
     {&opt_newkey}, {&opt_newkeypass}, {&opt_subject},
     {(char **)&opt_days}, {&opt_reqexts},
@@ -609,6 +620,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert},
     {&opt_expect_sender},
     {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors},
+    {(char **)&opt_no_cache_extracerts},
     {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
     {&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew},
 
@@ -631,7 +643,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
 
     {(char **)&opt_batch}, {(char **)&opt_repeat},
     {&opt_reqin}, {(char **)&opt_reqin_new_tid},
-    {&opt_reqout}, {&opt_rspin}, {&opt_rspout},
+    {&opt_reqout}, {&opt_reqout_only}, {&opt_rspin}, {&opt_rspout},
 
     {(char **)&opt_use_mock_srv},
 #if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
@@ -807,6 +819,14 @@ static OSSL_CMP_MSG *read_write_req_resp(OSSL_CMP_CTX *ctx,
     OSSL_CMP_PKIHEADER *hdr;
     const char *prev_opt_rspin = opt_rspin;
 
+    if (opt_reqout_only != NULL) {
+        if (OSSL_CMP_MSG_write(opt_reqout_only, req) < 0)
+            CMP_err1("cannot write request PKIMessage to file '%s'",
+                     opt_reqout_only);
+        else
+            reqout_only_done = 1;
+        return NULL; /* stop at this point, not contacting any server */
+    }
     if (opt_reqout != NULL && !write_PKIMESSAGE(req, &opt_reqout))
         goto err;
     if (opt_reqin != NULL && opt_rspin == NULL) {
@@ -1123,7 +1143,7 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (!setup_cert(srv_ctx, opt_ref_cert, opt_otherpass,
                     "reference cert to be expected by the mock server",
                     (add_X509_fn_t)ossl_cmp_mock_srv_set1_refCert))
-            goto err;
+        goto err;
     if (opt_rsp_cert == NULL) {
         CMP_warn("no -rsp_cert given for mock server");
     } else {
@@ -1235,9 +1255,6 @@ static int setup_verification_ctx(OSSL_CMP_CTX *ctx)
         }
     }
 
-    if (opt_ignore_keyusage)
-        (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1);
-
     if (opt_unprotected_errors)
         (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS, 1);
 
@@ -1541,6 +1558,48 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     return 1;
 }
 
+static int set_fallback_pubkey(OSSL_CMP_CTX *ctx)
+{
+    char *file = opt_reqin, *end = file, bak;
+    OSSL_CMP_MSG *req;
+    const X509_PUBKEY *pubkey;
+    EVP_PKEY *pkey;
+    EVP_PKEY *pkey1;
+    int res = 0;
+
+    /* temporarily separate first file name in opt_reqin */
+    while (*end != ',' && !isspace(_UC(*end)) && *end != '\0')
+        end++;
+    bak = *end;
+    *end = '\0';
+    req = OSSL_CMP_MSG_read(file, app_get0_libctx(), app_get0_propq());
+    *end = bak;
+
+    if (req == NULL) {
+        CMP_err1("failed to load ir/cr/kur file '%s' attempting to get fallback public key",
+                 file);
+        return 0;
+    }
+    if ((pubkey = OSSL_CMP_MSG_get0_certreq_publickey(req)) == NULL
+        || (pkey = X509_PUBKEY_get0(pubkey)) == NULL) {
+        CMP_err1("failed to get fallback public key from ir/cr/kur file '%s'",
+                 file);
+        goto err;
+    }
+    pkey1 = EVP_PKEY_dup(pkey);
+    if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, 0 /* priv */, pkey1)) {
+        EVP_PKEY_free(pkey1);
+        CMP_err1("failed to get fallback public key obtained from ir/cr/kur file '%s'",
+                 file);
+        goto err;
+    }
+    res = 1;
+
+ err:
+    OSSL_CMP_MSG_free(req);
+    return res;
+}
+
 /*
  * Set up IR/CR/P10CR/KUR/CertConf/RR/GENM specific parts of the OSSL_CMP_CTX
  * based on options from CLI and/or config file.
@@ -1560,26 +1619,28 @@ 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_newkey == NULL
+        if (opt_reqin == NULL && opt_newkey == NULL
             && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
-            CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, or -cert given for fallback public key");
+            CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key");
             return 0;
         }
         if (opt_newkey == NULL
             && opt_popo != OSSL_CRMF_POPO_NONE
             && opt_popo != OSSL_CRMF_POPO_RAVERIFIED) {
             if (opt_csr != NULL) {
-                CMP_err1("no -newkey option given with private key for POPO, -csr option only provides public key%s",
-                        opt_key == NULL ? "" :
-                        ", and -key option superseded by -csr");
+                CMP_err1("no -newkey option given with private key for POPO, -csr option provides just public key%s",
+                         opt_key == NULL ? "" :
+                         ", and -key option superseded by -csr");
+                if (opt_reqin != NULL)
+                    CMP_info("since -reqin is used, may use -popo -1 or -popo 0 to disable the needless generation of a POPO");
                 return 0;
             }
             if (opt_key == NULL) {
-                CMP_err("missing -newkey (or -key) option for POPO");
+                CMP_err("missing -newkey (or -key) option for key to be certified and for POPO");
                 return 0;
             }
         }
-        if (opt_certout == NULL) {
+        if (opt_certout == NULL && opt_reqout_only == NULL) {
             CMP_err("-certout not given, nowhere to save newly enrolled certificate");
             return 0;
         }
@@ -1594,7 +1655,8 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
                 if (!set_name(opt_subject, OSSL_CMP_CTX_set1_subjectName, ctx, "subject"))
                     return 0;
             } else {
-                CMP_warn1("-subject %s since sender is taken from -ref or -cert", msg);
+                CMP_warn1("-subject %s since sender is taken from -ref or -cert",
+                          msg);
             }
         }
         if (opt_issuer != NULL && opt_cmd != CMP_RR)
@@ -1678,7 +1740,7 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
 
     if (opt_recipient == NULL && opt_srvcert == NULL && opt_issuer == NULL
             && opt_oldcert == NULL && opt_cert == NULL)
-        CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient will be set to \"NULL-DN\"");
+        CMP_warn("missing -recipient, -srvcert, -issuer, -oldcert or -cert; recipient for any requests not covered by -reqin will be set to \"NULL-DN\"");
 
     if (opt_cmd == CMP_P10CR || opt_cmd == CMP_RR || opt_cmd == CMP_GENM) {
         const char *msg = "option is ignored for 'p10cr', 'rr', and 'genm' commands";
@@ -1718,6 +1780,10 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             EVP_PKEY_free(pkey);
             return 0;
         }
+    } else if (opt_reqin != NULL
+               && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
+        if (!set_fallback_pubkey(ctx))
+            return 0;
     }
 
     if (opt_days > 0
@@ -1791,9 +1857,11 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         char *next = next_item(opt_policy_oids);
 
         if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) {
-            CMP_err1("unknown policy OID '%s'", opt_policy_oids);
+            CMP_err1("Invalid -policy_oids arg '%s'", opt_policy_oids);
             return 0;
         }
+        if (OBJ_obj2nid(policy) == NID_undef)
+            CMP_warn1("Unknown -policy_oids arg: %.40s", opt_policy_oids);
 
         if ((pinfo = POLICYINFO_new()) == NULL) {
             ASN1_OBJECT_free(policy);
@@ -1808,7 +1876,6 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         }
         opt_policy_oids = next;
     }
-
     if (opt_popo >= OSSL_CRMF_POPO_NONE)
         (void)OSSL_CMP_CTX_set_option(ctx, OSSL_CMP_OPT_POPO_METHOD, opt_popo);
 
@@ -1837,64 +1904,127 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     return 0;
 }
 
-static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
+static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name)
 {
-    long value;
-    ASN1_OBJECT *type;
-    ASN1_INTEGER *aint;
-    ASN1_TYPE *val;
-    OSSL_CMP_ITAV *itav;
-    char *endstr;
-    char *valptr = strchr(opt_geninfo, ':');
+    OSSL_CMP_ITAV *itav = NULL;
+    STACK_OF(ASN1_UTF8STRING) *sk;
+    ASN1_UTF8STRING *utf8string;
 
-    if (valptr == NULL) {
-        CMP_err("missing ':' in -geninfo option");
+    if (ctx == NULL || name == NULL)
         return 0;
-    }
-    valptr[0] = '\0';
-    valptr++;
 
-    if (!CHECK_AND_SKIP_CASE_PREFIX(valptr, "int:")) {
-        CMP_err("missing 'int:' in -geninfo option");
+    if ((sk = sk_ASN1_UTF8STRING_new_reserve(NULL, 1)) == NULL)
         return 0;
-    }
+   if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
+       goto err;
+   if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) {
+       ASN1_STRING_free(utf8string);
+       goto err;
+   }
+   /* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */
+   (void)sk_ASN1_UTF8STRING_push(sk, utf8string);
+   if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL)
+       goto err;
+   if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav))
+       return 1;
+   OSSL_CMP_ITAV_free(itav);
+   return 0;
 
-    value = strtol(valptr, &endstr, 10);
-    if (endstr == valptr || *endstr != '\0') {
-        CMP_err("cannot parse int in -geninfo option");
-        return 0;
-    }
+ err:
+    sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free);
+    return 0;
+}
 
-    type = OBJ_txt2obj(opt_geninfo, 1);
-    if (type == NULL) {
-        CMP_err("cannot parse OID in -geninfo option");
-        return 0;
-    }
+static int handle_opt_geninfo(OSSL_CMP_CTX *ctx)
+{
+    ASN1_OBJECT *obj = NULL;
+    ASN1_TYPE *type = NULL;
+    long value;
+    ASN1_INTEGER *aint = NULL;
+    ASN1_UTF8STRING *text = NULL;
+    OSSL_CMP_ITAV *itav;
+    char *ptr = opt_geninfo, *oid, *end;
+
+    do {
+        while (isspace(_UC(*ptr)))
+            ptr++;
+        oid = ptr;
+        if ((ptr = strchr(oid, ':')) == NULL) {
+            CMP_err1("Missing ':' in -geninfo arg %.40s", oid);
+            return 0;
+        }
+        *ptr++ = '\0';
+        if ((obj = OBJ_txt2obj(oid, 0)) == NULL) {
+            CMP_err1("Invalid OID in -geninfo arg %.40s", oid);
+            return 0;
+        }
+        if (OBJ_obj2nid(obj) == NID_undef)
+            CMP_warn1("Unknown OID in -geninfo arg: %.40s", oid);
+        if ((type = ASN1_TYPE_new()) == NULL)
+            goto oom;
 
-    if ((aint = ASN1_INTEGER_new()) == NULL)
-        goto oom;
+        if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "int:")) {
+            value = strtol(ptr, &end, 10);
+            if (end == ptr) {
+                CMP_err1("Cannot parse int in -geninfo arg %.40s", ptr);
+                goto err;
+            }
+            ptr = end;
+            if (*ptr != '\0') {
+                if (*ptr != ',') {
+                    CMP_err1("Missing ',' or end of -geninfo arg after int at %.40s",
+                        ptr);
+                    goto err;
+                }
+                ptr++;
+            }
 
-    val = ASN1_TYPE_new();
-    if (!ASN1_INTEGER_set(aint, value) || val == NULL) {
-        ASN1_INTEGER_free(aint);
-        goto oom;
-    }
-    ASN1_TYPE_set(val, V_ASN1_INTEGER, aint);
-    itav = OSSL_CMP_ITAV_create(type, val);
-    if (itav == NULL) {
-        ASN1_TYPE_free(val);
-        goto oom;
-    }
+            if ((aint = ASN1_INTEGER_new()) == NULL
+                    || !ASN1_INTEGER_set(aint, value))
+                goto oom;
+            ASN1_TYPE_set(type, V_ASN1_INTEGER, aint);
+            aint = NULL;
+
+        } else if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "str:")) {
+            end = strchr(ptr, ',');
+            if (end == NULL)
+                end = ptr + strlen(ptr);
+            else
+                *end++ = '\0';
+            if ((text = ASN1_UTF8STRING_new()) == NULL
+                    || !ASN1_STRING_set(text, ptr, -1))
+                goto oom;
+            ptr = end;
+            ASN1_TYPE_set(type, V_ASN1_UTF8STRING, text);
+            text = NULL;
 
-    if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) {
-        OSSL_CMP_ITAV_free(itav);
-        return 0;
-    }
+        } else {
+            CMP_err1("Missing 'int:' or 'str:' in -geninfo arg %.40s", ptr);
+            goto err;
+        }
+
+        if ((itav = OSSL_CMP_ITAV_create(obj, type)) == NULL) {
+            CMP_err("Unable to create 'OSSL_CMP_ITAV' structure");
+            goto err;
+        }
+        obj = NULL;
+        type = NULL;
+
+        if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) {
+            CMP_err("Failed to add ITAV for geninfo of the PKI message header");
+            OSSL_CMP_ITAV_free(itav);
+            return 0;
+        }
+    } while (*ptr != '\0');
     return 1;
 
  oom:
-    ASN1_OBJECT_free(type);
     CMP_err("out of memory");
+ err:
+    ASN1_OBJECT_free(obj);
+    ASN1_TYPE_free(type);
+    ASN1_INTEGER_free(aint);
+    ASN1_UTF8STRING_free(text);
     return 0;
 }
 
@@ -1916,9 +2046,11 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     char server_buf[200] = "mock server";
     char proxy_buf[200] = "";
 
+    if (!opt_use_mock_srv)
+        strcpy(server_buf, "no server");
     if (!opt_use_mock_srv && opt_rspin == NULL) { /* note: -port is not given */
 #if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
-        if (opt_server == NULL) {
+        if (opt_server == NULL && opt_reqout_only == NULL) {
             CMP_err("missing -server or -use_mock_srv or -rspin option");
             goto err;
         }
@@ -2078,14 +2210,14 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
 
     if (opt_geninfo != NULL && !handle_opt_geninfo(ctx))
         goto err;
+    if (opt_profile != NULL && !add_certProfile(ctx, opt_profile))
+        goto err;
 
     /* not printing earlier, to minimize confusion in case setup fails before */
-    if (opt_rspin != NULL)
-        CMP_info2("will contact %s%s "
-                  "only if -rspin argument gives too few filenames",
-                  server_buf, proxy_buf);
-    else
-        CMP_info2("will contact %s%s", server_buf, proxy_buf);
+    if (opt_reqout_only == NULL)
+        CMP_info3("will contact %s%s%s ", server_buf, proxy_buf,
+                  opt_rspin == NULL ? "" :
+                  " only if -rspin argument gives too few filenames");
 
     ret = 1;
 
@@ -2571,6 +2703,9 @@ static int get_opts(int argc, char **argv)
         case OPT_UNPROTECTED_ERRORS:
             opt_unprotected_errors = 1;
             break;
+        case OPT_NO_CACHE_EXTRACERTS:
+            opt_no_cache_extracerts = 1;
+            break;
         case OPT_SRVCERTOUT:
             opt_srvcertout = opt_str();
             break;
@@ -2603,6 +2738,9 @@ static int get_opts(int argc, char **argv)
         case OPT_INFOTYPE:
             opt_infotype_s = opt_str();
             break;
+        case OPT_PROFILE:
+            opt_profile = opt_str();
+            break;
         case OPT_GENINFO:
             opt_geninfo = opt_str();
             break;
@@ -2719,6 +2857,9 @@ static int get_opts(int argc, char **argv)
         case OPT_REQOUT:
             opt_reqout = opt_str();
             break;
+        case OPT_REQOUT_ONLY:
+            opt_reqout_only = opt_str();
+            break;
         case OPT_RSPIN:
             opt_rspin = opt_str();
             break;
@@ -3028,25 +3169,17 @@ static int do_genm(OSSL_CMP_CTX *ctx)
     }
 }
 
-int cmp_main(int argc, char **argv)
+static int handle_opts_upfront(int argc, char **argv)
 {
-    char *configfile = NULL;
     int i;
-    X509 *newcert = NULL;
-    ENGINE *engine = NULL;
-    OSSL_CMP_CTX *srv_cmp_ctx = NULL;
-    int ret = 0; /* default: failure */
 
     prog = opt_appname(argv[0]);
     if (argc <= 1) {
         opt_help(cmp_options);
-        goto err;
+        return 0;
     }
 
-    /*
-     * handle options -config, -section, and -verbosity upfront
-     * to take effect for other options
-     */
+    /* handle -config, -section, and -verbosity to take effect for other opts */
     for (i = 1; i < argc - 1; i++) {
         if (*argv[i] == '-') {
             if (!strcmp(argv[i] + 1, cmp_options[OPT_CONFIG - OPT_HELP].name))
@@ -3057,11 +3190,25 @@ int cmp_main(int argc, char **argv)
             else if (strcmp(argv[i] + 1,
                             cmp_options[OPT_VERBOSITY - OPT_HELP].name) == 0
                      && !set_verbosity(atoi(argv[++i])))
-                goto err;
+                return 0;
         }
     }
     if (opt_section[0] == '\0') /* empty string */
         opt_section = DEFAULT_SECTION;
+    return 1;
+}
+
+int cmp_main(int argc, char **argv)
+{
+    char *configfile = NULL;
+    int i;
+    X509 *newcert = NULL;
+    ENGINE *engine = NULL;
+    OSSL_CMP_CTX *srv_cmp_ctx = NULL;
+    int ret = 0; /* default: failure */
+
+    if (!handle_opts_upfront(argc, argv))
+        goto err;
 
     vpm = X509_VERIFY_PARAM_new();
     if (vpm == NULL) {
@@ -3108,6 +3255,10 @@ int cmp_main(int argc, char **argv)
     }
     (void)BIO_flush(bio_err); /* prevent interference with opt_help() */
 
+    cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
+    if (cmp_ctx == NULL)
+        goto err;
+
     ret = get_opts(argc, argv);
     if (ret <= 0)
         goto err;
@@ -3128,9 +3279,6 @@ int cmp_main(int argc, char **argv)
         }
     }
 
-    cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq());
-    if (cmp_ctx == NULL)
-        goto err;
     OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity);
     if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) {
         CMP_err1("cannot set up error reporting and logging for %s", prog);
@@ -3170,11 +3318,17 @@ int cmp_main(int argc, char **argv)
     }
 #endif
 
-    if (opt_use_mock_srv
+    if (opt_ignore_keyusage)
+        (void)OSSL_CMP_CTX_set_option(cmp_ctx, OSSL_CMP_OPT_IGNORE_KEYUSAGE, 1);
+    if (opt_no_cache_extracerts)
+        (void)OSSL_CMP_CTX_set_option(cmp_ctx, OSSL_CMP_OPT_NO_CACHE_EXTRACERTS,
+                                      1);
+
+    if (opt_reqout_only == NULL && (opt_use_mock_srv
 #if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
-        || opt_port != NULL
+                                    || opt_port != NULL
 #endif
-        ) {
+                                    )) {
         OSSL_CMP_SRV_CTX *srv_ctx;
 
         if ((srv_ctx = setup_srv_ctx(engine)) == NULL)
@@ -3201,6 +3355,23 @@ int cmp_main(int argc, char **argv)
 
     /* act as CMP client, possibly using internal mock server */
 
+    if (opt_reqout_only != NULL) {
+        const char *msg = "option is ignored since -reqout_only option is given";
+
+#if !defined(OPENSSL_NO_SOCK) && !defined(OPENSSL_NO_HTTP)
+        if (opt_server != NULL)
+            CMP_warn1("-server %s", msg);
+#endif
+        if (opt_use_mock_srv)
+            CMP_warn1("-use_mock_srv %s", msg);
+        if (opt_reqout != NULL)
+            CMP_warn1("-reqout %s", msg);
+        if (opt_rspin != NULL)
+            CMP_warn1("-rspin %s", msg);
+        if (opt_rspout != NULL)
+            CMP_warn1("-rspout %s", msg);
+        opt_reqout = opt_reqout_only;
+    }
     if (opt_rspin != NULL) {
         if (opt_server != NULL)
             CMP_warn("-server option is not used if enough filenames given for -rspin");
@@ -3245,8 +3416,13 @@ int cmp_main(int argc, char **argv)
             break;
         }
         if (OSSL_CMP_CTX_get_status(cmp_ctx) < OSSL_CMP_PKISTATUS_accepted) {
+            /* we got no response, maybe even did not send request */
             ret = 0;
-            goto err; /* we got no response, maybe even did not send request */
+            if (reqout_only_done) {
+                ERR_clear_error();
+                ret = 1;
+            }
+            goto err;
         }
         print_status();
         if (!save_cert_or_delete(OSSL_CMP_CTX_get0_validatedSrvCert(cmp_ctx),

+ 4 - 3
libs/openssl/apps/crl.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -248,9 +248,10 @@ int crl_main(int argc, char **argv)
         EVP_PKEY_free(pkey);
         if (i < 0)
             goto end;
-        if (i == 0)
+        if (i == 0) {
             BIO_printf(bio_err, "verify failure\n");
-        else
+	    goto end;
+        } else
             BIO_printf(bio_err, "verify OK\n");
     }
 

+ 2 - 1
libs/openssl/apps/enc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -593,6 +593,7 @@ int enc_main(int argc, char **argv)
         }
         if (hiv != NULL) {
             int siz = EVP_CIPHER_get_iv_length(cipher);
+
             if (siz == 0) {
                 BIO_printf(bio_err, "warning: iv not used by this cipher\n");
             } else if (!set_hex(hiv, iv, siz)) {

+ 5 - 2
libs/openssl/apps/engine.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -251,7 +251,7 @@ static void util_do_cmds(ENGINE *e, STACK_OF(OPENSSL_STRING) *cmds,
         cmd = sk_OPENSSL_STRING_value(cmds, loop);
         res = 1;                /* assume success */
         /* Check if this command has no ":arg" */
-        if ((arg = strstr(cmd, ":")) == NULL) {
+        if ((arg = strchr(cmd, ':')) == NULL) {
             if (!ENGINE_ctrl_cmd_string(e, cmd, NULL, 0))
                 res = 0;
         } else {
@@ -405,6 +405,9 @@ int engine_main(int argc, char **argv)
                 if (ENGINE_get_RSA(e) != NULL
                     && !append_buf(&cap_buf, &cap_size, "RSA"))
                     goto end;
+                if (ENGINE_get_EC(e) != NULL
+                    && !append_buf(&cap_buf, &cap_size, "EC"))
+                    goto end;
                 if (ENGINE_get_DSA(e) != NULL
                     && !append_buf(&cap_buf, &cap_size, "DSA"))
                     goto end;

+ 10 - 2
libs/openssl/apps/genpkey.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -24,7 +24,7 @@ typedef enum OPTION_choice {
     OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE,
     OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER,
     OPT_VERBOSE, OPT_QUIET, OPT_CONFIG, OPT_OUTPUBKEY,
-    OPT_PROV_ENUM
+    OPT_PROV_ENUM, OPT_R_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS genpkey_options[] = {
@@ -51,6 +51,7 @@ const OPTIONS genpkey_options[] = {
     {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"},
 
     OPT_PROV_OPTIONS,
+    OPT_R_OPTIONS,
 
     /* This is deliberately last. */
     {OPT_HELP_STR, 1, 1,
@@ -188,6 +189,10 @@ int genpkey_main(int argc, char **argv)
             if (!opt_provider(o))
                 goto end;
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         }
     }
 
@@ -195,6 +200,9 @@ int genpkey_main(int argc, char **argv)
     if (!opt_check_rest_arg(NULL))
         goto opthelp;
 
+    if (!app_RAND_load())
+        goto end;
+
     /* Fetch cipher, etc. */
     if (paramfile != NULL) {
         if (!init_keygen_file(&ctx, paramfile, e, libctx, app_get0_propq()))

+ 5 - 1
libs/openssl/apps/include/opt.h

@@ -157,7 +157,8 @@
         OPT_S_NOTLS1_3, OPT_S_BUGS, OPT_S_NO_COMP, OPT_S_NOTICKET, \
         OPT_S_SERVERPREF, OPT_S_LEGACYRENEG, OPT_S_CLIENTRENEG, \
         OPT_S_LEGACYCONN, \
-        OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_ALLOW_NO_DHE_KEX, \
+        OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, \
+        OPT_S_ALLOW_NO_DHE_KEX, OPT_S_PREFER_NO_DHE_KEX, \
         OPT_S_PRIORITIZE_CHACHA, \
         OPT_S_STRICT, OPT_S_SIGALGS, OPT_S_CLIENTSIGALGS, OPT_S_GROUPS, \
         OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, OPT_S_CIPHERSUITES, \
@@ -198,6 +199,8 @@
             "Disallow initial connection to servers that don't support RI"}, \
         {"allow_no_dhe_kex", OPT_S_ALLOW_NO_DHE_KEX, '-', \
             "In TLSv1.3 allow non-(ec)dhe based key exchange on resumption"}, \
+        {"prefer_no_dhe_kex", OPT_S_PREFER_NO_DHE_KEX, '-', \
+            "In TLSv1.3 prefer non-(ec)dhe over (ec)dhe-based key exchange on resumption"}, \
         {"prioritize_chacha", OPT_S_PRIORITIZE_CHACHA, '-', \
             "Prioritize ChaCha ciphers when preferred by clients"}, \
         {"strict", OPT_S_STRICT, '-', \
@@ -248,6 +251,7 @@
         case OPT_S_ONRESUMP: \
         case OPT_S_NOLEGACYCONN: \
         case OPT_S_ALLOW_NO_DHE_KEX: \
+        case OPT_S_PREFER_NO_DHE_KEX: \
         case OPT_S_PRIORITIZE_CHACHA: \
         case OPT_S_STRICT: \
         case OPT_S_SIGALGS: \

+ 1 - 16
libs/openssl/apps/lib/apps.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -2952,11 +2952,6 @@ int raw_read_stdin(void *buf, int siz)
     return recv(fileno_stdin(), buf, siz, 0);
 }
 #else
-# if defined(__TANDEM)
-#  if defined(OPENSSL_TANDEM_FLOSS)
-#   include <floss.h(floss_read)>
-#  endif
-# endif
 int raw_read_stdin(void *buf, int siz)
 {
     return read(fileno_stdin(), buf, siz);
@@ -2975,21 +2970,11 @@ int raw_write_stdout(const void *buf, int siz)
 }
 #elif defined(OPENSSL_SYS_TANDEM) && defined(OPENSSL_THREADS) \
     && defined(_SPT_MODEL_)
-# if defined(__TANDEM)
-#  if defined(OPENSSL_TANDEM_FLOSS)
-#   include <floss.h(floss_write)>
-#  endif
-# endif
 int raw_write_stdout(const void *buf, int siz)
 {
     return write(fileno(stdout), (void *)buf, siz);
 }
 #else
-# if defined(__TANDEM)
-#  if defined(OPENSSL_TANDEM_FLOSS)
-#   include <floss.h(floss_write)>
-#  endif
-# endif
 int raw_write_stdout(const void *buf, int siz)
 {
     return write(fileno_stdout(), buf, siz);

+ 101 - 19
libs/openssl/apps/lib/cmp_mock_srv.c

@@ -27,7 +27,7 @@ typedef struct
     X509 *oldWithNew;          /* to return in oldWithNew of rootKeyUpdate */
     OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */
     int sendError;             /* send error response on given request type */
-    OSSL_CMP_MSG *certReq;     /* ir/cr/p10cr/kur remembered while polling */
+    OSSL_CMP_MSG *req;         /* original request message during polling */
     int pollCount;             /* number of polls before actual cert response */
     int curr_pollCount;        /* number of polls so far for current request */
     int checkAfterTime;        /* time the client should wait between polling */
@@ -43,7 +43,7 @@ static void mock_srv_ctx_free(mock_srv_ctx *ctx)
     X509_free(ctx->certOut);
     OSSL_STACK_OF_X509_free(ctx->chainOut);
     OSSL_STACK_OF_X509_free(ctx->caPubsOut);
-    OSSL_CMP_MSG_free(ctx->certReq);
+    OSSL_CMP_MSG_free(ctx->req);
     OPENSSL_free(ctx);
 }
 
@@ -183,6 +183,38 @@ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec)
     return 1;
 }
 
+/* determine whether to delay response to (non-polling) request */
+static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req)
+{
+    mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+    int req_type = OSSL_CMP_MSG_get_bodytype(req);
+
+    if (ctx == NULL || req == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return -1;
+    }
+
+    /*
+     * For ir/cr/p10cr/kur delayed delivery is handled separately in
+     * process_cert_request
+     */
+    if (req_type == OSSL_CMP_IR
+        || req_type == OSSL_CMP_CR
+        || req_type == OSSL_CMP_P10CR
+        || req_type == OSSL_CMP_KUR
+        /* Client may use error to abort the ongoing polling */
+        || req_type == OSSL_CMP_ERROR)
+        return 0;
+
+    if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) {
+        /* start polling */
+        if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL)
+            return -1;
+        return 1;
+    }
+    return 0;
+}
+
 /* check for matching reference cert components, as far as given */
 static int refcert_cmp(const X509 *refcert,
                        const X509_NAME *issuer, const ASN1_INTEGER *serial)
@@ -198,6 +230,23 @@ static int refcert_cmp(const X509 *refcert,
         && (ref_serial == NULL || ASN1_INTEGER_cmp(serial, ref_serial) == 0);
 }
 
+/* reset the state that belongs to a transaction */
+static int clean_transaction(OSSL_CMP_SRV_CTX *srv_ctx,
+                             ossl_unused const ASN1_OCTET_STRING *id)
+{
+    mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    ctx->curr_pollCount = 0;
+    OSSL_CMP_MSG_free(ctx->req);
+    ctx->req = NULL;
+    return 1;
+}
+
 static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
                                             const OSSL_CMP_MSG *cert_req,
                                             ossl_unused int certReqId,
@@ -228,12 +277,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
 
     if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) {
         /* start polling */
-        if (ctx->certReq != NULL) {
-            /* already in polling mode */
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-            return NULL;
-        }
-        if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL)
+        if ((ctx->req = OSSL_CMP_MSG_dup(cert_req)) == NULL)
             return NULL;
         return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL);
     }
@@ -241,6 +285,42 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
         /* give final response after polling */
         ctx->curr_pollCount = 0;
 
+    /* accept cert profile for cr messages only with the configured name */
+    if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_CR) {
+        STACK_OF(OSSL_CMP_ITAV) *itavs =
+            OSSL_CMP_HDR_get0_geninfo_ITAVs(OSSL_CMP_MSG_get0_header(cert_req));
+        int i;
+
+        for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) {
+            OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_value(itavs, i);
+            ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(itav);
+            STACK_OF(ASN1_UTF8STRING) *strs;
+            ASN1_UTF8STRING *str;
+            const char *data;
+
+            if (OBJ_obj2nid(obj) == NID_id_it_certProfile) {
+                if (!OSSL_CMP_ITAV_get0_certProfile(itav, &strs))
+                    return NULL;
+                if (sk_ASN1_UTF8STRING_num(strs) < 1) {
+                    ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE);
+                    return NULL;
+                }
+                str = sk_ASN1_UTF8STRING_value(strs, 0);
+                if (str == NULL
+                    || (data =
+                        (const char *)ASN1_STRING_get0_data(str)) == NULL) {
+                    ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+                    return NULL;
+                }
+                if (strcmp(data, "profile1") != 0) {
+                    ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE);
+                    return NULL;
+                }
+                break;
+            }
+        }
+    }
+
     /* accept cert update request only for the reference cert, if given */
     if (bodytype == OSSL_CMP_KUR
             && crm != NULL /* thus not p10cr */ && ctx->refCert != NULL) {
@@ -455,38 +535,38 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
     return 1;
 }
 
+/* return 0 on failure, 1 on success, setting *req or otherwise *check_after */
 static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
                            const OSSL_CMP_MSG *pollReq,
                            ossl_unused int certReqId,
-                           OSSL_CMP_MSG **certReq, int64_t *check_after)
+                           OSSL_CMP_MSG **req, int64_t *check_after)
 {
     mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
 
+    if (req != NULL)
+        *req = NULL;
     if (ctx == NULL || pollReq == NULL
-            || certReq == NULL || check_after == NULL) {
+            || req == NULL || check_after == NULL) {
         ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
         return 0;
     }
+
     if (ctx->sendError == 1
             || ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) {
-        *certReq = NULL;
         ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
         return 0;
     }
-    if (ctx->certReq == NULL) {
-        /* not currently in polling mode */
-        *certReq = NULL;
-        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+    if (ctx->req == NULL) { /* not currently in polling mode */
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ);
         return 0;
     }
 
     if (++ctx->curr_pollCount >= ctx->pollCount) {
         /* end polling */
-        *certReq = ctx->certReq;
-        ctx->certReq = NULL;
+        *req = ctx->req;
+        ctx->req = NULL;
         *check_after = 0;
     } else {
-        *certReq = NULL;
         *check_after = ctx->checkAfterTime;
     }
     return 1;
@@ -500,7 +580,9 @@ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq)
     if (srv_ctx != NULL && ctx != NULL
             && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request,
                                      process_rr, process_genm, process_error,
-                                     process_certConf, process_pollReq))
+                                     process_certConf, process_pollReq)
+            && OSSL_CMP_SRV_CTX_init_trans(srv_ctx,
+                                           delayed_delivery, clean_transaction))
         return srv_ctx;
 
     mock_srv_ctx_free(ctx);

+ 2 - 8
libs/openssl/apps/lib/http_server.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -26,12 +26,6 @@
 #include "s_apps.h"
 #include "log.h"
 
-#if defined(__TANDEM)
-# if defined(OPENSSL_TANDEM_FLOSS)
-#  include <floss.h(floss_fork)>
-# endif
-#endif
-
 #define HTTP_PREFIX "HTTP/"
 #define HTTP_VERSION_PATT "1." /* allow 1.x */
 #define HTTP_PREFIX_VERSION HTTP_PREFIX""HTTP_VERSION_PATT
@@ -200,7 +194,7 @@ BIO *http_server_init(const char *prog, const char *port, int verb)
     int port_num;
     char name[40];
 
-    snprintf(name, sizeof(name), "*:%s", port); /* port may be "0" */
+    BIO_snprintf(name, sizeof(name), "*:%s", port); /* port may be "0" */
     if (verb >= 0 && !log_set_verbosity(prog, verb))
         return NULL;
     bufbio = BIO_new(BIO_f_buffer());

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -41,12 +41,6 @@ typedef unsigned int u_int;
 # include "s_apps.h"
 # include "internal/sockets.h"
 
-# if defined(__TANDEM)
-#  if defined(OPENSSL_TANDEM_FLOSS)
-#   include <floss.h(floss_read)>
-#  endif
-# endif
-
 # include <openssl/bio.h>
 # include <openssl/err.h>
 

+ 1 - 7
libs/openssl/apps/ocsp.c

@@ -11,7 +11,7 @@
 
 #ifdef OPENSSL_SYS_VMS
   /* So fd_set and friends get properly defined on OpenVMS */
-# define _XOPEN_SOURCE_EXTENDED 1
+# define _XOPEN_SOURCE_EXTENDED
 #endif
 
 #include <stdio.h>
@@ -33,12 +33,6 @@
 #include <openssl/bn.h>
 #include <openssl/x509v3.h>
 
-#if defined(__TANDEM)
-# if defined(OPENSSL_TANDEM_FLOSS)
-#  include <floss.h(floss_fork)>
-# endif
-#endif
-
 #if defined(OPENSSL_SYS_VXWORKS)
 /* not supported */
 int setpgid(pid_t pid, pid_t pgid)

+ 86 - 7
libs/openssl/apps/rand.c

@@ -25,7 +25,7 @@ typedef enum OPTION_choice {
 } OPTION_CHOICE;
 
 const OPTIONS rand_options[] = {
-    {OPT_HELP_STR, 1, '-', "Usage: %s [options] num\n"},
+    {OPT_HELP_STR, 1, '-', "Usage: %s [options] num[K|M|G|T]\n"},
 
     OPT_SECTION("General"),
     {"help", OPT_HELP, '-', "Display this summary"},
@@ -52,8 +52,10 @@ int rand_main(int argc, char **argv)
     BIO *out = NULL;
     char *outfile = NULL, *prog;
     OPTION_CHOICE o;
-    int format = FORMAT_BINARY, r, i, ret = 1, buflen = 131072;
+    int format = FORMAT_BINARY, r, i, ret = 1;
+    size_t buflen = (1 << 16); /* max rand chunk size is 2^16 bytes */
     long num = -1;
+    uint64_t scaled_num = 0;
     uint8_t *buf = NULL;
 
     prog = opt_init(argc, argv, rand_options);
@@ -95,8 +97,85 @@ int rand_main(int argc, char **argv)
     argc = opt_num_rest();
     argv = opt_rest();
     if (argc == 1) {
-        if (!opt_long(argv[0], &num) || num <= 0)
+        int factoridx = 0;
+        int shift = 0;
+
+        /*
+         * special case for requesting the max allowed
+         * number of random bytes to be generated
+         */
+        if (!strcmp(argv[0], "max")) {
+            /*
+             * 2^61 bytes is the limit of random output
+             * per drbg instantiation
+             */
+            scaled_num = UINT64_MAX >> 3;
+        } else {
+            /*
+             * iterate over the value and check to see if there are
+             * any non-numerical chars
+             * A non digit suffix indicates we need to shift the
+             * number of requested bytes by a factor of:
+             * K = 1024^1 (1 << (10 * 1))
+             * M = 1024^2 (1 << (10 * 2))
+             * G = 1024^3 (1 << (10 * 3))
+             * T = 1024^4 (1 << (10 * 4))
+             * which can be achieved by bit-shifting the number
+             */
+            while (argv[0][factoridx]) {
+                if (!isdigit((int)(argv[0][factoridx]))) {
+                    switch(argv[0][factoridx]) {
+                    case 'K':
+                        shift = 10;
+                        break;
+                    case 'M':
+                        shift = 20;
+                        break;
+                    case 'G':
+                        shift = 30;
+                        break;
+                    case 'T':
+                        shift = 40;
+                        break;
+                    default:
+                        BIO_printf(bio_err, "Invalid size suffix %s\n",
+                                   &argv[0][factoridx]);
+                        goto opthelp;
+                    }
+                    break;
+                }
+                factoridx++;
+            }
+
+            if (shift != 0 && strlen(&argv[0][factoridx]) != 1) {
+                BIO_printf(bio_err, "Invalid size suffix %s\n",
+                           &argv[0][factoridx]);
+                goto opthelp;
+            }
+        }
+        /* Remove the suffix from the arg so that opt_long works */
+        if (shift != 0)
+            argv[0][factoridx] = '\0';
+
+        if ((scaled_num == 0) && (!opt_long(argv[0], &num) || num <= 0))
             goto opthelp;
+
+        if (shift != 0) {
+            /* check for overflow */
+            if ((UINT64_MAX >> shift) < (size_t)num) {
+                BIO_printf(bio_err, "%lu bytes with suffix overflows\n",
+                           num);
+                goto opthelp;
+            }
+            scaled_num = num << shift;
+            if (scaled_num > (UINT64_MAX >> 3)) {
+                BIO_printf(bio_err, "Request exceeds max allowed output\n");
+                goto opthelp;
+            }
+        } else {
+            if (scaled_num == 0)
+                scaled_num = num;
+        }
     } else if (!opt_check_rest_arg(NULL)) {
         goto opthelp;
     }
@@ -116,10 +195,10 @@ int rand_main(int argc, char **argv)
     }
 
     buf = app_malloc(buflen, "buffer for output file");
-    while (num > 0) {
-        long chunk;
+    while (scaled_num > 0) {
+        int chunk;
 
-        chunk = (num > buflen) ? buflen : num;
+        chunk = scaled_num > buflen ? (int)buflen : (int)scaled_num;
         r = RAND_bytes(buf, chunk);
         if (r <= 0)
             goto end;
@@ -131,7 +210,7 @@ int rand_main(int argc, char **argv)
                 if (BIO_printf(out, "%02x", buf[i]) != 2)
                     goto end;
         }
-        num -= chunk;
+        scaled_num -= chunk;
     }
     if (format == FORMAT_TEXT)
         BIO_puts(out, "\n");

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2013-2014 Timo Teräs <[email protected]>
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -266,7 +266,7 @@ static int do_file(const char *filename, const char *fullpath, enum Hash h)
 
     if (sk_X509_INFO_num(inf) != 1) {
         BIO_printf(bio_err,
-                   "%s: warning: skipping %s,"
+                   "%s: warning: skipping %s, "
                    "it does not contain exactly one certificate or CRL\n",
                    opt_getprog(), filename);
         /* This is not an error. */

+ 3 - 2
libs/openssl/apps/req.c

@@ -918,9 +918,10 @@ int req_main(int argc, char **argv)
 
         if (i < 0)
             goto end;
-        if (i == 0)
+        if (i == 0) {
             BIO_printf(bio_err, "Certificate request self-signature verify failure\n");
-        else /* i > 0 */
+	    goto end;
+        } else /* i > 0 */
             BIO_printf(bio_out, "Certificate request self-signature verify OK\n");
     }
 

+ 30 - 14
libs/openssl/apps/s_server.c

@@ -476,7 +476,10 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
     char *proxy = NULL, *no_proxy = NULL;
     int use_ssl;
     STACK_OF(OPENSSL_STRING) *aia = NULL;
-    X509 *x = NULL;
+    X509 *x = NULL, *cert;
+    X509_NAME *iname;
+    STACK_OF(X509) *chain = NULL;
+    SSL_CTX *ssl_ctx;
     X509_STORE_CTX *inctx = NULL;
     X509_OBJECT *obj;
     OCSP_REQUEST *req = NULL;
@@ -487,6 +490,7 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
 
     /* Build up OCSP query from server certificate */
     x = SSL_get_certificate(s);
+    iname = X509_get_issuer_name(x);
     aia = X509_get1_ocsp(x);
     if (aia != NULL) {
         if (!OSSL_HTTP_parse_url(sk_OPENSSL_STRING_value(aia, 0), &use_ssl,
@@ -511,21 +515,33 @@ static int get_ocsp_resp_from_responder(SSL *s, tlsextstatusctx *srctx,
     proxy = srctx->proxy;
     no_proxy = srctx->no_proxy;
 
-    inctx = X509_STORE_CTX_new();
-    if (inctx == NULL)
+    ssl_ctx = SSL_get_SSL_CTX(s);
+    if (!SSL_CTX_get0_chain_certs(ssl_ctx, &chain))
         goto err;
-    if (!X509_STORE_CTX_init(inctx,
-                             SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
-                             NULL, NULL))
-        goto err;
-    obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509,
-                                            X509_get_issuer_name(x));
-    if (obj == NULL) {
-        BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
-        goto done;
+    for (i = 0; i < sk_X509_num(chain); i++) {
+        /* check the untrusted certificate chain (-cert_chain option) */
+        cert = sk_X509_value(chain, i);
+        if (X509_name_cmp(iname, X509_get_subject_name(cert)) == 0) {
+            /* the issuer certificate is found */
+            id = OCSP_cert_to_id(NULL, x, cert);
+            break;
+        }
+    }
+    if (id == NULL) {
+        inctx = X509_STORE_CTX_new();
+        if (inctx == NULL)
+            goto err;
+        if (!X509_STORE_CTX_init(inctx, SSL_CTX_get_cert_store(ssl_ctx),
+                                 NULL, NULL))
+            goto err;
+        obj = X509_STORE_CTX_get_obj_by_subject(inctx, X509_LU_X509, iname);
+        if (obj == NULL) {
+            BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
+            goto done;
+        }
+        id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
+        X509_OBJECT_free(obj);
     }
-    id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
-    X509_OBJECT_free(obj);
     if (id == NULL)
         goto err;
     req = OCSP_REQUEST_new();

+ 2 - 3
libs/openssl/apps/s_time.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -310,7 +310,6 @@ int s_time_main(int argc, char **argv)
     }
     totalTime += tm_Time_F(STOP); /* Add the time for this iteration */
 
-    i = (int)((long)time(NULL) - finishtime + maxtime);
     printf
         ("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
          nConn, totalTime, ((double)nConn / totalTime), bytes_read);
@@ -338,7 +337,7 @@ int s_time_main(int argc, char **argv)
         buf_len = BIO_snprintf(buf, sizeof(buf), fmt_http_get_cmd, www_path);
         if (buf_len <= 0 || SSL_write(scon, buf, buf_len) <= 0)
             goto end;
-        while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
+        while (SSL_read(scon, buf, sizeof(buf)) > 0)
             continue;
     }
     SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);

+ 120 - 58
libs/openssl/apps/speed.c

@@ -47,12 +47,6 @@
 # include <unistd.h>
 #endif
 
-#if defined(__TANDEM)
-# if defined(OPENSSL_TANDEM_FLOSS)
-#  include <floss.h(floss_fork)>
-# endif
-#endif
-
 #if defined(_WIN32)
 # include <windows.h>
 /*
@@ -305,17 +299,18 @@ enum {
     D_CBC_RC2, D_CBC_RC5, D_CBC_BF, D_CBC_CAST,
     D_CBC_128_AES, D_CBC_192_AES, D_CBC_256_AES,
     D_CBC_128_CML, D_CBC_192_CML, D_CBC_256_CML,
-    D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, ALGOR_NUM
+    D_EVP, D_GHASH, D_RAND, D_EVP_CMAC, D_KMAC128, D_KMAC256,
+    ALGOR_NUM
 };
 /* name of algorithms to test. MUST BE KEEP IN SYNC with above enum ! */
 static const char *names[ALGOR_NUM] = {
     "md2", "mdc2", "md4", "md5", "sha1", "rmd160",
-    "sha256", "sha512", "whirlpool", "hmac(md5)",
+    "sha256", "sha512", "whirlpool", "hmac(sha256)",
     "des-cbc", "des-ede3", "rc4", "idea-cbc", "seed-cbc",
     "rc2-cbc", "rc5-cbc", "blowfish", "cast-cbc",
     "aes-128-cbc", "aes-192-cbc", "aes-256-cbc",
     "camellia-128-cbc", "camellia-192-cbc", "camellia-256-cbc",
-    "evp", "ghash", "rand", "cmac"
+    "evp", "ghash", "rand", "cmac", "kmac128", "kmac256"
 };
 
 /* list of configured algorithm (remaining), with some few alias */
@@ -356,7 +351,9 @@ static const OPT_PAIR doit_choices[] = {
     {"cast", D_CBC_CAST},
     {"cast5", D_CBC_CAST},
     {"ghash", D_GHASH},
-    {"rand", D_RAND}
+    {"rand", D_RAND},
+    {"kmac128", D_KMAC128},
+    {"kmac256", D_KMAC256},
 };
 
 static double results[ALGOR_NUM][SIZE_NUM];
@@ -570,7 +567,7 @@ static int run_benchmark(int async_jobs, int (*loop_function) (void *),
 
 static unsigned int testnum;
 
-static char *evp_mac_mdname = "md5";
+static char *evp_mac_mdname = "sha256";
 static char *evp_hmac_name = NULL;
 static const char *evp_md_name = NULL;
 static char *evp_mac_ciphername = "aes-128-cbc";
@@ -655,6 +652,41 @@ static int MD5_loop(void *args)
     return EVP_Digest_loop("md5", D_MD5, args);
 }
 
+static int mac_setup(const char *name,
+                     EVP_MAC **mac, OSSL_PARAM params[],
+                     loopargs_t *loopargs, unsigned int loopargs_len)
+{
+    unsigned int i;
+
+    *mac = EVP_MAC_fetch(app_get0_libctx(), name, app_get0_propq());
+    if (*mac == NULL)
+        return 0;
+
+    for (i = 0; i < loopargs_len; i++) {
+        loopargs[i].mctx = EVP_MAC_CTX_new(*mac);
+        if (loopargs[i].mctx == NULL)
+            return 0;
+
+        if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
+            return 0;
+    }
+
+    return 1;
+}
+
+static void mac_teardown(EVP_MAC **mac,
+                         loopargs_t *loopargs, unsigned int loopargs_len)
+{
+    unsigned int i;
+
+    for (i = 0; i < loopargs_len; i++)
+        EVP_MAC_CTX_free(loopargs[i].mctx);
+    EVP_MAC_free(*mac);
+    *mac = NULL;
+
+    return;
+}
+
 static int EVP_MAC_loop(ossl_unused int algindex, void *args)
 {
     loopargs_t *tempargs = *(loopargs_t **) args;
@@ -684,6 +716,16 @@ static int CMAC_loop(void *args)
     return EVP_MAC_loop(D_EVP_CMAC, args);
 }
 
+static int KMAC128_loop(void *args)
+{
+    return EVP_MAC_loop(D_KMAC128, args);
+}
+
+static int KMAC256_loop(void *args)
+{
+    return EVP_MAC_loop(D_KMAC256, args);
+}
+
 static int SHA1_loop(void *args)
 {
     return EVP_Digest_loop("sha1", D_SHA1, args);
@@ -2226,6 +2268,14 @@ int speed_main(int argc, char **argv)
             do_sigs = 1;
             algo_found = 1;
         }
+        if (strcmp(algo, "kmac") == 0) {
+            doit[D_KMAC128] = doit[D_KMAC256] = 1;
+            algo_found = 1;
+        }
+        if (strcmp(algo, "cmac") == 0) {
+            doit[D_EVP_CMAC] = 1;
+            algo_found = 1;
+        }
 
         if (!algo_found) {
             BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
@@ -2525,10 +2575,8 @@ int speed_main(int argc, char **argv)
         int len = strlen(hmac_key);
         OSSL_PARAM params[3];
 
-        mac = EVP_MAC_fetch(app_get0_libctx(), "HMAC", app_get0_propq());
-        if (mac == NULL || evp_mac_mdname == NULL)
+        if (evp_mac_mdname == NULL)
             goto end;
-
         evp_hmac_name = app_malloc(sizeof("hmac()") + strlen(evp_mac_mdname),
                                    "HMAC name");
         sprintf(evp_hmac_name, "hmac(%s)", evp_mac_mdname);
@@ -2542,14 +2590,8 @@ int speed_main(int argc, char **argv)
                                               (char *)hmac_key, len);
         params[2] = OSSL_PARAM_construct_end();
 
-        for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].mctx = EVP_MAC_CTX_new(mac);
-            if (loopargs[i].mctx == NULL)
-                goto end;
-
-            if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
-                goto skip_hmac; /* Digest not found */
-        }
+        if (mac_setup("HMAC", &mac, params, loopargs, loopargs_len) < 1)
+            goto end;
         for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_HMAC], lengths[testnum], seconds.sym);
             Time_F(START);
@@ -2559,12 +2601,9 @@ int speed_main(int argc, char **argv)
             if (count < 0)
                 break;
         }
-        for (i = 0; i < loopargs_len; i++)
-            EVP_MAC_CTX_free(loopargs[i].mctx);
-        EVP_MAC_free(mac);
-        mac = NULL;
+        mac_teardown(&mac, loopargs, loopargs_len);
     }
-skip_hmac:
+
     if (doit[D_CBC_DES]) {
         int st = 1;
 
@@ -2681,25 +2720,22 @@ skip_hmac:
     }
     if (doit[D_GHASH]) {
         static const char gmac_iv[] = "0123456789ab";
-        OSSL_PARAM params[3];
-
-        mac = EVP_MAC_fetch(app_get0_libctx(), "GMAC", app_get0_propq());
-        if (mac == NULL)
-            goto end;
+        OSSL_PARAM params[4];
 
         params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER,
                                                      "aes-128-gcm", 0);
         params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
                                                       (char *)gmac_iv,
                                                       sizeof(gmac_iv) - 1);
-        params[2] = OSSL_PARAM_construct_end();
+        params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+                                                      (void *)key32, 16);
+        params[3] = OSSL_PARAM_construct_end();
 
+        if (mac_setup("GMAC", &mac, params, loopargs, loopargs_len) < 1)
+            goto end;
+        /* b/c of the definition of GHASH_loop(), init() calls are needed here */
         for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].mctx = EVP_MAC_CTX_new(mac);
-            if (loopargs[i].mctx == NULL)
-                goto end;
-
-            if (!EVP_MAC_init(loopargs[i].mctx, key32, 16, params))
+            if (!EVP_MAC_init(loopargs[i].mctx, NULL, 0, NULL))
                 goto end;
         }
         for (testnum = 0; testnum < size_num; testnum++) {
@@ -2711,10 +2747,7 @@ skip_hmac:
             if (count < 0)
                 break;
         }
-        for (i = 0; i < loopargs_len; i++)
-            EVP_MAC_CTX_free(loopargs[i].mctx);
-        EVP_MAC_free(mac);
-        mac = NULL;
+        mac_teardown(&mac, loopargs, loopargs_len);
     }
 
     if (doit[D_RAND]) {
@@ -2813,9 +2846,6 @@ skip_hmac:
         OSSL_PARAM params[3];
         EVP_CIPHER *cipher = NULL;
 
-        mac = EVP_MAC_fetch(app_get0_libctx(), "CMAC", app_get0_propq());
-        if (mac == NULL || evp_mac_ciphername == NULL)
-            goto end;
         if (!opt_cipher(evp_mac_ciphername, &cipher))
             goto end;
 
@@ -2836,15 +2866,8 @@ skip_hmac:
                                                       (char *)key32, keylen);
         params[2] = OSSL_PARAM_construct_end();
 
-        for (i = 0; i < loopargs_len; i++) {
-            loopargs[i].mctx = EVP_MAC_CTX_new(mac);
-            if (loopargs[i].mctx == NULL)
-                goto end;
-
-            if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params))
-                goto end;
-        }
-
+        if (mac_setup("CMAC", &mac, params, loopargs, loopargs_len) < 1)
+            goto end;
         for (testnum = 0; testnum < size_num; testnum++) {
             print_message(names[D_EVP_CMAC], lengths[testnum], seconds.sym);
             Time_F(START);
@@ -2854,10 +2877,49 @@ skip_hmac:
             if (count < 0)
                 break;
         }
-        for (i = 0; i < loopargs_len; i++)
-            EVP_MAC_CTX_free(loopargs[i].mctx);
-        EVP_MAC_free(mac);
-        mac = NULL;
+        mac_teardown(&mac, loopargs, loopargs_len);
+    }
+
+    if (doit[D_KMAC128]) {
+        OSSL_PARAM params[2];
+
+        params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+                                                      (void *)key32, 16);
+        params[1] = OSSL_PARAM_construct_end();
+
+        if (mac_setup("KMAC-128", &mac, params, loopargs, loopargs_len) < 1)
+            goto end;
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_KMAC128], lengths[testnum], seconds.sym);
+            Time_F(START);
+            count = run_benchmark(async_jobs, KMAC128_loop, loopargs);
+            d = Time_F(STOP);
+            print_result(D_KMAC128, testnum, count, d);
+            if (count < 0)
+                break;
+        }
+        mac_teardown(&mac, loopargs, loopargs_len);
+    }
+
+    if (doit[D_KMAC256]) {
+        OSSL_PARAM params[2];
+
+        params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+                                                      (void *)key32, 32);
+        params[1] = OSSL_PARAM_construct_end();
+
+        if (mac_setup("KMAC-256", &mac, params, loopargs, loopargs_len) < 1)
+            goto end;
+        for (testnum = 0; testnum < size_num; testnum++) {
+            print_message(names[D_KMAC256], lengths[testnum], seconds.sym);
+            Time_F(START);
+            count = run_benchmark(async_jobs, KMAC256_loop, loopargs);
+            d = Time_F(STOP);
+            print_result(D_KMAC256, testnum, count, d);
+            if (count < 0)
+                break;
+        }
+        mac_teardown(&mac, loopargs, loopargs_len);
     }
 
     for (i = 0; i < loopargs_len; i++)

+ 20 - 6
libs/openssl/apps/x509.c

@@ -44,7 +44,7 @@ typedef enum OPTION_choice {
     OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM,
     OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE,
     OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY,
-    OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ,
+    OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_ISSU, OPT_SUBJ,
     OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT,
     OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL,
     OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH,
@@ -139,7 +139,9 @@ const OPTIONS x509_options[] = {
      "Number of days until newly generated certificate expires - default 30"},
     {"preserve_dates", OPT_PRESERVE_DATES, '-',
      "Preserve existing validity dates"},
-    {"subj", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
+    {"set_issuer", OPT_ISSU, 's', "Set or override certificate issuer"},
+    {"set_subject", OPT_SUBJ, 's', "Set or override certificate subject (and issuer)"},
+    {"subj", OPT_SUBJ, 's', "Alias for -set_subject"},
     {"force_pubkey", OPT_FORCE_PUBKEY, '<',
      "Key to be placed in new certificate or certificate request"},
     {"clrext", OPT_CLREXT, '-',
@@ -263,8 +265,8 @@ int x509_main(int argc, char **argv)
     EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL;
     EVP_PKEY *pkey;
     int newcert = 0;
-    char *subj = NULL, *digest = NULL;
-    X509_NAME *fsubj = NULL;
+    char *issu = NULL, *subj = NULL, *digest = NULL;
+    X509_NAME *fissu = NULL, *fsubj = NULL;
     const unsigned long chtype = MBSTRING_ASC;
     const int multirdn = 1;
     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
@@ -426,6 +428,9 @@ int x509_main(int argc, char **argv)
         case OPT_FORCE_PUBKEY:
             pubkeyfile = opt_arg();
             break;
+        case OPT_ISSU:
+            issu = opt_arg();
+            break;
         case OPT_SUBJ:
             subj = opt_arg();
             break;
@@ -652,6 +657,9 @@ int x509_main(int argc, char **argv)
             goto err;
         }
     }
+    if (issu != NULL
+            && (fissu = parse_name(issu, chtype, multirdn, "issuer")) == NULL)
+        goto end;
     if (subj != NULL
             && (fsubj = parse_name(subj, chtype, multirdn, "subject")) == NULL)
         goto end;
@@ -831,8 +839,13 @@ int x509_main(int argc, char **argv)
     if (reqfile || newcert || privkey != NULL || CAfile != NULL) {
         if (!preserve_dates && !set_cert_times(x, NULL, NULL, days))
             goto end;
-        if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
-            goto end;
+        if (fissu != NULL) {
+            if (!X509_set_issuer_name(x, fissu))
+                goto end;
+        } else {
+            if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert)))
+                goto end;
+        }
     }
 
     X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE);
@@ -1080,6 +1093,7 @@ int x509_main(int argc, char **argv)
     NCONF_free(extconf);
     BIO_free_all(out);
     X509_STORE_free(ctx);
+    X509_NAME_free(fissu);
     X509_NAME_free(fsubj);
     X509_REQ_free(req);
     X509_free(x);

+ 25 - 0
libs/openssl/build.info

@@ -8,6 +8,7 @@ ENDIF
 IF[{- !$disabled{'deprecated-3.0'} -}]
   SUBDIRS=engines
 ENDIF
+SUBDIRS=exporters
 
 LIBS=libcrypto libssl
 INCLUDE[libcrypto]=. include
@@ -99,3 +100,27 @@ IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}]
   SHARED_SOURCE[libcrypto]=libcrypto.rc
   SHARED_SOURCE[libssl]=libssl.rc
 ENDIF
+
+# This file sets the build directory up for CMake inclusion
+GENERATE[OpenSSLConfig.cmake]=exporters/cmake/OpenSSLConfig.cmake.in
+DEPEND[OpenSSLConfig.cmake]=builddata.pm
+GENERATE[OpenSSLConfigVersion.cmake]=exporters/cmake/OpenSSLConfigVersion.cmake.in
+DEPEND[OpenSSLConfigVersion.cmake]=builddata.pm
+DEPEND[OpenSSLConfigVersion.cmake]=OpenSSLConfig.cmake
+DEPEND[""]=OpenSSLConfigVersion.cmake
+
+# This file sets the build directory up for pkg-config
+GENERATE[libcrypto.pc]=exporters/pkg-config/libcrypto.pc.in
+DEPEND[libcrypto.pc]=builddata.pm
+GENERATE[libssl.pc]=exporters/pkg-config/libssl.pc.in
+DEPEND[libssl.pc]=builddata.pm
+GENERATE[openssl.pc]=exporters/pkg-config/openssl.pc.in
+DEPEND[openssl.pc]=builddata.pm
+DEPEND[openssl.pc]=libcrypto.pc libssl.pc
+
+GENERATE[builddata.pm]=util/mkinstallvars.pl \
+    PREFIX=. BINDIR=apps LIBDIR= INCLUDEDIR=include APPLINKDIR=ms \
+    ENGINESDIR=engines MODULESDIR=providers \
+    "VERSION=$(VERSION)" "LDLIBS=$(LIB_EX_LIBS)"
+
+DEPEND[""]=openssl.pc

+ 0 - 3
libs/openssl/crypto/aes/aes_x86core.c

@@ -81,13 +81,10 @@ static void prefetch256(const void *table)
 #define GETU32(p) (*((u32*)(p)))
 
 #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
-typedef unsigned __int64 u64;
 #define U64(C)  C##UI64
 #elif defined(__arch64__)
-typedef unsigned long u64;
 #define U64(C)  C##UL
 #else
-typedef unsigned long long u64;
 #define U64(C)  C##ULL
 #endif
 

+ 710 - 0
libs/openssl/crypto/aes/asm/aes-riscv64-zvbb-zvkg-zvkned.pl

@@ -0,0 +1,710 @@
+#! /usr/bin/env perl
+# This file is dual-licensed, meaning that you can use it under your
+# choice of either of the following two licenses:
+#
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You can obtain
+# a copy in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# or
+#
+# Copyright (c) 2023, Jerry Shih <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# - RV64I
+# - RISC-V Vector ('V') with VLEN >= 128
+# - RISC-V Vector Bit-manipulation extension ('Zvbb')
+# - RISC-V Vector GCM/GMAC extension ('Zvkg')
+# - RISC-V Vector AES block cipher extension ('Zvkned')
+# - RISC-V Zicclsm(Main memory supports misaligned loads/stores)
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin";
+use lib "$Bin/../../perlasm";
+use riscv;
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
+
+my $code=<<___;
+.text
+___
+
+{
+################################################################################
+# void rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt(const unsigned char *in,
+#                                             unsigned char *out, size_t length,
+#                                             const AES_KEY *key1,
+#                                             const AES_KEY *key2,
+#                                             const unsigned char iv[16])
+my ($INPUT, $OUTPUT, $LENGTH, $KEY1, $KEY2, $IV) = ("a0", "a1", "a2", "a3", "a4", "a5");
+my ($TAIL_LENGTH) = ("a6");
+my ($VL) = ("a7");
+my ($T0, $T1, $T2) = ("t0", "t1", "t2");
+my ($STORE_LEN32) = ("t3");
+my ($LEN32) = ("t4");
+my ($V0, $V1, $V2, $V3, $V4, $V5, $V6, $V7,
+    $V8, $V9, $V10, $V11, $V12, $V13, $V14, $V15,
+    $V16, $V17, $V18, $V19, $V20, $V21, $V22, $V23,
+    $V24, $V25, $V26, $V27, $V28, $V29, $V30, $V31,
+) = map("v$_",(0..31));
+
+sub compute_xts_iv0 {
+    my $code=<<___;
+    # Load number of rounds
+    lwu $T0, 240($KEY2)
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V28, $IV]}
+    @{[vle32_v $V29, $KEY2]}
+    @{[vaesz_vs $V28, $V29]}
+    addi $T0, $T0, -1
+    addi $KEY2, $KEY2, 16
+1:
+    @{[vle32_v $V29, $KEY2]}
+    @{[vaesem_vs $V28, $V29]}
+    addi $T0, $T0, -1
+    addi $KEY2, $KEY2, 16
+    bnez $T0, 1b
+    @{[vle32_v $V29, $KEY2]}
+    @{[vaesef_vs $V28, $V29]}
+___
+
+    return $code;
+}
+
+# prepare input data(v24), iv(v28), bit-reversed-iv(v16), bit-reversed-iv-multiplier(v20)
+sub init_first_round {
+    my $code=<<___;
+    # load input
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vle32_v $V24, $INPUT]}
+
+    li $T0, 5
+    # We could simplify the initialization steps if we have `block<=1`.
+    blt $LEN32, $T0, 1f
+
+    # Note: We use `vgmul` for GF(2^128) multiplication. The `vgmul` uses
+    # different order of coefficients. We should use`vbrev8` to reverse the
+    # data when we use `vgmul`.
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vbrev8_v $V0, $V28]}
+    @{[vsetvli "zero", $LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vmv_v_i $V16, 0]}
+    # v16: [r-IV0, r-IV0, ...]
+    @{[vaesz_vs $V16, $V0]}
+
+    # Prepare GF(2^128) multiplier [1, x, x^2, x^3, ...] in v8.
+    slli $T0, $LEN32, 2
+    @{[vsetvli "zero", $T0, "e32", "m1", "ta", "ma"]}
+    # v2: [`1`, `1`, `1`, `1`, ...]
+    @{[vmv_v_i $V2, 1]}
+    # v3: [`0`, `1`, `2`, `3`, ...]
+    @{[vid_v $V3]}
+    @{[vsetvli "zero", $T0, "e64", "m2", "ta", "ma"]}
+    # v4: [`1`, 0, `1`, 0, `1`, 0, `1`, 0, ...]
+    @{[vzext_vf2 $V4, $V2]}
+    # v6: [`0`, 0, `1`, 0, `2`, 0, `3`, 0, ...]
+    @{[vzext_vf2 $V6, $V3]}
+    slli $T0, $LEN32, 1
+    @{[vsetvli "zero", $T0, "e32", "m2", "ta", "ma"]}
+    # v8: [1<<0=1, 0, 0, 0, 1<<1=x, 0, 0, 0, 1<<2=x^2, 0, 0, 0, ...]
+    @{[vwsll_vv $V8, $V4, $V6]}
+
+    # Compute [r-IV0*1, r-IV0*x, r-IV0*x^2, r-IV0*x^3, ...] in v16
+    @{[vsetvli "zero", $LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vbrev8_v $V8, $V8]}
+    @{[vgmul_vv $V16, $V8]}
+
+    # Compute [IV0*1, IV0*x, IV0*x^2, IV0*x^3, ...] in v28.
+    # Reverse the bits order back.
+    @{[vbrev8_v $V28, $V16]}
+
+    # Prepare the x^n multiplier in v20. The `n` is the aes-xts block number
+    # in a LMUL=4 register group.
+    #   n = ((VLEN*LMUL)/(32*4)) = ((VLEN*4)/(32*4))
+    #     = (VLEN/32)
+    # We could use vsetvli with `e32, m1` to compute the `n` number.
+    @{[vsetvli $T0, "zero", "e32", "m1", "ta", "ma"]}
+    li $T1, 1
+    sll $T0, $T1, $T0
+    @{[vsetivli "zero", 2, "e64", "m1", "ta", "ma"]}
+    @{[vmv_v_i $V0, 0]}
+    @{[vsetivli "zero", 1, "e64", "m1", "tu", "ma"]}
+    @{[vmv_v_x $V0, $T0]}
+    @{[vsetivli "zero", 2, "e64", "m1", "ta", "ma"]}
+    @{[vbrev8_v $V0, $V0]}
+    @{[vsetvli "zero", $LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vmv_v_i $V20, 0]}
+    @{[vaesz_vs $V20, $V0]}
+
+    j 2f
+1:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vbrev8_v $V16, $V28]}
+2:
+___
+
+    return $code;
+}
+
+# prepare xts enc last block's input(v24) and iv(v28)
+sub handle_xts_enc_last_block {
+    my $code=<<___;
+    bnez $TAIL_LENGTH, 1f
+    ret
+1:
+    # slidedown second to last block
+    addi $VL, $VL, -4
+    @{[vsetivli "zero", 4, "e32", "m4", "ta", "ma"]}
+    # ciphertext
+    @{[vslidedown_vx $V24, $V24, $VL]}
+    # multiplier
+    @{[vslidedown_vx $V16, $V16, $VL]}
+
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vmv_v_v $V25, $V24]}
+
+    # load last block into v24
+    # note: We should load the last block before store the second to last block
+    #       for in-place operation.
+    @{[vsetvli "zero", $TAIL_LENGTH, "e8", "m1", "tu", "ma"]}
+    @{[vle8_v $V24, $INPUT]}
+
+    # setup `x` multiplier with byte-reversed order
+    # 0b00000010 => 0b01000000 (0x40)
+    li $T0, 0x40
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vmv_v_i $V28, 0]}
+    @{[vsetivli "zero", 1, "e8", "m1", "tu", "ma"]}
+    @{[vmv_v_x $V28, $T0]}
+
+    # compute IV for last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vgmul_vv $V16, $V28]}
+    @{[vbrev8_v $V28, $V16]}
+
+    # store second to last block
+    @{[vsetvli "zero", $TAIL_LENGTH, "e8", "m1", "ta", "ma"]}
+    @{[vse8_v $V25, $OUTPUT]}
+___
+
+    return $code;
+}
+
+# prepare xts dec second to last block's input(v24) and iv(v29) and
+# last block's and iv(v28)
+sub handle_xts_dec_last_block {
+    my $code=<<___;
+    bnez $TAIL_LENGTH, 1f
+    ret
+1:
+    # load second to last block's ciphertext
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V24, $INPUT]}
+    addi $INPUT, $INPUT, 16
+
+    # setup `x` multiplier with byte-reversed order
+    # 0b00000010 => 0b01000000 (0x40)
+    li $T0, 0x40
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vmv_v_i $V20, 0]}
+    @{[vsetivli "zero", 1, "e8", "m1", "tu", "ma"]}
+    @{[vmv_v_x $V20, $T0]}
+
+    beqz $LENGTH, 1f
+    # slidedown third to last block
+    addi $VL, $VL, -4
+    @{[vsetivli "zero", 4, "e32", "m4", "ta", "ma"]}
+    # multiplier
+    @{[vslidedown_vx $V16, $V16, $VL]}
+
+    # compute IV for last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vgmul_vv $V16, $V20]}
+    @{[vbrev8_v $V28, $V16]}
+
+    # compute IV for second to last block
+    @{[vgmul_vv $V16, $V20]}
+    @{[vbrev8_v $V29, $V16]}
+    j 2f
+1:
+    # compute IV for second to last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vgmul_vv $V16, $V20]}
+    @{[vbrev8_v $V29, $V16]}
+2:
+___
+
+    return $code;
+}
+
+# Load all 11 round keys to v1-v11 registers.
+sub aes_128_load_key {
+    my $code=<<___;
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V2, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V3, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V4, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V5, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V6, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V7, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V8, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V9, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V10, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V11, $KEY1]}
+___
+
+    return $code;
+}
+
+# Load all 15 round keys to v1-v15 registers.
+sub aes_256_load_key {
+    my $code=<<___;
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V2, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V3, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V4, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V5, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V6, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V7, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V8, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V9, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V10, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V11, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V12, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V13, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V14, $KEY1]}
+    addi $KEY1, $KEY1, 16
+    @{[vle32_v $V15, $KEY1]}
+___
+
+    return $code;
+}
+
+# aes-128 enc with round keys v1-v11
+sub aes_128_enc {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V1]}
+    @{[vaesem_vs $V24, $V2]}
+    @{[vaesem_vs $V24, $V3]}
+    @{[vaesem_vs $V24, $V4]}
+    @{[vaesem_vs $V24, $V5]}
+    @{[vaesem_vs $V24, $V6]}
+    @{[vaesem_vs $V24, $V7]}
+    @{[vaesem_vs $V24, $V8]}
+    @{[vaesem_vs $V24, $V9]}
+    @{[vaesem_vs $V24, $V10]}
+    @{[vaesef_vs $V24, $V11]}
+___
+
+    return $code;
+}
+
+# aes-128 dec with round keys v1-v11
+sub aes_128_dec {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V11]}
+    @{[vaesdm_vs $V24, $V10]}
+    @{[vaesdm_vs $V24, $V9]}
+    @{[vaesdm_vs $V24, $V8]}
+    @{[vaesdm_vs $V24, $V7]}
+    @{[vaesdm_vs $V24, $V6]}
+    @{[vaesdm_vs $V24, $V5]}
+    @{[vaesdm_vs $V24, $V4]}
+    @{[vaesdm_vs $V24, $V3]}
+    @{[vaesdm_vs $V24, $V2]}
+    @{[vaesdf_vs $V24, $V1]}
+___
+
+    return $code;
+}
+
+# aes-256 enc with round keys v1-v15
+sub aes_256_enc {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V1]}
+    @{[vaesem_vs $V24, $V2]}
+    @{[vaesem_vs $V24, $V3]}
+    @{[vaesem_vs $V24, $V4]}
+    @{[vaesem_vs $V24, $V5]}
+    @{[vaesem_vs $V24, $V6]}
+    @{[vaesem_vs $V24, $V7]}
+    @{[vaesem_vs $V24, $V8]}
+    @{[vaesem_vs $V24, $V9]}
+    @{[vaesem_vs $V24, $V10]}
+    @{[vaesem_vs $V24, $V11]}
+    @{[vaesem_vs $V24, $V12]}
+    @{[vaesem_vs $V24, $V13]}
+    @{[vaesem_vs $V24, $V14]}
+    @{[vaesef_vs $V24, $V15]}
+___
+
+    return $code;
+}
+
+# aes-256 dec with round keys v1-v15
+sub aes_256_dec {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V15]}
+    @{[vaesdm_vs $V24, $V14]}
+    @{[vaesdm_vs $V24, $V13]}
+    @{[vaesdm_vs $V24, $V12]}
+    @{[vaesdm_vs $V24, $V11]}
+    @{[vaesdm_vs $V24, $V10]}
+    @{[vaesdm_vs $V24, $V9]}
+    @{[vaesdm_vs $V24, $V8]}
+    @{[vaesdm_vs $V24, $V7]}
+    @{[vaesdm_vs $V24, $V6]}
+    @{[vaesdm_vs $V24, $V5]}
+    @{[vaesdm_vs $V24, $V4]}
+    @{[vaesdm_vs $V24, $V3]}
+    @{[vaesdm_vs $V24, $V2]}
+    @{[vaesdf_vs $V24, $V1]}
+___
+
+    return $code;
+}
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt
+.type rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt,\@function
+rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt:
+    @{[compute_xts_iv0]}
+
+    # aes block size is 16
+    andi $TAIL_LENGTH, $LENGTH, 15
+    mv $STORE_LEN32, $LENGTH
+    beqz $TAIL_LENGTH, 1f
+    sub $LENGTH, $LENGTH, $TAIL_LENGTH
+    addi $STORE_LEN32, $LENGTH, -16
+1:
+    # We make the `LENGTH` become e32 length here.
+    srli $LEN32, $LENGTH, 2
+    srli $STORE_LEN32, $STORE_LEN32, 2
+
+    # Load number of rounds
+    lwu $T0, 240($KEY1)
+    li $T1, 14
+    li $T2, 10
+    beq $T0, $T1, aes_xts_enc_256
+    beq $T0, $T2, aes_xts_enc_128
+.size rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt,.-rv64i_zvbb_zvkg_zvkned_aes_xts_encrypt
+___
+
+$code .= <<___;
+.p2align 3
+aes_xts_enc_128:
+    @{[init_first_round]}
+    @{[aes_128_load_key]}
+
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    j 1f
+
+.Lenc_blocks_128:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    # load plaintext into v24
+    @{[vle32_v $V24, $INPUT]}
+    # update iv
+    @{[vgmul_vv $V16, $V20]}
+    # reverse the iv's bits order back
+    @{[vbrev8_v $V28, $V16]}
+1:
+    @{[vxor_vv $V24, $V24, $V28]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INPUT, $INPUT, $T0
+    @{[aes_128_enc]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store ciphertext
+    @{[vsetvli "zero", $STORE_LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vse32_v $V24, $OUTPUT]}
+    add $OUTPUT, $OUTPUT, $T0
+    sub $STORE_LEN32, $STORE_LEN32, $VL
+
+    bnez $LEN32, .Lenc_blocks_128
+
+    @{[handle_xts_enc_last_block]}
+
+    # xts last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V28]}
+    @{[aes_128_enc]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store last block ciphertext
+    addi $OUTPUT, $OUTPUT, -16
+    @{[vse32_v $V24, $OUTPUT]}
+
+    ret
+.size aes_xts_enc_128,.-aes_xts_enc_128
+___
+
+$code .= <<___;
+.p2align 3
+aes_xts_enc_256:
+    @{[init_first_round]}
+    @{[aes_256_load_key]}
+
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    j 1f
+
+.Lenc_blocks_256:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    # load plaintext into v24
+    @{[vle32_v $V24, $INPUT]}
+    # update iv
+    @{[vgmul_vv $V16, $V20]}
+    # reverse the iv's bits order back
+    @{[vbrev8_v $V28, $V16]}
+1:
+    @{[vxor_vv $V24, $V24, $V28]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INPUT, $INPUT, $T0
+    @{[aes_256_enc]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store ciphertext
+    @{[vsetvli "zero", $STORE_LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vse32_v $V24, $OUTPUT]}
+    add $OUTPUT, $OUTPUT, $T0
+    sub $STORE_LEN32, $STORE_LEN32, $VL
+
+    bnez $LEN32, .Lenc_blocks_256
+
+    @{[handle_xts_enc_last_block]}
+
+    # xts last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V28]}
+    @{[aes_256_enc]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store last block ciphertext
+    addi $OUTPUT, $OUTPUT, -16
+    @{[vse32_v $V24, $OUTPUT]}
+
+    ret
+.size aes_xts_enc_256,.-aes_xts_enc_256
+___
+
+################################################################################
+# void rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt(const unsigned char *in,
+#                                             unsigned char *out, size_t length,
+#                                             const AES_KEY *key1,
+#                                             const AES_KEY *key2,
+#                                             const unsigned char iv[16])
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt
+.type rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt,\@function
+rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt:
+    @{[compute_xts_iv0]}
+
+    # aes block size is 16
+    andi $TAIL_LENGTH, $LENGTH, 15
+    beqz $TAIL_LENGTH, 1f
+    sub $LENGTH, $LENGTH, $TAIL_LENGTH
+    addi $LENGTH, $LENGTH, -16
+1:
+    # We make the `LENGTH` become e32 length here.
+    srli $LEN32, $LENGTH, 2
+
+    # Load number of rounds
+    lwu $T0, 240($KEY1)
+    li $T1, 14
+    li $T2, 10
+    beq $T0, $T1, aes_xts_dec_256
+    beq $T0, $T2, aes_xts_dec_128
+.size rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt,.-rv64i_zvbb_zvkg_zvkned_aes_xts_decrypt
+___
+
+$code .= <<___;
+.p2align 3
+aes_xts_dec_128:
+    @{[init_first_round]}
+    @{[aes_128_load_key]}
+
+    beqz $LEN32, 2f
+
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    j 1f
+
+.Ldec_blocks_128:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    # load ciphertext into v24
+    @{[vle32_v $V24, $INPUT]}
+    # update iv
+    @{[vgmul_vv $V16, $V20]}
+    # reverse the iv's bits order back
+    @{[vbrev8_v $V28, $V16]}
+1:
+    @{[vxor_vv $V24, $V24, $V28]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INPUT, $INPUT, $T0
+    @{[aes_128_dec]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store plaintext
+    @{[vse32_v $V24, $OUTPUT]}
+    add $OUTPUT, $OUTPUT, $T0
+
+    bnez $LEN32, .Ldec_blocks_128
+
+2:
+    @{[handle_xts_dec_last_block]}
+
+    ## xts second to last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V29]}
+    @{[aes_128_dec]}
+    @{[vxor_vv $V24, $V24, $V29]}
+    @{[vmv_v_v $V25, $V24]}
+
+    # load last block ciphertext
+    @{[vsetvli "zero", $TAIL_LENGTH, "e8", "m1", "tu", "ma"]}
+    @{[vle8_v $V24, $INPUT]}
+
+    # store second to last block plaintext
+    addi $T0, $OUTPUT, 16
+    @{[vse8_v $V25, $T0]}
+
+    ## xts last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V28]}
+    @{[aes_128_dec]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store second to last block plaintext
+    @{[vse32_v $V24, $OUTPUT]}
+
+    ret
+.size aes_xts_dec_128,.-aes_xts_dec_128
+___
+
+$code .= <<___;
+.p2align 3
+aes_xts_dec_256:
+    @{[init_first_round]}
+    @{[aes_256_load_key]}
+
+    beqz $LEN32, 2f
+
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    j 1f
+
+.Ldec_blocks_256:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    # load ciphertext into v24
+    @{[vle32_v $V24, $INPUT]}
+    # update iv
+    @{[vgmul_vv $V16, $V20]}
+    # reverse the iv's bits order back
+    @{[vbrev8_v $V28, $V16]}
+1:
+    @{[vxor_vv $V24, $V24, $V28]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INPUT, $INPUT, $T0
+    @{[aes_256_dec]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store plaintext
+    @{[vse32_v $V24, $OUTPUT]}
+    add $OUTPUT, $OUTPUT, $T0
+
+    bnez $LEN32, .Ldec_blocks_256
+
+2:
+    @{[handle_xts_dec_last_block]}
+
+    ## xts second to last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V29]}
+    @{[aes_256_dec]}
+    @{[vxor_vv $V24, $V24, $V29]}
+    @{[vmv_v_v $V25, $V24]}
+
+    # load last block ciphertext
+    @{[vsetvli "zero", $TAIL_LENGTH, "e8", "m1", "tu", "ma"]}
+    @{[vle8_v $V24, $INPUT]}
+
+    # store second to last block plaintext
+    addi $T0, $OUTPUT, 16
+    @{[vse8_v $V25, $T0]}
+
+    ## xts last block
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vxor_vv $V24, $V24, $V28]}
+    @{[aes_256_dec]}
+    @{[vxor_vv $V24, $V24, $V28]}
+
+    # store second to last block plaintext
+    @{[vse32_v $V24, $OUTPUT]}
+
+    ret
+.size aes_xts_dec_256,.-aes_xts_dec_256
+___
+}
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";

+ 376 - 0
libs/openssl/crypto/aes/asm/aes-riscv64-zvkb-zvkned.pl

@@ -0,0 +1,376 @@
+#! /usr/bin/env perl
+# This file is dual-licensed, meaning that you can use it under your
+# choice of either of the following two licenses:
+#
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You can obtain
+# a copy in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# or
+#
+# Copyright (c) 2023, Jerry Shih <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# - RV64I
+# - RISC-V Vector ('V') with VLEN >= 128
+# - RISC-V Vector Cryptography Bit-manipulation extension ('Zvkb')
+# - RISC-V Vector AES block cipher extension ('Zvkned')
+# - RISC-V Zicclsm(Main memory supports misaligned loads/stores)
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin";
+use lib "$Bin/../../perlasm";
+use riscv;
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
+
+my $code=<<___;
+.text
+___
+
+################################################################################
+# void rv64i_zvkb_zvkned_ctr32_encrypt_blocks(const unsigned char *in,
+#                                             unsigned char *out, size_t blocks,
+#                                             const void *key,
+#                                             const unsigned char ivec[16]);
+{
+my ($INP, $OUTP, $BLOCK_NUM, $KEYP, $IVP) = ("a0", "a1", "a2", "a3", "a4");
+my ($T0, $T1, $T2, $T3) = ("t0", "t1", "t2", "t3");
+my ($VL) = ("t4");
+my ($LEN32) = ("t5");
+my ($CTR) = ("t6");
+my ($MASK) = ("v0");
+my ($V0, $V1, $V2, $V3, $V4, $V5, $V6, $V7,
+    $V8, $V9, $V10, $V11, $V12, $V13, $V14, $V15,
+    $V16, $V17, $V18, $V19, $V20, $V21, $V22, $V23,
+    $V24, $V25, $V26, $V27, $V28, $V29, $V30, $V31,
+) = map("v$_",(0..31));
+
+# Prepare the AES ctr input data into v16.
+sub init_aes_ctr_input {
+    my $code=<<___;
+    # Setup mask into v0
+    # The mask pattern for 4*N-th elements
+    # mask v0: [000100010001....]
+    # Note:
+    #   We could setup the mask just for the maximum element length instead of
+    #   the VLMAX.
+    li $T0, 0b10001000
+    @{[vsetvli $T2, "zero", "e8", "m1", "ta", "ma"]}
+    @{[vmv_v_x $MASK, $T0]}
+    # Load IV.
+    # v31:[IV0, IV1, IV2, big-endian count]
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V31, $IVP]}
+    # Convert the big-endian counter into little-endian.
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "mu"]}
+    @{[vrev8_v $V31, $V31, $MASK]}
+    # Splat the IV to v16
+    @{[vsetvli "zero", $LEN32, "e32", "m4", "ta", "ma"]}
+    @{[vmv_v_i $V16, 0]}
+    @{[vaesz_vs $V16, $V31]}
+    # Prepare the ctr pattern into v20
+    # v20: [x, x, x, 0, x, x, x, 1, x, x, x, 2, ...]
+    @{[viota_m $V20, $MASK, $MASK]}
+    # v16:[IV0, IV1, IV2, count+0, IV0, IV1, IV2, count+1, ...]
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "mu"]}
+    @{[vadd_vv $V16, $V16, $V20, $MASK]}
+___
+
+    return $code;
+}
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkb_zvkned_ctr32_encrypt_blocks
+.type rv64i_zvkb_zvkned_ctr32_encrypt_blocks,\@function
+rv64i_zvkb_zvkned_ctr32_encrypt_blocks:
+    beqz $BLOCK_NUM, 1f
+
+    # Load number of rounds
+    lwu $T0, 240($KEYP)
+    li $T1, 14
+    li $T2, 12
+    li $T3, 10
+
+    slli $LEN32, $BLOCK_NUM, 2
+
+    beq $T0, $T1, ctr32_encrypt_blocks_256
+    beq $T0, $T2, ctr32_encrypt_blocks_192
+    beq $T0, $T3, ctr32_encrypt_blocks_128
+
+1:
+    ret
+
+.size rv64i_zvkb_zvkned_ctr32_encrypt_blocks,.-rv64i_zvkb_zvkned_ctr32_encrypt_blocks
+___
+
+$code .= <<___;
+.p2align 3
+ctr32_encrypt_blocks_128:
+    # Load all 11 round keys to v1-v11 registers.
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+
+    @{[init_aes_ctr_input]}
+
+    ##### AES body
+    j 2f
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "mu"]}
+    # Increase ctr in v16.
+    @{[vadd_vx $V16, $V16, $CTR, $MASK]}
+2:
+    # Load plaintext into v20
+    @{[vle32_v $V20, $INP]}
+    slli $T0, $VL, 2
+    srli $CTR, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INP, $INP, $T0
+    # Prepare the AES ctr input into v24.
+    # The ctr data uses big-endian form.
+    @{[vmv_v_v $V24, $V16]}
+    @{[vrev8_v $V24, $V24, $MASK]}
+
+    @{[vaesz_vs $V24, $V1]}
+    @{[vaesem_vs $V24, $V2]}
+    @{[vaesem_vs $V24, $V3]}
+    @{[vaesem_vs $V24, $V4]}
+    @{[vaesem_vs $V24, $V5]}
+    @{[vaesem_vs $V24, $V6]}
+    @{[vaesem_vs $V24, $V7]}
+    @{[vaesem_vs $V24, $V8]}
+    @{[vaesem_vs $V24, $V9]}
+    @{[vaesem_vs $V24, $V10]}
+    @{[vaesef_vs $V24, $V11]}
+
+    # ciphertext
+    @{[vxor_vv $V24, $V24, $V20]}
+
+    # Store the ciphertext.
+    @{[vse32_v $V24, $OUTP]}
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size ctr32_encrypt_blocks_128,.-ctr32_encrypt_blocks_128
+___
+
+$code .= <<___;
+.p2align 3
+ctr32_encrypt_blocks_192:
+    # Load all 13 round keys to v1-v13 registers.
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+
+    @{[init_aes_ctr_input]}
+
+    ##### AES body
+    j 2f
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "mu"]}
+    # Increase ctr in v16.
+    @{[vadd_vx $V16, $V16, $CTR, $MASK]}
+2:
+    # Load plaintext into v20
+    @{[vle32_v $V20, $INP]}
+    slli $T0, $VL, 2
+    srli $CTR, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INP, $INP, $T0
+    # Prepare the AES ctr input into v24.
+    # The ctr data uses big-endian form.
+    @{[vmv_v_v $V24, $V16]}
+    @{[vrev8_v $V24, $V24, $MASK]}
+
+    @{[vaesz_vs $V24, $V1]}
+    @{[vaesem_vs $V24, $V2]}
+    @{[vaesem_vs $V24, $V3]}
+    @{[vaesem_vs $V24, $V4]}
+    @{[vaesem_vs $V24, $V5]}
+    @{[vaesem_vs $V24, $V6]}
+    @{[vaesem_vs $V24, $V7]}
+    @{[vaesem_vs $V24, $V8]}
+    @{[vaesem_vs $V24, $V9]}
+    @{[vaesem_vs $V24, $V10]}
+    @{[vaesem_vs $V24, $V11]}
+    @{[vaesem_vs $V24, $V12]}
+    @{[vaesef_vs $V24, $V13]}
+
+    # ciphertext
+    @{[vxor_vv $V24, $V24, $V20]}
+
+    # Store the ciphertext.
+    @{[vse32_v $V24, $OUTP]}
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size ctr32_encrypt_blocks_192,.-ctr32_encrypt_blocks_192
+___
+
+$code .= <<___;
+.p2align 3
+ctr32_encrypt_blocks_256:
+    # Load all 15 round keys to v1-v15 registers.
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V14, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V15, $KEYP]}
+
+    @{[init_aes_ctr_input]}
+
+    ##### AES body
+    j 2f
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "mu"]}
+    # Increase ctr in v16.
+    @{[vadd_vx $V16, $V16, $CTR, $MASK]}
+2:
+    # Load plaintext into v20
+    @{[vle32_v $V20, $INP]}
+    slli $T0, $VL, 2
+    srli $CTR, $VL, 2
+    sub $LEN32, $LEN32, $VL
+    add $INP, $INP, $T0
+    # Prepare the AES ctr input into v24.
+    # The ctr data uses big-endian form.
+    @{[vmv_v_v $V24, $V16]}
+    @{[vrev8_v $V24, $V24, $MASK]}
+
+    @{[vaesz_vs $V24, $V1]}
+    @{[vaesem_vs $V24, $V2]}
+    @{[vaesem_vs $V24, $V3]}
+    @{[vaesem_vs $V24, $V4]}
+    @{[vaesem_vs $V24, $V5]}
+    @{[vaesem_vs $V24, $V6]}
+    @{[vaesem_vs $V24, $V7]}
+    @{[vaesem_vs $V24, $V8]}
+    @{[vaesem_vs $V24, $V9]}
+    @{[vaesem_vs $V24, $V10]}
+    @{[vaesem_vs $V24, $V11]}
+    @{[vaesem_vs $V24, $V12]}
+    @{[vaesem_vs $V24, $V13]}
+    @{[vaesem_vs $V24, $V14]}
+    @{[vaesef_vs $V24, $V15]}
+
+    # ciphertext
+    @{[vxor_vv $V24, $V24, $V20]}
+
+    # Store the ciphertext.
+    @{[vse32_v $V24, $OUTP]}
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size ctr32_encrypt_blocks_256,.-ctr32_encrypt_blocks_256
+___
+}
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";

+ 1376 - 0
libs/openssl/crypto/aes/asm/aes-riscv64-zvkned.pl

@@ -0,0 +1,1376 @@
+#! /usr/bin/env perl
+# This file is dual-licensed, meaning that you can use it under your
+# choice of either of the following two licenses:
+#
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License"). You can obtain
+# a copy in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+#
+# or
+#
+# Copyright (c) 2023, Christoph Müllner <[email protected]>
+# Copyright (c) 2023, Phoebe Chen <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# - RV64I
+# - RISC-V Vector ('V') with VLEN >= 128
+# - RISC-V Vector AES block cipher extension ('Zvkned')
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin";
+use lib "$Bin/../../perlasm";
+use riscv;
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
+
+my $code=<<___;
+.text
+___
+
+my ($V0, $V1, $V2, $V3, $V4, $V5, $V6, $V7,
+    $V8, $V9, $V10, $V11, $V12, $V13, $V14, $V15,
+    $V16, $V17, $V18, $V19, $V20, $V21, $V22, $V23,
+    $V24, $V25, $V26, $V27, $V28, $V29, $V30, $V31,
+) = map("v$_",(0..31));
+
+# Load all 11 round keys to v1-v11 registers.
+sub aes_128_load_key {
+    my $KEYP = shift;
+
+    my $code=<<___;
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+___
+
+    return $code;
+}
+
+# Load all 13 round keys to v1-v13 registers.
+sub aes_192_load_key {
+    my $KEYP = shift;
+
+    my $code=<<___;
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+___
+
+    return $code;
+}
+
+# Load all 15 round keys to v1-v15 registers.
+sub aes_256_load_key {
+    my $KEYP = shift;
+
+    my $code=<<___;
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+    @{[vle32_v $V1, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V2, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V3, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V4, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V5, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V6, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V7, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V8, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V9, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V14, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V15, $KEYP]}
+___
+
+    return $code;
+}
+
+# aes-128 encryption with round keys v1-v11
+sub aes_128_encrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V1]}     # with round key w[ 0, 3]
+    @{[vaesem_vs $V24, $V2]}    # with round key w[ 4, 7]
+    @{[vaesem_vs $V24, $V3]}    # with round key w[ 8,11]
+    @{[vaesem_vs $V24, $V4]}    # with round key w[12,15]
+    @{[vaesem_vs $V24, $V5]}    # with round key w[16,19]
+    @{[vaesem_vs $V24, $V6]}    # with round key w[20,23]
+    @{[vaesem_vs $V24, $V7]}    # with round key w[24,27]
+    @{[vaesem_vs $V24, $V8]}    # with round key w[28,31]
+    @{[vaesem_vs $V24, $V9]}    # with round key w[32,35]
+    @{[vaesem_vs $V24, $V10]}   # with round key w[36,39]
+    @{[vaesef_vs $V24, $V11]}   # with round key w[40,43]
+___
+
+    return $code;
+}
+
+# aes-128 decryption with round keys v1-v11
+sub aes_128_decrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V11]}   # with round key w[40,43]
+    @{[vaesdm_vs $V24, $V10]}  # with round key w[36,39]
+    @{[vaesdm_vs $V24, $V9]}   # with round key w[32,35]
+    @{[vaesdm_vs $V24, $V8]}   # with round key w[28,31]
+    @{[vaesdm_vs $V24, $V7]}   # with round key w[24,27]
+    @{[vaesdm_vs $V24, $V6]}   # with round key w[20,23]
+    @{[vaesdm_vs $V24, $V5]}   # with round key w[16,19]
+    @{[vaesdm_vs $V24, $V4]}   # with round key w[12,15]
+    @{[vaesdm_vs $V24, $V3]}   # with round key w[ 8,11]
+    @{[vaesdm_vs $V24, $V2]}   # with round key w[ 4, 7]
+    @{[vaesdf_vs $V24, $V1]}   # with round key w[ 0, 3]
+___
+
+    return $code;
+}
+
+# aes-192 encryption with round keys v1-v13
+sub aes_192_encrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V1]}     # with round key w[ 0, 3]
+    @{[vaesem_vs $V24, $V2]}    # with round key w[ 4, 7]
+    @{[vaesem_vs $V24, $V3]}    # with round key w[ 8,11]
+    @{[vaesem_vs $V24, $V4]}    # with round key w[12,15]
+    @{[vaesem_vs $V24, $V5]}    # with round key w[16,19]
+    @{[vaesem_vs $V24, $V6]}    # with round key w[20,23]
+    @{[vaesem_vs $V24, $V7]}    # with round key w[24,27]
+    @{[vaesem_vs $V24, $V8]}    # with round key w[28,31]
+    @{[vaesem_vs $V24, $V9]}    # with round key w[32,35]
+    @{[vaesem_vs $V24, $V10]}   # with round key w[36,39]
+    @{[vaesem_vs $V24, $V11]}   # with round key w[40,43]
+    @{[vaesem_vs $V24, $V12]}   # with round key w[44,47]
+    @{[vaesef_vs $V24, $V13]}   # with round key w[48,51]
+___
+
+    return $code;
+}
+
+# aes-192 decryption with round keys v1-v13
+sub aes_192_decrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V13]}    # with round key w[48,51]
+    @{[vaesdm_vs $V24, $V12]}   # with round key w[44,47]
+    @{[vaesdm_vs $V24, $V11]}   # with round key w[40,43]
+    @{[vaesdm_vs $V24, $V10]}   # with round key w[36,39]
+    @{[vaesdm_vs $V24, $V9]}    # with round key w[32,35]
+    @{[vaesdm_vs $V24, $V8]}    # with round key w[28,31]
+    @{[vaesdm_vs $V24, $V7]}    # with round key w[24,27]
+    @{[vaesdm_vs $V24, $V6]}    # with round key w[20,23]
+    @{[vaesdm_vs $V24, $V5]}    # with round key w[16,19]
+    @{[vaesdm_vs $V24, $V4]}    # with round key w[12,15]
+    @{[vaesdm_vs $V24, $V3]}    # with round key w[ 8,11]
+    @{[vaesdm_vs $V24, $V2]}    # with round key w[ 4, 7]
+    @{[vaesdf_vs $V24, $V1]}    # with round key w[ 0, 3]
+___
+
+    return $code;
+}
+
+# aes-256 encryption with round keys v1-v15
+sub aes_256_encrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V1]}     # with round key w[ 0, 3]
+    @{[vaesem_vs $V24, $V2]}    # with round key w[ 4, 7]
+    @{[vaesem_vs $V24, $V3]}    # with round key w[ 8,11]
+    @{[vaesem_vs $V24, $V4]}    # with round key w[12,15]
+    @{[vaesem_vs $V24, $V5]}    # with round key w[16,19]
+    @{[vaesem_vs $V24, $V6]}    # with round key w[20,23]
+    @{[vaesem_vs $V24, $V7]}    # with round key w[24,27]
+    @{[vaesem_vs $V24, $V8]}    # with round key w[28,31]
+    @{[vaesem_vs $V24, $V9]}    # with round key w[32,35]
+    @{[vaesem_vs $V24, $V10]}   # with round key w[36,39]
+    @{[vaesem_vs $V24, $V11]}   # with round key w[40,43]
+    @{[vaesem_vs $V24, $V12]}   # with round key w[44,47]
+    @{[vaesem_vs $V24, $V13]}   # with round key w[48,51]
+    @{[vaesem_vs $V24, $V14]}   # with round key w[52,55]
+    @{[vaesef_vs $V24, $V15]}   # with round key w[56,59]
+___
+
+    return $code;
+}
+
+# aes-256 decryption with round keys v1-v15
+sub aes_256_decrypt {
+    my $code=<<___;
+    @{[vaesz_vs $V24, $V15]}    # with round key w[56,59]
+    @{[vaesdm_vs $V24, $V14]}   # with round key w[52,55]
+    @{[vaesdm_vs $V24, $V13]}   # with round key w[48,51]
+    @{[vaesdm_vs $V24, $V12]}   # with round key w[44,47]
+    @{[vaesdm_vs $V24, $V11]}   # with round key w[40,43]
+    @{[vaesdm_vs $V24, $V10]}   # with round key w[36,39]
+    @{[vaesdm_vs $V24, $V9]}    # with round key w[32,35]
+    @{[vaesdm_vs $V24, $V8]}    # with round key w[28,31]
+    @{[vaesdm_vs $V24, $V7]}    # with round key w[24,27]
+    @{[vaesdm_vs $V24, $V6]}    # with round key w[20,23]
+    @{[vaesdm_vs $V24, $V5]}    # with round key w[16,19]
+    @{[vaesdm_vs $V24, $V4]}    # with round key w[12,15]
+    @{[vaesdm_vs $V24, $V3]}    # with round key w[ 8,11]
+    @{[vaesdm_vs $V24, $V2]}    # with round key w[ 4, 7]
+    @{[vaesdf_vs $V24, $V1]}    # with round key w[ 0, 3]
+___
+
+    return $code;
+}
+
+{
+###############################################################################
+# void rv64i_zvkned_cbc_encrypt(const unsigned char *in, unsigned char *out,
+#                               size_t length, const AES_KEY *key,
+#                               unsigned char *ivec, const int enc);
+my ($INP, $OUTP, $LEN, $KEYP, $IVP, $ENC) = ("a0", "a1", "a2", "a3", "a4", "a5");
+my ($T0, $T1, $ROUNDS) = ("t0", "t1", "t2");
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_cbc_encrypt
+.type rv64i_zvkned_cbc_encrypt,\@function
+rv64i_zvkned_cbc_encrypt:
+    # check whether the length is a multiple of 16 and >= 16
+    li $T1, 16
+    blt $LEN, $T1, L_end
+    andi $T1, $LEN, 15
+    bnez $T1, L_end
+
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T0, 10
+    beq $ROUNDS, $T0, L_cbc_enc_128
+
+    li $T0, 12
+    beq $ROUNDS, $T0, L_cbc_enc_192
+
+    li $T0, 14
+    beq $ROUNDS, $T0, L_cbc_enc_256
+
+    ret
+.size rv64i_zvkned_cbc_encrypt,.-rv64i_zvkned_cbc_encrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_enc_128:
+    # Load all 11 round keys to v1-v11 registers.
+    @{[aes_128_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vxor_vv $V24, $V24, $V16]}
+    j 2f
+
+1:
+    @{[vle32_v $V17, $INP]}
+    @{[vxor_vv $V24, $V24, $V17]}
+
+2:
+    # AES body
+    @{[aes_128_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    addi $INP, $INP, 16
+    addi $OUTP, $OUTP, 16
+    addi $LEN, $LEN, -16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V24, $IVP]}
+
+    ret
+.size L_cbc_enc_128,.-L_cbc_enc_128
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_enc_192:
+    # Load all 13 round keys to v1-v13 registers.
+    @{[aes_192_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vxor_vv $V24, $V24, $V16]}
+    j 2f
+
+1:
+    @{[vle32_v $V17, $INP]}
+    @{[vxor_vv $V24, $V24, $V17]}
+
+2:
+    # AES body
+    @{[aes_192_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    addi $INP, $INP, 16
+    addi $OUTP, $OUTP, 16
+    addi $LEN, $LEN, -16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V24, $IVP]}
+
+    ret
+.size L_cbc_enc_192,.-L_cbc_enc_192
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_enc_256:
+    # Load all 15 round keys to v1-v15 registers.
+    @{[aes_256_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vxor_vv $V24, $V24, $V16]}
+    j 2f
+
+1:
+    @{[vle32_v $V17, $INP]}
+    @{[vxor_vv $V24, $V24, $V17]}
+
+2:
+    # AES body
+    @{[aes_256_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    addi $INP, $INP, 16
+    addi $OUTP, $OUTP, 16
+    addi $LEN, $LEN, -16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V24, $IVP]}
+
+    ret
+.size L_cbc_enc_256,.-L_cbc_enc_256
+___
+
+###############################################################################
+# void rv64i_zvkned_cbc_decrypt(const unsigned char *in, unsigned char *out,
+#                               size_t length, const AES_KEY *key,
+#                               unsigned char *ivec, const int enc);
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_cbc_decrypt
+.type rv64i_zvkned_cbc_decrypt,\@function
+rv64i_zvkned_cbc_decrypt:
+    # check whether the length is a multiple of 16 and >= 16
+    li $T1, 16
+    blt $LEN, $T1, L_end
+    andi $T1, $LEN, 15
+    bnez $T1, L_end
+
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T0, 10
+    beq $ROUNDS, $T0, L_cbc_dec_128
+
+    li $T0, 12
+    beq $ROUNDS, $T0, L_cbc_dec_192
+
+    li $T0, 14
+    beq $ROUNDS, $T0, L_cbc_dec_256
+
+    ret
+.size rv64i_zvkned_cbc_decrypt,.-rv64i_zvkned_cbc_decrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_dec_128:
+    # Load all 11 round keys to v1-v11 registers.
+    @{[aes_128_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    j 2f
+
+1:
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    addi $OUTP, $OUTP, 16
+
+2:
+    # AES body
+    @{[aes_128_decrypt]}
+
+    @{[vxor_vv $V24, $V24, $V16]}
+    @{[vse32_v $V24, $OUTP]}
+    @{[vmv_v_v $V16, $V17]}
+
+    addi $LEN, $LEN, -16
+    addi $INP, $INP, 16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V16, $IVP]}
+
+    ret
+.size L_cbc_dec_128,.-L_cbc_dec_128
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_dec_192:
+    # Load all 13 round keys to v1-v13 registers.
+    @{[aes_192_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    j 2f
+
+1:
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    addi $OUTP, $OUTP, 16
+
+2:
+    # AES body
+    @{[aes_192_decrypt]}
+
+    @{[vxor_vv $V24, $V24, $V16]}
+    @{[vse32_v $V24, $OUTP]}
+    @{[vmv_v_v $V16, $V17]}
+
+    addi $LEN, $LEN, -16
+    addi $INP, $INP, 16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V16, $IVP]}
+
+    ret
+.size L_cbc_dec_192,.-L_cbc_dec_192
+___
+
+$code .= <<___;
+.p2align 3
+L_cbc_dec_256:
+    # Load all 15 round keys to v1-v15 registers.
+    @{[aes_256_load_key $KEYP]}
+
+    # Load IV.
+    @{[vle32_v $V16, $IVP]}
+
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    j 2f
+
+1:
+    @{[vle32_v $V24, $INP]}
+    @{[vmv_v_v $V17, $V24]}
+    addi $OUTP, $OUTP, 16
+
+2:
+    # AES body
+    @{[aes_256_decrypt]}
+
+    @{[vxor_vv $V24, $V24, $V16]}
+    @{[vse32_v $V24, $OUTP]}
+    @{[vmv_v_v $V16, $V17]}
+
+    addi $LEN, $LEN, -16
+    addi $INP, $INP, 16
+
+    bnez $LEN, 1b
+
+    @{[vse32_v $V16, $IVP]}
+
+    ret
+.size L_cbc_dec_256,.-L_cbc_dec_256
+___
+}
+
+{
+###############################################################################
+# void rv64i_zvkned_ecb_encrypt(const unsigned char *in, unsigned char *out,
+#                               size_t length, const AES_KEY *key,
+#                               const int enc);
+my ($INP, $OUTP, $LEN, $KEYP, $ENC) = ("a0", "a1", "a2", "a3", "a4");
+my ($REMAIN_LEN) = ("a5");
+my ($VL) = ("a6");
+my ($T0, $T1, $ROUNDS) = ("t0", "t1", "t2");
+my ($LEN32) = ("t3");
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_ecb_encrypt
+.type rv64i_zvkned_ecb_encrypt,\@function
+rv64i_zvkned_ecb_encrypt:
+    # Make the LEN become e32 length.
+    srli $LEN32, $LEN, 2
+
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T0, 10
+    beq $ROUNDS, $T0, L_ecb_enc_128
+
+    li $T0, 12
+    beq $ROUNDS, $T0, L_ecb_enc_192
+
+    li $T0, 14
+    beq $ROUNDS, $T0, L_ecb_enc_256
+
+    ret
+.size rv64i_zvkned_ecb_encrypt,.-rv64i_zvkned_ecb_encrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_enc_128:
+    # Load all 11 round keys to v1-v11 registers.
+    @{[aes_128_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_128_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_enc_128,.-L_ecb_enc_128
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_enc_192:
+    # Load all 13 round keys to v1-v13 registers.
+    @{[aes_192_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_192_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_enc_192,.-L_ecb_enc_192
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_enc_256:
+    # Load all 15 round keys to v1-v15 registers.
+    @{[aes_256_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_256_encrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_enc_256,.-L_ecb_enc_256
+___
+
+###############################################################################
+# void rv64i_zvkned_ecb_decrypt(const unsigned char *in, unsigned char *out,
+#                               size_t length, const AES_KEY *key,
+#                               const int enc);
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_ecb_decrypt
+.type rv64i_zvkned_ecb_decrypt,\@function
+rv64i_zvkned_ecb_decrypt:
+    # Make the LEN become e32 length.
+    srli $LEN32, $LEN, 2
+
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T0, 10
+    beq $ROUNDS, $T0, L_ecb_dec_128
+
+    li $T0, 12
+    beq $ROUNDS, $T0, L_ecb_dec_192
+
+    li $T0, 14
+    beq $ROUNDS, $T0, L_ecb_dec_256
+
+    ret
+.size rv64i_zvkned_ecb_decrypt,.-rv64i_zvkned_ecb_decrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_dec_128:
+    # Load all 11 round keys to v1-v11 registers.
+    @{[aes_128_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_128_decrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_dec_128,.-L_ecb_dec_128
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_dec_192:
+    # Load all 13 round keys to v1-v13 registers.
+    @{[aes_192_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_192_decrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_dec_192,.-L_ecb_dec_192
+___
+
+$code .= <<___;
+.p2align 3
+L_ecb_dec_256:
+    # Load all 15 round keys to v1-v15 registers.
+    @{[aes_256_load_key $KEYP]}
+
+1:
+    @{[vsetvli $VL, $LEN32, "e32", "m4", "ta", "ma"]}
+    slli $T0, $VL, 2
+    sub $LEN32, $LEN32, $VL
+
+    @{[vle32_v $V24, $INP]}
+
+    # AES body
+    @{[aes_256_decrypt]}
+
+    @{[vse32_v $V24, $OUTP]}
+
+    add $INP, $INP, $T0
+    add $OUTP, $OUTP, $T0
+
+    bnez $LEN32, 1b
+
+    ret
+.size L_ecb_dec_256,.-L_ecb_dec_256
+___
+
+}
+
+{
+################################################################################
+# int rv64i_zvkned_set_encrypt_key(const unsigned char *userKey, const int bits,
+#                                  AES_KEY *key)
+# int rv64i_zvkned_set_decrypt_key(const unsigned char *userKey, const int bits,
+#                                  AES_KEY *key)
+my ($UKEY,$BITS,$KEYP) = ("a0", "a1", "a2");
+my ($T0,$T1,$T4) = ("t1", "t2", "t4");
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_set_encrypt_key
+.type rv64i_zvkned_set_encrypt_key,\@function
+rv64i_zvkned_set_encrypt_key:
+    beqz $UKEY, L_fail_m1
+    beqz $KEYP, L_fail_m1
+
+    # Get proper routine for key size
+    li $T0, 256
+    beq $BITS, $T0, L_set_key_256
+    li $T0, 128
+    beq $BITS, $T0, L_set_key_128
+
+    j L_fail_m2
+
+.size rv64i_zvkned_set_encrypt_key,.-rv64i_zvkned_set_encrypt_key
+___
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_set_decrypt_key
+.type rv64i_zvkned_set_decrypt_key,\@function
+rv64i_zvkned_set_decrypt_key:
+    beqz $UKEY, L_fail_m1
+    beqz $KEYP, L_fail_m1
+
+    # Get proper routine for key size
+    li $T0, 256
+    beq $BITS, $T0, L_set_key_256
+    li $T0, 128
+    beq $BITS, $T0, L_set_key_128
+
+    j L_fail_m2
+
+.size rv64i_zvkned_set_decrypt_key,.-rv64i_zvkned_set_decrypt_key
+___
+
+$code .= <<___;
+.p2align 3
+L_set_key_128:
+    # Store the number of rounds
+    li $T1, 10
+    sw $T1, 240($KEYP)
+
+    @{[vsetivli__x0_4_e32_m1_tu_mu]}
+
+    # Load the key
+    @{[vle32_v $V10, ($UKEY)]}
+
+    # Generate keys for round 2-11 into registers v11-v20.
+    @{[vaeskf1_vi $V11, $V10, 1]}   # v11 <- rk2  (w[ 4, 7])
+    @{[vaeskf1_vi $V12, $V11, 2]}   # v12 <- rk3  (w[ 8,11])
+    @{[vaeskf1_vi $V13, $V12, 3]}   # v13 <- rk4  (w[12,15])
+    @{[vaeskf1_vi $V14, $V13, 4]}   # v14 <- rk5  (w[16,19])
+    @{[vaeskf1_vi $V15, $V14, 5]}   # v15 <- rk6  (w[20,23])
+    @{[vaeskf1_vi $V16, $V15, 6]}   # v16 <- rk7  (w[24,27])
+    @{[vaeskf1_vi $V17, $V16, 7]}   # v17 <- rk8  (w[28,31])
+    @{[vaeskf1_vi $V18, $V17, 8]}   # v18 <- rk9  (w[32,35])
+    @{[vaeskf1_vi $V19, $V18, 9]}   # v19 <- rk10 (w[36,39])
+    @{[vaeskf1_vi $V20, $V19, 10]}  # v20 <- rk11 (w[40,43])
+
+    # Store the round keys
+    @{[vse32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V13, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V14, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V15, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V16, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V17, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V18, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V19, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V20, $KEYP]}
+
+    li a0, 1
+    ret
+.size L_set_key_128,.-L_set_key_128
+___
+
+$code .= <<___;
+.p2align 3
+L_set_key_256:
+    # Store the number of rounds
+    li $T1, 14
+    sw $T1, 240($KEYP)
+
+    @{[vsetivli__x0_4_e32_m1_tu_mu]}
+
+    # Load the key
+    @{[vle32_v $V10, ($UKEY)]}
+    addi $UKEY, $UKEY, 16
+    @{[vle32_v $V11, ($UKEY)]}
+
+    @{[vmv_v_v $V12, $V10]}
+    @{[vaeskf2_vi $V12, $V11, 2]}
+    @{[vmv_v_v $V13, $V11]}
+    @{[vaeskf2_vi $V13, $V12, 3]}
+    @{[vmv_v_v $V14, $V12]}
+    @{[vaeskf2_vi $V14, $V13, 4]}
+    @{[vmv_v_v $V15, $V13]}
+    @{[vaeskf2_vi $V15, $V14, 5]}
+    @{[vmv_v_v $V16, $V14]}
+    @{[vaeskf2_vi $V16, $V15, 6]}
+    @{[vmv_v_v $V17, $V15]}
+    @{[vaeskf2_vi $V17, $V16, 7]}
+    @{[vmv_v_v $V18, $V16]}
+    @{[vaeskf2_vi $V18, $V17, 8]}
+    @{[vmv_v_v $V19, $V17]}
+    @{[vaeskf2_vi $V19, $V18, 9]}
+    @{[vmv_v_v $V20, $V18]}
+    @{[vaeskf2_vi $V20, $V19, 10]}
+    @{[vmv_v_v $V21, $V19]}
+    @{[vaeskf2_vi $V21, $V20, 11]}
+    @{[vmv_v_v $V22, $V20]}
+    @{[vaeskf2_vi $V22, $V21, 12]}
+    @{[vmv_v_v $V23, $V21]}
+    @{[vaeskf2_vi $V23, $V22, 13]}
+    @{[vmv_v_v $V24, $V22]}
+    @{[vaeskf2_vi $V24, $V23, 14]}
+
+    @{[vse32_v $V10, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V11, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V12, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V13, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V14, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V15, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V16, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V17, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V18, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V19, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V20, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V21, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V22, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V23, $KEYP]}
+    addi $KEYP, $KEYP, 16
+    @{[vse32_v $V24, $KEYP]}
+
+    li a0, 1
+    ret
+.size L_set_key_256,.-L_set_key_256
+___
+}
+
+{
+################################################################################
+# void rv64i_zvkned_encrypt(const unsigned char *in, unsigned char *out,
+#                           const AES_KEY *key);
+my ($INP,$OUTP,$KEYP) = ("a0", "a1", "a2");
+my ($T0,$T1, $ROUNDS, $T6) = ("a3", "a4", "t5", "t6");
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_encrypt
+.type rv64i_zvkned_encrypt,\@function
+rv64i_zvkned_encrypt:
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T6, 14
+    beq $ROUNDS, $T6, L_enc_256
+    li $T6, 10
+    beq $ROUNDS, $T6, L_enc_128
+    li $T6, 12
+    beq $ROUNDS, $T6, L_enc_192
+
+    j L_fail_m2
+.size rv64i_zvkned_encrypt,.-rv64i_zvkned_encrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_enc_128:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesz_vs $V1, $V10]}    # with round key w[ 0, 3]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesem_vs $V1, $V11]}   # with round key w[ 4, 7]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesem_vs $V1, $V12]}   # with round key w[ 8,11]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesem_vs $V1, $V13]}   # with round key w[12,15]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesem_vs $V1, $V14]}   # with round key w[16,19]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesem_vs $V1, $V15]}   # with round key w[20,23]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesem_vs $V1, $V16]}   # with round key w[24,27]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesem_vs $V1, $V17]}   # with round key w[28,31]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesem_vs $V1, $V18]}   # with round key w[32,35]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesem_vs $V1, $V19]}   # with round key w[36,39]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesef_vs $V1, $V20]}   # with round key w[40,43]
+
+    @{[vse32_v $V1, $OUTP]}
+
+    ret
+.size L_enc_128,.-L_enc_128
+___
+
+$code .= <<___;
+.p2align 3
+L_enc_192:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesz_vs $V1, $V10]}     # with round key w[ 0, 3]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesem_vs $V1, $V11]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesem_vs $V1, $V12]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesem_vs $V1, $V13]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesem_vs $V1, $V14]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesem_vs $V1, $V15]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesem_vs $V1, $V16]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesem_vs $V1, $V17]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesem_vs $V1, $V18]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesem_vs $V1, $V19]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesem_vs $V1, $V20]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V21, $KEYP]}
+    @{[vaesem_vs $V1, $V21]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V22, $KEYP]}
+    @{[vaesef_vs $V1, $V22]}
+
+    @{[vse32_v $V1, $OUTP]}
+    ret
+.size L_enc_192,.-L_enc_192
+___
+
+$code .= <<___;
+.p2align 3
+L_enc_256:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesz_vs $V1, $V10]}     # with round key w[ 0, 3]
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesem_vs $V1, $V11]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesem_vs $V1, $V12]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesem_vs $V1, $V13]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesem_vs $V1, $V14]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesem_vs $V1, $V15]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesem_vs $V1, $V16]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesem_vs $V1, $V17]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesem_vs $V1, $V18]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesem_vs $V1, $V19]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesem_vs $V1, $V20]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V21, $KEYP]}
+    @{[vaesem_vs $V1, $V21]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V22, $KEYP]}
+    @{[vaesem_vs $V1, $V22]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V23, $KEYP]}
+    @{[vaesem_vs $V1, $V23]}
+    addi $KEYP, $KEYP, 16
+    @{[vle32_v $V24, $KEYP]}
+    @{[vaesef_vs $V1, $V24]}
+
+    @{[vse32_v $V1, $OUTP]}
+    ret
+.size L_enc_256,.-L_enc_256
+___
+
+################################################################################
+# void rv64i_zvkned_decrypt(const unsigned char *in, unsigned char *out,
+#                           const AES_KEY *key);
+
+$code .= <<___;
+.p2align 3
+.globl rv64i_zvkned_decrypt
+.type rv64i_zvkned_decrypt,\@function
+rv64i_zvkned_decrypt:
+    # Load number of rounds
+    lwu $ROUNDS, 240($KEYP)
+
+    # Get proper routine for key size
+    li $T6, 14
+    beq $ROUNDS, $T6, L_dec_256
+    li $T6, 10
+    beq $ROUNDS, $T6, L_dec_128
+    li $T6, 12
+    beq $ROUNDS, $T6, L_dec_192
+
+    j L_fail_m2
+.size rv64i_zvkned_decrypt,.-rv64i_zvkned_decrypt
+___
+
+$code .= <<___;
+.p2align 3
+L_dec_128:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    addi $KEYP, $KEYP, 160
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesz_vs $V1, $V20]}    # with round key w[40,43]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesdm_vs $V1, $V19]}   # with round key w[36,39]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesdm_vs $V1, $V18]}   # with round key w[32,35]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesdm_vs $V1, $V17]}   # with round key w[28,31]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesdm_vs $V1, $V16]}   # with round key w[24,27]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesdm_vs $V1, $V15]}   # with round key w[20,23]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesdm_vs $V1, $V14]}   # with round key w[16,19]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesdm_vs $V1, $V13]}   # with round key w[12,15]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesdm_vs $V1, $V12]}   # with round key w[ 8,11]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesdm_vs $V1, $V11]}   # with round key w[ 4, 7]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesdf_vs $V1, $V10]}   # with round key w[ 0, 3]
+
+    @{[vse32_v $V1, $OUTP]}
+
+    ret
+.size L_dec_128,.-L_dec_128
+___
+
+$code .= <<___;
+.p2align 3
+L_dec_192:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    addi $KEYP, $KEYP, 192
+    @{[vle32_v $V22, $KEYP]}
+    @{[vaesz_vs $V1, $V22]}    # with round key w[48,51]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V21, $KEYP]}
+    @{[vaesdm_vs $V1, $V21]}   # with round key w[44,47]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesdm_vs $V1, $V20]}    # with round key w[40,43]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesdm_vs $V1, $V19]}   # with round key w[36,39]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesdm_vs $V1, $V18]}   # with round key w[32,35]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesdm_vs $V1, $V17]}   # with round key w[28,31]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesdm_vs $V1, $V16]}   # with round key w[24,27]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesdm_vs $V1, $V15]}   # with round key w[20,23]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesdm_vs $V1, $V14]}   # with round key w[16,19]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesdm_vs $V1, $V13]}   # with round key w[12,15]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesdm_vs $V1, $V12]}   # with round key w[ 8,11]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesdm_vs $V1, $V11]}   # with round key w[ 4, 7]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesdf_vs $V1, $V10]}   # with round key w[ 0, 3]
+
+    @{[vse32_v $V1, $OUTP]}
+
+    ret
+.size L_dec_192,.-L_dec_192
+___
+
+$code .= <<___;
+.p2align 3
+L_dec_256:
+    @{[vsetivli "zero", 4, "e32", "m1", "ta", "ma"]}
+
+    @{[vle32_v $V1, $INP]}
+
+    addi $KEYP, $KEYP, 224
+    @{[vle32_v $V24, $KEYP]}
+    @{[vaesz_vs $V1, $V24]}    # with round key w[56,59]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V23, $KEYP]}
+    @{[vaesdm_vs $V1, $V23]}   # with round key w[52,55]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V22, $KEYP]}
+    @{[vaesdm_vs $V1, $V22]}    # with round key w[48,51]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V21, $KEYP]}
+    @{[vaesdm_vs $V1, $V21]}   # with round key w[44,47]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V20, $KEYP]}
+    @{[vaesdm_vs $V1, $V20]}    # with round key w[40,43]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V19, $KEYP]}
+    @{[vaesdm_vs $V1, $V19]}   # with round key w[36,39]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V18, $KEYP]}
+    @{[vaesdm_vs $V1, $V18]}   # with round key w[32,35]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V17, $KEYP]}
+    @{[vaesdm_vs $V1, $V17]}   # with round key w[28,31]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V16, $KEYP]}
+    @{[vaesdm_vs $V1, $V16]}   # with round key w[24,27]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V15, $KEYP]}
+    @{[vaesdm_vs $V1, $V15]}   # with round key w[20,23]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V14, $KEYP]}
+    @{[vaesdm_vs $V1, $V14]}   # with round key w[16,19]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V13, $KEYP]}
+    @{[vaesdm_vs $V1, $V13]}   # with round key w[12,15]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V12, $KEYP]}
+    @{[vaesdm_vs $V1, $V12]}   # with round key w[ 8,11]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V11, $KEYP]}
+    @{[vaesdm_vs $V1, $V11]}   # with round key w[ 4, 7]
+    addi $KEYP, $KEYP, -16
+    @{[vle32_v $V10, $KEYP]}
+    @{[vaesdf_vs $V1, $V10]}   # with round key w[ 0, 3]
+
+    @{[vse32_v $V1, $OUTP]}
+
+    ret
+.size L_dec_256,.-L_dec_256
+___
+}
+
+$code .= <<___;
+L_fail_m1:
+    li a0, -1
+    ret
+.size L_fail_m1,.-L_fail_m1
+
+L_fail_m2:
+    li a0, -2
+    ret
+.size L_fail_m2,.-L_fail_m2
+
+L_end:
+  ret
+.size L_end,.-L_end
+___
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";

+ 1 - 1
libs/openssl/crypto/aes/asm/aesp8-ppc.pl

@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy

+ 765 - 3
libs/openssl/crypto/aes/asm/aesv8-armx.pl

@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# Copyright 2014-2023 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-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
@@ -1751,6 +1751,755 @@ $code.=<<___;
 .size	${prefix}_cbc_encrypt,.-${prefix}_cbc_encrypt
 ___
 }}}
+
+{{{
+my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4));
+my ($rounds,$roundsx,$cnt,$key_)=("w5","x5","w6","x7");
+my ($ctr,$tctr0,$tctr1,$tctr2)=map("w$_",(8..10,12));
+my ($tctr3,$tctr4,$tctr5,$tctr6)=map("w$_",(11,13..15));
+my ($tctr7,$tctr8,$tctr9,$tctr10,$tctr11)=map("w$_",(19..23));
+
+# q0-q7 => v0-v7; q8-q23 => v16-v31; q24-q31 => v8-v15
+my ($ivec,$rndlast,$rndping,$rndpang)=map("q$_",(0..3));
+my ($in0,$in1,$in2,$in3,$in4,$in5)=map("q$_",(4..9));
+my ($in6,$in7,$in8,$in9,$in10,$in11)=map("q$_",(10..15));
+my ($dat0,$dat1,$dat2,$dat3,$dat4,$dat5)=map("q$_",(16..21));
+my ($dat6,$dat7,$dat8,$dat9,$dat10,$dat11)=map("q$_",(22..27));
+my ($tmp0,$tmp1,$tmp2)=map("q$_",(25..27));
+
+#q_X => qX, for ldp & stp
+my ($in0q,$in1q,$in2q,$in3q)=map("q_$_",(4..7));
+my ($in4q,$in5q,$in6q,$in7q,$in8q,$in9q,$in10q,$in11q)=map("q_$_",(16..23));
+
+my ($dat8d,$dat9d,$dat10d,$dat11d)=map("d$_",(8..11));
+
+$code.=<<___	if ($flavour =~ /64/);
+.globl	${prefix}_ctr32_encrypt_blocks_unroll12_eor3
+.type	${prefix}_ctr32_encrypt_blocks_unroll12_eor3,%function
+.align	5
+${prefix}_ctr32_encrypt_blocks_unroll12_eor3:
+	AARCH64_VALID_CALL_TARGET
+	// Armv8.3-A PAuth: even though x30 is pushed to stack it is not popped later.
+	stp		x29,x30,[sp,#-80]!
+	stp		d8,d9,[sp, #16]
+	stp		d10,d11,[sp, #32]
+	stp		d12,d13,[sp, #48]
+	stp		d14,d15,[sp, #64]
+	add		x29,sp,#0
+
+	 ldr		$rounds,[$key,#240]
+
+	 ldr		$ctr, [$ivp, #12]
+#ifdef __AARCH64EB__
+	vld1.8		{$dat0},[$ivp]
+#else
+	vld1.32		{$dat0},[$ivp]
+#endif
+	vld1.32		{$rndping-$rndpang},[$key]		// load key schedule...
+	 sub		$rounds,$rounds,#4
+	 cmp		$len,#2
+	 add		$key_,$key,$roundsx,lsl#4	// pointer to last round key
+	 sub		$rounds,$rounds,#2
+	 add		$key_, $key_, #64
+	vld1.32		{$rndlast},[$key_]
+	 add		$key_,$key,#32
+	 mov		$cnt,$rounds
+#ifndef __AARCH64EB__
+	rev		$ctr, $ctr
+#endif
+
+	vorr		$dat1,$dat0,$dat0
+	 add		$tctr1, $ctr, #1
+	vorr		$dat2,$dat0,$dat0
+	 add		$ctr, $ctr, #2
+	vorr		$ivec,$dat0,$dat0
+	 rev		$tctr1, $tctr1
+	vmov.32		${dat1}[3],$tctr1
+	b.ls		.Lctr32_tail_unroll
+	 cmp		$len,#6
+	 rev		$tctr2, $ctr
+	 sub		$len,$len,#3		// bias
+	vmov.32		${dat2}[3],$tctr2
+	b.lo		.Loop3x_ctr32_unroll
+	 cmp		$len,#9
+	vorr		$dat3,$dat0,$dat0
+	 add		$tctr3, $ctr, #1
+	vorr		$dat4,$dat0,$dat0
+	 add		$tctr4, $ctr, #2
+	 rev		$tctr3, $tctr3
+	vorr		$dat5,$dat0,$dat0
+	 add		$ctr, $ctr, #3
+	 rev		$tctr4, $tctr4
+	vmov.32		${dat3}[3],$tctr3
+	 rev		$tctr5, $ctr
+	vmov.32		${dat4}[3],$tctr4
+	vmov.32		${dat5}[3],$tctr5
+	 sub		$len,$len,#3
+	b.lo		.Loop6x_ctr32_unroll
+
+	// push regs to stack when 12 data chunks are interleaved
+	 stp		x19,x20,[sp,#-16]!
+	 stp		x21,x22,[sp,#-16]!
+	 stp		x23,x24,[sp,#-16]!
+	 stp		$dat8d,$dat9d,[sp,#-32]!
+	 stp		$dat10d,$dat11d,[sp,#-32]!
+
+	 add		$tctr6,$ctr,#1
+	 add		$tctr7,$ctr,#2
+	 add		$tctr8,$ctr,#3
+	 add		$tctr9,$ctr,#4
+	 add		$tctr10,$ctr,#5
+	 add		$ctr,$ctr,#6
+	vorr		$dat6,$dat0,$dat0
+	 rev		$tctr6,$tctr6
+	vorr		$dat7,$dat0,$dat0
+	 rev		$tctr7,$tctr7
+	vorr		$dat8,$dat0,$dat0
+	 rev		$tctr8,$tctr8
+	vorr		$dat9,$dat0,$dat0
+	 rev		$tctr9,$tctr9
+	vorr		$dat10,$dat0,$dat0
+	 rev		$tctr10,$tctr10
+	vorr		$dat11,$dat0,$dat0
+	 rev		$tctr11,$ctr
+
+	 sub		$len,$len,#6		// bias
+	vmov.32		${dat6}[3],$tctr6
+	vmov.32		${dat7}[3],$tctr7
+	vmov.32		${dat8}[3],$tctr8
+	vmov.32		${dat9}[3],$tctr9
+	vmov.32		${dat10}[3],$tctr10
+	vmov.32		${dat11}[3],$tctr11
+	b		.Loop12x_ctr32_unroll
+
+.align	4
+.Loop12x_ctr32_unroll:
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndping
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndping
+	aesmc		$dat7,$dat7
+	aese		$dat8,$rndping
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndping
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndping
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndping
+	aesmc		$dat11,$dat11
+	vld1.32		{$rndping},[$key_],#16
+	subs		$cnt,$cnt,#2
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndpang
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndpang
+	aesmc		$dat7,$dat7
+	aese		$dat8,$rndpang
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndpang
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndpang
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndpang
+	aesmc		$dat11,$dat11
+	vld1.32		{$rndpang},[$key_],#16
+	b.gt		.Loop12x_ctr32_unroll
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndping
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndping
+	aesmc		$dat7,$dat7
+	aese		$dat8,$rndping
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndping
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndping
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndping
+	aesmc		$dat11,$dat11
+	vld1.32	 	{$rndping},[$key_],#16
+
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndpang
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndpang
+	aesmc		$dat7,$dat7
+	aese		$dat8,$rndpang
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndpang
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndpang
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndpang
+	aesmc		$dat11,$dat11
+	vld1.32	 	{$rndpang},[$key_],#16
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	 add		$tctr0,$ctr,#1
+	 add		$tctr1,$ctr,#2
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	 add		$tctr2,$ctr,#3
+	 add		$tctr3,$ctr,#4
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	 add		$tctr4,$ctr,#5
+	 add		$tctr5,$ctr,#6
+	 rev		$tctr0,$tctr0
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	 add		$tctr6,$ctr,#7
+	 add		$tctr7,$ctr,#8
+	 rev		$tctr1,$tctr1
+	 rev		$tctr2,$tctr2
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	 add		$tctr8,$ctr,#9
+	 add		$tctr9,$ctr,#10
+	 rev		$tctr3,$tctr3
+	 rev		$tctr4,$tctr4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	 add		$tctr10,$ctr,#11
+	 add		$tctr11,$ctr,#12
+	 rev		$tctr5,$tctr5
+	 rev		$tctr6,$tctr6
+	aese		$dat6,$rndping
+	aesmc		$dat6,$dat6
+	 rev		$tctr7,$tctr7
+	 rev		$tctr8,$tctr8
+	aese		$dat7,$rndping
+	aesmc		$dat7,$dat7
+	 rev		$tctr9,$tctr9
+	 rev		$tctr10,$tctr10
+	aese		$dat8,$rndping
+	aesmc		$dat8,$dat8
+	 rev		$tctr11,$tctr11
+	aese		$dat9,$rndping
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndping
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndping
+	aesmc		$dat11,$dat11
+	vld1.32	 	{$rndping},[$key_],#16
+
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	vld1.8		{$in0,$in1,$in2,$in3},[$inp],#64
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndpang
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndpang
+	aesmc		$dat7,$dat7
+	vld1.8		{$in4,$in5,$in6,$in7},[$inp],#64
+	aese		$dat8,$rndpang
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndpang
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndpang
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndpang
+	aesmc		$dat11,$dat11
+	vld1.8		{$in8,$in9,$in10,$in11},[$inp],#64
+	vld1.32	 	{$rndpang},[$key_],#16
+
+	 mov		$key_, $key
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	aese		$dat6,$rndping
+	aesmc		$dat6,$dat6
+	aese		$dat7,$rndping
+	aesmc		$dat7,$dat7
+	aese		$dat8,$rndping
+	aesmc		$dat8,$dat8
+	aese		$dat9,$rndping
+	aesmc		$dat9,$dat9
+	aese		$dat10,$rndping
+	aesmc		$dat10,$dat10
+	aese		$dat11,$rndping
+	aesmc		$dat11,$dat11
+	vld1.32	 	{$rndping},[$key_],#16	// re-pre-load rndkey[0]
+
+	aese		$dat0,$rndpang
+	 eor3		$in0,$in0,$rndlast,$dat0
+	vorr		$dat0,$ivec,$ivec
+	aese		$dat1,$rndpang
+	 eor3		$in1,$in1,$rndlast,$dat1
+	vorr		$dat1,$ivec,$ivec
+	aese		$dat2,$rndpang
+	 eor3		$in2,$in2,$rndlast,$dat2
+	vorr		$dat2,$ivec,$ivec
+	aese		$dat3,$rndpang
+	 eor3		$in3,$in3,$rndlast,$dat3
+	vorr		$dat3,$ivec,$ivec
+	aese		$dat4,$rndpang
+	 eor3		$in4,$in4,$rndlast,$dat4
+	vorr		$dat4,$ivec,$ivec
+	aese		$dat5,$rndpang
+	 eor3		$in5,$in5,$rndlast,$dat5
+	vorr		$dat5,$ivec,$ivec
+	aese		$dat6,$rndpang
+	 eor3		$in6,$in6,$rndlast,$dat6
+	vorr		$dat6,$ivec,$ivec
+	aese		$dat7,$rndpang
+	 eor3		$in7,$in7,$rndlast,$dat7
+	vorr		$dat7,$ivec,$ivec
+	aese		$dat8,$rndpang
+	 eor3		$in8,$in8,$rndlast,$dat8
+	vorr		$dat8,$ivec,$ivec
+	aese		$dat9,$rndpang
+	 eor3		$in9,$in9,$rndlast,$dat9
+	vorr		$dat9,$ivec,$ivec
+	aese		$dat10,$rndpang
+	 eor3		$in10,$in10,$rndlast,$dat10
+	vorr		$dat10,$ivec,$ivec
+	aese		$dat11,$rndpang
+	 eor3		$in11,$in11,$rndlast,$dat11
+	vorr		$dat11,$ivec,$ivec
+	vld1.32	 	{$rndpang},[$key_],#16	// re-pre-load rndkey[1]
+
+	vmov.32		${dat0}[3],$tctr0
+	vmov.32		${dat1}[3],$tctr1
+	vmov.32		${dat2}[3],$tctr2
+	vmov.32		${dat3}[3],$tctr3
+	vst1.8		{$in0,$in1,$in2,$in3},[$out],#64
+	vmov.32		${dat4}[3],$tctr4
+	vmov.32		${dat5}[3],$tctr5
+	vmov.32		${dat6}[3],$tctr6
+	vmov.32		${dat7}[3],$tctr7
+	vst1.8		{$in4,$in5,$in6,$in7},[$out],#64
+	vmov.32		${dat8}[3],$tctr8
+	vmov.32		${dat9}[3],$tctr9
+	vmov.32		${dat10}[3],$tctr10
+	vmov.32		${dat11}[3],$tctr11
+	vst1.8		{$in8,$in9,$in10,$in11},[$out],#64
+
+	 mov		$cnt,$rounds
+
+	 add		$ctr,$ctr,#12
+	subs		$len,$len,#12
+	b.hs		.Loop12x_ctr32_unroll
+
+	// pop regs from stack when 12 data chunks are interleaved
+	 ldp		$dat10d,$dat11d,[sp],#32
+	 ldp		$dat8d,$dat9d,[sp],#32
+	 ldp		x23,x24,[sp],#16
+	 ldp		x21,x22,[sp],#16
+	 ldp		x19,x20,[sp],#16
+
+	 add		$len,$len,#12
+	 cbz		$len,.Lctr32_done_unroll
+	 sub		$ctr,$ctr,#12
+
+	 cmp		$len,#2
+	b.ls		.Lctr32_tail_unroll
+
+	 cmp		$len,#6
+	 sub		$len,$len,#3		// bias
+	 add		$ctr,$ctr,#3
+	b.lo		.Loop3x_ctr32_unroll
+
+	 sub		$len,$len,#3
+	 add		$ctr,$ctr,#3
+	b.lo		.Loop6x_ctr32_unroll
+
+.align	4
+.Loop6x_ctr32_unroll:
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	vld1.32		{$rndping},[$key_],#16
+	subs		$cnt,$cnt,#2
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	vld1.32		{$rndpang},[$key_],#16
+	b.gt		.Loop6x_ctr32_unroll
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	vld1.32	 	{$rndping},[$key_],#16
+
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	vld1.32	 	{$rndpang},[$key_],#16
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	 add		$tctr0,$ctr,#1
+	 add		$tctr1,$ctr,#2
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	 add		$tctr2,$ctr,#3
+	 add		$tctr3,$ctr,#4
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	 add		$tctr4,$ctr,#5
+	 add		$tctr5,$ctr,#6
+	 rev		$tctr0,$tctr0
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	 rev		$tctr1,$tctr1
+	 rev		$tctr2,$tctr2
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	 rev		$tctr3,$tctr3
+	 rev		$tctr4,$tctr4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	 rev		$tctr5,$tctr5
+	vld1.32	 	{$rndping},[$key_],#16
+
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	vld1.8		{$in0,$in1,$in2,$in3},[$inp],#64
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndpang
+	aesmc		$dat3,$dat3
+	vld1.8		{$in4,$in5},[$inp],#32
+	aese		$dat4,$rndpang
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndpang
+	aesmc		$dat5,$dat5
+	vld1.32	 	{$rndpang},[$key_],#16
+
+	 mov		$key_, $key
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	aese		$dat3,$rndping
+	aesmc		$dat3,$dat3
+	aese		$dat4,$rndping
+	aesmc		$dat4,$dat4
+	aese		$dat5,$rndping
+	aesmc		$dat5,$dat5
+	vld1.32	 	{$rndping},[$key_],#16	// re-pre-load rndkey[0]
+
+	aese		$dat0,$rndpang
+	 eor3		$in0,$in0,$rndlast,$dat0
+	aese		$dat1,$rndpang
+	 eor3		$in1,$in1,$rndlast,$dat1
+	aese		$dat2,$rndpang
+	 eor3		$in2,$in2,$rndlast,$dat2
+	aese		$dat3,$rndpang
+	 eor3		$in3,$in3,$rndlast,$dat3
+	aese		$dat4,$rndpang
+	 eor3		$in4,$in4,$rndlast,$dat4
+	aese		$dat5,$rndpang
+	 eor3		$in5,$in5,$rndlast,$dat5
+	vld1.32	 	{$rndpang},[$key_],#16	// re-pre-load rndkey[1]
+
+	vorr		$dat0,$ivec,$ivec
+	vorr		$dat1,$ivec,$ivec
+	vorr		$dat2,$ivec,$ivec
+	vorr		$dat3,$ivec,$ivec
+	vorr		$dat4,$ivec,$ivec
+	vorr		$dat5,$ivec,$ivec
+
+	vmov.32		${dat0}[3],$tctr0
+	vmov.32		${dat1}[3],$tctr1
+	vst1.8		{$in0,$in1,$in2,$in3},[$out],#64
+	vmov.32		${dat2}[3],$tctr2
+	vmov.32		${dat3}[3],$tctr3
+	vst1.8		{$in4,$in5},[$out],#32
+	vmov.32		${dat4}[3],$tctr4
+	vmov.32		${dat5}[3],$tctr5
+
+	 cbz		$len,.Lctr32_done_unroll
+	 mov		$cnt,$rounds
+
+	 cmp		$len,#2
+	b.ls		.Lctr32_tail_unroll
+
+	 sub		$len,$len,#3		// bias
+	 add		$ctr,$ctr,#3
+	 b		.Loop3x_ctr32_unroll
+
+.align	4
+.Loop3x_ctr32_unroll:
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	vld1.32		{$rndping},[$key_],#16
+	subs		$cnt,$cnt,#2
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	aese		$dat2,$rndpang
+	aesmc		$dat2,$dat2
+	vld1.32		{$rndpang},[$key_],#16
+	b.gt		.Loop3x_ctr32_unroll
+
+	aese		$dat0,$rndping
+	aesmc		$tmp0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$tmp1,$dat1
+	vld1.8		{$in0,$in1,$in2},[$inp],#48
+	vorr		$dat0,$ivec,$ivec
+	aese		$dat2,$rndping
+	aesmc		$dat2,$dat2
+	vld1.32		{$rndping},[$key_],#16
+	vorr		$dat1,$ivec,$ivec
+	aese		$tmp0,$rndpang
+	aesmc		$tmp0,$tmp0
+	aese		$tmp1,$rndpang
+	aesmc		$tmp1,$tmp1
+	aese		$dat2,$rndpang
+	aesmc		$tmp2,$dat2
+	vld1.32		{$rndpang},[$key_],#16
+	vorr		$dat2,$ivec,$ivec
+	 add		$tctr0,$ctr,#1
+	aese		$tmp0,$rndping
+	aesmc		$tmp0,$tmp0
+	aese		$tmp1,$rndping
+	aesmc		$tmp1,$tmp1
+	 add		$tctr1,$ctr,#2
+	aese		$tmp2,$rndping
+	aesmc		$tmp2,$tmp2
+	vld1.32		{$rndping},[$key_],#16
+	 add		$ctr,$ctr,#3
+	aese		$tmp0,$rndpang
+	aesmc		$tmp0,$tmp0
+	aese		$tmp1,$rndpang
+	aesmc		$tmp1,$tmp1
+
+	 rev		$tctr0,$tctr0
+	aese		$tmp2,$rndpang
+	aesmc		$tmp2,$tmp2
+	vld1.32		{$rndpang},[$key_],#16
+	vmov.32		${dat0}[3], $tctr0
+	 mov		$key_,$key
+	 rev		$tctr1,$tctr1
+	aese		$tmp0,$rndping
+	aesmc		$tmp0,$tmp0
+
+	aese		$tmp1,$rndping
+	aesmc		$tmp1,$tmp1
+	vmov.32		${dat1}[3], $tctr1
+	 rev		$tctr2,$ctr
+	aese		$tmp2,$rndping
+	aesmc		$tmp2,$tmp2
+	vmov.32		${dat2}[3], $tctr2
+
+	aese		$tmp0,$rndpang
+	aese		$tmp1,$rndpang
+	aese		$tmp2,$rndpang
+
+	 eor3		$in0,$in0,$rndlast,$tmp0
+	vld1.32		{$rndping},[$key_],#16	// re-pre-load rndkey[0]
+	 eor3		$in1,$in1,$rndlast,$tmp1
+	 mov		$cnt,$rounds
+	 eor3		$in2,$in2,$rndlast,$tmp2
+	vld1.32		{$rndpang},[$key_],#16	// re-pre-load rndkey[1]
+	vst1.8		{$in0,$in1,$in2},[$out],#48
+
+	 cbz		$len,.Lctr32_done_unroll
+
+.Lctr32_tail_unroll:
+	 cmp		$len,#1
+	b.eq		.Lctr32_tail_1_unroll
+
+.Lctr32_tail_2_unroll:
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndping},[$key_],#16
+	subs		$cnt,$cnt,#2
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndpang},[$key_],#16
+	b.gt		.Lctr32_tail_2_unroll
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndping},[$key_],#16
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndpang},[$key_],#16
+	vld1.8		{$in0,$in1},[$inp],#32
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndping},[$key_],#16
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndpang
+	aesmc		$dat1,$dat1
+	vld1.32		{$rndpang},[$key_],#16
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat1,$rndping
+	aesmc		$dat1,$dat1
+	aese		$dat0,$rndpang
+	aese		$dat1,$rndpang
+
+	 eor3		$in0,$in0,$rndlast,$dat0
+	 eor3		$in1,$in1,$rndlast,$dat1
+	vst1.8		{$in0,$in1},[$out],#32
+	 b		.Lctr32_done_unroll
+
+.Lctr32_tail_1_unroll:
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndping},[$key_],#16
+	subs		$cnt,$cnt,#2
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndpang},[$key_],#16
+	b.gt		.Lctr32_tail_1_unroll
+
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndping},[$key_],#16
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndpang},[$key_],#16
+	vld1.8		{$in0},[$inp]
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndping},[$key_],#16
+	aese		$dat0,$rndpang
+	aesmc		$dat0,$dat0
+	vld1.32		{$rndpang},[$key_],#16
+	aese		$dat0,$rndping
+	aesmc		$dat0,$dat0
+	aese		$dat0,$rndpang
+
+	 eor3		$in0,$in0,$rndlast,$dat0
+	vst1.8		{$in0},[$out],#16
+
+.Lctr32_done_unroll:
+	ldp		d8,d9,[sp, #16]
+	ldp		d10,d11,[sp, #32]
+	ldp		d12,d13,[sp, #48]
+	ldp		d15,d16,[sp, #64]
+	ldr		x29,[sp],#80
+	ret
+.size	${prefix}_ctr32_encrypt_blocks_unroll12_eor3,.-${prefix}_ctr32_encrypt_blocks_unroll12_eor3
+___
+}}}
+
 {{{
 my ($inp,$out,$len,$key,$ivp)=map("x$_",(0..4));
 my ($rounds,$cnt,$key_)=("w5","w6","x7");
@@ -3640,7 +4389,8 @@ ___
 if ($flavour =~ /64/) {			######## 64-bit code
     my %opcode = (
 	"aesd"	=>	0x4e285800,	"aese"	=>	0x4e284800,
-	"aesimc"=>	0x4e287800,	"aesmc"	=>	0x4e286800	);
+	"aesimc"=>	0x4e287800,	"aesmc"	=>	0x4e286800,
+	"eor3"	=>	0xce000000,	);
 
     local *unaes = sub {
 	my ($mnemonic,$arg)=@_;
@@ -3651,10 +4401,21 @@ if ($flavour =~ /64/) {			######## 64-bit code
 			$mnemonic,$arg;
     };
 
+    sub unsha3 {
+		 my ($mnemonic,$arg)=@_;
+
+		 $arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv#]([0-9\-]+))?)?/
+		 &&
+		 sprintf ".inst\t0x%08x\t//%s %s",
+			$opcode{$mnemonic}|$1|($2<<5)|($3<<16)|(eval($4)<<10),
+			$mnemonic,$arg;
+    }
+
     foreach(split("\n",$code)) {
 	s/\`([^\`]*)\`/eval($1)/geo;
 
-	s/\bq([0-9]+)\b/"v".($1<8?$1:$1+8).".16b"/geo;	# old->new registers
+	s/\bq([0-9]+)\b/"v".($1<8?$1:($1<24?$1+8:$1-16)).".16b"/geo;	# old->new registers
+	s/\bq_([0-9]+)\b/"q".$1/geo;	# old->new registers
 	s/@\s/\/\//o;			# old->new style commentary
 
 	#s/[v]?(aes\w+)\s+([qv].*)/unaes($1,$2)/geo	or
@@ -3667,6 +4428,7 @@ if ($flavour =~ /64/) {			######## 64-bit code
 	s/vshr/ushr/o		or
 	s/^(\s+)v/$1/o		or	# strip off v prefix
 	s/\bbx\s+lr\b/ret/o;
+	s/\b(eor3)\s+(v.*)/unsha3($1,$2)/ge;
 
 	# fix up remaining legacy suffixes
 	s/\.[ui]?8//o;

+ 4 - 1
libs/openssl/crypto/aes/build.info

@@ -51,7 +51,7 @@ IF[{- !$disabled{asm} -}]
   # aes-c64xplus.s implements AES_ctr32_encrypt
   $AESDEF_c64xplus=AES_ASM AES_CTR_ASM
 
-  $AESASM_riscv64=aes_cbc.c aes-riscv64.s aes-riscv64-zkn.s
+  $AESASM_riscv64=aes_cbc.c aes-riscv64.s aes-riscv64-zkn.s aes-riscv64-zvkb-zvkned.s aes-riscv64-zvkned.s aes-riscv64-zvbb-zvkg-zvkned.s
   $AESDEF_riscv64=AES_ASM
   $AESASM_riscv32=aes_core.c aes_cbc.c aes-riscv32-zkn.s
 
@@ -128,6 +128,9 @@ INCLUDE[aes-mips.o]=..
 GENERATE[aes-riscv64.s]=asm/aes-riscv64.pl
 GENERATE[aes-riscv64-zkn.s]=asm/aes-riscv64-zkn.pl
 GENERATE[aes-riscv32-zkn.s]=asm/aes-riscv32-zkn.pl
+GENERATE[aes-riscv64-zvkb-zvkned.s]=asm/aes-riscv64-zvkb-zvkned.pl
+GENERATE[aes-riscv64-zvkned.s]=asm/aes-riscv64-zvkned.pl
+GENERATE[aes-riscv64-zvbb-zvkg-zvkned.s]=asm/aes-riscv64-zvbb-zvkg-zvkned.pl
 
 GENERATE[aesv8-armx.S]=asm/aesv8-armx.pl
 INCLUDE[aesv8-armx.o]=..

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -88,6 +88,7 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
 # define ARMV8_SVE       (1<<13)
 # define ARMV8_SVE2      (1<<14)
 # define ARMV8_HAVE_SHA3_AND_WORTH_USING     (1<<15)
+# define ARMV8_UNROLL12_EOR3     (1<<16)
 
 /*
  * MIDR_EL1 system register
@@ -102,6 +103,7 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
 # define ARM_CPU_IMP_ARM           0x41
 # define HISI_CPU_IMP              0x48
 # define ARM_CPU_IMP_APPLE         0x61
+# define ARM_CPU_IMP_MICROSOFT     0x6D
 
 # define ARM_CPU_PART_CORTEX_A72   0xD08
 # define ARM_CPU_PART_N1           0xD0C
@@ -123,6 +125,8 @@ extern unsigned int OPENSSL_armv8_rsa_neonized;
 # define APPLE_CPU_PART_M2_BLIZZARD_MAX     0x038
 # define APPLE_CPU_PART_M2_AVALANCHE_MAX    0x039
 
+# define MICROSOFT_CPU_PART_COBALT_100      0xD49
+
 # define MIDR_PARTNUM_SHIFT       4
 # define MIDR_PARTNUM_MASK        (0xfffU << MIDR_PARTNUM_SHIFT)
 # define MIDR_PARTNUM(midr)       \

+ 8 - 2
libs/openssl/crypto/armcap.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -298,7 +298,8 @@ void OPENSSL_cpuid_setup(void)
             size_t len = sizeof(uarch);
             if ((sysctlbyname("machdep.cpu.brand_string", uarch, &len, NULL, 0) == 0) &&
                ((strncmp(uarch, "Apple M1", 8) == 0) ||
-                (strncmp(uarch, "Apple M2", 8) == 0))) {
+                (strncmp(uarch, "Apple M2", 8) == 0) ||
+                (strncmp(uarch, "Apple M3", 8) == 0))) {
                 OPENSSL_armcap_P |= ARMV8_UNROLL8_EOR3;
                 OPENSSL_armcap_P |= ARMV8_HAVE_SHA3_AND_WORTH_USING;
             }
@@ -417,9 +418,14 @@ 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)) &&
         (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)) &&
+        (OPENSSL_armcap_P & ARMV8_SHA3))
+        OPENSSL_armcap_P |= ARMV8_UNROLL12_EOR3;
     if ((MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)     ||
          MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)      ||
          MIDR_IS_CPU_MODEL(OPENSSL_arm_midr, ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO) ||

+ 3 - 5
libs/openssl/crypto/asn1/a_time.c

@@ -79,7 +79,7 @@ int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
     static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
     static const int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
     char *a;
-    int n, i, i2, l, o, min_l = 11, strict = 0, end = 6, btz = 5, md;
+    int n, i, i2, l, o, min_l, strict = 0, end = 6, btz = 5, md;
     struct tm tmp;
 #if defined(CHARSET_EBCDIC)
     const char upper_z = 0x5A, num_zero = 0x30, period = 0x2E, minus = 0x2D, plus = 0x2B;
@@ -95,18 +95,16 @@ int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
      * 3. "+|-" is not allowed to indicate a timezone
      */
     if (d->type == V_ASN1_UTCTIME) {
+        min_l = 13;
         if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
-            min_l = 13;
             strict = 1;
         }
     } else if (d->type == V_ASN1_GENERALIZEDTIME) {
         end = 7;
         btz = 6;
+        min_l = 15;
         if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
-            min_l = 15;
             strict = 1;
-        } else {
-            min_l = 13;
         }
     } else {
         return 0;

+ 5 - 1
libs/openssl/crypto/asn1/asn1_err.c

@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -55,6 +55,8 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIELD_MISSING), "field missing"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_FIRST_NUM_TOO_LARGE),
     "first num too large"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT),
+    "generalizedtime is too short"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_HEADER_TOO_LONG), "header too long"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ILLEGAL_BITSTRING_FORMAT),
     "illegal bitstring format"},
@@ -192,6 +194,8 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE),
     "unsupported public key type"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNSUPPORTED_TYPE), "unsupported type"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UTCTIME_IS_TOO_SHORT),
+    "utctime is too short"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_INTEGER_TYPE),
     "wrong integer type"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_WRONG_PUBLIC_KEY_TYPE),

+ 9 - 1
libs/openssl/crypto/asn1/tasn_dec.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -921,6 +921,14 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
             ERR_raise(ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
             goto err;
         }
+        if (utype == V_ASN1_GENERALIZEDTIME && (len < 15)) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT);
+            goto err;
+        }
+        if (utype == V_ASN1_UTCTIME && (len < 13)) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UTCTIME_IS_TOO_SHORT);
+            goto err;
+        }
         /* All based on ASN1_STRING and handled the same */
         if (*pval == NULL) {
             stmp = ASN1_STRING_type_new(utype);

+ 3 - 2
libs/openssl/crypto/bio/bio_dump.c

@@ -141,9 +141,10 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data,
 
         BIO_printf(out, "%02X:", d[i]);
 
-        j = (j + 1) % width;
-        if (!j)
+        if (++j >= width) {
+            j = 0;
             BIO_printf(out, "\n");
+        }
     }
 
     if (i && !j)

+ 1 - 1
libs/openssl/crypto/bio/bio_lib.c

@@ -817,7 +817,7 @@ BIO *BIO_find_type(BIO *bio, int type)
         ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER);
         return NULL;
     }
-    mask = type & 0xff;
+    mask = type & BIO_TYPE_MASK;
     do {
         if (bio->method != NULL) {
             mt = bio->method->type;

+ 3 - 1
libs/openssl/crypto/bio/bio_meth.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -29,6 +29,8 @@ int BIO_get_new_index(void)
     }
     if (!CRYPTO_UP_REF(&bio_type_count, &newval))
         return -1;
+    if (newval > BIO_TYPE_MASK)
+        return -1;
     return newval;
 }
 

+ 0 - 3
libs/openssl/crypto/bio/bio_sock.c

@@ -26,9 +26,6 @@ static int wsa_init_done = 0;
 # if defined __TANDEM
 #  include <unistd.h>
 #  include <sys/time.h> /* select */
-#  if defined(OPENSSL_TANDEM_FLOSS)
-#   include <floss.h(floss_select)>
-#  endif
 # elif defined _WIN32
 #  include <winsock.h> /* for type fd_set */
 # else

+ 1 - 1
libs/openssl/crypto/bio/bss_dgram.c

@@ -107,7 +107,7 @@
     || M_METHOD == M_METHOD_WSARECVMSG
 #  if defined(__APPLE__)
     /*
-     * CMSG_SPACE is not a constant expresson on OSX even though POSIX
+     * CMSG_SPACE is not a constant expression on OSX even though POSIX
      * says it's supposed to be. This should be adequate.
      */
 #   define BIO_CMSG_ALLOC_LEN   64

+ 1 - 1
libs/openssl/crypto/bn/bn_gcd.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy

+ 1 - 1
libs/openssl/crypto/bn/bn_mod.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy

+ 476 - 0
libs/openssl/crypto/chacha/asm/chacha-riscv64-zbb-zvkb.pl

@@ -0,0 +1,476 @@
+#! /usr/bin/env perl
+# This file is dual-licensed, meaning that you can use it under your
+# choice of either of the following two licenses:
+#
+# Copyright 2023-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
+#
+# or
+#
+# Copyright (c) 2023, Jerry Shih <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# - RV64I
+# - RISC-V Vector ('V') with VLEN >= 128
+# - RISC-V Vector Cryptography Bit-manipulation extension ('Zvkb')
+# - RISC-V Basic Bit-manipulation extension ('Zbb')
+# - RISC-V Zicclsm(Main memory supports misaligned loads/stores)
+
+use strict;
+use warnings;
+
+use FindBin qw($Bin);
+use lib "$Bin";
+use lib "$Bin/../../perlasm";
+use riscv;
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+my $output  = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop   : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.|          ? shift : undef;
+
+$output and open STDOUT, ">$output";
+
+my $code = <<___;
+.text
+___
+
+# void ChaCha20_ctr32_zbb_zvkb(unsigned char *out, const unsigned char *inp,
+#                              size_t len, const unsigned int key[8],
+#                              const unsigned int counter[4]);
+################################################################################
+my ( $OUTPUT, $INPUT, $LEN, $KEY, $COUNTER ) = ( "a0", "a1", "a2", "a3", "a4" );
+my ( $CONST_DATA0, $CONST_DATA1, $CONST_DATA2, $CONST_DATA3 ) = ( "a5", "a6",
+  "a7", "s0" );
+my ( $KEY0, $KEY1, $KEY2, $KEY3, $KEY4, $KEY5, $KEY6, $KEY7, $COUNTER0,
+     $COUNTER1, $NONCE0, $NONCE1) = ( "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+  "s8", "s9", "s10", "s11", "t0" );
+my ( $STATE0, $STATE1, $STATE2, $STATE3,
+     $STATE4, $STATE5, $STATE6, $STATE7,
+     $STATE8, $STATE9, $STATE10, $STATE11,
+     $STATE12, $STATE13, $STATE14, $STATE15) = (
+     $CONST_DATA0, $CONST_DATA1, $CONST_DATA2, $CONST_DATA3,
+     $KEY0, $KEY1, $KEY2, $KEY3,
+     $KEY4, $KEY5, $KEY6, $KEY7,
+     $COUNTER0, $COUNTER1, $NONCE0, $NONCE1 );
+my ( $VL ) = ( "t1" );
+my ( $CURRENT_COUNTER ) = ( "t2" );
+my ( $T0 ) = ( "t3" );
+my ( $T1 ) = ( "t4" );
+my ( $T2 ) = ( "t5" );
+my ( $T3 ) = ( "t6" );
+my (
+    $V0,  $V1,  $V2,  $V3,  $V4,  $V5,  $V6,  $V7,  $V8,  $V9,  $V10,
+    $V11, $V12, $V13, $V14, $V15, $V16, $V17, $V18, $V19, $V20, $V21,
+    $V22, $V23, $V24, $V25, $V26, $V27, $V28, $V29, $V30, $V31,
+) = map( "v$_", ( 0 .. 31 ) );
+
+sub chacha_quad_round_group {
+    my (
+        $A0, $B0, $C0, $D0,
+        $A1, $B1, $C1, $D1,
+        $A2, $B2, $C2, $D2,
+        $A3, $B3, $C3, $D3,
+
+        $S_A0, $S_B0, $S_C0, $S_D0,
+        $S_A1, $S_B1, $S_C1, $S_D1,
+        $S_A2, $S_B2, $S_C2, $S_D2,
+        $S_A3, $S_B3, $S_C3, $S_D3,
+    ) = @_;
+
+    my $code = <<___;
+    # a += b; d ^= a; d <<<= 16;
+    @{[vadd_vv $A0, $A0, $B0]}
+    add $S_A0, $S_A0, $S_B0
+    @{[vadd_vv $A1, $A1, $B1]}
+    add $S_A1, $S_A1, $S_B1
+    @{[vadd_vv $A2, $A2, $B2]}
+    add $S_A2, $S_A2, $S_B2
+    @{[vadd_vv $A3, $A3, $B3]}
+    add $S_A3, $S_A3, $S_B3
+    @{[vxor_vv $D0, $D0, $A0]}
+    xor $S_D0, $S_D0, $S_A0
+    @{[vxor_vv $D1, $D1, $A1]}
+    xor $S_D1, $S_D1, $S_A1
+    @{[vxor_vv $D2, $D2, $A2]}
+    xor $S_D2, $S_D2, $S_A2
+    @{[vxor_vv $D3, $D3, $A3]}
+    xor $S_D3, $S_D3, $S_A3
+    @{[vror_vi $D0, $D0, 32 - 16]}
+    @{[roriw $S_D0, $S_D0, 32 - 16]}
+    @{[vror_vi $D1, $D1, 32 - 16]}
+    @{[roriw $S_D1, $S_D1, 32 - 16]}
+    @{[vror_vi $D2, $D2, 32 - 16]}
+    @{[roriw $S_D2, $S_D2, 32 - 16]}
+    @{[vror_vi $D3, $D3, 32 - 16]}
+    @{[roriw $S_D3, $S_D3, 32 - 16]}
+    # c += d; b ^= c; b <<<= 12;
+    @{[vadd_vv $C0, $C0, $D0]}
+    add $S_C0, $S_C0, $S_D0
+    @{[vadd_vv $C1, $C1, $D1]}
+    add $S_C1, $S_C1, $S_D1
+    @{[vadd_vv $C2, $C2, $D2]}
+    add $S_C2, $S_C2, $S_D2
+    @{[vadd_vv $C3, $C3, $D3]}
+    add $S_C3, $S_C3, $S_D3
+    @{[vxor_vv $B0, $B0, $C0]}
+    xor $S_B0, $S_B0, $S_C0
+    @{[vxor_vv $B1, $B1, $C1]}
+    xor $S_B1, $S_B1, $S_C1
+    @{[vxor_vv $B2, $B2, $C2]}
+    xor $S_B2, $S_B2, $S_C2
+    @{[vxor_vv $B3, $B3, $C3]}
+    xor $S_B3, $S_B3, $S_C3
+    @{[vror_vi $B0, $B0, 32 - 12]}
+    @{[roriw $S_B0, $S_B0, 32 - 12]}
+    @{[vror_vi $B1, $B1, 32 - 12]}
+    @{[roriw $S_B1, $S_B1, 32 - 12]}
+    @{[vror_vi $B2, $B2, 32 - 12]}
+    @{[roriw $S_B2, $S_B2, 32 - 12]}
+    @{[vror_vi $B3, $B3, 32 - 12]}
+    @{[roriw $S_B3, $S_B3, 32 - 12]}
+    # a += b; d ^= a; d <<<= 8;
+    @{[vadd_vv $A0, $A0, $B0]}
+    add $S_A0, $S_A0, $S_B0
+    @{[vadd_vv $A1, $A1, $B1]}
+    add $S_A1, $S_A1, $S_B1
+    @{[vadd_vv $A2, $A2, $B2]}
+    add $S_A2, $S_A2, $S_B2
+    @{[vadd_vv $A3, $A3, $B3]}
+    add $S_A3, $S_A3, $S_B3
+    @{[vxor_vv $D0, $D0, $A0]}
+    xor $S_D0, $S_D0, $S_A0
+    @{[vxor_vv $D1, $D1, $A1]}
+    xor $S_D1, $S_D1, $S_A1
+    @{[vxor_vv $D2, $D2, $A2]}
+    xor $S_D2, $S_D2, $S_A2
+    @{[vxor_vv $D3, $D3, $A3]}
+    xor $S_D3, $S_D3, $S_A3
+    @{[vror_vi $D0, $D0, 32 - 8]}
+    @{[roriw $S_D0, $S_D0, 32 - 8]}
+    @{[vror_vi $D1, $D1, 32 - 8]}
+    @{[roriw $S_D1, $S_D1, 32 - 8]}
+    @{[vror_vi $D2, $D2, 32 - 8]}
+    @{[roriw $S_D2, $S_D2, 32 - 8]}
+    @{[vror_vi $D3, $D3, 32 - 8]}
+    @{[roriw $S_D3, $S_D3, 32 - 8]}
+    # c += d; b ^= c; b <<<= 7;
+    @{[vadd_vv $C0, $C0, $D0]}
+    add $S_C0, $S_C0, $S_D0
+    @{[vadd_vv $C1, $C1, $D1]}
+    add $S_C1, $S_C1, $S_D1
+    @{[vadd_vv $C2, $C2, $D2]}
+    add $S_C2, $S_C2, $S_D2
+    @{[vadd_vv $C3, $C3, $D3]}
+    add $S_C3, $S_C3, $S_D3
+    @{[vxor_vv $B0, $B0, $C0]}
+    xor $S_B0, $S_B0, $S_C0
+    @{[vxor_vv $B1, $B1, $C1]}
+    xor $S_B1, $S_B1, $S_C1
+    @{[vxor_vv $B2, $B2, $C2]}
+    xor $S_B2, $S_B2, $S_C2
+    @{[vxor_vv $B3, $B3, $C3]}
+    xor $S_B3, $S_B3, $S_C3
+    @{[vror_vi $B0, $B0, 32 - 7]}
+    @{[roriw $S_B0, $S_B0, 32 - 7]}
+    @{[vror_vi $B1, $B1, 32 - 7]}
+    @{[roriw $S_B1, $S_B1, 32 - 7]}
+    @{[vror_vi $B2, $B2, 32 - 7]}
+    @{[roriw $S_B2, $S_B2, 32 - 7]}
+    @{[vror_vi $B3, $B3, 32 - 7]}
+    @{[roriw $S_B3, $S_B3, 32 - 7]}
+___
+
+    return $code;
+}
+
+$code .= <<___;
+.p2align 3
+.globl ChaCha20_ctr32_zbb_zvkb
+.type ChaCha20_ctr32_zbb_zvkb,\@function
+ChaCha20_ctr32_zbb_zvkb:
+    addi sp, sp, -96
+    sd s0, 0(sp)
+    sd s1, 8(sp)
+    sd s2, 16(sp)
+    sd s3, 24(sp)
+    sd s4, 32(sp)
+    sd s5, 40(sp)
+    sd s6, 48(sp)
+    sd s7, 56(sp)
+    sd s8, 64(sp)
+    sd s9, 72(sp)
+    sd s10, 80(sp)
+    sd s11, 88(sp)
+    addi sp, sp, -64
+
+    lw $CURRENT_COUNTER, 0($COUNTER)
+
+.Lblock_loop:
+    # We will use the scalar ALU for 1 chacha block.
+    srli $T0, $LEN, 6
+    @{[vsetvli $VL, $T0, "e32", "m1", "ta", "ma"]}
+    slli $T1, $VL, 6
+    bltu $T1, $LEN, 1f
+    # Since there is no more chacha block existed, we need to split 1 block
+    # from vector ALU.
+    addi $T1, $VL, -1
+    @{[vsetvli $VL, $T1, "e32", "m1", "ta", "ma"]}
+1:
+
+    #### chacha block data
+    # init chacha const states
+    # "expa" little endian
+    li $CONST_DATA0, 0x61707865
+    @{[vmv_v_x $V0, $CONST_DATA0]}
+    # "nd 3" little endian
+    li $CONST_DATA1, 0x3320646e
+    @{[vmv_v_x $V1, $CONST_DATA1]}
+    # "2-by" little endian
+    li $CONST_DATA2, 0x79622d32
+    @{[vmv_v_x $V2, $CONST_DATA2]}
+    # "te k" little endian
+    li $CONST_DATA3, 0x6b206574
+    lw $KEY0, 0($KEY)
+    @{[vmv_v_x $V3, $CONST_DATA3]}
+
+    # init chacha key states
+    lw $KEY1, 4($KEY)
+    @{[vmv_v_x $V4, $KEY0]}
+    lw $KEY2, 8($KEY)
+    @{[vmv_v_x $V5, $KEY1]}
+    lw $KEY3, 12($KEY)
+    @{[vmv_v_x $V6, $KEY2]}
+    lw $KEY4, 16($KEY)
+    @{[vmv_v_x $V7, $KEY3]}
+    lw $KEY5, 20($KEY)
+    @{[vmv_v_x $V8, $KEY4]}
+    lw $KEY6, 24($KEY)
+    @{[vmv_v_x $V9, $KEY5]}
+    lw $KEY7, 28($KEY)
+    @{[vmv_v_x $V10, $KEY6]}
+    @{[vmv_v_x $V11, $KEY7]}
+
+    # init chacha key states
+    lw $COUNTER1, 4($COUNTER)
+    @{[vid_v $V12]}
+    lw $NONCE0, 8($COUNTER)
+    @{[vadd_vx $V12, $V12, $CURRENT_COUNTER]}
+    lw $NONCE1, 12($COUNTER)
+    @{[vmv_v_x $V13, $COUNTER1]}
+    add $COUNTER0, $CURRENT_COUNTER, $VL
+
+    # init chacha nonce states
+    @{[vmv_v_x $V14, $NONCE0]}
+    @{[vmv_v_x $V15, $NONCE1]}
+
+    li $T0, 64
+    # load the top-half of input data
+    @{[vlsseg_nf_e32_v 8, $V16, $INPUT, $T0]}
+
+    # 20 round groups
+    li $T0, 10
+.Lround_loop:
+    addi $T0, $T0, -1
+    @{[chacha_quad_round_group
+      $V0, $V4, $V8, $V12,
+      $V1, $V5, $V9, $V13,
+      $V2, $V6, $V10, $V14,
+      $V3, $V7, $V11, $V15,
+      $STATE0, $STATE4, $STATE8, $STATE12,
+      $STATE1, $STATE5, $STATE9, $STATE13,
+      $STATE2, $STATE6, $STATE10, $STATE14,
+      $STATE3, $STATE7, $STATE11, $STATE15]}
+    @{[chacha_quad_round_group
+      $V3, $V4, $V9, $V14,
+      $V0, $V5, $V10, $V15,
+      $V1, $V6, $V11, $V12,
+      $V2, $V7, $V8, $V13,
+      $STATE3, $STATE4, $STATE9, $STATE14,
+      $STATE0, $STATE5, $STATE10, $STATE15,
+      $STATE1, $STATE6, $STATE11, $STATE12,
+      $STATE2, $STATE7, $STATE8, $STATE13]}
+    bnez $T0, .Lround_loop
+
+    li $T0, 64
+    # load the bottom-half of input data
+    addi $T1, $INPUT, 32
+    @{[vlsseg_nf_e32_v 8, $V24, $T1, $T0]}
+
+    # add chacha top-half initial block states
+    # "expa" little endian
+    li $T0, 0x61707865
+    @{[vadd_vx $V0, $V0, $T0]}
+    add $STATE0, $STATE0, $T0
+    # "nd 3" little endian
+    li $T1, 0x3320646e
+    @{[vadd_vx $V1, $V1, $T1]}
+    add $STATE1, $STATE1, $T1
+    lw $T0, 0($KEY)
+    # "2-by" little endian
+    li $T2, 0x79622d32
+    @{[vadd_vx $V2, $V2, $T2]}
+    add $STATE2, $STATE2, $T2
+    lw $T1, 4($KEY)
+    # "te k" little endian
+    li $T3, 0x6b206574
+    @{[vadd_vx $V3, $V3, $T3]}
+    add $STATE3, $STATE3, $T3
+    lw $T2, 8($KEY)
+    @{[vadd_vx $V4, $V4, $T0]}
+    add $STATE4, $STATE4, $T0
+    lw $T3, 12($KEY)
+    @{[vadd_vx $V5, $V5, $T1]}
+    add $STATE5, $STATE5, $T1
+    @{[vadd_vx $V6, $V6, $T2]}
+    add $STATE6, $STATE6, $T2
+    @{[vadd_vx $V7, $V7, $T3]}
+    add $STATE7, $STATE7, $T3
+
+    # xor with the top-half input
+    @{[vxor_vv $V16, $V16, $V0]}
+    sw $STATE0, 0(sp)
+    sw $STATE1, 4(sp)
+    @{[vxor_vv $V17, $V17, $V1]}
+    sw $STATE2, 8(sp)
+    sw $STATE3, 12(sp)
+    @{[vxor_vv $V18, $V18, $V2]}
+    sw $STATE4, 16(sp)
+    sw $STATE5, 20(sp)
+    @{[vxor_vv $V19, $V19, $V3]}
+    sw $STATE6, 24(sp)
+    sw $STATE7, 28(sp)
+    @{[vxor_vv $V20, $V20, $V4]}
+    lw $T0, 16($KEY)
+    @{[vxor_vv $V21, $V21, $V5]}
+    lw $T1, 20($KEY)
+    @{[vxor_vv $V22, $V22, $V6]}
+    lw $T2, 24($KEY)
+    @{[vxor_vv $V23, $V23, $V7]}
+
+    # save the top-half of output
+    li $T3, 64
+    @{[vssseg_nf_e32_v 8, $V16, $OUTPUT, $T3]}
+
+    # add chacha bottom-half initial block states
+    @{[vadd_vx $V8, $V8, $T0]}
+    add $STATE8, $STATE8, $T0
+    lw $T3, 28($KEY)
+    @{[vadd_vx $V9, $V9, $T1]}
+    add $STATE9, $STATE9, $T1
+    lw $T0, 4($COUNTER)
+    @{[vadd_vx $V10, $V10, $T2]}
+    add $STATE10, $STATE10, $T2
+    lw $T1, 8($COUNTER)
+    @{[vadd_vx $V11, $V11, $T3]}
+    add $STATE11, $STATE11, $T3
+    lw $T2, 12($COUNTER)
+    @{[vid_v $V0]}
+    add $STATE12, $STATE12, $CURRENT_COUNTER
+    @{[vadd_vx $V12, $V12, $CURRENT_COUNTER]}
+    add $STATE12, $STATE12, $VL
+    @{[vadd_vx $V13, $V13, $T0]}
+    add $STATE13, $STATE13, $T0
+    @{[vadd_vx $V14, $V14, $T1]}
+    add $STATE14, $STATE14, $T1
+    @{[vadd_vx $V15, $V15, $T2]}
+    add $STATE15, $STATE15, $T2
+    @{[vadd_vv $V12, $V12, $V0]}
+    # xor with the bottom-half input
+    @{[vxor_vv $V24, $V24, $V8]}
+    sw $STATE8, 32(sp)
+    @{[vxor_vv $V25, $V25, $V9]}
+    sw $STATE9, 36(sp)
+    @{[vxor_vv $V26, $V26, $V10]}
+    sw $STATE10, 40(sp)
+    @{[vxor_vv $V27, $V27, $V11]}
+    sw $STATE11, 44(sp)
+    @{[vxor_vv $V29, $V29, $V13]}
+    sw $STATE12, 48(sp)
+    @{[vxor_vv $V28, $V28, $V12]}
+    sw $STATE13, 52(sp)
+    @{[vxor_vv $V30, $V30, $V14]}
+    sw $STATE14, 56(sp)
+    @{[vxor_vv $V31, $V31, $V15]}
+    sw $STATE15, 60(sp)
+
+    # save the bottom-half of output
+    li $T0, 64
+    addi $T1, $OUTPUT, 32
+    @{[vssseg_nf_e32_v 8, $V24, $T1, $T0]}
+
+    # the computed vector parts: `64 * VL`
+    slli $T0, $VL, 6
+
+    add $INPUT, $INPUT, $T0
+    add $OUTPUT, $OUTPUT, $T0
+    sub $LEN, $LEN, $T0
+    add $CURRENT_COUNTER, $CURRENT_COUNTER, $VL
+
+    # process the scalar data block
+    addi $CURRENT_COUNTER, $CURRENT_COUNTER, 1
+    li $T0, 64
+    @{[minu $T1, $LEN, $T0]}
+    sub $LEN, $LEN, $T1
+    mv $T2, sp
+.Lscalar_data_loop:
+    @{[vsetvli $VL, $T1, "e8", "m8", "ta", "ma"]}
+    @{[vle8_v $V8, $INPUT]}
+    @{[vle8_v $V16, $T2]}
+    @{[vxor_vv $V8, $V8, $V16]}
+    @{[vse8_v $V8, $OUTPUT]}
+    add $INPUT, $INPUT, $VL
+    add $OUTPUT, $OUTPUT, $VL
+    add $T2, $T2, $VL
+    sub $T1, $T1, $VL
+    bnez $T1, .Lscalar_data_loop
+
+    bnez $LEN, .Lblock_loop
+
+    addi sp, sp, 64
+    ld s0, 0(sp)
+    ld s1, 8(sp)
+    ld s2, 16(sp)
+    ld s3, 24(sp)
+    ld s4, 32(sp)
+    ld s5, 40(sp)
+    ld s6, 48(sp)
+    ld s7, 56(sp)
+    ld s8, 64(sp)
+    ld s9, 72(sp)
+    ld s10, 80(sp)
+    ld s11, 88(sp)
+    addi sp, sp, 96
+
+    ret
+.size ChaCha20_ctr32_zbb_zvkb,.-ChaCha20_ctr32_zbb_zvkb
+___
+
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!";

+ 6 - 0
libs/openssl/crypto/chacha/build.info

@@ -22,14 +22,19 @@ IF[{- !$disabled{asm} -}]
 
   $CHACHAASM_c64xplus=chacha-c64xplus.s
 
+  $CHACHAASM_riscv64=chacha_riscv.c chacha_enc.c chacha-riscv64-zbb-zvkb.s
+  $CHACHADEF_riscv64=INCLUDE_C_CHACHA20
+
   # Now that we have defined all the arch specific variables, use the
   # appropriate one
   IF[$CHACHAASM_{- $target{asm_arch} -}]
     $CHACHAASM=$CHACHAASM_{- $target{asm_arch} -}
+    $CHACHADEF=$CHACHADEF_{- $target{asm_arch} -}
   ENDIF
 ENDIF
 
 SOURCE[../../libcrypto]=$CHACHAASM
+DEFINE[../../libcrypto]=$CHACHADEF
 
 GENERATE[chacha-x86.S]=asm/chacha-x86.pl
 GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl
@@ -48,3 +53,4 @@ GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl
 GENERATE[chacha-ia64.S]=asm/chacha-ia64.pl
 GENERATE[chacha-ia64.s]=chacha-ia64.S
 GENERATE[chacha-loongarch64.S]=asm/chacha-loongarch64.pl
+GENERATE[chacha-riscv64-zbb-zvkb.s]=asm/chacha-riscv64-zbb-zvkb.pl

+ 7 - 3
libs/openssl/crypto/chacha/chacha_enc.c

@@ -90,9 +90,13 @@ static void chacha20_core(chacha_buf *output, const u32 input[16])
     }
 }
 
-void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
-                    size_t len, const unsigned int key[8],
-                    const unsigned int counter[4])
+#ifdef INCLUDE_C_CHACHA20
+void ChaCha20_ctr32_c(unsigned char *out, const unsigned char *inp, size_t len,
+                      const unsigned int key[8], const unsigned int counter[4])
+#else
+void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len,
+                    const unsigned int key[8], const unsigned int counter[4])
+#endif
 {
     u32 input[16];
     chacha_buf buf;

+ 56 - 0
libs/openssl/crypto/chacha/chacha_riscv.c

@@ -0,0 +1,56 @@
+/*
+ * This file is dual-licensed, meaning that you can use it under your
+ * choice of either of the following two licenses:
+ *
+ * Copyright 2023-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
+ *
+ * or
+ *
+ * Copyright (c) 2023, Jerry Shih <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <openssl/opensslconf.h>
+#include "crypto/chacha.h"
+#include "crypto/riscv_arch.h"
+
+void ChaCha20_ctr32_zbb_zvkb(unsigned char *out, const unsigned char *inp,
+                             size_t len, const unsigned int key[8],
+                             const unsigned int counter[4]);
+
+void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp, size_t len,
+                    const unsigned int key[8], const unsigned int counter[4])
+{
+    if (len > CHACHA_BLK_SIZE && RISCV_HAS_ZVKB() && RISCV_HAS_ZBB() &&
+        riscv_vlen() >= 128) {
+        ChaCha20_ctr32_zbb_zvkb(out, inp, len, key, counter);
+    } else {
+        ChaCha20_ctr32_c(out, inp, len, key, counter);
+    }
+}

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

@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -95,7 +95,7 @@ int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
 
     if (in->nlast_block == -1)
         return 0;
-    if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) < 0)
+    if ((bl = EVP_CIPHER_CTX_get_block_size(in->cctx)) == 0)
         return 0;
     if (!EVP_CIPHER_CTX_copy(out->cctx, in->cctx))
         return 0;
@@ -111,6 +111,7 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
               const EVP_CIPHER *cipher, ENGINE *impl)
 {
     static const unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH] = { 0 };
+    int block_len;
 
     /* All zeros means restart */
     if (!key && !cipher && !impl && keylen == 0) {
@@ -119,7 +120,10 @@ int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
             return 0;
         if (!EVP_EncryptInit_ex(ctx->cctx, NULL, NULL, NULL, zero_iv))
             return 0;
-        memset(ctx->tbl, 0, EVP_CIPHER_CTX_get_block_size(ctx->cctx));
+        block_len = EVP_CIPHER_CTX_get_block_size(ctx->cctx);
+        if (block_len == 0)
+            return 0;
+        memset(ctx->tbl, 0, block_len);
         ctx->nlast_block = 0;
         return 1;
     }
@@ -170,7 +174,7 @@ int CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
         return 0;
     if (dlen == 0)
         return 1;
-    if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0)
+    if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0)
         return 0;
     /* Copy into partial block if we need to */
     if (ctx->nlast_block > 0) {
@@ -234,7 +238,7 @@ int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen)
 
     if (ctx->nlast_block == -1)
         return 0;
-    if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) < 0)
+    if ((bl = EVP_CIPHER_CTX_get_block_size(ctx->cctx)) == 0)
         return 0;
     if (poutlen != NULL)
         *poutlen = (size_t)bl;

+ 36 - 18
libs/openssl/crypto/cmp/cmp_asn.c

@@ -58,11 +58,7 @@ IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
 ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = {
     ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI),
     ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER),
-    /*
-     * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
-     * so it is used directly
-     *
-     */
+    /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
     ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails,
                          ASN1_UTF8STRING)
 } ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT)
@@ -121,6 +117,9 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
     ADB_ENTRY(NID_id_it_rootCaKeyUpdate,
               ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate,
                        OSSL_CMP_ROOTCAKEYUPDATE)),
+    ADB_ENTRY(NID_id_it_certProfile,
+              ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile,
+                                   ASN1_UTF8STRING)),
 } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
                &infotypeandvalue_default_tt, NULL);
 
@@ -190,13 +189,40 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
     return 1;
 
  err:
-    if (created != 0) {
+    if (created) {
         sk_OSSL_CMP_ITAV_free(*itav_sk_p);
         *itav_sk_p = NULL;
     }
     return 0;
 }
 
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile)
+{
+    OSSL_CMP_ITAV *itav;
+
+    if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+        return NULL;
+    itav->infoType = OBJ_nid2obj(NID_id_it_certProfile);
+    itav->infoValue.certProfile = certProfile;
+    return itav;
+}
+
+int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav,
+                                   STACK_OF(ASN1_UTF8STRING) **out)
+{
+    if (itav == NULL || out == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_certProfile) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    *out = itav->infoValue.certProfile;
+    return 1;
+}
+
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts)
 {
     OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new();
@@ -334,7 +360,7 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
 }
 
 static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval,
-                           const ASN1_ITEM *it, void *exarg)
+                           ossl_unused const ASN1_ITEM *it, void *exarg)
 {
     OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval;
 
@@ -424,14 +450,9 @@ ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS)
 
 ASN1_SEQUENCE(OSSL_CMP_PKISI) = {
     ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS),
-    /*
-     * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
-     * so it is used directly
-     */
+    /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
     ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING),
-    /*
-     * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly
-     */
+    /* OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING, used directly */
     ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END(OSSL_CMP_PKISI)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
@@ -548,10 +569,7 @@ ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = {
     ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4),
     ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5),
     ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6),
-    /*
-     * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
-     * so it is used directly
-     */
+    /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
     ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7),
     ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo,
                              OSSL_CMP_ITAV, 8)

+ 162 - 34
libs/openssl/crypto/cmp/cmp_client.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -113,6 +113,23 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
     return 1;
 }
 
+static int is_crep_with_waiting(const OSSL_CMP_MSG *resp, int rid)
+{
+    OSSL_CMP_CERTREPMESSAGE *crepmsg;
+    OSSL_CMP_CERTRESPONSE *crep;
+    int bt = OSSL_CMP_MSG_get_bodytype(resp);
+
+    if (!IS_CREP(bt))
+        return 0;
+
+    crepmsg = resp->body->value.ip; /* same for cp and kup */
+    crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+
+    return (crep != NULL
+            && ossl_cmp_pkisi_get_status(crep->status)
+            == OSSL_CMP_PKISTATUS_waiting);
+}
+
 /*-
  * Perform the generic aspects of sending a request and receiving a response.
  * Returns 1 on success and provides the received PKIMESSAGE in *rep.
@@ -160,7 +177,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
     /* should print error queue since transfer_cb may call ERR_clear_error() */
     OSSL_CMP_CTX_print_errors(ctx);
 
-    ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
+    if (ctx->server != NULL)
+        ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
 
     *rep = (*transfer_cb)(ctx, req);
     ctx->msg_timeout = bak_msg_timeout;
@@ -180,7 +198,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
      * Still we use this preliminary value already for a progress report because
      * the following msg verification may also produce log entries and may fail.
      */
-    ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
+    ossl_cmp_log2(INFO, ctx, "received %s%s", ossl_cmp_bodytype_to_string(bt),
+                  ossl_cmp_is_error_with_waiting(*rep) ? " (waiting)" : "");
 
     /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
     if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF
@@ -191,9 +210,17 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
                                    expected_type))
         return 0;
 
+    /*
+     * rep can have the expected response type, which during polling is pollRep.
+     * When polling, also any other non-error response (the final response)
+     * is fine here. When not yet polling, delayed delivery may be initiated
+     * by the server returning an error message with 'waiting' status (or a
+     * response message of expected type ip/cp/kup with 'waiting' status).
+     */
     if (bt == expected_type
-        /* as an answer to polling, there could be IP/CP/KUP: */
-            || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
+        || (expected_type == OSSL_CMP_PKIBODY_POLLREP
+            ? bt != OSSL_CMP_PKIBODY_ERROR
+            : ossl_cmp_is_error_with_waiting(*rep)))
         return 1;
 
     /* received message type is not one of the expected ones (e.g., error) */
@@ -235,7 +262,7 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
 
 /*-
  * When a 'waiting' PKIStatus has been received, this function is used to
- * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
+ * poll, which should yield a pollRep or the final response.
  * On receiving a pollRep, which includes a checkAfter value, it return this
  * value if sleep == 0, else it sleeps as long as indicated and retries.
  *
@@ -246,7 +273,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
  * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
  * Returns 1 on success and provides the received PKIMESSAGE in *rep.
  *           In this case the caller is responsible for freeing *rep.
- * Returns 0 on error (which includes the case that timeout has been reached).
+ * Returns 0 on error (which includes the cases that timeout has been reached
+ *           or a response with 'waiting' status has been received).
  */
 static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
                              OSSL_CMP_MSG **rep, int *checkAfter)
@@ -312,7 +340,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
                           str, check_after);
 
             if (ctx->total_timeout != 0) { /* timeout is not infinite */
-                const int exp = 5; /* expected max time per msg round trip */
+                const int exp = OSSL_CMP_EXPECTED_RESP_TIME;
                 int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
 
                 if (time_left <= 0) {
@@ -335,9 +363,19 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
                     *checkAfter = (int)check_after;
                 return -1; /* exits the loop */
             }
+        } else if (is_crep_with_waiting(prep, rid)
+                   || ossl_cmp_is_error_with_waiting(prep)) {
+            /* received status must not be 'waiting' */
+            (void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
+                                          OSSL_CMP_CTX_FAILINFO_badRequest,
+                                          "polling already started",
+                                          0 /* errorCode */, NULL);
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
+            goto err;
         } else {
-            ossl_cmp_info(ctx, "received ip/cp/kup after polling");
-            /* any other body type has been rejected by send_receive_check() */
+            ossl_cmp_info(ctx, "received final response after polling");
+            if (!ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL))
+                return 0;
             break;
         }
     }
@@ -349,11 +387,63 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
 
     return 1;
  err:
+    (void)ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL);
     OSSL_CMP_MSG_free(preq);
     OSSL_CMP_MSG_free(prep);
     return 0;
 }
 
+static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx,
+                                       const OSSL_CMP_MSG *rep, int rid)
+{
+    /*
+     * Lightweight CMP Profile section 4.4 states: the senderNonce of the
+     * preceding request message because this value will be needed for checking
+     * the recipNonce of the final response to be received after polling.
+     */
+    if ((is_crep_with_waiting(rep, rid)
+         || ossl_cmp_is_error_with_waiting(rep))
+        && !ossl_cmp_ctx_set1_first_senderNonce(ctx, ctx->senderNonce))
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Send request and get response possibly with polling initiated by error msg.
+ * Polling for ip/cp/kup/ with 'waiting' status is handled by cert_response().
+ */
+static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
+                                     OSSL_CMP_MSG **rep, int expected_type)
+{
+
+    if (!send_receive_check(ctx, req, rep, expected_type))
+        return 0;
+
+    if (ossl_cmp_is_error_with_waiting(*rep)) {
+        if (!save_senderNonce_if_waiting(ctx, *rep, OSSL_CMP_CERTREQID_NONE))
+            return 0;
+        /* not modifying ctx->status during certConf and error exchanges */
+        if (expected_type != OSSL_CMP_PKIBODY_PKICONF
+            && !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo))
+            return 0;
+
+        OSSL_CMP_MSG_free(*rep);
+        *rep = NULL;
+
+        if (poll_for_response(ctx, 1 /* can sleep */, OSSL_CMP_CERTREQID_NONE,
+                              rep, NULL /* checkAfter */) <= 0) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
+            return 0;
+        }
+    }
+    if (OSSL_CMP_MSG_get_bodytype(*rep) != expected_type) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        return 0;
+    }
+
+    return 1;
+}
 /*
  * Send certConf for IR, CR or KUR sequences and check response,
  * not modifying ctx->status during the certConf exchange
@@ -370,7 +460,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
     if (certConf == NULL)
         goto err;
 
-    res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+    res = send_receive_also_delayed(ctx, certConf, &PKIconf,
+                                    OSSL_CMP_PKIBODY_PKICONF);
 
  err:
     OSSL_CMP_MSG_free(certConf);
@@ -394,7 +485,8 @@ int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
     if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
         goto err;
 
-    res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+    res = send_receive_also_delayed(ctx, error,
+                                    &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
 
  err:
     OSSL_CMP_MSG_free(error);
@@ -515,7 +607,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
         if (X509_verify_cert(csc) <= 0)
             goto err;
 
-        if (!ossl_x509_add_certs_new(&chain,  X509_STORE_CTX_get0_chain(csc),
+        if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc),
                                      X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
                                      | X509_ADD_FLAG_NO_SS)) {
             sk_X509_free(chain);
@@ -564,48 +656,78 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
     EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
     int fail_info = 0; /* no failure */
     const char *txt = NULL;
-    OSSL_CMP_CERTREPMESSAGE *crepmsg;
-    OSSL_CMP_CERTRESPONSE *crep;
+    OSSL_CMP_CERTREPMESSAGE *crepmsg = NULL;
+    OSSL_CMP_CERTRESPONSE *crep = NULL;
     OSSL_CMP_certConf_cb_t cb;
     X509 *cert;
     char *subj = NULL;
     int ret = 1;
+    int rcvd_type;
+    OSSL_CMP_PKISI *si;
 
     if (!ossl_assert(ctx != NULL))
         return 0;
 
  retry:
-    crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
-    if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
-        ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
-        return 0;
-    }
-    crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
-    if (crep == NULL)
-        return 0;
-    if (!save_statusInfo(ctx, crep->status))
-        return 0;
-    if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
-        rid = ossl_cmp_asn1_get_int(crep->certReqId);
-        if (rid < OSSL_CMP_CERTREQID_NONE) {
-            ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+    rcvd_type = OSSL_CMP_MSG_get_bodytype(*resp);
+    if (IS_CREP(rcvd_type)) {
+        crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
+        if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
             return 0;
         }
+        crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+        if (crep == NULL)
+            return 0;
+        si = crep->status;
+
+        if (rid == OSSL_CMP_CERTREQID_NONE) {
+            /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
+            rid = ossl_cmp_asn1_get_int(crep->certReqId);
+            if (rid < OSSL_CMP_CERTREQID_NONE) {
+                ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+                return 0;
+            }
+        }
+    } else if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) {
+        si = (*resp)->body->value.error->pKIStatusInfo;
+    } else {
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        return 0;
     }
 
-    if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
+    if (!save_statusInfo(ctx, si))
+        return 0;
+
+    if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) {
+        /*
+         * Here we allow both and error message with waiting indication
+         * as well as a certificate response with waiting indication, where
+         * its flavor (ip, cp, or kup) may not strictly match ir/cr/p10cr/kur.
+         */
         OSSL_CMP_MSG_free(*resp);
         *resp = NULL;
         if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
             if (ret == -1) /* at this point implies sleep == 0 */
                 return ret; /* waiting */
-            goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
+            goto retry; /* got some response other than pollRep */
         } else {
             ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
             return 0;
         }
     }
 
+    /* at this point, we have received ip/cp/kup/error without waiting */
+    if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR);
+        return 0;
+    }
+    /* here we are strict on the flavor of ip/cp/kup: must match request */
+    if (rcvd_type != expected_type) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        return 0;
+    }
+
     cert = get1_cert_status(ctx, (*resp)->body->type, crep);
     if (cert == NULL) {
         ERR_add_error_data(1, "; cannot extract certificate from response");
@@ -618,7 +740,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
      * if the CMP server returned certificates in the caPubs field, copy them
      * to the context so that they can be retrieved if necessary
      */
-    if (crepmsg->caPubs != NULL
+    if (crepmsg != NULL && crepmsg->caPubs != NULL
             && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
         return 0;
 
@@ -709,6 +831,9 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
     if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
         if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
             goto err;
+
+        if (!save_senderNonce_if_waiting(ctx, rep, rid))
+            return 0;
     } else {
         if (req_type < 0)
             return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
@@ -750,6 +875,9 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
     if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
         goto err;
 
+    if (!save_senderNonce_if_waiting(ctx, rep, rid))
+        return 0;
+
     if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
         <= 0)
         goto err;
@@ -787,7 +915,7 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
         goto end;
 
     ctx->status = OSSL_CMP_PKISTATUS_trans;
-    if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
+    if (!send_receive_also_delayed(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
         goto end;
 
     rrep = rp->body->value.rp;
@@ -908,7 +1036,7 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
         goto err;
 
     ctx->status = OSSL_CMP_PKISTATUS_trans;
-    if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
+    if (!send_receive_also_delayed(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
         goto err;
     ctx->status = OSSL_CMP_PKISTATUS_accepted;
 

+ 13 - 1
libs/openssl/crypto/cmp/cmp_ctx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -183,6 +183,7 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
         && ossl_cmp_ctx_set1_caPubs(ctx, NULL)
         && ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
         && ossl_cmp_ctx_set1_validatedSrvCert(ctx, NULL)
+        && ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL)
         && OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
         && OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
         && ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
@@ -226,6 +227,7 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
     ASN1_OCTET_STRING_free(ctx->transactionID);
     ASN1_OCTET_STRING_free(ctx->senderNonce);
     ASN1_OCTET_STRING_free(ctx->recipNonce);
+    ASN1_OCTET_STRING_free(ctx->first_senderNonce);
     OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs);
     OSSL_STACK_OF_X509_free(ctx->extraCertsOut);
 
@@ -534,6 +536,8 @@ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx)
     return 1;
 }
 
+DEFINE_OSSL_CMP_CTX_get0(geninfo_ITAVs, STACK_OF(OSSL_CMP_ITAV))
+
 /* Add an itav for the body of outgoing general messages */
 int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
 {
@@ -812,6 +816,9 @@ DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, recipNonce)
 /* Stores the given nonce as the last senderNonce sent out */
 DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, senderNonce)
 
+/* store the first req sender nonce for verifying delayed delivery */
+DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, first_senderNonce)
+
 /* Set the proxy server to use for HTTP(S) connections */
 DEFINE_OSSL_CMP_CTX_set1(proxy, char)
 
@@ -908,6 +915,9 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
     case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
         ctx->unprotectedErrors = val;
         break;
+    case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
+        ctx->noCacheExtraCerts = val;
+        break;
     case OSSL_CMP_OPT_VALIDITY_DAYS:
         ctx->days = val;
         break;
@@ -993,6 +1003,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
         return ctx->unprotectedSend;
     case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
         return ctx->unprotectedErrors;
+    case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
+        return ctx->noCacheExtraCerts;
     case OSSL_CMP_OPT_VALIDITY_DAYS:
         return ctx->days;
     case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:

+ 8 - 1
libs/openssl/crypto/cmp/cmp_err.c

@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -76,6 +76,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "error validating protection"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE),
     "error validating signature"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_EXPECTED_POLLREQ), "expected pollreq"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
     "failed building own chain"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
@@ -144,10 +145,14 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "transactionid unmatched"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
+     "unexpected certprofile"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
     "unexpected pkistatus"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_POLLREQ), "unexpected pollreq"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_SENDER), "unexpected sender"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
     "unknown algorithm id"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
@@ -156,6 +161,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "unsupported algorithm"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
     "unsupported key type"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PKIBODY),
+    "unsupported pkibody"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
     "unsupported protection alg dhbasedmac"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"},

+ 10 - 0
libs/openssl/crypto/cmp/cmp_hdr.c

@@ -72,6 +72,16 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
     return hdr->recipNonce;
 }
 
+STACK_OF(OSSL_CMP_ITAV)
+    *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr)
+{
+    if (hdr == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    return hdr->generalInfo;
+}
+
 /* a NULL-DN as an empty sequence of RDNs */
 int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
 {

+ 10 - 1
libs/openssl/crypto/cmp/cmp_local.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -64,6 +64,7 @@ struct ossl_cmp_ctx_st {
      * certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
      */
     int unprotectedErrors;
+    int noCacheExtraCerts;
     X509 *srvCert; /* certificate used to identify the server */
     X509 *validatedSrvCert; /* caches any already validated server cert */
     X509_NAME *expected_sender; /* expected sender in header of response */
@@ -95,6 +96,7 @@ struct ossl_cmp_ctx_st {
     ASN1_OCTET_STRING *transactionID; /* the current transaction ID */
     ASN1_OCTET_STRING *senderNonce; /* last nonce sent */
     ASN1_OCTET_STRING *recipNonce; /* last nonce received */
+    ASN1_OCTET_STRING *first_senderNonce; /* sender nonce when starting to poll */
     ASN1_UTF8STRING *freeText; /* optional string to include each msg */
     STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs;
     int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */
@@ -254,6 +256,8 @@ struct ossl_cmp_itav_st {
         OSSL_CMP_MSGS *origPKIMessage;
         /* NID_id_it_suppLangTags - Supported Language Tags */
         STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
+        /* NID_id_it_certProfile - Certificate Profile */
+        STACK_OF(ASN1_UTF8STRING) *certProfile;
         /* NID_id_it_caCerts - CA Certificates */
         STACK_OF(X509) *caCerts;
         /* NID_id_it_rootCaCert - Root CA Certificate */
@@ -821,6 +825,8 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
 int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
                                  const ASN1_OCTET_STRING *nonce);
 EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx);
+int ossl_cmp_ctx_set1_first_senderNonce(OSSL_CMP_CTX *ctx,
+                                        const ASN1_OCTET_STRING *nonce);
 
 /* from cmp_status.c */
 int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
@@ -937,6 +943,7 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
 X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
                                       const OSSL_CMP_CERTRESPONSE *crep);
 OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
+int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg);
 
 /* from cmp_protect.c */
 int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
@@ -956,6 +963,8 @@ int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
                          const OSSL_CMP_MSG *msg, int accept_RAVerified);
 
 /* from cmp_client.c */
+/* expected max time per msg round trip, used for last try during polling: */
+# define OSSL_CMP_EXPECTED_RESP_TIME 2
 int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
                                int fail_info, const char *txt);
 int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,

+ 41 - 5
libs/openssl/crypto/cmp/cmp_msg.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2019
  * Copyright Siemens AG 2015-2019
  *
@@ -100,6 +100,34 @@ int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg)
     return msg->body->type;
 }
 
+X509_PUBKEY *OSSL_CMP_MSG_get0_certreq_publickey(const OSSL_CMP_MSG *msg)
+{
+    const OSSL_CRMF_MSGS *reqs;
+    const OSSL_CRMF_MSG *crm;
+    const OSSL_CRMF_CERTTEMPLATE *tmpl;
+    X509_PUBKEY *pubkey;
+
+    switch (OSSL_CMP_MSG_get_bodytype(msg)) {
+    case OSSL_CMP_PKIBODY_IR:
+    case OSSL_CMP_PKIBODY_CR:
+    case OSSL_CMP_PKIBODY_KUR:
+        reqs = msg->body->value.ir; /* value.ir is same for cr and kur */
+        if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
+            return NULL;
+        }
+        if ((tmpl = OSSL_CRMF_MSG_get0_tmpl(crm)) == NULL
+            || (pubkey = OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl)) == NULL) {
+            ERR_raise(ERR_LIB_CMP, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+            return NULL;
+        }
+        return pubkey;
+    default:
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        return NULL;
+    }
+}
+
 /* Add an extension to the referenced extension stack, which may be NULL */
 static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
 {
@@ -542,8 +570,7 @@ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
     } else if (ctx->p10CSR != NULL) {
         pubkey = X509_REQ_get0_pubkey(ctx->p10CSR);
         subject = X509_REQ_get_subject_name(ctx->p10CSR);
-    }
-    else {
+    } else {
         goto err;
     }
 
@@ -984,8 +1011,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
         return 1;
 
     trid = ossl_cmp_asn1_get_int(certReqId);
-
-    if (trid == OSSL_CMP_CERTREQID_NONE) {
+    if (trid <= OSSL_CMP_CERTREQID_INVALID) {
         ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
         return 0;
     }
@@ -1200,3 +1226,13 @@ int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
 {
     return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
 }
+
+int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg)
+{
+    if (!ossl_assert(msg != NULL))
+        return 0;
+
+    return (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_ERROR
+            && ossl_cmp_pkisi_get_status(msg->body->value.error->pKIStatusInfo)
+            == OSSL_CMP_PKISTATUS_waiting);
+}

+ 165 - 63
libs/openssl/crypto/cmp/cmp_server.c

@@ -22,9 +22,10 @@
 /* the context for the generic CMP server */
 struct ossl_cmp_srv_ctx_st
 {
-    void *custom_ctx;  /* pointer to application-specific server context */
-    OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */
-    int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
+    OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */
+    void *custom_ctx;  /* application-specific server context */
+    int certReqId;     /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
+    int polling;       /* current transaction is in polling mode */
 
     OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
     OSSL_CMP_SRV_rr_cb_t process_rr;
@@ -32,6 +33,8 @@ struct ossl_cmp_srv_ctx_st
     OSSL_CMP_SRV_error_cb_t process_error;
     OSSL_CMP_SRV_certConf_cb_t process_certConf;
     OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
+    OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery;
+    OSSL_CMP_SRV_clean_transaction_cb_t clean_transaction;
 
     int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
     int acceptUnprotected;     /* Accept requests with no/invalid prot. */
@@ -59,6 +62,7 @@ OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
     if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL)
         goto err;
     ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
+    ctx->polling = 0;
 
     /* all other elements are initialized to 0 or NULL, respectively */
     return ctx;
@@ -89,6 +93,19 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
     return 1;
 }
 
+int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx,
+                                OSSL_CMP_SRV_delayed_delivery_cb_t delay,
+                                OSSL_CMP_SRV_clean_transaction_cb_t clean)
+{
+    if (srv_ctx == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    srv_ctx->delayed_delivery = delay;
+    srv_ctx->clean_transaction = clean;
+    return 1;
+}
+
 OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
 {
     if (srv_ctx == NULL) {
@@ -149,6 +166,46 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
     return 1;
 }
 
+/* return error msg with waiting status if polling is initiated, else NULL */
+static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
+                                      const OSSL_CMP_MSG *req)
+{
+    int ret;
+    unsigned long err;
+    int status = OSSL_CMP_PKISTATUS_waiting,
+        fail_info = 0, errorCode = 0;
+    const char *txt = NULL, *details = NULL;
+    OSSL_CMP_PKISI *si;
+    OSSL_CMP_MSG *msg;
+
+    if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL
+                     && srv_ctx->delayed_delivery != NULL))
+        return NULL;
+
+    ret = srv_ctx->delayed_delivery(srv_ctx, req);
+    if (ret == 0)
+        return NULL;
+    if (ret == 1) {
+        srv_ctx->polling = 1;
+    } else {
+        status = OSSL_CMP_PKISTATUS_rejection;
+        fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_systemFailure;
+        txt = "server application error";
+        err = ERR_peek_error();
+        errorCode = ERR_GET_REASON(err);
+        details = ERR_reason_error_string(err);
+    }
+
+    si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt);
+    if (si == NULL)
+        return NULL;
+
+    msg = ossl_cmp_error_new(srv_ctx->ctx, si, errorCode, details,
+                             srv_ctx->sendUnprotectedErrors);
+    OSSL_CMP_PKISI_free(si);
+    return msg;
+}
+
 /*
  * Processes an ir/cr/p10cr/kur and returns a certification response.
  * Only handles the first certification request contained in req
@@ -195,15 +252,14 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
             ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
             return NULL;
         }
-
-        if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
+        if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) {
             ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
             return NULL;
         }
         certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
-        if (certReqId != OSSL_CMP_CERTREQID) {
+        if (certReqId != OSSL_CMP_CERTREQID) { /* so far, only possible value */
             ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
-            return 0;
+            return NULL;
         }
     }
     srv_ctx->certReqId = certReqId;
@@ -222,6 +278,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
                                            &certOut, &chainOut, &caPubs);
         if (si == NULL)
             goto err;
+        if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting)
+            srv_ctx->polling = 1;
         /* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
         if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx,
                                      OSSL_CMP_OPT_IMPLICIT_CONFIRM,
@@ -265,9 +323,8 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
         ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
         return NULL;
     }
-
-    if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
-                                                OSSL_CMP_REVREQSID)) == NULL) {
+    details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, 0);
+    if (details == NULL) {
         ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
         return NULL;
     }
@@ -356,7 +413,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
     } else {
         if (num > 1)
             ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
-        status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
+        status = sk_OSSL_CMP_CERTSTATUS_value(ccc, 0);
     }
 
     if (status != NULL) {
@@ -387,38 +444,96 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
     return msg;
 }
 
+/* pollReq is handled separately, to avoid recursive call */
+static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx,
+                                                 const OSSL_CMP_MSG *req)
+{
+    OSSL_CMP_MSG *rsp = NULL;
+
+    if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL
+                     && req->body != NULL))
+        return NULL;
+
+    switch (OSSL_CMP_MSG_get_bodytype(req)) {
+    case OSSL_CMP_PKIBODY_IR:
+    case OSSL_CMP_PKIBODY_CR:
+    case OSSL_CMP_PKIBODY_P10CR:
+    case OSSL_CMP_PKIBODY_KUR:
+        if (srv_ctx->process_cert_request == NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        else
+            rsp = process_cert_request(srv_ctx, req);
+        break;
+    case OSSL_CMP_PKIBODY_RR:
+        if (srv_ctx->process_rr == NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        else
+            rsp = process_rr(srv_ctx, req);
+        break;
+    case OSSL_CMP_PKIBODY_GENM:
+        if (srv_ctx->process_genm == NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        else
+            rsp = process_genm(srv_ctx, req);
+        break;
+    case OSSL_CMP_PKIBODY_ERROR:
+        if (srv_ctx->process_error == NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        else
+            rsp = process_error(srv_ctx, req);
+        break;
+    case OSSL_CMP_PKIBODY_CERTCONF:
+        if (srv_ctx->process_certConf == NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        else
+            rsp = process_certConf(srv_ctx, req);
+        break;
+
+    case OSSL_CMP_PKIBODY_POLLREQ:
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        break;
+    default:
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+        break;
+    }
+
+    return rsp;
+}
+
 static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
                                      const OSSL_CMP_MSG *req)
 {
     OSSL_CMP_POLLREQCONTENT *prc;
     OSSL_CMP_POLLREQ *pr;
     int certReqId;
-    OSSL_CMP_MSG *certReq;
+    OSSL_CMP_MSG *orig_req;
     int64_t check_after = 0;
     OSSL_CMP_MSG *msg = NULL;
 
     if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
         return NULL;
 
+    if (!srv_ctx->polling) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+        return NULL;
+    }
+
     prc = req->body->value.pollReq;
     if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) {
         ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
         return NULL;
     }
 
-    pr = sk_OSSL_CMP_POLLREQ_value(prc, OSSL_CMP_CERTREQID);
+    pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
     certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
-    if (certReqId != srv_ctx->certReqId) {
-        ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
-        return NULL;
-    }
     if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
-                                  &certReq, &check_after))
+                                  &orig_req, &check_after))
         return NULL;
 
-    if (certReq != NULL) {
-        msg = process_cert_request(srv_ctx, certReq);
-        OSSL_CMP_MSG_free(certReq);
+    if (orig_req != NULL) {
+        srv_ctx->polling = 0;
+        msg = process_non_polling_request(srv_ctx, orig_req);
+        OSSL_CMP_MSG_free(orig_req);
     } else {
         if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
                                         check_after)) == NULL)
@@ -488,6 +603,12 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
     if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
         goto err;
 
+    if (srv_ctx->polling && req_type != OSSL_CMP_PKIBODY_POLLREQ
+            && req_type != OSSL_CMP_PKIBODY_ERROR) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ);
+        goto err;
+    }
+
     switch (req_type) {
     case OSSL_CMP_PKIBODY_IR:
     case OSSL_CMP_PKIBODY_CR:
@@ -509,6 +630,13 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
         if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
                 || !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL))
             goto err;
+
+        if (srv_ctx->clean_transaction != NULL
+                && !srv_ctx->clean_transaction(srv_ctx, NULL)) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+            goto err;
+        }
+
         break;
     default:
         /* transactionID should be already initialized */
@@ -528,50 +656,17 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
     if (!req_verified)
         goto err;
 
-    switch (req_type) {
-    case OSSL_CMP_PKIBODY_IR:
-    case OSSL_CMP_PKIBODY_CR:
-    case OSSL_CMP_PKIBODY_P10CR:
-    case OSSL_CMP_PKIBODY_KUR:
-        if (srv_ctx->process_cert_request == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        else
-            rsp = process_cert_request(srv_ctx, req);
-        break;
-    case OSSL_CMP_PKIBODY_RR:
-        if (srv_ctx->process_rr == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        else
-            rsp = process_rr(srv_ctx, req);
-        break;
-    case OSSL_CMP_PKIBODY_GENM:
-        if (srv_ctx->process_genm == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        else
-            rsp = process_genm(srv_ctx, req);
-        break;
-    case OSSL_CMP_PKIBODY_ERROR:
-        if (srv_ctx->process_error == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        else
-            rsp = process_error(srv_ctx, req);
-        break;
-    case OSSL_CMP_PKIBODY_CERTCONF:
-        if (srv_ctx->process_certConf == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        else
-            rsp = process_certConf(srv_ctx, req);
-        break;
-    case OSSL_CMP_PKIBODY_POLLREQ:
+    if (req_type == OSSL_CMP_PKIBODY_POLLREQ) {
         if (srv_ctx->process_pollReq == NULL)
-            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
         else
             rsp = process_pollReq(srv_ctx, req);
-        break;
-    default:
-        /* Other request message types are not supported */
-        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
-        break;
+    } else {
+        if (srv_ctx->delayed_delivery != NULL
+            && (rsp = delayed_delivery(srv_ctx, req)) != NULL) {
+            goto err;
+        }
+        rsp = process_non_polling_request(srv_ctx, req);
     }
 
  err:
@@ -627,12 +722,19 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
             break;
         /* fall through */
 
+    case OSSL_CMP_PKIBODY_ERROR:
+        if (rsp != NULL && ossl_cmp_is_error_with_waiting(rsp))
+            break;
+        /* fall through */
+
     case OSSL_CMP_PKIBODY_RP:
     case OSSL_CMP_PKIBODY_PKICONF:
     case OSSL_CMP_PKIBODY_GENP:
-    case OSSL_CMP_PKIBODY_ERROR:
         /* Other terminating response message types are not supported */
+        srv_ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
         /* Prepare for next transaction, ignoring any errors here: */
+        if (srv_ctx->clean_transaction != NULL)
+            (void)srv_ctx->clean_transaction(srv_ctx, ctx->transactionID);
         (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
         (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
         ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */

+ 89 - 60
libs/openssl/crypto/cmp/cmp_vfy.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Nokia 2007-2020
  * Copyright Siemens AG 2015-2020
  *
@@ -175,8 +175,8 @@ static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
     str = X509_NAME_oneline(actual_name, NULL, 0);
     if (X509_NAME_cmp(actual_name, expect_name) == 0) {
         if (log_success && str != NULL)
-            ossl_cmp_log2(INFO, ctx, " subject matches %s: %s", expect_desc,
-                          str);
+            ossl_cmp_log3(INFO, ctx, " %s matches %s: %s",
+                          actual_desc, expect_desc, str);
         OPENSSL_free(str);
         return 1;
     }
@@ -424,14 +424,14 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
 {
     int ret = 0;
 
-    if (mode_3gpp
-            && ((!ctx->permitTAInExtraCertsForIR
-                     || OSSL_CMP_MSG_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
+    if (ctx->permitTAInExtraCertsForIR
+            && OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP)
+        ossl_cmp_info(ctx, mode_3gpp ?
+                      "normal mode failed; trying now 3GPP mode trusting extraCerts"
+                      : "trying first normal mode using trust store");
+    else if (mode_3gpp)
         return 0;
 
-    ossl_cmp_info(ctx,
-                  mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
-                            : "trying first normal mode using trust store");
     if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
                              NULL, NULL, msg, mode_3gpp))
         return 1;
@@ -705,64 +705,89 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
 {
     OSSL_CMP_PKIHEADER *hdr;
     const X509_NAME *expected_sender;
+    int num_untrusted, num_added, res;
 
     if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
         return 0;
     hdr = OSSL_CMP_MSG_get0_header(msg);
 
-    /* validate sender name of received msg */
-    if (hdr->sender->type != GEN_DIRNAME) {
-        ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
-        return 0;
-    }
-    /*
-     * Compare actual sender name of response with expected sender name.
-     * Mitigates risk to accept misused PBM secret
-     * or misused certificate of an unauthorized entity of a trusted hierarchy.
-     */
+    /* If expected_sender is given, validate sender name of received msg */
     expected_sender = ctx->expected_sender;
     if (expected_sender == NULL && ctx->srvCert != NULL)
         expected_sender = X509_get_subject_name(ctx->srvCert);
-    if (!check_name(ctx, 0, "sender DN field", hdr->sender->d.directoryName,
-                    "expected sender", expected_sender))
-        return 0;
+    if (expected_sender != NULL) {
+        const X509_NAME *actual_sender;
+        char *str;
+
+        if (hdr->sender->type != GEN_DIRNAME) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+            return 0;
+        }
+        actual_sender = hdr->sender->d.directoryName;
+        /*
+         * Compare actual sender name of response with expected sender name.
+         * Mitigates risk of accepting misused PBM secret or
+         * misused certificate of an unauthorized entity of a trusted hierarchy.
+         */
+        if (!check_name(ctx, 0, "sender DN field", actual_sender,
+                        "expected sender", expected_sender)) {
+            str = X509_NAME_oneline(actual_sender, NULL, 0);
+            ERR_raise_data(ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER,
+                           str != NULL ? str : "<unknown>");
+            OPENSSL_free(str);
+            return 0;
+        }
+    }
     /* Note: if recipient was NULL-DN it could be learned here if needed */
 
-    if (sk_X509_num(msg->extraCerts) > 10)
-        ossl_cmp_warn(ctx,
-                      "received CMP message contains more than 10 extraCerts");
+    num_added = sk_X509_num(msg->extraCerts);
+    if (num_added > 10)
+        ossl_cmp_log1(WARN, ctx, "received CMP message contains %d extraCerts",
+                      num_added);
     /*
      * Store any provided extraCerts in ctx for use in OSSL_CMP_validate_msg()
      * and for future use, such that they are available to ctx->certConf_cb and
      * the peer does not need to send them again in the same transaction.
      * Note that it does not help validating the message before storing the
      * extraCerts because they do not belong to the protected msg part anyway.
-     * For efficiency, the extraCerts are prepended so they get used first.
+     * The extraCerts are prepended. Allows simple removal if they shall not be
+     * cached. Also they get used first, which is likely good for efficiency.
      */
-    if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
-                        /* this allows self-signed certs */
-                        X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
-                        | X509_ADD_FLAG_PREPEND))
+    num_untrusted = ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted);
+    res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts,
+                                  /* this allows self-signed certs */
+                                  X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+                                  | X509_ADD_FLAG_PREPEND);
+    num_added = (ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted))
+        - num_untrusted;
+    if (!res) {
+        while (num_added-- > 0)
+            X509_free(sk_X509_shift(ctx->untrusted));
         return 0;
+    }
 
-    /* validate message protection */
-    if (hdr->protectionAlg != NULL) {
-        /* detect explicitly permitted exceptions for invalid protection */
-        if (!OSSL_CMP_validate_msg(ctx, msg)
-                && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-            ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
-            return 0;
+    if (hdr->protectionAlg != NULL)
+        res = OSSL_CMP_validate_msg(ctx, msg)
+            /* explicitly permitted exceptions for invalid protection: */
+            || (cb != NULL && (*cb)(ctx, msg, 1, cb_arg) > 0);
+    else
+        /* explicitly permitted exceptions for missing protection: */
+        res = cb != NULL && (*cb)(ctx, msg, 0, cb_arg) > 0;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    res = 1; /* support more aggressive fuzzing by letting invalid msg pass */
 #endif
-        }
-    } else {
-        /* detect explicitly permitted exceptions for missing protection */
-        if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+
+    /* remove extraCerts again if not caching */
+    if (ctx->noCacheExtraCerts)
+        while (num_added-- > 0)
+            X509_free(sk_X509_shift(ctx->untrusted));
+
+    if (!res) {
+        if (hdr->protectionAlg != NULL)
+            ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
+        else
             ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
-            return 0;
-#endif
-        }
+        return 0;
     }
 
     /* check CMP version number in header */
@@ -786,10 +811,26 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
                                       CMP_R_TRANSACTIONID_UNMATCHED))
         return 0;
 
+    /*
+     * enable clearing irrelevant errors
+     * in attempts to validate recipient nonce in case of delayed delivery.
+     */
+    (void)ERR_set_mark();
     /* compare received nonce with the one we sent */
     if (!check_transactionID_or_nonce(ctx->senderNonce, hdr->recipNonce,
-                                      CMP_R_RECIPNONCE_UNMATCHED))
-        return 0;
+                                      CMP_R_RECIPNONCE_UNMATCHED)) {
+        /* check if we are polling and received final response */
+        if (ctx->first_senderNonce == NULL
+            || OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_POLLREP
+            /* compare received nonce with our sender nonce at poll start */
+            || !check_transactionID_or_nonce(ctx->first_senderNonce,
+                                             hdr->recipNonce,
+                                             CMP_R_RECIPNONCE_UNMATCHED)) {
+            (void)ERR_clear_last_mark();
+            return 0;
+        }
+    }
+    (void)ERR_pop_to_mark();
 
     /* if not yet present, learn transactionID */
     if (ctx->transactionID == NULL
@@ -804,18 +845,6 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
     if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
         return 0;
 
-    /*
-     * Store any provided extraCerts in ctx for future use,
-     * such that they are available to ctx->certConf_cb and
-     * the peer does not need to send them again in the same transaction.
-     * For efficiency, the extraCerts are prepended so they get used first.
-     */
-    if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
-                        /* this allows self-signed certs */
-                        X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
-                        | X509_ADD_FLAG_PREPEND))
-        return 0;
-
     if (ossl_cmp_hdr_get_protection_nid(hdr) == NID_id_PasswordBasedMAC) {
         /*
          * RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is

+ 1 - 1
libs/openssl/crypto/cms/cms_enc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy

+ 9 - 1
libs/openssl/crypto/cms/cms_pwri.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2009-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -204,6 +204,10 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
     size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
     unsigned char *tmp;
     int outl, rv = 0;
+
+    if (blocklen == 0)
+        return 0;
+
     if (inlen < 2 * blocklen) {
         /* too small */
         return 0;
@@ -257,6 +261,10 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
     size_t blocklen = EVP_CIPHER_CTX_get_block_size(ctx);
     size_t olen;
     int dummy;
+
+    if (blocklen == 0)
+        return 0;
+
     /*
      * First decide length of output buffer: need header and round up to
      * multiple of block length.

+ 1 - 1
libs/openssl/crypto/conf/conf_lib.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2023 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

+ 92 - 47
libs/openssl/crypto/conf/conf_mod.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -11,6 +11,7 @@
 #define OPENSSL_SUPPRESS_DEPRECATED
 
 #include "internal/cryptlib.h"
+#include "internal/rcu.h"
 #include <stdio.h>
 #include <ctype.h>
 #include <openssl/crypto.h>
@@ -63,7 +64,7 @@ struct conf_imodule_st {
 };
 
 static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT;
-static CRYPTO_RWLOCK *module_list_lock = NULL;
+static CRYPTO_RCU_LOCK *module_list_lock = NULL;
 static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */
 static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */
 
@@ -86,7 +87,7 @@ static int conf_modules_finish_int(void);
 
 static void module_lists_free(void)
 {
-    CRYPTO_THREAD_lock_free(module_list_lock);
+    ossl_rcu_lock_free(module_list_lock);
     module_list_lock = NULL;
 
     sk_CONF_MODULE_free(supported_modules);
@@ -98,7 +99,7 @@ static void module_lists_free(void)
 
 DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
 {
-    module_list_lock = CRYPTO_THREAD_lock_new();
+    module_list_lock = ossl_rcu_lock_new(1);
     if (module_list_lock == NULL) {
         ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
         return 0;
@@ -327,17 +328,24 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
                                conf_init_func *ifunc, conf_finish_func *ffunc)
 {
     CONF_MODULE *tmod = NULL;
+    STACK_OF(CONF_MODULE) *old_modules;
+    STACK_OF(CONF_MODULE) *new_modules;
 
     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
         return NULL;
 
-    if (!CRYPTO_THREAD_write_lock(module_list_lock))
-        return NULL;
+    ossl_rcu_write_lock(module_list_lock);
+
+    old_modules = ossl_rcu_deref(&supported_modules);
+
+    if (old_modules == NULL)
+        new_modules = sk_CONF_MODULE_new_null();
+    else
+        new_modules = sk_CONF_MODULE_dup(old_modules);
 
-    if (supported_modules == NULL)
-        supported_modules = sk_CONF_MODULE_new_null();
-    if (supported_modules == NULL)
+    if (new_modules == NULL)
         goto err;
+
     if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL)
         goto err;
 
@@ -348,18 +356,24 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
     if (tmod->name == NULL)
         goto err;
 
-    if (!sk_CONF_MODULE_push(supported_modules, tmod))
+    if (!sk_CONF_MODULE_push(new_modules, tmod))
         goto err;
 
-    CRYPTO_THREAD_unlock(module_list_lock);
+    ossl_rcu_assign_ptr(&supported_modules, &new_modules);
+    ossl_rcu_write_unlock(module_list_lock);
+    ossl_synchronize_rcu(module_list_lock);
+
+    sk_CONF_MODULE_free(old_modules);
     return tmod;
 
  err:
-    CRYPTO_THREAD_unlock(module_list_lock);
+    ossl_rcu_write_unlock(module_list_lock);
+    sk_CONF_MODULE_free(new_modules);
     if (tmod != NULL) {
         OPENSSL_free(tmod->name);
         OPENSSL_free(tmod);
     }
+    sk_CONF_MODULE_free(new_modules);
     return NULL;
 }
 
@@ -374,6 +388,8 @@ static CONF_MODULE *module_find(const char *name)
     CONF_MODULE *tmod;
     int i, nchar;
     char *p;
+    STACK_OF(CONF_MODULE) *mods;
+
     p = strrchr(name, '.');
 
     if (p)
@@ -384,18 +400,18 @@ static CONF_MODULE *module_find(const char *name)
     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
         return NULL;
 
-    if (!CRYPTO_THREAD_read_lock(module_list_lock))
-        return NULL;
+    ossl_rcu_read_lock(module_list_lock);
+    mods = ossl_rcu_deref(&supported_modules);
 
-    for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
-        tmod = sk_CONF_MODULE_value(supported_modules, i);
+    for (i = 0; i < sk_CONF_MODULE_num(mods); i++) {
+        tmod = sk_CONF_MODULE_value(mods, i);
         if (strncmp(tmod->name, name, nchar) == 0) {
-            CRYPTO_THREAD_unlock(module_list_lock);
+            ossl_rcu_read_unlock(module_list_lock);
             return tmod;
         }
     }
 
-    CRYPTO_THREAD_unlock(module_list_lock);
+    ossl_rcu_read_unlock(module_list_lock);
     return NULL;
 }
 
@@ -406,6 +422,8 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
     int ret = 1;
     int init_called = 0;
     CONF_IMODULE *imod = NULL;
+    STACK_OF(CONF_IMODULE) *old_modules;
+    STACK_OF(CONF_IMODULE) *new_modules;
 
     /* Otherwise add initialized module to list */
     imod = OPENSSL_malloc(sizeof(*imod));
@@ -432,27 +450,34 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
         goto err;
 
-    if (!CRYPTO_THREAD_write_lock(module_list_lock))
-        goto err;
+    ossl_rcu_write_lock(module_list_lock);
 
-    if (initialized_modules == NULL) {
-        initialized_modules = sk_CONF_IMODULE_new_null();
-        if (initialized_modules == NULL) {
-            CRYPTO_THREAD_unlock(module_list_lock);
-            ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
-            goto err;
-        }
+    old_modules = ossl_rcu_deref(&initialized_modules);
+
+    if (old_modules == NULL)
+        new_modules = sk_CONF_IMODULE_new_null();
+    else
+        new_modules = sk_CONF_IMODULE_dup(old_modules);
+
+    if (new_modules == NULL) {
+        ossl_rcu_write_unlock(module_list_lock);
+        ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
+        goto err;
     }
 
-    if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
-        CRYPTO_THREAD_unlock(module_list_lock);
+    if (!sk_CONF_IMODULE_push(new_modules, imod)) {
+        ossl_rcu_write_unlock(module_list_lock);
+        sk_CONF_IMODULE_free(new_modules);
         ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
         goto err;
     }
 
     pmod->links++;
 
-    CRYPTO_THREAD_unlock(module_list_lock);
+    ossl_rcu_assign_ptr(&initialized_modules, &new_modules);
+    ossl_rcu_write_unlock(module_list_lock);
+    ossl_synchronize_rcu(module_list_lock);
+    sk_CONF_IMODULE_free(old_modules);
     return ret;
 
  err:
@@ -482,30 +507,46 @@ void CONF_modules_unload(int all)
 {
     int i;
     CONF_MODULE *md;
+    STACK_OF(CONF_MODULE) *old_modules;
+    STACK_OF(CONF_MODULE) *new_modules;
+    STACK_OF(CONF_MODULE) *to_delete;
 
     if (!conf_modules_finish_int()) /* also inits module list lock */
         return;
 
-    if (!CRYPTO_THREAD_write_lock(module_list_lock))
+    ossl_rcu_write_lock(module_list_lock);
+
+    old_modules = ossl_rcu_deref(&supported_modules);
+    new_modules = sk_CONF_MODULE_dup(old_modules);
+    to_delete = sk_CONF_MODULE_new_null();
+
+    if (new_modules == NULL) {
+        ossl_rcu_write_unlock(module_list_lock);
         return;
+    }
 
     /* unload modules in reverse order */
-    for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
-        md = sk_CONF_MODULE_value(supported_modules, i);
+    for (i = sk_CONF_MODULE_num(new_modules) - 1; i >= 0; i--) {
+        md = sk_CONF_MODULE_value(new_modules, i);
         /* If static or in use and 'all' not set ignore it */
         if (((md->links > 0) || !md->dso) && !all)
             continue;
         /* Since we're working in reverse this is OK */
-        (void)sk_CONF_MODULE_delete(supported_modules, i);
-        module_free(md);
+        (void)sk_CONF_MODULE_delete(new_modules, i);
+        sk_CONF_MODULE_push(to_delete, md);
     }
 
-    if (sk_CONF_MODULE_num(supported_modules) == 0) {
-        sk_CONF_MODULE_free(supported_modules);
-        supported_modules = NULL;
+    if (sk_CONF_MODULE_num(new_modules) == 0) {
+        sk_CONF_MODULE_free(new_modules);
+        new_modules = NULL;
     }
 
-    CRYPTO_THREAD_unlock(module_list_lock);
+    ossl_rcu_assign_ptr(&supported_modules, &new_modules);
+    ossl_rcu_write_unlock(module_list_lock);
+    ossl_synchronize_rcu(module_list_lock);
+    sk_CONF_MODULE_free(old_modules);
+    sk_CONF_MODULE_pop_free(to_delete, module_free);
+
 }
 
 /* unload a single module */
@@ -521,23 +562,27 @@ static void module_free(CONF_MODULE *md)
 static int conf_modules_finish_int(void)
 {
     CONF_IMODULE *imod;
+    STACK_OF(CONF_IMODULE) *old_modules;
+    STACK_OF(CONF_IMODULE) *new_modules = NULL;
 
     if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
         return 0;
 
     /* If module_list_lock is NULL here it means we were already unloaded */
-    if (module_list_lock == NULL
-        || !CRYPTO_THREAD_write_lock(module_list_lock))
+    if (module_list_lock == NULL)
         return 0;
 
-    while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
-        imod = sk_CONF_IMODULE_pop(initialized_modules);
+    ossl_rcu_write_lock(module_list_lock);
+    old_modules = ossl_rcu_deref(&initialized_modules);
+    ossl_rcu_assign_ptr(&initialized_modules, &new_modules);
+    ossl_rcu_write_unlock(module_list_lock);
+    ossl_synchronize_rcu(module_list_lock);
+
+    while (sk_CONF_IMODULE_num(old_modules) > 0) {
+        imod = sk_CONF_IMODULE_pop(old_modules);
         module_finish(imod);
     }
-    sk_CONF_IMODULE_free(initialized_modules);
-    initialized_modules = NULL;
-
-    CRYPTO_THREAD_unlock(module_list_lock);
+    sk_CONF_IMODULE_free(old_modules);
 
     return 1;
 }

+ 1 - 1
libs/openssl/crypto/conf/conf_sap.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy

+ 2 - 2
libs/openssl/crypto/dh/dh_check.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -351,7 +351,7 @@ int ossl_dh_check_pairwise(const DH *dh)
     /* recalculate the public key = (g ^ priv) mod p */
     if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
         goto err;
-    /* check it matches the existing pubic_key */
+    /* check it matches the existing public_key */
     ret = BN_cmp(pub_key, dh->pub_key) == 0;
 err:
     BN_free(pub_key);

+ 1 - 1
libs/openssl/crypto/dsa/dsa_check.c

@@ -124,7 +124,7 @@ int ossl_dsa_check_pairwise(const DSA *dsa)
     /* recalculate the public key = (g ^ priv) mod p */
     if (!ossl_dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key))
         goto err;
-    /* check it matches the existing pubic_key */
+    /* check it matches the existing public_key */
     ret = BN_cmp(pub_key, dsa->pub_key) == 0;
 err:
     BN_free(pub_key);

+ 2 - 2
libs/openssl/crypto/dso/dso_dl.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -217,7 +217,7 @@ static char *dl_name_converter(DSO *dso, const char *filename)
 
     len = strlen(filename);
     rsize = len + 1;
-    transform = (strstr(filename, "/") == NULL);
+    transform = (strchr(filename, '/') == NULL);
     if (transform) {
         /* We will convert this to "%s.s?" or "lib%s.s?" */
         rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */

+ 2 - 2
libs/openssl/crypto/dso/dso_dlfcn.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
@@ -251,7 +251,7 @@ static char *dlfcn_name_converter(DSO *dso, const char *filename)
 
     len = strlen(filename);
     rsize = len + 1;
-    transform = (strstr(filename, "/") == NULL);
+    transform = (strchr(filename, '/') == NULL);
     if (transform) {
         /* We will convert this to "%s.so" or "lib%s.so" etc */
         rsize += strlen(DSO_EXTENSION);    /* The length of ".so" */

+ 1 - 1
libs/openssl/crypto/ec/curve448/ed448.h

@@ -21,7 +21,7 @@
 /* Number of bytes in an EdDSA private key. */
 # define EDDSA_448_PRIVATE_BYTES EDDSA_448_PUBLIC_BYTES
 
-/* Number of bytes in an EdDSA private key. */
+/* Number of bytes in an EdDSA signature. */
 # define EDDSA_448_SIGNATURE_BYTES (EDDSA_448_PUBLIC_BYTES + \
                                     EDDSA_448_PRIVATE_BYTES)
 

+ 13 - 0
libs/openssl/crypto/err/err_mark.c

@@ -26,6 +26,19 @@ int ERR_set_mark(void)
     return 1;
 }
 
+int ERR_pop(void)
+{
+    ERR_STATE *es;
+
+    es = ossl_err_get_state_int();
+    if (es == NULL || es->bottom == es->top)
+        return 0;
+
+    err_clear(es, es->top, 0);
+    es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
+    return 1;
+}
+
 int ERR_pop_to_mark(void)
 {
     ERR_STATE *es;

+ 15 - 0
libs/openssl/crypto/err/openssl.txt

@@ -32,6 +32,7 @@ ASN1_R_EXPLICIT_LENGTH_MISMATCH:119:explicit length mismatch
 ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED:120:explicit tag not constructed
 ASN1_R_FIELD_MISSING:121:field missing
 ASN1_R_FIRST_NUM_TOO_LARGE:122:first num too large
+ASN1_R_GENERALIZEDTIME_IS_TOO_SHORT:232:generalizedtime is too short
 ASN1_R_HEADER_TOO_LONG:123:header too long
 ASN1_R_ILLEGAL_BITSTRING_FORMAT:175:illegal bitstring format
 ASN1_R_ILLEGAL_BOOLEAN:176:illegal boolean
@@ -119,6 +120,7 @@ ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE:164:unsupported any defined by type
 ASN1_R_UNSUPPORTED_CIPHER:228:unsupported cipher
 ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:167:unsupported public key type
 ASN1_R_UNSUPPORTED_TYPE:196:unsupported type
+ASN1_R_UTCTIME_IS_TOO_SHORT:233:utctime is too short
 ASN1_R_WRONG_INTEGER_TYPE:225:wrong integer type
 ASN1_R_WRONG_PUBLIC_KEY_TYPE:200:wrong public key type
 ASN1_R_WRONG_TAG:168:wrong tag
@@ -227,6 +229,7 @@ CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
 CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
 CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
 CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature
+CMP_R_EXPECTED_POLLREQ:104:expected pollreq
 CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
 CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
 CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
@@ -272,14 +275,18 @@ CMP_R_TOTAL_TIMEOUT:184:total timeout
 CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
 CMP_R_TRANSFER_ERROR:159:transfer error
 CMP_R_UNCLEAN_CTX:191:unclean ctx
+CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile
 CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
 CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
+CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq
 CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
+CMP_R_UNEXPECTED_SENDER:106:unexpected sender
 CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
 CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
 CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
 CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
 CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
+CMP_R_UNSUPPORTED_PKIBODY:101:unsupported pkibody
 CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
 	unsupported protection alg dhbasedmac
 CMP_R_VALUE_TOO_LARGE:175:value too large
@@ -830,6 +837,7 @@ HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
 HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
 HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
 HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error
+HTTP_R_RESPONSE_TOO_MANY_HDRLINES:130:response too many hdrlines
 HTTP_R_RETRY_TIMEOUT:129:retry timeout
 HTTP_R_SERVER_CANCELED_CONNECTION:127:server canceled connection
 HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported
@@ -1396,6 +1404,8 @@ SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
 SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
 SSL_R_FAILED_TO_GET_PARAMETER:316:failed to get parameter
 SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
+SSL_R_FEATURE_NEGOTIATION_NOT_COMPLETE:417:feature negotiation not complete
+SSL_R_FEATURE_NOT_RENEGOTIABLE:413:feature not renegotiable
 SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
 SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
 SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request
@@ -1500,6 +1510,7 @@ SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE:199:peer did not return a certificate
 SSL_R_PEM_NAME_BAD_PREFIX:391:pem name bad prefix
 SSL_R_PEM_NAME_TOO_SHORT:392:pem name too short
 SSL_R_PIPELINE_FAILURE:406:pipeline failure
+SSL_R_POLL_REQUEST_NOT_SUPPORTED:418:poll request not supported
 SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR:278:post handshake auth encoding err
 SSL_R_PRIVATE_KEY_MISMATCH:288:private key mismatch
 SSL_R_PROTOCOL_IS_SHUTDOWN:207:protocol is shutdown
@@ -1632,10 +1643,14 @@ SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:338:\
 	unsafe legacy renegotiation disabled
 SSL_R_UNSOLICITED_EXTENSION:217:unsolicited extension
 SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM:257:unsupported compression algorithm
+SSL_R_UNSUPPORTED_CONFIG_VALUE:414:unsupported config value
+SSL_R_UNSUPPORTED_CONFIG_VALUE_CLASS:415:unsupported config value class
+SSL_R_UNSUPPORTED_CONFIG_VALUE_OP:416:unsupported config value op
 SSL_R_UNSUPPORTED_ELLIPTIC_CURVE:315:unsupported elliptic curve
 SSL_R_UNSUPPORTED_PROTOCOL:258:unsupported protocol
 SSL_R_UNSUPPORTED_SSL_VERSION:259:unsupported ssl version
 SSL_R_UNSUPPORTED_STATUS_TYPE:329:unsupported status type
+SSL_R_UNSUPPORTED_WRITE_FLAG:412:unsupported write flag
 SSL_R_USE_SRTP_NOT_NEGOTIATED:369:use srtp not negotiated
 SSL_R_VERSION_TOO_HIGH:166:version too high
 SSL_R_VERSION_TOO_LOW:396:version too low

+ 5 - 1
libs/openssl/crypto/evp/bio_enc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -132,6 +132,10 @@ static int enc_read(BIO *b, char *out, int outl)
     }
 
     blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher);
+
+    if (blocksize == 0)
+        return 0;
+
     if (blocksize == 1)
         blocksize = 0;
 

+ 35 - 2
libs/openssl/crypto/evp/digest.c

@@ -502,6 +502,7 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
     return ret;
 }
 
+/* This is a one shot operation */
 int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
 {
     int ret = 0;
@@ -526,10 +527,15 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
         return 0;
     }
 
+    /*
+     * For backward compatibility we pass the XOFLEN via a param here so that
+     * older providers can use the supplied value. Ideally we should have just
+     * used the size passed into ctx->digest->dfinal().
+     */
     params[i++] = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN, &size);
     params[i++] = OSSL_PARAM_construct_end();
 
-    if (EVP_MD_CTX_set_params(ctx, params) > 0)
+    if (EVP_MD_CTX_set_params(ctx, params) >= 0)
         ret = ctx->digest->dfinal(ctx->algctx, md, &size, size);
 
     ctx->flags |= EVP_MD_CTX_FLAG_FINALISED;
@@ -553,6 +559,27 @@ legacy:
     return ret;
 }
 
+/* EVP_DigestSqueeze() can be called multiple times */
+int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
+{
+    if (ctx->digest == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM);
+        return 0;
+    }
+
+    if (ctx->digest->prov == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
+        return 0;
+    }
+
+    if (ctx->digest->dsqueeze == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_METHOD_NOT_SUPPORTED);
+        return 0;
+    }
+
+    return ctx->digest->dsqueeze(ctx->algctx, md, &size, size);
+}
+
 EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in)
 {
     EVP_MD_CTX *out = EVP_MD_CTX_new();
@@ -1032,6 +1059,12 @@ static void *evp_md_from_algorithm(int name_id,
                 fncnt++;
             }
             break;
+        case OSSL_FUNC_DIGEST_SQUEEZE:
+            if (md->dsqueeze == NULL) {
+                md->dsqueeze = OSSL_FUNC_digest_squeeze(fns);
+                fncnt++;
+            }
+            break;
         case OSSL_FUNC_DIGEST_DIGEST:
             if (md->digest == NULL)
                 md->digest = OSSL_FUNC_digest_digest(fns);
@@ -1075,7 +1108,7 @@ static void *evp_md_from_algorithm(int name_id,
             break;
         }
     }
-    if ((fncnt != 0 && fncnt != 5)
+    if ((fncnt != 0 && fncnt != 5 && fncnt != 6)
         || (fncnt == 0 && md->digest == NULL)) {
         /*
          * In order to be a consistent set of functions we either need the

+ 13 - 13
libs/openssl/crypto/evp/evp_enc.c

@@ -253,7 +253,7 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx,
             memcpy(q++, p, sizeof(*q));
 
         /*
-         * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synomym for
+         * Note that OSSL_CIPHER_PARAM_AEAD_IVLEN is a synonym for
          * OSSL_CIPHER_PARAM_IVLEN so both are covered here.
          */
         p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN);
@@ -662,7 +662,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     size_t soutl, inl_ = (size_t)inl;
     int blocksize;
 
-    if (likely(outl != NULL)) {
+    if (ossl_likely(outl != NULL)) {
         *outl = 0;
     } else {
         ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
@@ -670,22 +670,22 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     }
 
     /* Prevent accidental use of decryption context when encrypting */
-    if (unlikely(!ctx->encrypt)) {
+    if (ossl_unlikely(!ctx->encrypt)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
         return 0;
     }
 
-    if (unlikely(ctx->cipher == NULL)) {
+    if (ossl_unlikely(ctx->cipher == NULL)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
         return 0;
     }
 
-    if (unlikely(ctx->cipher->prov == NULL))
+    if (ossl_unlikely(ctx->cipher->prov == NULL))
         goto legacy;
 
     blocksize = ctx->cipher->block_size;
 
-    if (unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
+    if (ossl_unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
         return 0;
     }
@@ -694,7 +694,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                                inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
                                in, inl_);
 
-    if (likely(ret)) {
+    if (ossl_likely(ret)) {
         if (soutl > INT_MAX) {
             ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
             return 0;
@@ -811,7 +811,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     size_t soutl, inl_ = (size_t)inl;
     int blocksize;
 
-    if (likely(outl != NULL)) {
+    if (ossl_likely(outl != NULL)) {
         *outl = 0;
     } else {
         ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
@@ -819,21 +819,21 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
     }
 
     /* Prevent accidental use of encryption context when decrypting */
-    if (unlikely(ctx->encrypt)) {
+    if (ossl_unlikely(ctx->encrypt)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
         return 0;
     }
 
-    if (unlikely(ctx->cipher == NULL)) {
+    if (ossl_unlikely(ctx->cipher == NULL)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
         return 0;
     }
-    if (unlikely(ctx->cipher->prov == NULL))
+    if (ossl_unlikely(ctx->cipher->prov == NULL))
         goto legacy;
 
     blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
 
-    if (unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
+    if (ossl_unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
         return 0;
     }
@@ -841,7 +841,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                                inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
                                in, inl_);
 
-    if (likely(ret)) {
+    if (ossl_likely(ret)) {
         if (soutl > INT_MAX) {
             ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
             return 0;

+ 1 - 1
libs/openssl/crypto/evp/evp_fetch.c

@@ -323,7 +323,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
              * will create a method against all names, but the lookup will fail
              * as ossl_namemap_name2num treats the name string as a single name
              * rather than introducing new features where in the EVP_<obj>_fetch
-             * parses the string and querys for each, return an error.
+             * parses the string and queries for each, return an error.
              */
             if (name_id == 0)
                 name_id = ossl_namemap_name2num(namemap, name);

+ 2 - 2
libs/openssl/crypto/evp/evp_key.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -88,7 +88,7 @@ int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
     nkey = EVP_CIPHER_get_key_length(type);
     niv = EVP_CIPHER_get_iv_length(type);
     OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
-    OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);
+    OPENSSL_assert(niv >= 0 && niv <= EVP_MAX_IV_LENGTH);
 
     if (data == NULL)
         return nkey;

+ 27 - 9
libs/openssl/crypto/evp/evp_lib.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -81,8 +81,12 @@ int evp_cipher_param_to_asn1_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
                                 evp_cipher_aead_asn1_params *asn1_params)
 {
     int ret = -1;                /* Assume the worst */
-    const EVP_CIPHER *cipher = c->cipher;
+    const EVP_CIPHER *cipher;
 
+    if (c == NULL || c->cipher == NULL)
+        goto err;
+
+    cipher = c->cipher;
     /*
      * For legacy implementations, we detect custom AlgorithmIdentifier
      * parameter handling by checking if the function pointer
@@ -172,8 +176,12 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
                                 evp_cipher_aead_asn1_params *asn1_params)
 {
     int ret = -1;                /* Assume the worst */
-    const EVP_CIPHER *cipher = c->cipher;
+    const EVP_CIPHER *cipher;
+
+    if (c == NULL || c->cipher == NULL)
+        goto err;
 
+    cipher = c->cipher;
     /*
      * For legacy implementations, we detect custom AlgorithmIdentifier
      * parameter handling by checking if there the function pointer
@@ -230,6 +238,7 @@ int evp_cipher_asn1_to_param_ex(EVP_CIPHER_CTX *c, ASN1_TYPE *type,
         ret = -2;
     }
 
+err:
     if (ret == -2)
         ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
     else if (ret <= 0)
@@ -387,7 +396,7 @@ int evp_cipher_cache_constants(EVP_CIPHER *cipher)
 
 int EVP_CIPHER_get_block_size(const EVP_CIPHER *cipher)
 {
-    return cipher->block_size;
+    return (cipher == NULL) ? 0 : cipher->block_size;
 }
 
 int EVP_CIPHER_CTX_get_block_size(const EVP_CIPHER_CTX *ctx)
@@ -403,6 +412,9 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
 int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                const unsigned char *in, unsigned int inl)
 {
+    if (ctx == NULL || ctx->cipher == NULL)
+        return 0;
+
     if (ctx->cipher->prov != NULL) {
         /*
          * If the provided implementation has a ccipher function, we use it,
@@ -415,6 +427,9 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
         size_t outl = 0;
         size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
 
+        if (blocksize == 0)
+            return 0;
+
         if (ctx->cipher->ccipher != NULL)
             ret =  ctx->cipher->ccipher(ctx->algctx, out, &outl,
                                         inl + (blocksize == 1 ? 0 : blocksize),
@@ -454,7 +469,7 @@ EVP_CIPHER *EVP_CIPHER_CTX_get1_cipher(EVP_CIPHER_CTX *ctx)
 {
     EVP_CIPHER *cipher;
 
-    if (ctx == NULL)
+    if (ctx == NULL || ctx->cipher == NULL)
         return NULL;
     cipher = (EVP_CIPHER *)ctx->cipher;
     if (!EVP_CIPHER_up_ref(cipher))
@@ -469,7 +484,7 @@ int EVP_CIPHER_CTX_is_encrypting(const EVP_CIPHER_CTX *ctx)
 
 unsigned long EVP_CIPHER_get_flags(const EVP_CIPHER *cipher)
 {
-    return cipher->flags;
+    return cipher == NULL ? 0 : cipher->flags;
 }
 
 void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
@@ -499,11 +514,14 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
 
 int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher)
 {
-    return cipher->iv_len;
+    return (cipher == NULL) ? 0 : cipher->iv_len;
 }
 
 int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx)
 {
+    if (ctx->cipher == NULL)
+        return 0;
+
     if (ctx->iv_len < 0) {
         int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher);
         size_t v = len;
@@ -678,12 +696,12 @@ int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx)
 
 int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher)
 {
-    return cipher->nid;
+    return (cipher == NULL) ? NID_undef : cipher->nid;
 }
 
 int EVP_CIPHER_CTX_get_nid(const EVP_CIPHER_CTX *ctx)
 {
-    return ctx->cipher->nid;
+    return EVP_CIPHER_get_nid(ctx->cipher);
 }
 
 int EVP_CIPHER_is_a(const EVP_CIPHER *cipher, const char *name)

+ 3 - 1
libs/openssl/crypto/evp/evp_local.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2023 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
@@ -95,6 +95,8 @@ struct evp_keymgmt_st {
     int id;                      /* libcrypto internal */
 
     int name_id;
+    /* NID for the legacy alg if there is one */
+    int legacy_alg;
     char *type_name;
     const char *description;
     OSSL_PROVIDER *prov;

+ 30 - 1
libs/openssl/crypto/evp/keymgmt_meth.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
@@ -30,6 +30,26 @@ static void *keymgmt_new(void)
     return keymgmt;
 }
 
+#ifndef FIPS_MODULE
+static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
+                                                  void *arg)
+{
+    int *type = arg;
+
+    if (*type == NID_undef)
+        *type = evp_pkey_name2type(keytype);
+}
+
+static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
+{
+    int type = NID_undef;
+
+    EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
+                             &type);
+    return type;
+}
+#endif
+
 static void *keymgmt_from_algorithm(int name_id,
                                     const OSSL_ALGORITHM *algodef,
                                     OSSL_PROVIDER *prov)
@@ -218,6 +238,10 @@ static void *keymgmt_from_algorithm(int name_id,
     if (prov != NULL)
         ossl_provider_up_ref(prov);
 
+#ifndef FIPS_MODULE
+    keymgmt->legacy_alg = get_legacy_alg_type_from_keymgmt(keymgmt);
+#endif
+
     return keymgmt;
 }
 
@@ -275,6 +299,11 @@ int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
     return keymgmt->name_id;
 }
 
+int evp_keymgmt_get_legacy_alg(const EVP_KEYMGMT *keymgmt)
+{
+    return keymgmt->legacy_alg;
+}
+
 const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
 {
     return keymgmt->description;

+ 3 - 2
libs/openssl/crypto/evp/legacy_sha.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -37,7 +37,8 @@ static int nm##_update(EVP_MD_CTX *ctx, const void *data, size_t count)        \
 }                                                                              \
 static int nm##_final(EVP_MD_CTX *ctx, unsigned char *md)                      \
 {                                                                              \
-    return fn##_final(md, EVP_MD_CTX_get0_md_data(ctx));                       \
+    KECCAK1600_CTX *kctx = EVP_MD_CTX_get0_md_data(ctx);                       \
+    return fn##_final(kctx, md, kctx->md_size);                                \
 }
 #define IMPLEMENT_LEGACY_EVP_MD_METH_SHAKE(nm, fn, tag)                        \
 static int nm##_init(EVP_MD_CTX *ctx)                                          \

+ 1 - 19
libs/openssl/crypto/evp/pmeth_lib.c

@@ -133,24 +133,6 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
     pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
     return pmeth;
 }
-
-static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
-                                                  void *arg)
-{
-    int *type = arg;
-
-    if (*type == NID_undef)
-        *type = evp_pkey_name2type(keytype);
-}
-
-static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
-{
-    int type = NID_undef;
-
-    EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
-                             &type);
-    return type;
-}
 #endif /* FIPS_MODULE */
 
 int evp_pkey_ctx_state(const EVP_PKEY_CTX *ctx)
@@ -288,7 +270,7 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx,
          * directly.
          */
         if (keymgmt != NULL) {
-            int tmp_id = get_legacy_alg_type_from_keymgmt(keymgmt);
+            int tmp_id = evp_keymgmt_get_legacy_alg(keymgmt);
 
             if (tmp_id != NID_undef) {
                 if (id == -1) {

+ 24 - 1
libs/openssl/crypto/http/http_client.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2024 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright Siemens AG 2018-2020
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
@@ -67,6 +67,7 @@ struct ossl_http_req_ctx_st {
     time_t max_time;            /* Maximum end time of current transfer, or 0 */
     time_t max_total_time;      /* Maximum end time of total transfer, or 0 */
     char *redirection_url;      /* Location obtained from HTTP status 301/302 */
+    size_t max_hdr_lines;       /* Max. number of http hdr lines, or 0 */
 };
 
 /* HTTP states */
@@ -106,6 +107,7 @@ OSSL_HTTP_REQ_CTX *OSSL_HTTP_REQ_CTX_new(BIO *wbio, BIO *rbio, int buf_size)
     rctx->buf = OPENSSL_malloc(rctx->buf_size);
     rctx->wbio = wbio;
     rctx->rbio = rbio;
+    rctx->max_hdr_lines = OSSL_HTTP_DEFAULT_MAX_RESP_HDR_LINES;
     if (rctx->buf == NULL) {
         OPENSSL_free(rctx);
         return NULL;
@@ -355,6 +357,16 @@ int OSSL_HTTP_REQ_CTX_set1_req(OSSL_HTTP_REQ_CTX *rctx, const char *content_type
     return res;
 }
 
+void OSSL_HTTP_REQ_CTX_set_max_response_hdr_lines(OSSL_HTTP_REQ_CTX *rctx,
+                                                  size_t count)
+{
+    if (rctx == NULL) {
+        ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
+        return;
+    }
+    rctx->max_hdr_lines = count;
+}
+
 static int add1_headers(OSSL_HTTP_REQ_CTX *rctx,
                         const STACK_OF(CONF_VALUE) *headers, const char *host)
 {
@@ -537,6 +549,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
     size_t resp_len;
     const unsigned char *p;
     char *buf, *key, *value, *line_end = NULL;
+    size_t resp_hdr_lines = 0;
 
     if (rctx == NULL) {
         ERR_raise(ERR_LIB_HTTP, ERR_R_PASSED_NULL_PARAMETER);
@@ -682,6 +695,14 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
             return 0;
         }
 
+        resp_hdr_lines++;
+        if (rctx->max_hdr_lines != 0 && rctx->max_hdr_lines < resp_hdr_lines) {
+            ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_TOO_MANY_HDRLINES);
+            OSSL_TRACE(HTTP, "Received too many headers\n");
+            rctx->state = OHS_ERROR;
+            return 0;
+        }
+
         /* Don't allow excessive lines */
         if (n == rctx->buf_size) {
             ERR_raise(ERR_LIB_HTTP, HTTP_R_RESPONSE_LINE_TOO_LONG);
@@ -786,6 +807,8 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
         if (OSSL_TRACE_ENABLED(HTTP))
             OSSL_TRACE(HTTP, "]\n");
 
+        resp_hdr_lines = 0;
+
         if (rctx->keep_alive != 0 /* do not let server initiate keep_alive */
                 && !found_keep_alive /* otherwise there is no change */) {
             if (rctx->keep_alive == 2) {

+ 12 - 5
libs/openssl/crypto/http/http_err.c

@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -12,7 +12,9 @@
 #include <openssl/httperr.h>
 #include "crypto/httperr.h"
 
-#ifndef OPENSSL_NO_ERR
+#ifndef OPENSSL_NO_HTTP
+
+# ifndef OPENSSL_NO_ERR
 
 static const ERR_STRING_DATA HTTP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_ASN1_LEN_EXCEEDS_MAX_RESP_LEN),
@@ -55,6 +57,8 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = {
     "response line too long"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR),
     "response parse error"},
+    {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_TOO_MANY_HDRLINES),
+    "response too many hdrlines"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RETRY_TIMEOUT), "retry timeout"},
     {ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_CANCELED_CONNECTION),
     "server canceled connection"},
@@ -70,13 +74,16 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = {
     {0, NULL}
 };
 
-#endif
+# endif
 
 int ossl_err_load_HTTP_strings(void)
 {
-#ifndef OPENSSL_NO_ERR
+# ifndef OPENSSL_NO_ERR
     if (ERR_reason_error_string(HTTP_str_reasons[0].error) == NULL)
         ERR_load_strings_const(HTTP_str_reasons);
-#endif
+# endif
     return 1;
 }
+#else
+NON_EMPTY_TRANSLATION_UNIT
+#endif

+ 1 - 1
libs/openssl/crypto/initthread.c

@@ -27,7 +27,7 @@
  *
  * The FIPS provider tells libcrypto about which threads it is interested in
  * by calling "c_thread_start" which is a function pointer created during
- * provider initialisation (i.e. OSSL_init_provider).
+ * provider initialisation (i.e. OSSL_provider_init).
  */
 extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
 #endif

+ 1 - 1
libs/openssl/crypto/lhash/lh_stats.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy

+ 56 - 12
libs/openssl/crypto/lhash/lhash.c

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -44,6 +44,22 @@ static int expand(OPENSSL_LHASH *lh);
 static void contract(OPENSSL_LHASH *lh);
 static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh, const void *data, unsigned long *rhash);
 
+OPENSSL_LHASH *OPENSSL_LH_set_thunks(OPENSSL_LHASH *lh,
+                                     OPENSSL_LH_HASHFUNCTHUNK hw,
+                                     OPENSSL_LH_COMPFUNCTHUNK cw,
+                                     OPENSSL_LH_DOALL_FUNC_THUNK daw,
+                                     OPENSSL_LH_DOALL_FUNCARG_THUNK daaw)
+{
+
+    if (lh == NULL)
+        return NULL;
+    lh->compw = cw;
+    lh->hashw = hw;
+    lh->daw = daw;
+    lh->daaw = daaw;
+    return lh;
+}
+
 OPENSSL_LHASH *OPENSSL_LH_new(OPENSSL_LH_HASHFUNC h, OPENSSL_LH_COMPFUNC c)
 {
     OPENSSL_LHASH *ret;
@@ -168,8 +184,11 @@ void *OPENSSL_LH_retrieve(OPENSSL_LHASH *lh, const void *data)
 }
 
 static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg,
+                          OPENSSL_LH_DOALL_FUNC_THUNK wfunc,
                           OPENSSL_LH_DOALL_FUNC func,
-                          OPENSSL_LH_DOALL_FUNCARG func_arg, void *arg)
+                          OPENSSL_LH_DOALL_FUNCARG func_arg,
+                          OPENSSL_LH_DOALL_FUNCARG_THUNK wfunc_arg,
+                          void *arg)
 {
     int i;
     OPENSSL_LH_NODE *a, *n;
@@ -186,9 +205,9 @@ static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg,
         while (a != NULL) {
             n = a->next;
             if (use_arg)
-                func_arg(a->data, arg);
+                wfunc_arg(a->data, arg, func_arg);
             else
-                func(a->data);
+                wfunc(a->data, func);
             a = n;
         }
     }
@@ -196,12 +215,29 @@ static void doall_util_fn(OPENSSL_LHASH *lh, int use_arg,
 
 void OPENSSL_LH_doall(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNC func)
 {
-    doall_util_fn(lh, 0, func, (OPENSSL_LH_DOALL_FUNCARG)0, NULL);
+    if (lh == NULL)
+        return;
+
+    doall_util_fn(lh, 0, lh->daw, func, (OPENSSL_LH_DOALL_FUNCARG)NULL,
+                  (OPENSSL_LH_DOALL_FUNCARG_THUNK)NULL, NULL);
 }
 
-void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh, OPENSSL_LH_DOALL_FUNCARG func, void *arg)
+void OPENSSL_LH_doall_arg(OPENSSL_LHASH *lh,
+                          OPENSSL_LH_DOALL_FUNCARG func, void *arg)
 {
-    doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC)0, func, arg);
+    if (lh == NULL)
+        return;
+
+    doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC_THUNK)NULL,
+                  (OPENSSL_LH_DOALL_FUNC)NULL, func, lh->daaw, arg);
+}
+
+void OPENSSL_LH_doall_arg_thunk(OPENSSL_LHASH *lh,
+                                OPENSSL_LH_DOALL_FUNCARG_THUNK daaw,
+                                OPENSSL_LH_DOALL_FUNCARG fn, void *arg)
+{
+    doall_util_fn(lh, 1, (OPENSSL_LH_DOALL_FUNC_THUNK)NULL,
+                  (OPENSSL_LH_DOALL_FUNC)NULL, fn, daaw, arg);
 }
 
 static int expand(OPENSSL_LHASH *lh)
@@ -286,24 +322,32 @@ static OPENSSL_LH_NODE **getrn(OPENSSL_LHASH *lh,
 {
     OPENSSL_LH_NODE **ret, *n1;
     unsigned long hash, nn;
-    OPENSSL_LH_COMPFUNC cf;
 
-    hash = (*(lh->hash)) (data);
+    if (lh->hashw != NULL)
+        hash = lh->hashw(data, lh->hash);
+    else
+        hash = lh->hash(data);
+
     *rhash = hash;
 
     nn = hash % lh->pmax;
     if (nn < lh->p)
         nn = hash % lh->num_alloc_nodes;
 
-    cf = lh->comp;
     ret = &(lh->b[(int)nn]);
     for (n1 = *ret; n1 != NULL; n1 = n1->next) {
         if (n1->hash != hash) {
             ret = &(n1->next);
             continue;
         }
-        if (cf(n1->data, data) == 0)
-            break;
+
+        if (lh->compw != NULL) {
+            if (lh->compw(n1->data, data, lh->comp) == 0)
+                break;
+        } else {
+            if (lh->comp(n1->data, data) == 0)
+                break;
+        }
         ret = &(n1->next);
     }
     return ret;

+ 5 - 1
libs/openssl/crypto/lhash/lhash_local.h

@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -20,6 +20,10 @@ struct lhash_st {
     OPENSSL_LH_NODE **b;
     OPENSSL_LH_COMPFUNC comp;
     OPENSSL_LH_HASHFUNC hash;
+    OPENSSL_LH_HASHFUNCTHUNK hashw;
+    OPENSSL_LH_COMPFUNCTHUNK compw;
+    OPENSSL_LH_DOALL_FUNC_THUNK daw;
+    OPENSSL_LH_DOALL_FUNCARG_THUNK daaw;
     unsigned int num_nodes;
     unsigned int num_alloc_nodes;
     unsigned int p;

+ 2 - 2
libs/openssl/crypto/loongarch64cpuid.pl

@@ -101,8 +101,8 @@ $code.=<<___;
 .globl OPENSSL_rdtsc
 .type   OPENSSL_rdtsc,\@function
 OPENSSL_rdtsc:
-    move    $a0,$zero
-    jr      $ra
+    rdtimel.w $a0,$zero
+    jr        $ra
 ___
 }
 

+ 297 - 0
libs/openssl/crypto/md5/asm/md5-loongarch64.pl

@@ -0,0 +1,297 @@
+#! /usr/bin/env perl
+# Author: Min Zhou <[email protected]>
+# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# Reference to crypto/md5/asm/md5-x86_64.pl
+# MD5 optimized for LoongArch.
+
+use strict;
+
+my $code;
+
+my ($zero,$ra,$tp,$sp,$fp)=map("\$r$_",(0..3,22));
+my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$r$_",(4..11));
+my ($t0,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$x)=map("\$r$_",(12..21));
+
+my $output;
+for (@ARGV) {	$output=$_ if (/\w[\w\-]*\.\w+$/);	}
+open STDOUT,">$output";
+
+# round1_step() does:
+#   dst = x + ((dst + F(x,y,z) + X[k] + T_i) <<< s)
+#   $t1 = y ^ z
+#   $t2 = dst + X[k_next]
+sub round1_step
+{
+    my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+    my $T_i_h = ($T_i & 0xfffff000) >> 12;
+    my $T_i_l = $T_i & 0xfff;
+
+# In LoongArch we have to use two instructions of lu12i.w and ori to load a
+# 32-bit immediate into a general register. Meanwhile, the instruction lu12i.w
+# treats the 20-bit immediate as a signed number. So if the T_i_h is greater
+# than or equal to (1<<19), we need provide lu12i.w a corresponding negative
+# number whose complement equals to the sign extension of T_i_h.
+
+# The details of the instruction lu12i.w can be found as following:
+# https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_lu12i_w_lu32i_d_lu52i_d
+
+    $T_i_h = -((1<<32) - (0xfff00000 | $T_i_h)) if ($T_i_h >= (1<<19));
+
+    $code .= "	ld.w	$t0,$a1,0		/* (NEXT STEP) X[0] */\n" if ($pos == -1);
+    $code .= "	xor	$t1,$y,$z		/* y ^ z */\n" if ($pos == -1);
+    $code .= "	add.w	$t2,$dst,$t0		/* dst + X[k] */\n" if ($pos == -1);
+    $code .= <<EOF;
+	lu12i.w	$t8,$T_i_h			/* load bits [31:12] of constant */
+	and     $t1,$x,$t1			/* x & ... */
+	ori	$t8,$t8,$T_i_l			/* load bits [11:0] of constant */
+	xor     $t1,$z,$t1			/* z ^ ... */
+	add.w   $t7,$t2,$t8			/* dst + X[k] + Const */
+	ld.w	$t0,$a1,$k_next*4		/* (NEXT STEP) X[$k_next] */
+	add.w	$dst,$t7,$t1			/* dst += ... */
+	add.w	$t2,$z,$t0			/* (NEXT STEP) dst + X[$k_next] */
+EOF
+
+    $code .= "	rotri.w	$dst,$dst,32-$s		/* dst <<< s */\n";
+    if ($pos != 1) {
+        $code .= "	xor	$t1,$x,$y	/* (NEXT STEP) y ^ z */\n";
+    } else {
+        $code .= "	move	$t0,$a7		/* (NEXT ROUND) $t0 = z' (copy of z) */\n";
+        $code .= "	nor	$t1,$zero,$a7	/* (NEXT ROUND) $t1 = not z' (copy of not z) */\n";
+    }
+    $code .= "	add.w   $dst,$dst,$x		/* dst += x */\n";
+}
+
+# round2_step() does:
+#   dst = x + ((dst + G(x,y,z) + X[k] + T_i) <<< s)
+#   $t0 = z' (copy of z for the next step)
+#   $t1 = not z' (copy of not z for the next step)
+#   $t2 = dst + X[k_next]
+sub round2_step
+{
+    my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+    my $T_i_h = ($T_i & 0xfffff000) >> 12;
+    my $T_i_l = $T_i & 0xfff;
+    $T_i_h = -((1<<32) - (0xfff00000 | $T_i_h)) if ($T_i_h >= (1<<19));
+
+    $code .= <<EOF;
+	lu12i.w	$t8,$T_i_h			/* load bits [31:12] of Constant */
+	and	$t0,$x,$t0			/* x & z */
+	ori	$t8,$t8,$T_i_l			/* load bits [11:0] of Constant */
+	and	$t1,$y,$t1			/* y & (not z) */
+	add.w	$t7,$t2,$t8			/* dst + X[k] + Const */
+	or	$t1,$t0,$t1			/* (y & (not z)) | (x & z) */
+	ld.w	$t0,$a1,$k_next*4		/* (NEXT STEP) X[$k_next] */
+	add.w	$dst,$t7,$t1			/* dst += ... */
+	add.w	$t2,$z,$t0			/* (NEXT STEP) dst + X[$k_next] */
+EOF
+
+    $code .= "	rotri.w $dst,$dst,32-$s		/* dst <<< s */\n";
+    if ($pos != 1) {
+        $code .= "	move	$t0,$y		/* (NEXT STEP) z' = $y */\n";
+        $code .= "	nor	$t1,$zero,$y	/* (NEXT STEP) not z' = not $y */\n";
+    } else {
+        $code .= "	xor	$t1,$a6,$a7	/* (NEXT ROUND) $t1 = y ^ z */\n";
+    }
+    $code .= "	add.w	$dst,$dst,$x		/* dst += x */\n";
+}
+
+# round3_step() does:
+#   dst = x + ((dst + H(x,y,z) + X[k] + T_i) <<< s)
+#   $t1 = y ^ z
+#   $t2 = dst + X[k_next]
+sub round3_step
+{
+    my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+    my $T_i_h = ($T_i & 0xfffff000) >> 12;
+    my $T_i_l = $T_i & 0xfff;
+    $T_i_h = -((1<<32) - (0xfff00000 | $T_i_h)) if ($T_i_h >= (1<<19));
+
+    $code .= <<EOF;
+	lu12i.w	$t8,$T_i_h			/* load bits [31:12] of Constant */
+	xor	$t1,$x,$t1			/* x ^ ... */
+	ori	$t8,$t8,$T_i_l			/* load bits [11:0] of Constant */
+	add.w	$t7,$t2,$t8			/* dst + X[k] + Const */
+	ld.w	$t0,$a1,$k_next*4		/* (NEXT STEP) X[$k_next] */
+	add.w	$dst,$t7,$t1			/* dst += ... */
+	add.w	$t2,$z,$t0			/* (NEXT STEP) dst + X[$k_next] */
+EOF
+
+    $code .= "	rotri.w $dst,$dst,32-$s		/* dst <<< s */\n";
+    if ($pos != 1) {
+	$code .= "	xor	$t1,$x,$y	/* (NEXT STEP) y ^ z */\n";
+    } else {
+        $code .= "	nor	$t1,$zero,$a7	/* (NEXT ROUND) $t1 = not z */\n";
+    }
+    $code .= "	add.w	$dst,$dst,$x		/* dst += x */\n";
+}
+
+# round4_step() does:
+#   dst = x + ((dst + I(x,y,z) + X[k] + T_i) <<< s)
+#   $t1 = not z' (copy of not z for the next step)
+#   $t2 = dst + X[k_next]
+sub round4_step
+{
+    my ($pos, $dst, $x, $y, $z, $k_next, $T_i, $s) = @_;
+    my $T_i_h = ($T_i & 0xfffff000) >> 12;
+    my $T_i_l = $T_i & 0xfff;
+    $T_i_h = -((1<<32) - (0xfff00000 | $T_i_h)) if ($T_i_h >= (1<<19));
+
+    $code .= <<EOF;
+	lu12i.w	$t8,$T_i_h			/* load bits [31:12] of Constant */
+	or	$t1,$x,$t1			/* x | ... */
+	ori	$t8,$t8,$T_i_l			/* load bits [11:0] of Constant */
+	xor	$t1,$y,$t1			/* y ^ ... */
+	add.w	$t7,$t2,$t8			/* dst + X[k] + Const */
+EOF
+
+    if ($pos != 1) {
+        $code .= "	ld.w	$t0,$a1,$k_next*4		/* (NEXT STEP) X[$k_next] */\n";
+        $code .= "	add.w	$dst,$t7,$t1			/* dst += ... */\n";
+        $code .= "	add.w	$t2,$z,$t0			/* (NEXT STEP) dst + X[$k_next] */\n";
+        $code .= "	rotri.w $dst,$dst,32-$s			/* dst <<< s */\n";
+        $code .= "	nor	$t1,$zero,$y			/* (NEXT STEP) not z' = not $y */\n";
+        $code .= "	add.w	$dst,$dst,$x			/* dst += x */\n";
+    } else {
+        $code .= "	add.w	$a4,$t3,$a4			/* (NEXT LOOP) add old value of A */\n";
+        $code .= "	add.w	$dst,$t7,$t1			/* dst += ... */\n";
+        $code .= "	add.w	$a7,$t6,$a7			/* (NEXT LOOP) add old value of D */\n";
+        $code .= "	rotri.w $dst,$dst,32-$s			/* dst <<< s */\n";
+        $code .= "	addi.d	$a1,$a1,64			/* (NEXT LOOP) ptr += 64 */\n";
+        $code .= "	add.w	$dst,$dst,$x			/* dst += x */\n";
+    }
+}
+
+$code .= <<EOF;
+.text
+
+.globl ossl_md5_block_asm_data_order
+.type ossl_md5_block_asm_data_order function
+ossl_md5_block_asm_data_order:
+	# $a0 = arg #1 (ctx, MD5_CTX pointer)
+	# $a1 = arg #2 (ptr, data pointer)
+	# $a2 = arg #3 (nbr, number of 16-word blocks to process)
+	beqz	$a2,.Lend		# cmp nbr with 0, jmp if nbr == 0
+
+	# ptr is '$a1'
+	# end is '$a3'
+	slli.d	$t0,$a2,6
+	add.d	$a3,$a1,$t0
+
+	# A is '$a4'
+	# B is '$a5'
+	# C is '$a6'
+	# D is '$a7'
+	ld.w	$a4,$a0,0	# a4 = ctx->A
+	ld.w	$a5,$a0,4	# a5 = ctx->B
+	ld.w	$a6,$a0,8	# a6 = ctx->C
+	ld.w	$a7,$a0,12	# a7 = ctx->D
+
+# BEGIN of loop over 16-word blocks
+.align 6
+.Lloop:
+	# save old values of A, B, C, D
+	move	$t3,$a4
+	move	$t4,$a5
+	move	$t5,$a6
+	move	$t6,$a7
+
+	preld	0,$a1,0
+	preld	0,$a1,64
+EOF
+
+round1_step(-1, $a4, $a5, $a6, $a7, '1', 0xd76aa478, '7');
+round1_step(0, $a7, $a4, $a5, $a6, '2', 0xe8c7b756, '12');
+round1_step(0, $a6, $a7, $a4, $a5, '3', 0x242070db, '17');
+round1_step(0, $a5, $a6, $a7, $a4, '4', 0xc1bdceee, '22');
+round1_step(0, $a4, $a5, $a6, $a7, '5', 0xf57c0faf, '7');
+round1_step(0, $a7, $a4, $a5, $a6, '6', 0x4787c62a, '12');
+round1_step(0, $a6, $a7, $a4, $a5, '7', 0xa8304613, '17');
+round1_step(0, $a5, $a6, $a7, $a4, '8', 0xfd469501, '22');
+round1_step(0, $a4, $a5, $a6, $a7, '9', 0x698098d8, '7');
+round1_step(0, $a7, $a4, $a5, $a6, '10', 0x8b44f7af, '12');
+round1_step(0, $a6, $a7, $a4, $a5, '11', 0xffff5bb1, '17');
+round1_step(0, $a5, $a6, $a7, $a4, '12', 0x895cd7be, '22');
+round1_step(0, $a4, $a5, $a6, $a7, '13', 0x6b901122, '7');
+round1_step(0, $a7, $a4, $a5, $a6, '14', 0xfd987193, '12');
+round1_step(0, $a6, $a7, $a4, $a5, '15', 0xa679438e, '17');
+round1_step(1, $a5, $a6, $a7, $a4, '1', 0x49b40821, '22');
+
+round2_step(-1, $a4, $a5, $a6, $a7, '6', 0xf61e2562, '5');
+round2_step(0, $a7, $a4, $a5, $a6, '11', 0xc040b340, '9');
+round2_step(0, $a6, $a7, $a4, $a5, '0', 0x265e5a51, '14');
+round2_step(0, $a5, $a6, $a7, $a4, '5', 0xe9b6c7aa, '20');
+round2_step(0, $a4, $a5, $a6, $a7, '10', 0xd62f105d, '5');
+round2_step(0, $a7, $a4, $a5, $a6, '15', 0x2441453, '9');
+round2_step(0, $a6, $a7, $a4, $a5, '4', 0xd8a1e681, '14');
+round2_step(0, $a5, $a6, $a7, $a4, '9', 0xe7d3fbc8, '20');
+round2_step(0, $a4, $a5, $a6, $a7, '14', 0x21e1cde6, '5');
+round2_step(0, $a7, $a4, $a5, $a6, '3', 0xc33707d6, '9');
+round2_step(0, $a6, $a7, $a4, $a5, '8', 0xf4d50d87, '14');
+round2_step(0, $a5, $a6, $a7, $a4, '13', 0x455a14ed, '20');
+round2_step(0, $a4, $a5, $a6, $a7, '2', 0xa9e3e905, '5');
+round2_step(0, $a7, $a4, $a5, $a6, '7', 0xfcefa3f8, '9');
+round2_step(0, $a6, $a7, $a4, $a5, '12', 0x676f02d9, '14');
+round2_step(1, $a5, $a6, $a7, $a4, '5', 0x8d2a4c8a, '20');
+
+round3_step(-1, $a4, $a5, $a6, $a7, '8', 0xfffa3942, '4');
+round3_step(0, $a7, $a4, $a5, $a6, '11', 0x8771f681, '11');
+round3_step(0, $a6, $a7, $a4, $a5, '14', 0x6d9d6122, '16');
+round3_step(0, $a5, $a6, $a7, $a4, '1', 0xfde5380c, '23');
+round3_step(0, $a4, $a5, $a6, $a7, '4', 0xa4beea44, '4');
+round3_step(0, $a7, $a4, $a5, $a6, '7', 0x4bdecfa9, '11');
+round3_step(0, $a6, $a7, $a4, $a5, '10', 0xf6bb4b60, '16');
+round3_step(0, $a5, $a6, $a7, $a4, '13', 0xbebfbc70, '23');
+round3_step(0, $a4, $a5, $a6, $a7, '0', 0x289b7ec6, '4');
+round3_step(0, $a7, $a4, $a5, $a6, '3', 0xeaa127fa, '11');
+round3_step(0, $a6, $a7, $a4, $a5, '6', 0xd4ef3085, '16');
+round3_step(0, $a5, $a6, $a7, $a4, '9', 0x4881d05, '23');
+round3_step(0, $a4, $a5, $a6, $a7, '12', 0xd9d4d039, '4');
+round3_step(0, $a7, $a4, $a5, $a6, '15', 0xe6db99e5, '11');
+round3_step(0, $a6, $a7, $a4, $a5, '2', 0x1fa27cf8, '16');
+round3_step(1, $a5, $a6, $a7, $a4, '0', 0xc4ac5665, '23');
+
+round4_step(-1, $a4, $a5, $a6, $a7, '7', 0xf4292244, '6');
+round4_step(0, $a7, $a4, $a5, $a6, '14', 0x432aff97, '10');
+round4_step(0, $a6, $a7, $a4, $a5, '5', 0xab9423a7, '15');
+round4_step(0, $a5, $a6, $a7, $a4, '12', 0xfc93a039, '21');
+round4_step(0, $a4, $a5, $a6, $a7, '3', 0x655b59c3, '6');
+round4_step(0, $a7, $a4, $a5, $a6, '10', 0x8f0ccc92, '10');
+round4_step(0, $a6, $a7, $a4, $a5, '1', 0xffeff47d, '15');
+round4_step(0, $a5, $a6, $a7, $a4, '8', 0x85845dd1, '21');
+round4_step(0, $a4, $a5, $a6, $a7, '15', 0x6fa87e4f, '6');
+round4_step(0, $a7, $a4, $a5, $a6, '6', 0xfe2ce6e0, '10');
+round4_step(0, $a6, $a7, $a4, $a5, '13', 0xa3014314, '15');
+round4_step(0, $a5, $a6, $a7, $a4, '4', 0x4e0811a1, '21');
+round4_step(0, $a4, $a5, $a6, $a7, '11', 0xf7537e82, '6');
+round4_step(0, $a7, $a4, $a5, $a6, '2', 0xbd3af235, '10');
+round4_step(0, $a6, $a7, $a4, $a5, '9', 0x2ad7d2bb, '15');
+round4_step(1, $a5, $a6, $a7, $a4, '0', 0xeb86d391, '21');
+
+$code .= <<EOF;
+	# add old values of B, C
+	add.w	$a5,$t4,$a5
+	add.w	$a6,$t5,$a6
+
+	bltu	$a1,$a3,.Lloop	# jmp if ptr < end
+
+	st.w	$a4,$a0,0	# ctx->A = A
+	st.w	$a5,$a0,4	# ctx->B = B
+	st.w	$a6,$a0,8	# ctx->C = C
+	st.w	$a7,$a0,12	# ctx->D = D
+
+.Lend:
+	jr	$ra
+.size ossl_md5_block_asm_data_order,.-ossl_md5_block_asm_data_order
+EOF
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+
+print $code;
+
+close STDOUT;

+ 4 - 0
libs/openssl/crypto/md5/build.info

@@ -5,6 +5,7 @@ IF[{- !$disabled{asm} -}]
   $MD5ASM_x86=md5-586.S
   $MD5ASM_x86_64=md5-x86_64.s
   $MD5ASM_aarch64=md5-aarch64.S
+  $MD5ASM_loongarch64=md5-loongarch64.S
   $MD5ASM_sparcv9=md5-sparcv9.S
 
   # Now that we have defined all the arch specific variables, use the
@@ -39,5 +40,8 @@ GENERATE[md5-x86_64.s]=asm/md5-x86_64.pl
 GENERATE[md5-aarch64.S]=asm/md5-aarch64.pl
 INCLUDE[md5-aarch64.o]=..
 
+GENERATE[md5-loongarch64.S]=asm/md5-loongarch64.pl
+INCLUDE[md5-loongarch64.o]=..
+
 GENERATE[md5-sparcv9.S]=asm/md5-sparcv9.pl
 INCLUDE[md5-sparcv9.o]=..

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно