Jelajahi Sumber

Merge branch 'thirdparty_dev' into dev

Source commit: d7b8dd2b326da8321282ce5ac6956bc62580e53a
Martin Prikryl 2 tahun lalu
induk
melakukan
7f7b8e4bcf
100 mengubah file dengan 11594 tambahan dan 1978 penghapusan
  1. 0 2
      libs/openssl/ACKNOWLEDGEMENTS
  2. 6 0
      libs/openssl/ACKNOWLEDGEMENTS.md
  3. 0 42
      libs/openssl/AUTHORS
  4. 51 0
      libs/openssl/AUTHORS.md
  5. 1818 0
      libs/openssl/INSTALL.md
  6. 0 125
      libs/openssl/LICENSE
  7. 177 0
      libs/openssl/LICENSE.txt
  8. 93 0
      libs/openssl/SUPPORT.md
  9. 7 0
      libs/openssl/VERSION.dat
  10. 1 1
      libs/openssl/crypto/LPdir_win.c
  11. 1 1
      libs/openssl/crypto/LPdir_win32.c
  12. 9 2
      libs/openssl/crypto/aes/aes_cbc.c
  13. 8 2
      libs/openssl/crypto/aes/aes_cfb.c
  14. 160 144
      libs/openssl/crypto/aes/aes_core.c
  15. 8 2
      libs/openssl/crypto/aes/aes_ecb.c
  16. 17 4
      libs/openssl/crypto/aes/aes_ige.c
  17. 3 3
      libs/openssl/crypto/aes/aes_local.h
  18. 7 5
      libs/openssl/crypto/aes/aes_misc.c
  19. 8 2
      libs/openssl/crypto/aes/aes_ofb.c
  20. 8 2
      libs/openssl/crypto/aes/aes_wrap.c
  21. 2998 0
      libs/openssl/crypto/aes/asm/aes-586.pl
  22. 1061 0
      libs/openssl/crypto/aes/asm/aes-riscv32-zkn.pl
  23. 2378 0
      libs/openssl/crypto/aes/asm/bsaes-armv8.pl
  24. 17 17
      libs/openssl/crypto/aria/aria.c
  25. 117 7
      libs/openssl/crypto/arm_arch.h
  26. 7 7
      libs/openssl/crypto/asn1/a_bitstr.c
  27. 46 27
      libs/openssl/crypto/asn1/a_d2i_fp.c
  28. 40 13
      libs/openssl/crypto/asn1/a_digest.c
  29. 38 9
      libs/openssl/crypto/asn1/a_dup.c
  30. 10 6
      libs/openssl/crypto/asn1/a_gentm.c
  31. 28 10
      libs/openssl/crypto/asn1/a_i2d_fp.c
  32. 42 29
      libs/openssl/crypto/asn1/a_int.c
  33. 28 21
      libs/openssl/crypto/asn1/a_mbstr.c
  34. 29 22
      libs/openssl/crypto/asn1/a_object.c
  35. 1 1
      libs/openssl/crypto/asn1/a_octet.c
  36. 1 1
      libs/openssl/crypto/asn1/a_print.c
  37. 108 48
      libs/openssl/crypto/asn1/a_sign.c
  38. 5 5
      libs/openssl/crypto/asn1/a_strex.c
  39. 8 5
      libs/openssl/crypto/asn1/a_strnid.c
  40. 60 27
      libs/openssl/crypto/asn1/a_time.c
  41. 3 3
      libs/openssl/crypto/asn1/a_type.c
  42. 11 8
      libs/openssl/crypto/asn1/a_utctm.c
  43. 13 64
      libs/openssl/crypto/asn1/a_utf8.c
  44. 103 57
      libs/openssl/crypto/asn1/a_verify.c
  45. 36 50
      libs/openssl/crypto/asn1/ameth_lib.c
  46. 7 147
      libs/openssl/crypto/asn1/asn1_err.c
  47. 36 39
      libs/openssl/crypto/asn1/asn1_gen.c
  48. 89 36
      libs/openssl/crypto/asn1/asn1_lib.c
  49. 44 33
      libs/openssl/crypto/asn1/asn1_local.h
  50. 44 37
      libs/openssl/crypto/asn1/asn1_parse.c
  51. 121 66
      libs/openssl/crypto/asn1/asn_mime.c
  52. 5 5
      libs/openssl/crypto/asn1/asn_moid.c
  53. 9 9
      libs/openssl/crypto/asn1/asn_mstbl.c
  54. 7 7
      libs/openssl/crypto/asn1/asn_pack.c
  55. 6 6
      libs/openssl/crypto/asn1/bio_asn1.c
  56. 12 10
      libs/openssl/crypto/asn1/bio_ndef.c
  57. 2 2
      libs/openssl/crypto/asn1/charmap.h
  58. 65 0
      libs/openssl/crypto/asn1/d2i_param.c
  59. 142 61
      libs/openssl/crypto/asn1/d2i_pr.c
  60. 35 14
      libs/openssl/crypto/asn1/d2i_pu.c
  61. 97 25
      libs/openssl/crypto/asn1/evp_asn1.c
  62. 6 7
      libs/openssl/crypto/asn1/f_int.c
  63. 6 7
      libs/openssl/crypto/asn1/f_string.c
  64. 149 0
      libs/openssl/crypto/asn1/i2d_evp.c
  65. 0 33
      libs/openssl/crypto/asn1/i2d_pr.c
  66. 0 38
      libs/openssl/crypto/asn1/i2d_pu.c
  67. 22 26
      libs/openssl/crypto/asn1/n_pkey.c
  68. 1 1
      libs/openssl/crypto/asn1/nsseq.c
  69. 30 13
      libs/openssl/crypto/asn1/p5_pbe.c
  70. 48 23
      libs/openssl/crypto/asn1/p5_pbev2.c
  71. 43 31
      libs/openssl/crypto/asn1/p5_scrypt.c
  72. 13 2
      libs/openssl/crypto/asn1/p8_pkey.c
  73. 18 32
      libs/openssl/crypto/asn1/standard_methods.h
  74. 1 1
      libs/openssl/crypto/asn1/t_bitst.c
  75. 1 1
      libs/openssl/crypto/asn1/t_pkey.c
  76. 2 2
      libs/openssl/crypto/asn1/t_spki.c
  77. 192 149
      libs/openssl/crypto/asn1/tasn_dec.c
  78. 93 72
      libs/openssl/crypto/asn1/tasn_enc.c
  79. 27 27
      libs/openssl/crypto/asn1/tasn_fre.c
  80. 48 49
      libs/openssl/crypto/asn1/tasn_new.c
  81. 29 29
      libs/openssl/crypto/asn1/tasn_prn.c
  82. 3 3
      libs/openssl/crypto/asn1/tasn_typ.c
  83. 78 45
      libs/openssl/crypto/asn1/tasn_utl.c
  84. 4 3
      libs/openssl/crypto/asn1/tbl_standard.h
  85. 72 8
      libs/openssl/crypto/asn1/x_algor.c
  86. 6 6
      libs/openssl/crypto/asn1/x_bignum.c
  87. 3 3
      libs/openssl/crypto/asn1/x_info.c
  88. 26 26
      libs/openssl/crypto/asn1/x_int64.c
  89. 10 15
      libs/openssl/crypto/asn1/x_long.c
  90. 3 3
      libs/openssl/crypto/asn1/x_pkey.c
  91. 1 1
      libs/openssl/crypto/asn1/x_sig.c
  92. 1 1
      libs/openssl/crypto/asn1/x_spki.c
  93. 1 1
      libs/openssl/crypto/asn1/x_val.c
  94. 252 0
      libs/openssl/crypto/asn1_dsa.c
  95. 1 1
      libs/openssl/crypto/async/arch/async_null.h
  96. 34 3
      libs/openssl/crypto/async/arch/async_posix.h
  97. 6 2
      libs/openssl/crypto/async/arch/async_win.c
  98. 11 3
      libs/openssl/crypto/async/arch/async_win.h
  99. 57 21
      libs/openssl/crypto/async/async.c
  100. 5 19
      libs/openssl/crypto/async/async_err.c

+ 0 - 2
libs/openssl/ACKNOWLEDGEMENTS

@@ -1,2 +0,0 @@
-Please https://www.openssl.org/community/thanks.html for the current
-acknowledgements.

+ 6 - 0
libs/openssl/ACKNOWLEDGEMENTS.md

@@ -0,0 +1,6 @@
+Acknowledgements
+================
+
+Please see our [Thanks!][] page for the current acknowledgements.
+
+[Thanks!]: https://www.openssl.org/community/thanks.html

+ 0 - 42
libs/openssl/AUTHORS

@@ -1,42 +0,0 @@
-# This is the list of OpenSSL authors for copyright purposes.
-#
-# This does not necessarily list everyone who has contributed code, since in
-# some cases, their employer may be the copyright holder.  To see the full list
-# of contributors, see the revision history in source control.
-OpenSSL Software Services, Inc.
-OpenSSL Software Foundation, Inc.
-
-# Individuals
-Andy Polyakov
-Ben Laurie
-Ben Kaduk
-Bernd Edlinger
-Bodo Möller
-David Benjamin
-David von Oheimb
-Dmitry Belyavskiy (Дмитрий Белявский)
-Emilia Käsper
-Eric Young
-Geoff Thorpe
-Holger Reif
-Kurt Roeckx
-Lutz Jänicke
-Mark J. Cox
-Matt Caswell
-Matthias St. Pierre
-Nicola Tuveri
-Nils Larsch
-Patrick Steuer
-Paul Dale
-Paul C. Sutton
-Paul Yang
-Ralf S. Engelschall
-Rich Salz
-Richard Levitte
-Shane Lontis
-Stephen Henson
-Steve Marquess
-Tim Hudson
-Tomáš Mráz
-Ulf Möller
-Viktor Dukhovni

+ 51 - 0
libs/openssl/AUTHORS.md

@@ -0,0 +1,51 @@
+Authors
+=======
+
+This is the list of OpenSSL authors for copyright purposes.
+It does not necessarily list everyone who has contributed code,
+since in some cases, their employer may be the copyright holder.
+To see the full list of contributors, see the revision history in
+source control.
+
+Groups
+------
+
+ * OpenSSL Software Services, Inc.
+ * OpenSSL Software Foundation, Inc.
+
+Individuals
+-----------
+
+ * Andy Polyakov
+ * Ben Laurie
+ * Ben Kaduk
+ * Bernd Edlinger
+ * Bodo Möller
+ * David Benjamin
+ * David von Oheimb
+ * Dmitry Belyavskiy (Дмитрий Белявский)
+ * Emilia Käsper
+ * Eric Young
+ * Geoff Thorpe
+ * Holger Reif
+ * Kurt Roeckx
+ * Lutz Jänicke
+ * Mark J. Cox
+ * Matt Caswell
+ * Matthias St. Pierre
+ * Nicola Tuveri
+ * Nils Larsch
+ * Patrick Steuer
+ * Paul Dale
+ * Paul C. Sutton
+ * Paul Yang
+ * Ralf S. Engelschall
+ * Rich Salz
+ * Richard Levitte
+ * Shane Lontis
+ * Stephen Henson
+ * Steve Marquess
+ * Tim Hudson
+ * Tomáš Mráz
+ * Ulf Möller
+ * Viktor Dukhovni

+ 1818 - 0
libs/openssl/INSTALL.md

@@ -0,0 +1,1818 @@
+Build and Install
+=================
+
+This document describes installation on all supported operating
+systems (the Unix/Linux family, including macOS), OpenVMS,
+and Windows).
+
+Table of Contents
+=================
+
+ - [Prerequisites](#prerequisites)
+ - [Notational Conventions](#notational-conventions)
+ - [Quick Installation Guide](#quick-installation-guide)
+   - [Building OpenSSL](#building-openssl)
+   - [Installing OpenSSL](#installing-openssl)
+ - [Configuration Options](#configuration-options)
+   - [API Level](#api-level)
+   - [Cross Compile Prefix](#cross-compile-prefix)
+   - [Build Type](#build-type)
+   - [Directories](#directories)
+   - [Compiler Warnings](#compiler-warnings)
+   - [ZLib Flags](#zlib-flags)
+   - [Seeding the Random Generator](#seeding-the-random-generator)
+   - [Setting the FIPS HMAC key](#setting-the-FIPS-HMAC-key)
+   - [Enable and Disable Features](#enable-and-disable-features)
+   - [Displaying configuration data](#displaying-configuration-data)
+ - [Installation Steps in Detail](#installation-steps-in-detail)
+   - [Configure](#configure-openssl)
+   - [Build](#build-openssl)
+   - [Test](#test-openssl)
+   - [Install](#install-openssl)
+ - [Advanced Build Options](#advanced-build-options)
+   - [Environment Variables](#environment-variables)
+   - [Makefile Targets](#makefile-targets)
+   - [Running Selected Tests](#running-selected-tests)
+ - [Troubleshooting](#troubleshooting)
+   - [Configuration Problems](#configuration-problems)
+   - [Build Failures](#build-failures)
+   - [Test Failures](#test-failures)
+ - [Notes](#notes)
+   - [Notes on multi-threading](#notes-on-multi-threading)
+   - [Notes on shared libraries](#notes-on-shared-libraries)
+   - [Notes on random number generation](#notes-on-random-number-generation)
+   - [Notes on assembler modules compilation](#notes-on-assembler-modules-compilation)
+
+Prerequisites
+=============
+
+To install OpenSSL, you will need:
+
+ * A "make" implementation
+ * Perl 5 with core modules (please read [NOTES-PERL.md](NOTES-PERL.md))
+ * The Perl module `Text::Template` (please read [NOTES-PERL.md](NOTES-PERL.md))
+ * an ANSI C compiler
+ * a development environment in the form of development libraries and C
+   header files
+ * a supported operating system
+
+For additional platform specific requirements, solutions to specific
+issues and other details, please read one of these:
+
+ * [Notes for UNIX-like platforms](NOTES-UNIX.md)
+ * [Notes for Android platforms](NOTES-ANDROID.md)
+ * [Notes for Windows platforms](NOTES-WINDOWS.md)
+ * [Notes for the DOS platform with DJGPP](NOTES-DJGPP.md)
+ * [Notes for the OpenVMS platform](NOTES-VMS.md)
+ * [Notes on Perl](NOTES-PERL.md)
+ * [Notes on Valgrind](NOTES-VALGRIND.md)
+
+Notational conventions
+======================
+
+Throughout this document, we use the following conventions.
+
+Commands
+--------
+
+Any line starting with a dollar sign is a command line.
+
+    $ command
+
+The dollar sign indicates the shell prompt and is not to be entered as
+part of the command.
+
+Choices
+-------
+
+Several words in curly braces separated by pipe characters indicate a
+**mandatory choice**, to be replaced with one of the given words.
+For example, the line
+
+    $ echo { WORD1 | WORD2 | WORD3 }
+
+represents one of the following three commands
+
+    $ echo WORD1
+    - or -
+    $ echo WORD2
+    - or -
+    $ echo WORD3
+
+One or several words in square brackets separated by pipe characters
+denote an **optional choice**.  It is similar to the mandatory choice,
+but it can also be omitted entirely.
+
+So the line
+
+    $ echo [ WORD1 | WORD2 | WORD3 ]
+
+represents one of the four commands
+
+    $ echo WORD1
+    - or -
+    $ echo WORD2
+    - or -
+    $ echo WORD3
+    - or -
+    $ echo
+
+Arguments
+---------
+
+**Mandatory arguments** are enclosed in double curly braces.
+A simple example would be
+
+    $ type {{ filename }}
+
+which is to be understood to use the command `type` on some file name
+determined by the user.
+
+**Optional Arguments** are enclosed in double square brackets.
+
+    [[ options ]]
+
+Note that the notation assumes spaces around `{`, `}`, `[`, `]`, `{{`, `}}` and
+`[[`, `]]`.  This is to differentiate from OpenVMS directory
+specifications, which also use [ and ], but without spaces.
+
+Quick Installation Guide
+========================
+
+If you just want to get OpenSSL installed without bothering too much
+about the details, here is the short version of how to build and install
+OpenSSL.  If any of the following steps fails, please consult the
+[Installation in Detail](#installation-steps-in-detail) section below.
+
+Building OpenSSL
+----------------
+
+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
+
+    $ ./Configure
+    $ make
+    $ make test
+
+### OpenVMS
+
+Use the following commands to build OpenSSL:
+
+    $ perl Configure
+    $ mms
+    $ mms test
+
+### Windows
+
+If you are using Visual Studio, open a Developer Command Prompt and
+issue the following commands to build OpenSSL.
+
+    $ perl Configure
+    $ nmake
+    $ nmake test
+
+As mentioned in the [Choices](#choices) section, you need to pick one
+of the four Configure targets in the first command.
+
+Most likely you will be using the `VC-WIN64A` target for 64bit Windows
+binaries (AMD64) or `VC-WIN32` for 32bit Windows binaries (X86).
+The other two options are `VC-WIN64I` (Intel IA64, Itanium) and
+`VC-CE` (Windows CE) are rather uncommon nowadays.
+
+Installing OpenSSL
+------------------
+
+The following commands will install OpenSSL to a default system location.
+
+**Danger Zone:** even if you are impatient, please read the following two
+paragraphs carefully before you install OpenSSL.
+
+For security reasons the default system location is by default not writable
+for unprivileged users.  So for the final installation step administrative
+privileges are required.  The default system location and the procedure to
+obtain administrative privileges depends on the operating system.
+It is recommended to compile and test OpenSSL with normal user privileges
+and use administrative privileges only for the final installation step.
+
+On some platforms OpenSSL is preinstalled as part of the Operating System.
+In this case it is highly recommended not to overwrite the system versions,
+because other applications or libraries might depend on it.
+To avoid breaking other applications, install your copy of OpenSSL to a
+[different location](#installing-to-a-different-location) which is not in
+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
+
+Depending on your distribution, you need to run the following command as
+root user or prepend `sudo` to the command:
+
+    $ make install
+
+By default, OpenSSL will be installed to
+
+    /usr/local
+
+More precisely, the files will be installed into the  subdirectories
+
+    /usr/local/bin
+    /usr/local/lib
+    /usr/local/include
+    ...
+
+depending on the file type, as it is custom on Unix-like operating systems.
+
+### OpenVMS
+
+Use the following command to install OpenSSL.
+
+    $ mms install
+
+By default, OpenSSL will be installed to
+
+    SYS$COMMON:[OPENSSL]
+
+### Windows
+
+If you are using Visual Studio, open the Developer Command Prompt _elevated_
+and issue the following command.
+
+    $ nmake install
+
+The easiest way to elevate the Command Prompt is to press and hold down both
+the `<CTRL>` and `<SHIFT>` keys while clicking the menu item in the task menu.
+
+The default installation location is
+
+    C:\Program Files\OpenSSL
+
+for native binaries, or
+
+    C:\Program Files (x86)\OpenSSL
+
+for 32bit binaries on 64bit Windows (WOW64).
+
+#### Installing to a different location
+
+To install OpenSSL to a different location (for example into your home
+directory for testing purposes) run `Configure` as shown in the following
+examples.
+
+The options `--prefix` and `--openssldir` are explained in further detail in
+[Directories](#directories) below, and the values used here are mere examples.
+
+On Unix:
+
+    $ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl
+
+On OpenVMS:
+
+    $ perl Configure --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL]
+
+Note: if you do add options to the configuration command, please make sure
+you've read more than just this Quick Start, such as relevant `NOTES-*` files,
+the options outline below, as configuration options may change the outcome
+in otherwise unexpected ways.
+
+Configuration Options
+=====================
+
+There are several options to `./Configure` to customize the build (note that
+for Windows, the defaults for `--prefix` and `--openssldir` depend on what
+configuration is used and what Windows implementation OpenSSL is built on.
+For more information, see the [Notes for Windows platforms](NOTES-WINDOWS.md).
+
+API Level
+---------
+
+    --api=x.y[.z]
+
+Build the OpenSSL libraries to support the API for the specified version.
+If [no-deprecated](#no-deprecated) is also given, don't build with support
+for deprecated APIs in or below the specified version number.  For example,
+adding
+
+    --api=1.1.0 no-deprecated
+
+will remove support for all APIs that were deprecated in OpenSSL version
+1.1.0 or below.  This is a rather specialized option for developers.
+If you just intend to remove all deprecated APIs up to the current version
+entirely, just specify [no-deprecated](#no-deprecated).
+If `--api` isn't given, it defaults to the current (minor) OpenSSL version.
+
+Cross Compile Prefix
+--------------------
+
+    --cross-compile-prefix=<PREFIX>
+
+The `<PREFIX>` to include in front of commands for your toolchain.
+
+It is likely to have to end with dash, e.g. `a-b-c-` would invoke GNU compiler
+as `a-b-c-gcc`, etc.  Unfortunately cross-compiling is too case-specific to put
+together one-size-fits-all instructions.  You might have to pass more flags or
+set up environment variables to actually make it work.  Android and iOS cases
+are discussed in corresponding `Configurations/15-*.conf` files.  But there are
+cases when this option alone is sufficient.  For example to build the mingw64
+target on Linux `--cross-compile-prefix=x86_64-w64-mingw32-` works.  Naturally
+provided that mingw packages are installed.  Today Debian and Ubuntu users
+have option to install a number of prepackaged cross-compilers along with
+corresponding run-time and development packages for "alien" hardware.  To give
+another example `--cross-compile-prefix=mipsel-linux-gnu-` suffices in such
+case.
+
+For cross compilation, you must [configure manually](#manual-configuration).
+Also, note that `--openssldir` refers to target's file system, not one you are
+building on.
+
+Build Type
+----------
+
+    --debug
+
+Build OpenSSL with debugging symbols and zero optimization level.
+
+    --release
+
+Build OpenSSL without debugging symbols.  This is the default.
+
+Directories
+-----------
+
+### libdir
+
+    --libdir=DIR
+
+The name of the directory under the top of the installation directory tree
+(see the `--prefix` option) where libraries will be installed.  By default
+this is `lib`. Note that on Windows only static libraries (`*.lib`) will
+be stored in this location. Shared libraries (`*.dll`) will always be
+installed to the `bin` directory.
+
+Some build targets have a multilib postfix set in the build configuration.
+For these targets the default libdir is `lib<multilib-postfix>`. Please use
+`--libdir=lib` to override the libdir if adding the postfix is undesirable.
+
+### openssldir
+
+    --openssldir=DIR
+
+Directory for OpenSSL configuration files, and also the default certificate
+and key store.  Defaults are:
+
+    Unix:           /usr/local/ssl
+    Windows:        C:\Program Files\Common Files\SSL
+    OpenVMS:        SYS$COMMON:[OPENSSL-COMMON]
+
+For 32bit Windows applications on Windows 64bit (WOW64), always replace
+`C:\Program Files` by `C:\Program Files (x86)`.
+
+### prefix
+
+    --prefix=DIR
+
+The top of the installation directory tree.  Defaults are:
+
+    Unix:           /usr/local
+    Windows:        C:\Program Files\OpenSSL
+    OpenVMS:        SYS$COMMON:[OPENSSL]
+
+Compiler Warnings
+-----------------
+
+    --strict-warnings
+
+This is a developer flag that switches on various compiler options recommended
+for OpenSSL development.  It only works when using gcc or clang as the compiler.
+If you are developing a patch for OpenSSL then it is recommended that you use
+this option where possible.
+
+ZLib Flags
+----------
+
+### with-zlib-include
+
+    --with-zlib-include=DIR
+
+The directory for the location of the zlib include file.  This option is only
+necessary if [zlib](#zlib) is used and the include file is not
+already on the system include path.
+
+### with-zlib-lib
+
+    --with-zlib-lib=LIB
+
+**On Unix**: this is the directory containing the zlib library.
+If not provided the system library path will be used.
+
+**On Windows:** this is the filename of the zlib library (with or
+without a path).  This flag must be provided if the
+[zlib-dynamic](#zlib-dynamic) option is not also used. If `zlib-dynamic` is used
+then this flag is optional and defaults to `ZLIB1` if not provided.
+
+**On VMS:** this is the filename of the zlib library (with or without a path).
+This flag is optional and if not provided then `GNV$LIBZSHR`, `GNV$LIBZSHR32`
+or `GNV$LIBZSHR64` is used by default depending on the pointer size chosen.
+
+Seeding the Random Generator
+----------------------------
+
+    --with-rand-seed=seed1[,seed2,...]
+
+A comma separated list of seeding methods which will be tried by OpenSSL
+in order to obtain random input (a.k.a "entropy") for seeding its
+cryptographically secure random number generator (CSPRNG).
+The current seeding methods are:
+
+### os
+
+Use a trusted operating system entropy source.
+This is the default method if such an entropy source exists.
+
+### getrandom
+
+Use the [getrandom(2)][man-getrandom] or equivalent system call.
+
+[man-getrandom]: http://man7.org/linux/man-pages/man2/getrandom.2.html
+
+### devrandom
+
+Use the first device from the `DEVRANDOM` list which can be opened to read
+random bytes.  The `DEVRANDOM` preprocessor constant expands to
+
+    "/dev/urandom","/dev/random","/dev/srandom"
+
+on most unix-ish operating systems.
+
+### egd
+
+Check for an entropy generating daemon.
+This source is ignored by the FIPS provider.
+
+### rdcpu
+
+Use the `RDSEED` or `RDRAND` command on x86 or `RNDRRS` command on aarch64
+if provided by the CPU.
+
+### librandom
+
+Use librandom (not implemented yet).
+This source is ignored by the FIPS provider.
+
+### none
+
+Disable automatic seeding.  This is the default on some operating systems where
+no suitable entropy source exists, or no support for it is implemented yet.
+This option is ignored by the FIPS provider.
+
+For more information, see the section [Notes on random number generation][rng]
+at the end of this document.
+
+[rng]: #notes-on-random-number-generation
+
+Setting the FIPS HMAC key
+-------------------------
+
+    --fips-key=value
+
+As part of its self-test validation, the FIPS module must verify itself
+by performing a SHA-256 HMAC computation on itself. The default key is
+the SHA256 value of "the holy handgrenade of antioch" and is sufficient
+for meeting the FIPS requirements.
+
+To change the key to a different value, use this flag. The value should
+be a hex string no more than 64 characters.
+
+Enable and Disable Features
+---------------------------
+
+Feature options always come in pairs, an option to enable feature
+`xxxx`, and an option to disable it:
+
+    [ enable-xxxx | no-xxxx ]
+
+Whether a feature is enabled or disabled by default, depends on the feature.
+In the following list, always the non-default variant is documented: if
+feature `xxxx` is disabled by default then `enable-xxxx` is documented and
+if feature `xxxx` is enabled by default then `no-xxxx` is documented.
+
+### no-afalgeng
+
+Don't build the AFALG engine.
+
+This option will be forced on a platform that does not support AFALG.
+
+### enable-ktls
+
+Build with Kernel TLS support.
+
+This option will enable the use of the Kernel TLS data-path, which can improve
+performance and allow for the use of sendfile and splice system calls on
+TLS sockets.  The Kernel may use TLS accelerators if any are available on the
+system.  This option will be forced off on systems that do not support the
+Kernel TLS data-path.
+
+### enable-asan
+
+Build with the Address sanitiser.
+
+This is a developer option only.  It may not work on all platforms and should
+never be used in production environments.  It will only work when used with
+gcc or clang and should be used in conjunction with the [no-shared](#no-shared)
+option.
+
+### enable-acvp-tests
+
+Build support for Automated Cryptographic Validation Protocol (ACVP)
+tests.
+
+This is required for FIPS validation purposes. Certain ACVP tests require
+access to algorithm internals that are not normally accessible.
+Additional information related to ACVP can be found at
+<https://github.com/usnistgov/ACVP>.
+
+### no-asm
+
+Do not use assembler code.
+
+This should be viewed as debugging/troubleshooting option rather than for
+production use.  On some platforms a small amount of assembler code may still
+be used even with this option.
+
+### no-async
+
+Do not build support for async operations.
+
+### no-autoalginit
+
+Don't automatically load all supported ciphers and digests.
+
+Typically OpenSSL will make available all of its supported ciphers and digests.
+For a statically linked application this may be undesirable if small executable
+size is an objective.  This only affects libcrypto.  Ciphers and digests will
+have to be loaded manually using `EVP_add_cipher()` and `EVP_add_digest()`
+if this option is used.  This option will force a non-shared build.
+
+### no-autoerrinit
+
+Don't automatically load all libcrypto/libssl error strings.
+
+Typically OpenSSL will automatically load human readable error strings.  For a
+statically linked application this may be undesirable if small executable size
+is an objective.
+
+### no-autoload-config
+
+Don't automatically load the default `openssl.cnf` file.
+
+Typically OpenSSL will automatically load a system config file which configures
+default SSL options.
+
+### enable-buildtest-c++
+
+While testing, generate C++ buildtest files that simply check that the public
+OpenSSL header files are usable standalone with C++.
+
+Enabling this option demands extra care.  For any compiler flag given directly
+as configuration option, you must ensure that it's valid for both the C and
+the C++ compiler.  If not, the C++ build test will most likely break.  As an
+alternative, you can use the language specific variables, `CFLAGS` and `CXXFLAGS`.
+
+### --banner=text
+
+Use the specified text instead of the default banner at the end of
+configuration.
+
+### --w
+
+On platforms where the choice of 32-bit or 64-bit architecture
+is not explicitly specified, `Configure` will print a warning
+message and wait for a few seconds to let you interrupt the
+configuration. Using this flag skips the wait.
+
+### no-bulk
+
+Build only some minimal set of features.
+This is a developer option used internally for CI build tests of the project.
+
+### no-cached-fetch
+
+Never cache algorithms when they are fetched from a provider.  Normally, a
+provider indicates if the algorithms it supplies can be cached or not.  Using
+this option will reduce run-time memory usage but it also introduces a
+significant performance penalty.  This option is primarily designed to help
+with detecting incorrect reference counting.
+
+### no-capieng
+
+Don't build the CAPI engine.
+
+This option will be forced if on a platform that does not support CAPI.
+
+### no-cmp
+
+Don't build support for Certificate Management Protocol (CMP)
+and Certificate Request Message Format (CRMF).
+
+### no-cms
+
+Don't build support for Cryptographic Message Syntax (CMS).
+
+### no-comp
+
+Don't build support for SSL/TLS compression.
+
+If this option is enabled (the default), then compression will only work if
+the zlib or `zlib-dynamic` options are also chosen.
+
+### enable-crypto-mdebug
+
+This now only enables the `failed-malloc` feature.
+
+### enable-crypto-mdebug-backtrace
+
+This is a no-op; the project uses the compiler's address/leak sanitizer instead.
+
+### no-ct
+
+Don't build support for Certificate Transparency (CT).
+
+### no-deprecated
+
+Don't build with support for deprecated APIs up until and including the version
+given with `--api` (or the current version, if `--api` wasn't specified).
+
+### no-dgram
+
+Don't build support for datagram based BIOs.
+
+Selecting this option will also force the disabling of DTLS.
+
+### no-dso
+
+Don't build support for loading Dynamic Shared Objects (DSO)
+
+### enable-devcryptoeng
+
+Build the `/dev/crypto` engine.
+
+This option is automatically selected on the BSD platform, in which case it can
+be disabled with `no-devcryptoeng`.
+
+### no-dynamic-engine
+
+Don't build the dynamically loaded engines.
+
+This only has an effect in a shared build.
+
+### no-ec
+
+Don't build support for Elliptic Curves.
+
+### no-ec2m
+
+Don't build support for binary Elliptic Curves
+
+### enable-ec_nistp_64_gcc_128
+
+Enable support for optimised implementations of some commonly used NIST
+elliptic curves.
+
+This option is only supported on platforms:
+
+ - with little-endian storage of non-byte types
+ - that tolerate misaligned memory references
+ - where the compiler:
+   - supports the non-standard type `__uint128_t`
+   - defines the built-in macro `__SIZEOF_INT128__`
+
+### enable-egd
+
+Build support for gathering entropy from the Entropy Gathering Daemon (EGD).
+
+### no-engine
+
+Don't build support for loading engines.
+
+### no-err
+
+Don't compile in any error strings.
+
+### enable-external-tests
+
+Enable building of integration with external test suites.
+
+This is a developer option and may not work on all platforms.  The following
+external test suites are currently supported:
+
+ - GOST engine test suite
+ - Python PYCA/Cryptography test suite
+ - krb5 test suite
+
+See the file [test/README-external.md](test/README-external.md)
+for further details.
+
+### no-filenames
+
+Don't compile in filename and line number information (e.g.  for errors and
+memory allocation).
+
+### enable-fips
+
+Build (and install) the FIPS provider
+
+### no-fips-securitychecks
+
+Don't perform FIPS module run-time checks related to enforcement of security
+parameters such as minimum security strength of keys.
+
+### enable-fuzz-libfuzzer, enable-fuzz-afl
+
+Build with support for fuzzing using either libfuzzer or AFL.
+
+These are developer options only.  They may not work on all  platforms and
+should never be used in production environments.
+
+See the file [fuzz/README.md](fuzz/README.md) for further details.
+
+### no-gost
+
+Don't build support for GOST based ciphersuites.
+
+Note that if this feature is enabled then GOST ciphersuites are only available
+if the GOST algorithms are also available through loading an externally supplied
+engine.
+
+### no-legacy
+
+Don't build the legacy provider.
+
+Disabling this also disables the legacy algorithms: MD2 (already disabled by default).
+
+### no-makedepend
+
+Don't generate dependencies.
+
+### no-module
+
+Don't build any dynamically loadable engines.
+
+This also implies `no-dynamic-engine`.
+
+### no-multiblock
+
+Don't build support for writing multiple records in one go in libssl
+
+Note: this is a different capability to the pipelining functionality.
+
+### no-nextprotoneg
+
+Don't build support for the Next Protocol Negotiation (NPN) TLS extension.
+
+### no-ocsp
+
+Don't build support for Online Certificate Status Protocol (OCSP).
+
+### no-padlockeng
+
+Don't build the padlock engine.
+
+### no-hw-padlock
+
+As synonym for `no-padlockeng`.  Deprecated and should not be used.
+
+### no-pic
+
+Don't build with support for Position Independent Code.
+
+### no-pinshared
+
+Don't pin the shared libraries.
+
+By default OpenSSL will attempt to stay in memory until the process exits.
+This is so that libcrypto and libssl can be properly cleaned up automatically
+via an `atexit()` handler.  The handler is registered by libcrypto and cleans
+up both libraries.  On some platforms the `atexit()` handler will run on unload of
+libcrypto (if it has been dynamically loaded) rather than at process exit.  This
+option can be used to stop OpenSSL from attempting to stay in memory until the
+process exits.  This could lead to crashes if either libcrypto or libssl have
+already been unloaded at the point that the atexit handler is invoked, e.g.  on a
+platform which calls `atexit()` on unload of the library, and libssl is unloaded
+before libcrypto then a crash is likely to happen.  Applications can suppress
+running of the `atexit()` handler at run time by using the
+`OPENSSL_INIT_NO_ATEXIT` option to `OPENSSL_init_crypto()`.
+See the man page for it for further details.
+
+### no-posix-io
+
+Don't use POSIX IO capabilities.
+
+### no-psk
+
+Don't build support for Pre-Shared Key based ciphersuites.
+
+### no-rdrand
+
+Don't use hardware RDRAND capabilities.
+
+### no-rfc3779
+
+Don't build support for RFC3779, "X.509 Extensions for IP Addresses and
+AS Identifiers".
+
+### sctp
+
+Build support for Stream Control Transmission Protocol (SCTP).
+
+### no-shared
+
+Do not create shared libraries, only static ones.
+
+See [Notes on shared libraries](#notes-on-shared-libraries) below.
+
+### no-sock
+
+Don't build support for socket BIOs.
+
+### no-srp
+
+Don't build support for Secure Remote Password (SRP) protocol or
+SRP based ciphersuites.
+
+### no-srtp
+
+Don't build Secure Real-Time Transport Protocol (SRTP) support.
+
+### no-sse2
+
+Exclude SSE2 code paths from 32-bit x86 assembly modules.
+
+Normally SSE2 extension is detected at run-time, but the decision whether or not
+the machine code will be executed is taken solely on CPU capability vector.  This
+means that if you happen to run OS kernel which does not support SSE2 extension
+on Intel P4 processor, then your application might be exposed to "illegal
+instruction" exception.  There might be a way to enable support in kernel, e.g.
+FreeBSD kernel can be compiled with `CPU_ENABLE_SSE`, and there is a way to
+disengage SSE2 code paths upon application start-up, but if you aim for wider
+"audience" running such kernel, consider `no-sse2`.  Both the `386` and `no-asm`
+options imply `no-sse2`.
+
+### no-ssl-trace
+
+Don't build with SSL Trace capabilities.
+
+This removes the `-trace` option from `s_client` and `s_server`, and omits the
+`SSL_trace()` function from libssl.
+
+Disabling `ssl-trace` may provide a small reduction in libssl binary size.
+
+### no-static-engine
+
+Don't build the statically linked engines.
+
+This only has an impact when not built "shared".
+
+### no-stdio
+
+Don't use anything from the C header file `stdio.h` that makes use of the `FILE`
+type.  Only libcrypto and libssl can be built in this way.  Using this option will
+suppress building the command line applications.  Additionally, since the OpenSSL
+tests also use the command line applications, the tests will also be skipped.
+
+### no-tests
+
+Don't build test programs or run any tests.
+
+### no-threads
+
+Don't build with support for multi-threaded applications.
+
+### threads
+
+Build with support for multi-threaded applications.  Most platforms will enable
+this by default.  However, if on a platform where this is not the case then this
+will usually require additional system-dependent options!
+
+See [Notes on multi-threading](#notes-on-multi-threading) below.
+
+### enable-trace
+
+Build with support for the integrated tracing api.
+
+See manual pages OSSL_trace_set_channel(3) and OSSL_trace_enabled(3) for details.
+
+### no-ts
+
+Don't build Time Stamping (TS) Authority support.
+
+### enable-ubsan
+
+Build with the Undefined Behaviour sanitiser (UBSAN).
+
+This is a developer option only.  It may not work on all platforms and should
+never be used in production environments.  It will only work when used with
+gcc or clang and should be used in conjunction with the `-DPEDANTIC` option
+(or the `--strict-warnings` option).
+
+### no-ui-console
+
+Don't build with the User Interface (UI) console method
+
+The User Interface console method enables text based console prompts.
+
+### enable-unit-test
+
+Enable additional unit test APIs.
+
+This should not typically be used in production deployments.
+
+### no-uplink
+
+Don't build support for UPLINK interface.
+
+### enable-weak-ssl-ciphers
+
+Build support for SSL/TLS ciphers that are considered "weak"
+
+Enabling this includes for example the RC4 based ciphersuites.
+
+### zlib
+
+Build with support for zlib compression/decompression.
+
+### zlib-dynamic
+
+Like the zlib option, but has OpenSSL load the zlib library dynamically
+when needed.
+
+This is only supported on systems where loading of shared libraries is supported.
+
+### 386
+
+In 32-bit x86 builds, use the 80386 instruction set only in assembly modules
+
+The default x86 code is more efficient, but requires at least an 486 processor.
+Note: This doesn't affect compiler generated code, so this option needs to be
+accompanied by a corresponding compiler-specific option.
+
+### no-{protocol}
+
+    no-{ssl|ssl3|tls|tls1|tls1_1|tls1_2|tls1_3|dtls|dtls1|dtls1_2}
+
+Don't build support for negotiating the specified SSL/TLS protocol.
+
+If `no-tls` is selected then all of `tls1`, `tls1_1`, `tls1_2` and `tls1_3`
+are disabled.
+Similarly `no-dtls` will disable `dtls1` and `dtls1_2`.  The `no-ssl` option is
+synonymous with `no-ssl3`.  Note this only affects version negotiation.
+OpenSSL will still provide the methods for applications to explicitly select
+the individual protocol versions.
+
+### no-{protocol}-method
+
+    no-{ssl3|tls1|tls1_1|tls1_2|dtls1|dtls1_2}-method
+
+Analogous to `no-{protocol}` but in addition do not build the methods for
+applications to explicitly select individual protocol versions.  Note that there
+is no `no-tls1_3-method` option because there is no application method for
+TLSv1.3.
+
+Using individual protocol methods directly is deprecated.  Applications should
+use `TLS_method()` instead.
+
+### enable-{algorithm}
+
+    enable-{md2|rc5}
+
+Build with support for the specified algorithm.
+
+### no-{algorithm}
+
+    no-{aria|bf|blake2|camellia|cast|chacha|cmac|
+        des|dh|dsa|ecdh|ecdsa|idea|md4|mdc2|ocb|
+        poly1305|rc2|rc4|rmd160|scrypt|seed|
+        siphash|siv|sm2|sm3|sm4|whirlpool}
+
+Build without support for the specified algorithm.
+
+The `ripemd` algorithm is deprecated and if used is synonymous with `rmd160`.
+
+### Compiler-specific options
+
+    -Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
+
+These system specific options will be recognised and passed through to the
+compiler to allow you to define preprocessor symbols, specify additional
+libraries, library directories or other compiler options.  It might be worth
+noting that some compilers generate code specifically for processor the
+compiler currently executes on.  This is not necessarily what you might have
+in mind, since it might be unsuitable for execution on other, typically older,
+processor.  Consult your compiler documentation.
+
+Take note of the [Environment Variables](#environment-variables) documentation
+below and how these flags interact with those variables.
+
+    -xxx, +xxx, /xxx
+
+Additional options that are not otherwise recognised are passed through as
+they are to the compiler as well.  Unix-style options beginning with a
+`-` or `+` and Windows-style options beginning with a `/` are recognised.
+Again, consult your compiler documentation.
+
+If the option contains arguments separated by spaces, then the URL-style
+notation `%20` can be used for the space character in order to avoid having
+to quote the option.  For example, `-opt%20arg` gets expanded to `-opt arg`.
+In fact, any ASCII character can be encoded as %xx using its hexadecimal
+encoding.
+
+Take note of the [Environment Variables](#environment-variables) documentation
+below and how these flags interact with those variables.
+
+### Environment Variables
+
+    VAR=value
+
+Assign the given value to the environment variable `VAR` for `Configure`.
+
+These work just like normal environment variable assignments, but are supported
+on all platforms and are confined to the configuration scripts only.
+These assignments override the corresponding value in the inherited environment,
+if there is one.
+
+The following variables are used as "`make` variables" and can be used as an
+alternative to giving preprocessor, compiler and linker options directly as
+configuration.  The following variables are supported:
+
+    AR              The static library archiver.
+    ARFLAGS         Flags for the static library archiver.
+    AS              The assembler compiler.
+    ASFLAGS         Flags for the assembler compiler.
+    CC              The C compiler.
+    CFLAGS          Flags for the C compiler.
+    CXX             The C++ compiler.
+    CXXFLAGS        Flags for the C++ compiler.
+    CPP             The C/C++ preprocessor.
+    CPPFLAGS        Flags for the C/C++ preprocessor.
+    CPPDEFINES      List of CPP macro definitions, separated
+                    by a platform specific character (':' or
+                    space for Unix, ';' for Windows, ',' for
+                    VMS).  This can be used instead of using
+                    -D (or what corresponds to that on your
+                    compiler) in CPPFLAGS.
+    CPPINCLUDES     List of CPP inclusion directories, separated
+                    the same way as for CPPDEFINES.  This can
+                    be used instead of -I (or what corresponds
+                    to that on your compiler) in CPPFLAGS.
+    HASHBANGPERL    Perl invocation to be inserted after '#!'
+                    in public perl scripts (only relevant on
+                    Unix).
+    LD              The program linker (not used on Unix, $(CC)
+                    is used there).
+    LDFLAGS         Flags for the shared library, DSO and
+                    program linker.
+    LDLIBS          Extra libraries to use when linking.
+                    Takes the form of a space separated list
+                    of library specifications on Unix and
+                    Windows, and as a comma separated list of
+                    libraries on VMS.
+    RANLIB          The library archive indexer.
+    RC              The Windows resource compiler.
+    RCFLAGS         Flags for the Windows resource compiler.
+    RM              The command to remove files and directories.
+
+These cannot be mixed with compiling/linking flags given on the command line.
+In other words, something like this isn't permitted.
+
+    $ ./Configure -DFOO CPPFLAGS=-DBAR -DCOOKIE
+
+Backward compatibility note:
+
+To be compatible with older configuration scripts, the environment variables
+are ignored if compiling/linking flags are given on the command line, except
+for the following:
+
+    AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC, and WINDRES
+
+For example, the following command will not see `-DBAR`:
+
+    $ CPPFLAGS=-DBAR ./Configure -DCOOKIE
+
+However, the following will see both set variables:
+
+    $ CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- ./Configure -DCOOKIE
+
+If `CC` is set, it is advisable to also set `CXX` to ensure both the C and C++
+compiler are in the same "family".  This becomes relevant with
+`enable-external-tests` and `enable-buildtest-c++`.
+
+### Reconfigure
+
+    reconf
+    reconfigure
+
+Reconfigure from earlier data.
+
+This fetches the previous command line options and environment from data
+saved in `configdata.pm` and runs the configuration process again, using
+these options and environment.  Note: NO other option is permitted together
+with `reconf`.  Note: The original configuration saves away values for ALL
+environment variables that were used, and if they weren't defined, they are
+still saved away with information that they weren't originally defined.
+This information takes precedence over environment variables that are
+defined when reconfiguring.
+
+Displaying configuration data
+-----------------------------
+
+The configuration script itself will say very little, and finishes by
+creating `configdata.pm`.  This perl module can be loaded by other scripts
+to find all the configuration data, and it can also be used as a script to
+display all sorts of configuration data in a human readable form.
+
+For more information, please do:
+
+    $ ./configdata.pm --help                         # Unix
+
+or
+
+    $ perl configdata.pm --help                      # Windows and VMS
+
+Installation Steps in Detail
+============================
+
+Configure OpenSSL
+-----------------
+
+### Automatic Configuration
+
+In previous version, the `config` script determined the platform type and
+compiler and then called `Configure`. Starting with this release, they are
+the same.
+
+#### Unix / Linux / macOS
+
+    $ ./Configure [[ options ]]
+
+#### OpenVMS
+
+    $ perl Configure [[ options ]]
+
+#### Windows
+
+    $ perl Configure [[ options ]]
+
+### Manual Configuration
+
+OpenSSL knows about a range of different operating system, hardware and
+compiler combinations.  To see the ones it knows about, run
+
+    $ ./Configure LIST                               # Unix
+
+or
+
+    $ perl Configure LIST                            # All other platforms
+
+For the remainder of this text, the Unix form will be used in all examples.
+Please use the appropriate form for your platform.
+
+Pick a suitable name from the list that matches your system.  For most
+operating systems there is a choice between using cc or gcc.
+When you have identified your system (and if necessary compiler) use this
+name as the argument to `Configure`.  For example, a `linux-elf` user would
+run:
+
+    $ ./Configure linux-elf [[ options ]]
+
+### Creating your own Configuration
+
+If your system isn't listed, you will have to create a configuration
+file named `Configurations/{{ something }}.conf` and add the correct
+configuration for your system.  See the available configs as examples
+and read [Configurations/README.md](Configurations/README.md) and
+[Configurations/README-design.md](Configurations/README-design.md)
+for more information.
+
+The generic configurations `cc` or `gcc` should usually work on 32 bit
+Unix-like systems.
+
+`Configure` creates a build file (`Makefile` on Unix, `makefile` on Windows
+and `descrip.mms` on OpenVMS) from a suitable template in `Configurations/`,
+and defines various macros in `include/openssl/configuration.h` (generated
+from `include/openssl/configuration.h.in`.
+
+If none of the generated build files suit your purpose, it's possible to
+write your own build file template and give its name through the environment
+variable `BUILDFILE`.  For example, Ninja build files could be supported by
+writing `Configurations/build.ninja.tmpl` and then configure with `BUILDFILE`
+set like this (Unix syntax shown, you'll have to adapt for other platforms):
+
+    $ BUILDFILE=build.ninja perl Configure [options...]
+
+### Out of Tree Builds
+
+OpenSSL can be configured to build in a build directory separate from the
+source code directory.  It's done by placing yourself in some other
+directory and invoking the configuration commands from there.
+
+#### Unix example
+
+    $ mkdir /var/tmp/openssl-build
+    $ cd /var/tmp/openssl-build
+    $ /PATH/TO/OPENSSL/SOURCE/Configure [[ options ]]
+
+#### OpenVMS example
+
+    $ set default sys$login:
+    $ create/dir [.tmp.openssl-build]
+    $ set default [.tmp.openssl-build]
+    $ perl D:[PATH.TO.OPENSSL.SOURCE]Configure [[ options ]]
+
+#### Windows example
+
+    $ C:
+    $ mkdir \temp-openssl
+    $ cd \temp-openssl
+    $ perl d:\PATH\TO\OPENSSL\SOURCE\Configure [[ options ]]
+
+Paths can be relative just as well as absolute.  `Configure` will do its best
+to translate them to relative paths whenever possible.
+
+Build OpenSSL
+-------------
+
+Build OpenSSL by running:
+
+    $ make                                           # Unix
+    $ mms                                            ! (or mmk) OpenVMS
+    $ nmake                                          # Windows
+
+This will build the OpenSSL libraries (`libcrypto.a` and `libssl.a` on
+Unix, corresponding on other platforms) and the OpenSSL binary
+(`openssl`).  The libraries will be built in the top-level directory,
+and the binary will be in the `apps/` subdirectory.
+
+If the build fails, take a look at the [Build Failures](#build-failures)
+subsection of the [Troubleshooting](#troubleshooting) section.
+
+Test OpenSSL
+------------
+
+After a successful build, and before installing, the libraries should
+be tested.  Run:
+
+    $ make test                                      # Unix
+    $ mms test                                       ! OpenVMS
+    $ nmake test                                     # Windows
+
+**Warning:** you MUST run the tests from an unprivileged account (or disable
+your privileges temporarily if your platform allows it).
+
+See [test/README.md](test/README.md) for further details how run tests.
+
+See [test/README-dev.md](test/README-dev.md) for guidelines on adding tests.
+
+Install OpenSSL
+---------------
+
+If everything tests ok, install OpenSSL with
+
+    $ make install                                   # Unix
+    $ mms install                                    ! OpenVMS
+    $ nmake install                                  # Windows
+
+Note that in order to perform the install step above you need to have
+appropriate permissions to write to the installation directory.
+
+The above commands will install all the software components in this
+directory tree under `<PREFIX>` (the directory given with `--prefix` or
+its default):
+
+### Unix / Linux / macOS
+
+    bin/           Contains the openssl binary and a few other
+                   utility scripts.
+    include/openssl
+                   Contains the header files needed if you want
+                   to build your own programs that use libcrypto
+                   or libssl.
+    lib            Contains the OpenSSL library files.
+    lib/engines    Contains the OpenSSL dynamically loadable engines.
+
+    share/man/man1 Contains the OpenSSL command line man-pages.
+    share/man/man3 Contains the OpenSSL library calls man-pages.
+    share/man/man5 Contains the OpenSSL configuration format man-pages.
+    share/man/man7 Contains the OpenSSL other misc man-pages.
+
+    share/doc/openssl/html/man1
+    share/doc/openssl/html/man3
+    share/doc/openssl/html/man5
+    share/doc/openssl/html/man7
+                   Contains the HTML rendition of the man-pages.
+
+### OpenVMS
+
+'arch' is replaced with the architecture name, `ALPHA` or `IA64`,
+'sover' is replaced with the shared library version (`0101` for 1.1), and
+'pz' is replaced with the pointer size OpenSSL was built with:
+
+    [.EXE.'arch']  Contains the openssl binary.
+    [.EXE]         Contains a few utility scripts.
+    [.include.openssl]
+                   Contains the header files needed if you want
+                   to build your own programs that use libcrypto
+                   or libssl.
+    [.LIB.'arch']  Contains the OpenSSL library files.
+    [.ENGINES'sover''pz'.'arch']
+                   Contains the OpenSSL dynamically loadable engines.
+    [.SYS$STARTUP] Contains startup, login and shutdown scripts.
+                   These define appropriate logical names and
+                   command symbols.
+    [.SYSTEST]     Contains the installation verification procedure.
+    [.HTML]        Contains the HTML rendition of the manual pages.
+
+### Additional Directories
+
+Additionally, install will add the following directories under
+OPENSSLDIR (the directory given with `--openssldir` or its default)
+for you convenience:
+
+    certs          Initially empty, this is the default location
+                   for certificate files.
+    private        Initially empty, this is the default location
+                   for private key files.
+    misc           Various scripts.
+
+The installation directory should be appropriately protected to ensure
+unprivileged users cannot make changes to OpenSSL binaries or files, or
+install engines.  If you already have a pre-installed version of OpenSSL as
+part of your Operating System it is recommended that you do not overwrite
+the system version and instead install to somewhere else.
+
+Package builders who want to configure the library for standard locations,
+but have the package installed somewhere else so that it can easily be
+packaged, can use
+
+    $ make DESTDIR=/tmp/package-root install         # Unix
+    $ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS
+
+The specified destination directory will be prepended to all installation
+target paths.
+
+Compatibility issues with previous OpenSSL versions
+---------------------------------------------------
+
+### COMPILING existing applications
+
+Starting with version 1.1.0, OpenSSL hides a number of structures that were
+previously open.  This includes all internal libssl structures and a number
+of EVP types.  Accessor functions have been added to allow controlled access
+to the structures' data.
+
+This means that some software needs to be rewritten to adapt to the new ways
+of doing things.  This often amounts to allocating an instance of a structure
+explicitly where you could previously allocate them on the stack as automatic
+variables, and using the provided accessor functions where you would previously
+access a structure's field directly.
+
+Some APIs have changed as well.  However, older APIs have been preserved when
+possible.
+
+Post-installation Notes
+-----------------------
+
+With the default OpenSSL installation comes a FIPS provider module, which
+needs some post-installation attention, without which it will not be usable.
+This involves using the following command:
+
+    $ openssl fipsinstall
+
+See the openssl-fipsinstall(1) manual for details and examples.
+
+Advanced Build Options
+======================
+
+Environment Variables
+---------------------
+
+A number of environment variables can be used to provide additional control
+over the build process.  Typically these should be defined prior to running
+`Configure`.  Not all environment variables are relevant to all platforms.
+
+    AR
+                   The name of the ar executable to use.
+
+    BUILDFILE
+                   Use a different build file name than the platform default
+                   ("Makefile" on Unix-like platforms, "makefile" on native Windows,
+                   "descrip.mms" on OpenVMS).  This requires that there is a
+                   corresponding build file template.
+                   See [Configurations/README.md](Configurations/README.md)
+                   for further information.
+
+    CC
+                   The compiler to use. Configure will attempt to pick a default
+                   compiler for your platform but this choice can be overridden
+                   using this variable. Set it to the compiler executable you wish
+                   to use, e.g. gcc or clang.
+
+    CROSS_COMPILE
+                   This environment variable has the same meaning as for the
+                   "--cross-compile-prefix" Configure flag described above. If both
+                   are set then the Configure flag takes precedence.
+
+    HASHBANGPERL
+                   The command string for the Perl executable to insert in the
+                   #! line of perl scripts that will be publicly installed.
+                   Default: /usr/bin/env perl
+                   Note: the value of this variable is added to the same scripts
+                   on all platforms, but it's only relevant on Unix-like platforms.
+
+    KERNEL_BITS
+                   This can be the value `32` or `64` to specify the architecture
+                   when it is not "obvious" to the configuration. It should generally
+                   not be necessary to specify this environment variable.
+
+    NM
+                   The name of the nm executable to use.
+
+    OPENSSL_LOCAL_CONFIG_DIR
+                   OpenSSL comes with a database of information about how it
+                   should be built on different platforms as well as build file
+                   templates for those platforms. The database is comprised of
+                   ".conf" files in the Configurations directory.  The build
+                   file templates reside there as well as ".tmpl" files. See the
+                   file [Configurations/README.md](Configurations/README.md)
+                   for further information about the format of ".conf" files
+                   as well as information on the ".tmpl" files.
+                   In addition to the standard ".conf" and ".tmpl" files, it is
+                   possible to create your own ".conf" and ".tmpl" files and
+                   store them locally, outside the OpenSSL source tree.
+                   This environment variable can be set to the directory where
+                   these files are held and will be considered by Configure
+                   before it looks in the standard directories.
+
+    PERL
+                   The name of the Perl executable to use when building OpenSSL.
+                   Only needed if builing should use a different Perl executable
+                   than what is used to run the Configure script.
+
+    RANLIB
+                   The name of the ranlib executable to use.
+
+    RC
+                   The name of the rc executable to use. The default will be as
+                   defined for the target platform in the ".conf" file. If not
+                   defined then "windres" will be used. The WINDRES environment
+                   variable is synonymous to this. If both are defined then RC
+                   takes precedence.
+
+    WINDRES
+                   See RC.
+
+Makefile Targets
+----------------
+
+The `Configure` script generates a Makefile in a format relevant to the specific
+platform.  The Makefiles provide a number of targets that can be used.  Not all
+targets may be available on all platforms.  Only the most common targets are
+described here.  Examine the Makefiles themselves for the full list.
+
+    all
+                   The target to build all the software components and
+                   documentation.
+
+    build_sw
+                   Build all the software components.
+                   THIS IS THE DEFAULT TARGET.
+
+    build_docs
+                   Build all documentation components.
+
+    clean
+                   Remove all build artefacts and return the directory to a "clean"
+                   state.
+
+    depend
+                   Rebuild the dependencies in the Makefiles. This is a legacy
+                   option that no longer needs to be used since OpenSSL 1.1.0.
+
+    install
+                   Install all OpenSSL components.
+
+    install_sw
+                   Only install the OpenSSL software components.
+
+    install_docs
+                   Only install the OpenSSL documentation components.
+
+    install_man_docs
+                   Only install the OpenSSL man pages (Unix only).
+
+    install_html_docs
+                   Only install the OpenSSL HTML documentation.
+
+    install_fips
+                   Install the FIPS provider module configuration file.
+
+    list-tests
+                   Prints a list of all the self test names.
+
+    test
+                   Build and run the OpenSSL self tests.
+
+    uninstall
+                   Uninstall all OpenSSL components.
+
+    reconfigure
+    reconf
+                   Re-run the configuration process, as exactly as the last time
+                   as possible.
+
+    update
+                   This is a developer option. If you are developing a patch for
+                   OpenSSL you may need to use this if you want to update
+                   automatically generated files; add new error codes or add new
+                   (or change the visibility of) public API functions. (Unix only).
+
+Running Selected Tests
+----------------------
+
+You can specify a set of tests to be performed
+using the `make` variable `TESTS`.
+
+See the section [Running Selected Tests of
+test/README.md](test/README.md#running-selected-tests).
+
+Troubleshooting
+===============
+
+Configuration Problems
+----------------------
+
+### Selecting the correct target
+
+The `./Configure` script tries hard to guess your operating system, but in some
+cases it does not succeed. You will see a message like the following:
+
+    $ ./Configure
+    Operating system: x86-whatever-minix
+    This system (minix) is not supported. See file INSTALL.md for details.
+
+Even if the automatic target selection by the `./Configure` script fails,
+chances are that you still might find a suitable target in the `Configurations`
+directory, which you can supply to the `./Configure` command,
+possibly after some adjustment.
+
+The `Configurations/` directory contains a lot of examples of such targets.
+The main configuration file is [10-main.conf], which contains all targets that
+are officially supported by the OpenSSL team. Other configuration files contain
+targets contributed by other OpenSSL users. The list of targets can be found in
+a Perl list `my %targets = ( ... )`.
+
+    my %targets = (
+    ...
+    "target-name" => {
+        inherit_from     => [ "base-target" ],
+        CC               => "...",
+        cflags           => add("..."),
+        asm_arch         => '...',
+        perlasm_scheme   => "...",
+    },
+    ...
+    )
+
+If you call `./Configure` without arguments, it will give you a list of all
+known targets. Using `grep`, you can lookup the target definition in the
+`Configurations/` directory. For example the `android-x86_64` can be found in
+[Configurations/15-android.conf](Configurations/15-android.conf).
+
+The directory contains two README files, which explain the general syntax and
+design of the configuration files.
+
+ - [Configurations/README.md](Configurations/README.md)
+ - [Configurations/README-design.md](Configurations/README-design.md)
+
+If you need further help, try to search the [openssl-users] mailing list
+or the [GitHub Issues] for existing solutions. If you don't find anything,
+you can [raise an issue] to ask a question yourself.
+
+More about our support resources can be found in the [SUPPORT] file.
+
+### Configuration Errors
+
+If the `./Configure` or `./Configure` command fails with an error message,
+read the error message carefully and try to figure out whether you made
+a mistake (e.g., by providing a wrong option), or whether the script is
+working incorrectly. If you think you encountered a bug, please
+[raise an issue] on GitHub to file a bug report.
+
+Along with a short description of the bug, please provide the complete
+configure command line and the relevant output including the error message.
+
+Note: To make the output readable, please add a 'code fence' (three backquotes
+` ``` ` on a separate line) before and after your output:
+
+     ```
+     ./Configure [your arguments...]
+
+     [output...]
+
+     ```
+
+Build Failures
+--------------
+
+If the build fails, look carefully at the output. Try to locate and understand
+the error message. It might be that the compiler is already telling you
+exactly what you need to do to fix your problem.
+
+There may be reasons for the failure that aren't problems in OpenSSL itself,
+for example if the compiler reports missing standard or third party headers.
+
+If the build succeeded previously, but fails after a source or configuration
+change, it might be helpful to clean the build tree before attempting another
+build.  Use this command:
+
+    $ make clean                                     # Unix
+    $ mms clean                                      ! (or mmk) OpenVMS
+    $ nmake clean                                    # Windows
+
+Assembler error messages can sometimes be sidestepped by using the `no-asm`
+configuration option. See also [notes](#notes-on-assembler-modules-compilation).
+
+Compiling parts of OpenSSL with gcc and others with the system compiler will
+result in unresolved symbols on some systems.
+
+If you are still having problems, try to search the [openssl-users] mailing
+list or the [GitHub Issues] for existing solutions. If you think you
+encountered an OpenSSL bug, please [raise an issue] to file a bug report.
+Please take the time to review the existing issues first; maybe the bug was
+already reported or has already been fixed.
+
+Test Failures
+-------------
+
+If some tests fail, look at the output.  There may be reasons for the failure
+that isn't a problem in OpenSSL itself (like an OS malfunction or a Perl issue).
+
+You may want increased verbosity, that can be accomplished as described in
+section [Test Failures of test/README.md](test/README.md#test-failures).
+
+You may also want to selectively specify which test(s) to perform. This can be
+done using the `make` variable `TESTS` as described in section [Running
+Selected Tests of test/README.md](test/README.md#running-selected-tests).
+
+If you find a problem with OpenSSL itself, try removing any
+compiler optimization flags from the `CFLAGS` line in the Makefile and
+run `make clean; make` or corresponding.
+
+To report a bug please open an issue on GitHub, at
+<https://github.com/openssl/openssl/issues>.
+
+Notes
+=====
+
+Notes on multi-threading
+------------------------
+
+For some systems, the OpenSSL `Configure` script knows what compiler options
+are needed to generate a library that is suitable for multi-threaded
+applications.  On these systems, support for multi-threading is enabled
+by default; use the `no-threads` option to disable (this should never be
+necessary).
+
+On other systems, to enable support for multi-threading, you will have
+to specify at least two options: `threads`, and a system-dependent option.
+(The latter is `-D_REENTRANT` on various systems.)  The default in this
+case, obviously, is not to include support for multi-threading (but
+you can still use `no-threads` to suppress an annoying warning message
+from the `Configure` script.)
+
+OpenSSL provides built-in support for two threading models: pthreads (found on
+most UNIX/Linux systems), and Windows threads.  No other threading models are
+supported.  If your platform does not provide pthreads or Windows threads then
+you should use `Configure` with the `no-threads` option.
+
+For pthreads, all locks are non-recursive. In addition, in a debug build,
+the mutex attribute `PTHREAD_MUTEX_ERRORCHECK` is used. If this is not
+available on your platform, you might have to add
+`-DOPENSSL_NO_MUTEX_ERRORCHECK` to your `Configure` invocation.
+(On Linux `PTHREAD_MUTEX_ERRORCHECK` is an enum value, so a built-in
+ifdef test cannot be used.)
+
+Notes on shared libraries
+-------------------------
+
+For most systems the OpenSSL `Configure` script knows what is needed to
+build shared libraries for libcrypto and libssl.  On these systems
+the shared libraries will be created by default.  This can be suppressed and
+only static libraries created by using the `no-shared` option.  On systems
+where OpenSSL does not know how to build shared libraries the `no-shared`
+option will be forced and only static libraries will be created.
+
+Shared libraries are named a little differently on different platforms.
+One way or another, they all have the major OpenSSL version number as
+part of the file name, i.e.  for OpenSSL 1.1.x, `1.1` is somehow part of
+the name.
+
+On most POSIX platforms, shared libraries are named `libcrypto.so.1.1`
+and `libssl.so.1.1`.
+
+on Cygwin, shared libraries are named `cygcrypto-1.1.dll` and `cygssl-1.1.dll`
+with import libraries `libcrypto.dll.a` and `libssl.dll.a`.
+
+On Windows build with MSVC or using MingW, shared libraries are named
+`libcrypto-1_1.dll` and `libssl-1_1.dll` for 32-bit Windows,
+`libcrypto-1_1-x64.dll` and `libssl-1_1-x64.dll` for 64-bit x86_64 Windows,
+and `libcrypto-1_1-ia64.dll` and `libssl-1_1-ia64.dll` for IA64 Windows.
+With MSVC, the import libraries are named `libcrypto.lib` and `libssl.lib`,
+while with MingW, they are named `libcrypto.dll.a` and `libssl.dll.a`.
+
+On VMS, shareable images (VMS speak for shared libraries) are named
+`ossl$libcrypto0101_shr.exe` and `ossl$libssl0101_shr.exe`.  However, when
+OpenSSL is specifically built for 32-bit pointers, the shareable images
+are named `ossl$libcrypto0101_shr32.exe` and `ossl$libssl0101_shr32.exe`
+instead, and when built for 64-bit pointers, they are named
+`ossl$libcrypto0101_shr64.exe` and `ossl$libssl0101_shr64.exe`.
+
+Notes on random number generation
+---------------------------------
+
+Availability of cryptographically secure random numbers is required for
+secret key generation.  OpenSSL provides several options to seed the
+internal CSPRNG.  If not properly seeded, the internal CSPRNG will refuse
+to deliver random bytes and a "PRNG not seeded error" will occur.
+
+The seeding method can be configured using the `--with-rand-seed` option,
+which can be used to specify a comma separated list of seed methods.
+However, in most cases OpenSSL will choose a suitable default method,
+so it is not necessary to explicitly provide this option.  Note also
+that not all methods are available on all platforms.  The FIPS provider will
+silently ignore seed sources that were not validated.
+
+I) On operating systems which provide a suitable randomness source (in
+form  of a system call or system device), OpenSSL will use the optimal
+available  method to seed the CSPRNG from the operating system's
+randomness sources.  This corresponds to the option `--with-rand-seed=os`.
+
+II) On systems without such a suitable randomness source, automatic seeding
+and reseeding is disabled (`--with-rand-seed=none`) and it may be necessary
+to install additional support software to obtain a random seed and reseed
+the CSPRNG manually.  Please check out the manual pages for `RAND_add()`,
+`RAND_bytes()`, `RAND_egd()`, and the FAQ for more information.
+
+Notes on assembler modules compilation
+--------------------------------------
+
+Compilation of some code paths in assembler modules might depend on whether the
+current assembler version supports certain ISA extensions or not. Code paths
+that use the AES-NI, PCLMULQDQ, SSSE3, and SHA extensions are always assembled.
+Apart from that, the minimum requirements for the assembler versions are shown
+in the table below:
+
+| ISA extension | GNU as | nasm   | llvm    |
+|---------------|--------|--------|---------|
+| AVX           | 2.19   | 2.09   | 3.0     |
+| AVX2          | 2.22   | 2.10   | 3.1     |
+| ADCX/ADOX     | 2.23   | 2.10   | 3.3     |
+| AVX512        | 2.25   | 2.11.8 | 3.6 (*) |
+| AVX512IFMA    | 2.26   | 2.11.8 | 6.0 (*) |
+| VAES          | 2.30   | 2.13.3 | 6.0 (*) |
+
+---
+
+(*) Even though AVX512 support was implemented in llvm 3.6, prior to version 7.0
+an explicit -march flag was apparently required to compile assembly modules. But
+then the compiler generates processor-specific code, which in turn contradicts
+the idea of performing dispatch at run-time, which is facilitated by the special
+variable `OPENSSL_ia32cap`. For versions older than 7.0, it is possible to work
+around the problem by forcing the build procedure to use the following script:
+
+    #!/bin/sh
+    exec clang -no-integrated-as "$@"
+
+instead of the real clang. In which case it doesn't matter what clang version
+is used, as it is the version of the GNU assembler that will be checked.
+
+---
+
+<!-- Links  -->
+
+[openssl-users]:
+    <https://mta.openssl.org/mailman/listinfo/openssl-users>
+
+[SUPPORT]:
+    ./SUPPORT.md
+
+[GitHub Issues]:
+    <https://github.com/openssl/openssl/issues>
+
+[raise an issue]:
+    <https://github.com/openssl/openssl/issues/new/choose>
+
+[10-main.conf]:
+    Configurations/10-main.conf

+ 0 - 125
libs/openssl/LICENSE

@@ -1,125 +0,0 @@
-
-  LICENSE ISSUES
-  ==============
-
-  The OpenSSL toolkit stays under a double license, i.e. both the conditions of
-  the OpenSSL License and the original SSLeay license apply to the toolkit.
-  See below for the actual license texts.
-
-  OpenSSL License
-  ---------------
-
-/* ====================================================================
- * Copyright (c) 1998-2019 The OpenSSL Project.  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.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    [email protected].
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED 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 OpenSSL PROJECT OR
- * ITS 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.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * ([email protected]).  This product includes software written by Tim
- * Hudson ([email protected]).
- *
- */
-
- Original SSLeay License
- -----------------------
-
-/* Copyright (C) 1995-1998 Eric Young ([email protected])
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young ([email protected]).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson ([email protected]).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * 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 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young ([email protected])"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson ([email protected])"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-

+ 177 - 0
libs/openssl/LICENSE.txt

@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        https://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS

+ 93 - 0
libs/openssl/SUPPORT.md

@@ -0,0 +1,93 @@
+OpenSSL User Support resources
+==============================
+
+See the <https://www.openssl.org/support/contracts.html> for details on how to
+obtain commercial technical support.
+
+If you have general questions about using OpenSSL
+-------------------------------------------------
+
+In this case the [openssl-users] mailing list is the right place for you.
+The list is not only watched by the OpenSSL team members, but also by many
+other OpenSSL users. Here you will most likely get the answer to your questions.
+An overview over the [mailing lists](#mailing-lists) can be found below.
+
+If you think you found a Bug
+----------------------------
+
+*NOTE: this section assumes that you want to report it or figure it out and
+fix it.  What's written here is not to be taken as a recipe for how to get a
+working production installation*
+
+If you have any problems with OpenSSL then please take the following steps
+first:
+
+- Search the mailing lists and/or the GitHub issues to find out whether
+  the problem has already been reported.
+- Download the latest version from the repository to see if the problem
+  has already been addressed.
+- Configure without assembler support (`no-asm`) and check whether the
+  problem persists.
+- Remove compiler optimization flags.
+
+Please keep in mind: Just because something doesn't work the way you expect
+does not mean it is necessarily a bug in OpenSSL. If you are not sure,
+consider searching the mail archives and posting a question to the
+[openssl-users] mailing list first.
+
+### Open an Issue
+
+If you wish to report a bug, please open an [issue][github-issues] on GitHub
+and include the following information:
+
+- OpenSSL version: output of `openssl version -a`
+- Configuration data: output of `perl configdata.pm --dump`
+- OS Name, Version, Hardware platform
+- Compiler Details (name, version)
+- Application Details (name, version)
+- Problem Description (steps that will reproduce the problem, if known)
+- Stack Traceback (if the application dumps core)
+
+Not only errors in the software, also errors in the documentation, in
+particular the manual pages, can be reported as issues.
+
+### Submit a Pull Request
+
+The fastest way to get a bug fixed is to fix it yourself ;-). If you are
+experienced in programming and know how to fix the bug, you can open a
+pull request. The details are covered in the [Contributing][contributing] section.
+
+Don't hesitate to open a pull request, even if it's only a small change
+like a grammatical or typographical error in the documentation.
+
+Mailing Lists
+=============
+
+The OpenSSL maintains a number of [mailing lists] for various purposes.
+The most important lists are:
+
+- [openssl-users]    for general questions about using the OpenSSL software
+                     and discussions between OpenSSL users.
+
+- [openssl-announce] for official announcements to the OpenSSL community.
+
+- [openssl-project]  for discussion about the development roadmap
+                     and governance.
+
+Only subscribers can post to [openssl-users] or [openssl-project].  The
+archives are made public, however.  For more information, see the [mailing
+lists] page.
+
+There was an [openssl-dev] list that has been discontinued since development
+is now taking place in the form of GitHub pull requests. Although not active
+anymore, the searchable archive may still contain useful information.
+
+<!-- Links -->
+
+[mailing lists]:     https://www.openssl.org/community/mailinglists.html
+[openssl-users]:     https://mta.openssl.org/mailman/listinfo/openssl-users
+[openssl-announce]:  https://mta.openssl.org/mailman/listinfo/openssl-announce
+[openssl-project]:   https://mta.openssl.org/mailman/listinfo/openssl-project
+[openssl-dev]:       https://mta.openssl.org/mailman/listinfo/openssl-dev
+[github-issues]:     https://github.com/openssl/openssl/issues/new/choose
+[contributing]:      https://github.com/openssl/openssl/blob/master/CONTRIBUTING.md

+ 7 - 0
libs/openssl/VERSION.dat

@@ -0,0 +1,7 @@
+MAJOR=3
+MINOR=1
+PATCH=0
+PRE_RELEASE_TAG=
+BUILD_METADATA=
+RELEASE_DATE="14 Mar 2023"
+SHLIB_VERSION=3

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

@@ -1,7 +1,7 @@
 /*
  * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

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

@@ -1,7 +1,7 @@
 /*
  * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 9 - 2
libs/openssl/crypto/aes/aes_cbc.c

@@ -1,12 +1,19 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
 #include <openssl/aes.h>
 #include <openssl/modes.h>
 

+ 8 - 2
libs/openssl/crypto/aes/aes_cfb.c

@@ -1,12 +1,18 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * AES_encrypt is deprecated - but we need to use it to implement these other
+ * deprecated APIs.
+ */
+#include "internal/deprecated.h"
+
 #include <openssl/aes.h>
 #include <openssl/modes.h>
 

+ 160 - 144
libs/openssl/crypto/aes/aes_core.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -36,6 +36,13 @@
 /* Note: rewritten a little bit to provide error control and an OpenSSL-
    compatible API */
 
+/*
+ * AES low level APIs are deprecated for public use, but still ok for internal
+ * use where we're using them to implement the higher level EVP interface, as is
+ * the case here.
+ */
+#include "internal/deprecated.h"
+
 #include <assert.h>
 
 #include <stdlib.h>
@@ -44,6 +51,15 @@
 #include "aes_local.h"
 
 #if defined(OPENSSL_AES_CONST_TIME) && !defined(AES_ASM)
+
+# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+#  define U64(C) C##UI64
+# elif defined(__arch64__)
+#  define U64(C) C##UL
+# else
+#  define U64(C) C##ULL
+# endif
+
 typedef union {
     unsigned char b[8];
     u32 w[2];
@@ -72,10 +88,10 @@ static void XtimeLong(u64 *w)
     u64 a, b;
 
     a = *w;
-    b = a & 0x8080808080808080uLL;
+    b = a & U64(0x8080808080808080);
     a ^= b;
     b -= b >> 7;
-    b &= 0x1B1B1B1B1B1B1B1BuLL;
+    b &= U64(0x1B1B1B1B1B1B1B1B);
     b ^= a << 1;
     *w = b;
 }
@@ -222,89 +238,89 @@ static void SubLong(u64 *w)
     u64 x, y, a1, a2, a3, a4, a5, a6;
 
     x = *w;
-    y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
-    x &= 0xDDDDDDDDDDDDDDDDuLL;
-    x ^= y & 0x5757575757575757uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x1C1C1C1C1C1C1C1CuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x4A4A4A4A4A4A4A4AuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x4242424242424242uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x6464646464646464uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xE0E0E0E0E0E0E0E0uLL;
+    y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+    x &= U64(0xDDDDDDDDDDDDDDDD);
+    x ^= y & U64(0x5757575757575757);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x1C1C1C1C1C1C1C1C);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x4A4A4A4A4A4A4A4A);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x4242424242424242);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x6464646464646464);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xE0E0E0E0E0E0E0E0);
     a1 = x;
-    a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4;
-    a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2);
+    a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4;
+    a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2);
     a3 = x & a1;
-    a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL;
+    a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA);
     a4 = a2 & a1;
-    a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
-    a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
-    a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
-    a4 = a5 & 0x2222222222222222uLL;
+    a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+    a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+    a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+    a4 = a5 & U64(0x2222222222222222);
     a4 |= a4 >> 1;
-    a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+    a4 ^= (a5 << 1) & U64(0x2222222222222222);
     a3 ^= a4;
-    a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL;
+    a5 = a3 & U64(0xA0A0A0A0A0A0A0A0);
     a5 |= a5 >> 1;
-    a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL;
-    a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL;
+    a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0);
+    a4 = a5 & U64(0xC0C0C0C0C0C0C0C0);
     a6 = a4 >> 2;
-    a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL;
-    a5 = a6 & 0x2020202020202020uLL;
+    a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0);
+    a5 = a6 & U64(0x2020202020202020);
     a5 |= a5 >> 1;
-    a5 ^= (a6 << 1) & 0x2020202020202020uLL;
+    a5 ^= (a6 << 1) & U64(0x2020202020202020);
     a4 |= a5;
     a3 ^= a4 >> 4;
-    a3 &= 0x0F0F0F0F0F0F0F0FuLL;
+    a3 &= U64(0x0F0F0F0F0F0F0F0F);
     a2 = a3;
-    a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2;
+    a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2;
     a4 = a3 & a2;
-    a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
-    a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL;
-    a5 = a4 & 0x0808080808080808uLL;
+    a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+    a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A);
+    a5 = a4 & U64(0x0808080808080808);
     a5 |= a5 >> 1;
-    a5 ^= (a4 << 1) & 0x0808080808080808uLL;
+    a5 ^= (a4 << 1) & U64(0x0808080808080808);
     a4 ^= a5 >> 2;
-    a4 &= 0x0303030303030303uLL;
-    a4 ^= (a4 & 0x0202020202020202uLL) >> 1;
+    a4 &= U64(0x0303030303030303);
+    a4 ^= (a4 & U64(0x0202020202020202)) >> 1;
     a4 |= a4 << 2;
     a3 = a2 & a4;
-    a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
-    a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL;
+    a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+    a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A);
     a3 |= a3 << 4;
-    a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2);
+    a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2);
     x = a1 & a3;
-    x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL;
+    x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA);
     a4 = a2 & a3;
-    a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
-    a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
-    x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
-    a4 = a5 & 0x2222222222222222uLL;
+    a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+    a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+    x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+    a4 = a5 & U64(0x2222222222222222);
     a4 |= a4 >> 1;
-    a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+    a4 ^= (a5 << 1) & U64(0x2222222222222222);
     x ^= a4;
-    y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
-    x &= 0x3939393939393939uLL;
-    x ^= y & 0x3F3F3F3F3F3F3F3FuLL;
-    y = ((y & 0xFCFCFCFCFCFCFCFCuLL) >> 2) | ((y & 0x0303030303030303uLL) << 6);
-    x ^= y & 0x9797979797979797uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x9B9B9B9B9B9B9B9BuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x3C3C3C3C3C3C3C3CuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xDDDDDDDDDDDDDDDDuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x7272727272727272uLL;
-    x ^= 0x6363636363636363uLL;
+    y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+    x &= U64(0x3939393939393939);
+    x ^= y & U64(0x3F3F3F3F3F3F3F3F);
+    y = ((y & U64(0xFCFCFCFCFCFCFCFC)) >> 2) | ((y & U64(0x0303030303030303)) << 6);
+    x ^= y & U64(0x9797979797979797);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x9B9B9B9B9B9B9B9B);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x3C3C3C3C3C3C3C3C);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xDDDDDDDDDDDDDDDD);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x7272727272727272);
+    x ^= U64(0x6363636363636363);
     *w = x;
 }
 
@@ -316,93 +332,93 @@ static void InvSubLong(u64 *w)
     u64 x, y, a1, a2, a3, a4, a5, a6;
 
     x = *w;
-    x ^= 0x6363636363636363uLL;
-    y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
-    x &= 0xFDFDFDFDFDFDFDFDuLL;
-    x ^= y & 0x5E5E5E5E5E5E5E5EuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xF3F3F3F3F3F3F3F3uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xF5F5F5F5F5F5F5F5uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x7878787878787878uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x7777777777777777uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x1515151515151515uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xA5A5A5A5A5A5A5A5uLL;
+    x ^= U64(0x6363636363636363);
+    y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+    x &= U64(0xFDFDFDFDFDFDFDFD);
+    x ^= y & U64(0x5E5E5E5E5E5E5E5E);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xF3F3F3F3F3F3F3F3);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xF5F5F5F5F5F5F5F5);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x7878787878787878);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x7777777777777777);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x1515151515151515);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xA5A5A5A5A5A5A5A5);
     a1 = x;
-    a1 ^= (x & 0xF0F0F0F0F0F0F0F0uLL) >> 4;
-    a2 = ((x & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((x & 0x3333333333333333uLL) << 2);
+    a1 ^= (x & U64(0xF0F0F0F0F0F0F0F0)) >> 4;
+    a2 = ((x & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((x & U64(0x3333333333333333)) << 2);
     a3 = x & a1;
-    a3 ^= (a3 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & 0xAAAAAAAAAAAAAAAAuLL;
+    a3 ^= (a3 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a3 ^= (((x << 1) & a1) ^ ((a1 << 1) & x)) & U64(0xAAAAAAAAAAAAAAAA);
     a4 = a2 & a1;
-    a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
-    a5 = (a3 & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
-    a3 ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
-    a4 = a5 & 0x2222222222222222uLL;
+    a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a4 ^= (((a2 << 1) & a1) ^ ((a1 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+    a5 = (a3 & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+    a3 ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+    a4 = a5 & U64(0x2222222222222222);
     a4 |= a4 >> 1;
-    a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+    a4 ^= (a5 << 1) & U64(0x2222222222222222);
     a3 ^= a4;
-    a5 = a3 & 0xA0A0A0A0A0A0A0A0uLL;
+    a5 = a3 & U64(0xA0A0A0A0A0A0A0A0);
     a5 |= a5 >> 1;
-    a5 ^= (a3 << 1) & 0xA0A0A0A0A0A0A0A0uLL;
-    a4 = a5 & 0xC0C0C0C0C0C0C0C0uLL;
+    a5 ^= (a3 << 1) & U64(0xA0A0A0A0A0A0A0A0);
+    a4 = a5 & U64(0xC0C0C0C0C0C0C0C0);
     a6 = a4 >> 2;
-    a4 ^= (a5 << 2) & 0xC0C0C0C0C0C0C0C0uLL;
-    a5 = a6 & 0x2020202020202020uLL;
+    a4 ^= (a5 << 2) & U64(0xC0C0C0C0C0C0C0C0);
+    a5 = a6 & U64(0x2020202020202020);
     a5 |= a5 >> 1;
-    a5 ^= (a6 << 1) & 0x2020202020202020uLL;
+    a5 ^= (a6 << 1) & U64(0x2020202020202020);
     a4 |= a5;
     a3 ^= a4 >> 4;
-    a3 &= 0x0F0F0F0F0F0F0F0FuLL;
+    a3 &= U64(0x0F0F0F0F0F0F0F0F);
     a2 = a3;
-    a2 ^= (a3 & 0x0C0C0C0C0C0C0C0CuLL) >> 2;
+    a2 ^= (a3 & U64(0x0C0C0C0C0C0C0C0C)) >> 2;
     a4 = a3 & a2;
-    a4 ^= (a4 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
-    a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & 0x0A0A0A0A0A0A0A0AuLL;
-    a5 = a4 & 0x0808080808080808uLL;
+    a4 ^= (a4 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+    a4 ^= (((a3 << 1) & a2) ^ ((a2 << 1) & a3)) & U64(0x0A0A0A0A0A0A0A0A);
+    a5 = a4 & U64(0x0808080808080808);
     a5 |= a5 >> 1;
-    a5 ^= (a4 << 1) & 0x0808080808080808uLL;
+    a5 ^= (a4 << 1) & U64(0x0808080808080808);
     a4 ^= a5 >> 2;
-    a4 &= 0x0303030303030303uLL;
-    a4 ^= (a4 & 0x0202020202020202uLL) >> 1;
+    a4 &= U64(0x0303030303030303);
+    a4 ^= (a4 & U64(0x0202020202020202)) >> 1;
     a4 |= a4 << 2;
     a3 = a2 & a4;
-    a3 ^= (a3 & 0x0A0A0A0A0A0A0A0AuLL) >> 1;
-    a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & 0x0A0A0A0A0A0A0A0AuLL;
+    a3 ^= (a3 & U64(0x0A0A0A0A0A0A0A0A)) >> 1;
+    a3 ^= (((a2 << 1) & a4) ^ ((a4 << 1) & a2)) & U64(0x0A0A0A0A0A0A0A0A);
     a3 |= a3 << 4;
-    a2 = ((a1 & 0xCCCCCCCCCCCCCCCCuLL) >> 2) | ((a1 & 0x3333333333333333uLL) << 2);
+    a2 = ((a1 & U64(0xCCCCCCCCCCCCCCCC)) >> 2) | ((a1 & U64(0x3333333333333333)) << 2);
     x = a1 & a3;
-    x ^= (x & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & 0xAAAAAAAAAAAAAAAAuLL;
+    x ^= (x & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    x ^= (((a1 << 1) & a3) ^ ((a3 << 1) & a1)) & U64(0xAAAAAAAAAAAAAAAA);
     a4 = a2 & a3;
-    a4 ^= (a4 & 0xAAAAAAAAAAAAAAAAuLL) >> 1;
-    a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & 0xAAAAAAAAAAAAAAAAuLL;
-    a5 = (x & 0xCCCCCCCCCCCCCCCCuLL) >> 2;
-    x ^= ((a4 << 2) ^ a4) & 0xCCCCCCCCCCCCCCCCuLL;
-    a4 = a5 & 0x2222222222222222uLL;
+    a4 ^= (a4 & U64(0xAAAAAAAAAAAAAAAA)) >> 1;
+    a4 ^= (((a2 << 1) & a3) ^ ((a3 << 1) & a2)) & U64(0xAAAAAAAAAAAAAAAA);
+    a5 = (x & U64(0xCCCCCCCCCCCCCCCC)) >> 2;
+    x ^= ((a4 << 2) ^ a4) & U64(0xCCCCCCCCCCCCCCCC);
+    a4 = a5 & U64(0x2222222222222222);
     a4 |= a4 >> 1;
-    a4 ^= (a5 << 1) & 0x2222222222222222uLL;
+    a4 ^= (a5 << 1) & U64(0x2222222222222222);
     x ^= a4;
-    y = ((x & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((x & 0x0101010101010101uLL) << 7);
-    x &= 0xB5B5B5B5B5B5B5B5uLL;
-    x ^= y & 0x4040404040404040uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x8080808080808080uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x1616161616161616uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xEBEBEBEBEBEBEBEBuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x9797979797979797uLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0xFBFBFBFBFBFBFBFBuLL;
-    y = ((y & 0xFEFEFEFEFEFEFEFEuLL) >> 1) | ((y & 0x0101010101010101uLL) << 7);
-    x ^= y & 0x7D7D7D7D7D7D7D7DuLL;
+    y = ((x & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((x & U64(0x0101010101010101)) << 7);
+    x &= U64(0xB5B5B5B5B5B5B5B5);
+    x ^= y & U64(0x4040404040404040);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x8080808080808080);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x1616161616161616);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xEBEBEBEBEBEBEBEB);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x9797979797979797);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0xFBFBFBFBFBFBFBFB);
+    y = ((y & U64(0xFEFEFEFEFEFEFEFE)) >> 1) | ((y & U64(0x0101010101010101)) << 7);
+    x ^= y & U64(0x7D7D7D7D7D7D7D7D);
     *w = x;
 }
 
@@ -453,10 +469,10 @@ static void MixColumns(u64 *state)
     for (c = 0; c < 2; c++) {
         s1.d = state[c];
         s.d = s1.d;
-        s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16)
-               | ((s.d & 0x0000FFFF0000FFFFuLL) << 16);
-        s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8)
-               | ((s.d & 0x00FF00FF00FF00FFuLL) << 8);
+        s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16)
+               | ((s.d & U64(0x0000FFFF0000FFFF)) << 16);
+        s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8)
+               | ((s.d & U64(0x00FF00FF00FF00FF)) << 8);
         s.d ^= s1.d;
         XtimeLong(&s1.d);
         s.d ^= s1.d;
@@ -481,10 +497,10 @@ static void InvMixColumns(u64 *state)
     for (c = 0; c < 2; c++) {
         s1.d = state[c];
         s.d = s1.d;
-        s.d ^= ((s.d & 0xFFFF0000FFFF0000uLL) >> 16)
-               | ((s.d & 0x0000FFFF0000FFFFuLL) << 16);
-        s.d ^= ((s.d & 0xFF00FF00FF00FF00uLL) >> 8)
-               | ((s.d & 0x00FF00FF00FF00FFuLL) << 8);
+        s.d ^= ((s.d & U64(0xFFFF0000FFFF0000)) >> 16)
+               | ((s.d & U64(0x0000FFFF0000FFFF)) << 16);
+        s.d ^= ((s.d & U64(0xFF00FF00FF00FF00)) >> 8)
+               | ((s.d & U64(0x00FF00FF00FF00FF)) << 8);
         s.d ^= s1.d;
         XtimeLong(&s1.d);
         s.d ^= s1.d;
@@ -497,12 +513,12 @@ static void InvMixColumns(u64 *state)
         s.b[6] ^= s1.b[7];
         s.b[7] ^= s1.b[4];
         XtimeLong(&s1.d);
-        s1.d ^= ((s1.d & 0xFFFF0000FFFF0000uLL) >> 16)
-                | ((s1.d & 0x0000FFFF0000FFFFuLL) << 16);
+        s1.d ^= ((s1.d & U64(0xFFFF0000FFFF0000)) >> 16)
+                | ((s1.d & U64(0x0000FFFF0000FFFF)) << 16);
         s.d ^= s1.d;
         XtimeLong(&s1.d);
-        s1.d ^= ((s1.d & 0xFF00FF00FF00FF00uLL) >> 8)
-                | ((s1.d & 0x00FF00FF00FF00FFuLL) << 8);
+        s1.d ^= ((s1.d & U64(0xFF00FF00FF00FF00)) >> 8)
+                | ((s1.d & U64(0x00FF00FF00FF00FF)) << 8);
         s.d ^= s1.d;
         state[c] = s.d;
     }

+ 8 - 2
libs/openssl/crypto/aes/aes_ecb.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -9,6 +9,12 @@
 
 #include <assert.h>
 
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * AES_ecb_encrypt
+ */
+#include "internal/deprecated.h"
+
 #include <openssl/aes.h>
 #include "aes_local.h"
 

+ 17 - 4
libs/openssl/crypto/aes/aes_ige.c

@@ -1,12 +1,18 @@
 /*
  * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * these functions
+ */
+#include "internal/deprecated.h"
+
 #include "internal/cryptlib.h"
 
 #include <openssl/aes.h>
@@ -38,12 +44,13 @@ typedef struct {
 
 /* N.B. The IV for this mode is _twice_ the block size */
 
+/*  Use of this function is deprecated. */
 void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
                      size_t length, const AES_KEY *key,
                      unsigned char *ivec, const int enc)
 {
     size_t n;
-    size_t len = length;
+    size_t len = length / AES_BLOCK_SIZE;
 
     if (length == 0)
         return;
@@ -52,8 +59,6 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
 
-    len = length / AES_BLOCK_SIZE;
-
     if (AES_ENCRYPT == enc) {
         if (in != out &&
             (UNALIGNED_MEMOPS_ARE_FAST
@@ -166,6 +171,14 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
 /*
  * Note that its effectively impossible to do biIGE in anything other
  * than a single pass, so no provision is made for chaining.
+ *
+ * NB: The implementation of AES_bi_ige_encrypt has a bug. It is supposed to use
+ * 2 AES keys, but in fact only one is ever used. This bug has been present
+ * since this code was first implemented. It is believed to have minimal
+ * security impact in practice and has therefore not been fixed for backwards
+ * compatibility reasons.
+ *
+ * Use of this function is deprecated.
  */
 
 /* N.B. The IV for this mode is _four times_ the block size */

+ 3 - 3
libs/openssl/crypto/aes/aes_local.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -24,7 +24,7 @@
 #  define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
 # endif
 
-typedef unsigned long long u64;
+typedef uint64_t u64;
 # ifdef AES_LONG
 typedef unsigned long u32;
 # else

+ 7 - 5
libs/openssl/crypto/aes/aes_misc.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -11,11 +11,13 @@
 #include <openssl/aes.h>
 #include "aes_local.h"
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 const char *AES_options(void)
 {
-#ifdef FULL_UNROLL
+# ifdef FULL_UNROLL
     return "aes(full)";
-#else
+# else
     return "aes(partial)";
-#endif
+# endif
 }
+#endif

+ 8 - 2
libs/openssl/crypto/aes/aes_ofb.c

@@ -1,12 +1,18 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * AES_encrypt is deprecated - but we need to use it to implement
+ * AES_ofb128_encrypt
+ */
+#include "internal/deprecated.h"
+
 #include <openssl/aes.h>
 #include <openssl/modes.h>
 

+ 8 - 2
libs/openssl/crypto/aes/aes_wrap.c

@@ -1,12 +1,18 @@
 /*
- * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * AES_encrypt/AES_decrypt are deprecated - but we need to use them to implement
+ * these functions
+ */
+#include "internal/deprecated.h"
+
 #include "internal/cryptlib.h"
 #include <openssl/aes.h>
 #include <openssl/modes.h>

+ 2998 - 0
libs/openssl/crypto/aes/asm/aes-586.pl

@@ -0,0 +1,2998 @@
+#! /usr/bin/env perl
+# Copyright 2004-2020 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <[email protected]> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# Version 4.3.
+#
+# You might fail to appreciate this module performance from the first
+# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered
+# to be *the* best Intel C compiler without -KPIC, performance appears
+# to be virtually identical... But try to re-configure with shared
+# library support... Aha! Intel compiler "suddenly" lags behind by 30%
+# [on P4, more on others]:-) And if compared to position-independent
+# code generated by GNU C, this code performs *more* than *twice* as
+# fast! Yes, all this buzz about PIC means that unlike other hand-
+# coded implementations, this one was explicitly designed to be safe
+# to use even in shared library context... This also means that this
+# code isn't necessarily absolutely fastest "ever," because in order
+# to achieve position independence an extra register has to be
+# off-loaded to stack, which affects the benchmark result.
+#
+# Special note about instruction choice. Do you recall RC4_INT code
+# performing poorly on P4? It might be the time to figure out why.
+# RC4_INT code implies effective address calculations in base+offset*4
+# form. Trouble is that it seems that offset scaling turned to be
+# critical path... At least eliminating scaling resulted in 2.8x RC4
+# performance improvement [as you might recall]. As AES code is hungry
+# for scaling too, I [try to] avoid the latter by favoring off-by-2
+# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
+#
+# As was shown by Dean Gaudet, the above note turned out to be
+# void. Performance improvement with off-by-2 shifts was observed on
+# intermediate implementation, which was spilling yet another register
+# to stack... Final offset*4 code below runs just a tad faster on P4,
+# but exhibits up to 10% improvement on other cores.
+#
+# Second version is "monolithic" replacement for aes_core.c, which in
+# addition to AES_[de|en]crypt implements AES_set_[de|en]cryption_key.
+# This made it possible to implement little-endian variant of the
+# algorithm without modifying the base C code. Motivating factor for
+# the undertaken effort was that it appeared that in tight IA-32
+# register window little-endian flavor could achieve slightly higher
+# Instruction Level Parallelism, and it indeed resulted in up to 15%
+# better performance on most recent µ-archs...
+#
+# Third version adds AES_cbc_encrypt implementation, which resulted in
+# up to 40% performance improvement of CBC benchmark results. 40% was
+# observed on P4 core, where "overall" improvement coefficient, i.e. if
+# compared to PIC generated by GCC and in CBC mode, was observed to be
+# as large as 4x:-) CBC performance is virtually identical to ECB now
+# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
+# Opteron, because certain function prologues and epilogues are
+# effectively taken out of the loop...
+#
+# Version 3.2 implements compressed tables and prefetch of these tables
+# in CBC[!] mode. Former means that 3/4 of table references are now
+# misaligned, which unfortunately has negative impact on elder IA-32
+# implementations, Pentium suffered 30% penalty, PIII - 10%.
+#
+# Version 3.3 avoids L1 cache aliasing between stack frame and
+# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The
+# latter is achieved by copying the key schedule to controlled place in
+# stack. This unfortunately has rather strong impact on small block CBC
+# performance, ~2x deterioration on 16-byte block if compared to 3.3.
+#
+# Version 3.5 checks if there is L1 cache aliasing between user-supplied
+# key schedule and S-boxes and abstains from copying the former if
+# there is no. This allows end-user to consciously retain small block
+# performance by aligning key schedule in specific manner.
+#
+# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB.
+#
+# Current ECB performance numbers for 128-bit key in CPU cycles per
+# processed byte [measure commonly used by AES benchmarkers] are:
+#
+#		small footprint		fully unrolled
+# P4		24			22
+# AMD K8	20			19
+# PIII		25			23
+# Pentium	81			78
+#
+# Version 3.7 reimplements outer rounds as "compact." Meaning that
+# first and last rounds reference compact 256 bytes S-box. This means
+# that first round consumes a lot more CPU cycles and that encrypt
+# and decrypt performance becomes asymmetric. Encrypt performance
+# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is
+# aggressively pre-fetched.
+#
+# Version 4.0 effectively rolls back to 3.6 and instead implements
+# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact,
+# which use exclusively 256 byte S-box. These functions are to be
+# called in modes not concealing plain text, such as ECB, or when
+# we're asked to process smaller amount of data [or unconditionally
+# on hyper-threading CPU]. Currently it's called unconditionally from
+# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine
+# still needs to be modified to switch between slower and faster
+# mode when appropriate... But in either case benchmark landscape
+# changes dramatically and below numbers are CPU cycles per processed
+# byte for 128-bit key.
+#
+#		ECB encrypt	ECB decrypt	CBC large chunk
+# P4		52[54]		83[95]		23
+# AMD K8	46[41]		66[70]		18
+# PIII		41[50]		60[77]		24
+# Core 2	31[36]		45[64]		18.5
+# Atom		76[100]		96[138]		60
+# Pentium	115		150		77
+#
+# Version 4.1 switches to compact S-box even in key schedule setup.
+#
+# Version 4.2 prefetches compact S-box in every SSE round or in other
+# words every cache-line is *guaranteed* to be accessed within ~50
+# cycles window. Why just SSE? Because it's needed on hyper-threading
+# CPU! Which is also why it's prefetched with 64 byte stride. Best
+# part is that it has no negative effect on performance:-)
+#
+# Version 4.3 implements switch between compact and non-compact block
+# functions in AES_cbc_encrypt depending on how much data was asked
+# to be processed in one stroke.
+#
+######################################################################
+# Timing attacks are classified in two classes: synchronous when
+# attacker consciously initiates cryptographic operation and collects
+# timing data of various character afterwards, and asynchronous when
+# malicious code is executed on same CPU simultaneously with AES,
+# instruments itself and performs statistical analysis of this data.
+#
+# As far as synchronous attacks go the root to the AES timing
+# vulnerability is twofold. Firstly, of 256 S-box elements at most 160
+# are referred to in single 128-bit block operation. Well, in C
+# implementation with 4 distinct tables it's actually as little as 40
+# references per 256 elements table, but anyway... Secondly, even
+# though S-box elements are clustered into smaller amount of cache-
+# lines, smaller than 160 and even 40, it turned out that for certain
+# plain-text pattern[s] or simply put chosen plain-text and given key
+# few cache-lines remain unaccessed during block operation. Now, if
+# attacker can figure out this access pattern, he can deduct the key
+# [or at least part of it]. The natural way to mitigate this kind of
+# attacks is to minimize the amount of cache-lines in S-box and/or
+# prefetch them to ensure that every one is accessed for more uniform
+# timing. But note that *if* plain-text was concealed in such way that
+# input to block function is distributed *uniformly*, then attack
+# wouldn't apply. Now note that some encryption modes, most notably
+# CBC, do mask the plain-text in this exact way [secure cipher output
+# is distributed uniformly]. Yes, one still might find input that
+# would reveal the information about given key, but if amount of
+# candidate inputs to be tried is larger than amount of possible key
+# combinations then attack becomes infeasible. This is why revised
+# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk
+# of data is to be processed in one stroke. The current size limit of
+# 512 bytes is chosen to provide same [diminishingly low] probability
+# for cache-line to remain untouched in large chunk operation with
+# large S-box as for single block operation with compact S-box and
+# surely needs more careful consideration...
+#
+# As for asynchronous attacks. There are two flavours: attacker code
+# being interleaved with AES on hyper-threading CPU at *instruction*
+# level, and two processes time sharing single core. As for latter.
+# Two vectors. 1. Given that attacker process has higher priority,
+# yield execution to process performing AES just before timer fires
+# off the scheduler, immediately regain control of CPU and analyze the
+# cache state. For this attack to be efficient attacker would have to
+# effectively slow down the operation by several *orders* of magnitude,
+# by ratio of time slice to duration of handful of AES rounds, which
+# unlikely to remain unnoticed. Not to mention that this also means
+# that he would spend correspondingly more time to collect enough
+# statistical data to mount the attack. It's probably appropriate to
+# say that if adversary reckons that this attack is beneficial and
+# risks to be noticed, you probably have larger problems having him
+# mere opportunity. In other words suggested code design expects you
+# to preclude/mitigate this attack by overall system security design.
+# 2. Attacker manages to make his code interrupt driven. In order for
+# this kind of attack to be feasible, interrupt rate has to be high
+# enough, again comparable to duration of handful of AES rounds. But
+# is there interrupt source of such rate? Hardly, not even 1Gbps NIC
+# generates interrupts at such raging rate...
+#
+# And now back to the former, hyper-threading CPU or more specifically
+# Intel P4. Recall that asynchronous attack implies that malicious
+# code instruments itself. And naturally instrumentation granularity
+# has be noticeably lower than duration of codepath accessing S-box.
+# Given that all cache-lines are accessed during that time that is.
+# Current implementation accesses *all* cache-lines within ~50 cycles
+# window, which is actually *less* than RDTSC latency on Intel P4!
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+$output = pop and open STDOUT,">$output";
+
+&asm_init($ARGV[0],$x86only = $ARGV[$#ARGV] eq "386");
+&static_label("AES_Te");
+&static_label("AES_Td");
+
+$s0="eax";
+$s1="ebx";
+$s2="ecx";
+$s3="edx";
+$key="edi";
+$acc="esi";
+$tbl="ebp";
+
+# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated
+# by caller
+$__ra=&DWP(0,"esp");	# return address
+$__s0=&DWP(4,"esp");	# s0 backing store
+$__s1=&DWP(8,"esp");	# s1 backing store
+$__s2=&DWP(12,"esp");	# s2 backing store
+$__s3=&DWP(16,"esp");	# s3 backing store
+$__key=&DWP(20,"esp");	# pointer to key schedule
+$__end=&DWP(24,"esp");	# pointer to end of key schedule
+$__tbl=&DWP(28,"esp");	# %ebp backing store
+
+# stack frame layout in AES_[en|crypt] routines, which differs from
+# above by 4 and overlaps by %ebp backing store
+$_tbl=&DWP(24,"esp");
+$_esp=&DWP(28,"esp");
+
+sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
+
+$speed_limit=512;	# chunks smaller than $speed_limit are
+			# processed with compact routine in CBC mode
+$small_footprint=1;	# $small_footprint=1 code is ~5% slower [on
+			# recent µ-archs], but ~5 times smaller!
+			# I favor compact code to minimize cache
+			# contention and in hope to "collect" 5% back
+			# in real-life applications...
+
+$vertical_spin=0;	# shift "vertically" defaults to 0, because of
+			# its proof-of-concept status...
+# Note that there is no decvert(), as well as last encryption round is
+# performed with "horizontal" shifts. This is because this "vertical"
+# implementation [one which groups shifts on a given $s[i] to form a
+# "column," unlike "horizontal" one, which groups shifts on different
+# $s[i] to form a "row"] is work in progress. It was observed to run
+# few percents faster on Intel cores, but not AMD. On AMD K8 core it's
+# whole 12% slower:-( So we face a trade-off... Shall it be resolved
+# some day? Till then the code is considered experimental and by
+# default remains dormant...
+
+sub encvert()
+{ my ($te,@s) = @_;
+  my ($v0,$v1) = ($acc,$key);
+
+	&mov	($v0,$s[3]);				# copy s3
+	&mov	(&DWP(4,"esp"),$s[2]);			# save s2
+	&mov	($v1,$s[0]);				# copy s0
+	&mov	(&DWP(8,"esp"),$s[1]);			# save s1
+
+	&movz	($s[2],&HB($s[0]));
+	&and	($s[0],0xFF);
+	&mov	($s[0],&DWP(0,$te,$s[0],8));		# s0>>0
+	&shr	($v1,16);
+	&mov	($s[3],&DWP(3,$te,$s[2],8));		# s0>>8
+	&movz	($s[1],&HB($v1));
+	&and	($v1,0xFF);
+	&mov	($s[2],&DWP(2,$te,$v1,8));		# s0>>16
+	 &mov	($v1,$v0);
+	&mov	($s[1],&DWP(1,$te,$s[1],8));		# s0>>24
+
+	&and	($v0,0xFF);
+	&xor	($s[3],&DWP(0,$te,$v0,8));		# s3>>0
+	&movz	($v0,&HB($v1));
+	&shr	($v1,16);
+	&xor	($s[2],&DWP(3,$te,$v0,8));		# s3>>8
+	&movz	($v0,&HB($v1));
+	&and	($v1,0xFF);
+	&xor	($s[1],&DWP(2,$te,$v1,8));		# s3>>16
+	 &mov	($v1,&DWP(4,"esp"));			# restore s2
+	&xor	($s[0],&DWP(1,$te,$v0,8));		# s3>>24
+
+	&mov	($v0,$v1);
+	&and	($v1,0xFF);
+	&xor	($s[2],&DWP(0,$te,$v1,8));		# s2>>0
+	&movz	($v1,&HB($v0));
+	&shr	($v0,16);
+	&xor	($s[1],&DWP(3,$te,$v1,8));		# s2>>8
+	&movz	($v1,&HB($v0));
+	&and	($v0,0xFF);
+	&xor	($s[0],&DWP(2,$te,$v0,8));		# s2>>16
+	 &mov	($v0,&DWP(8,"esp"));			# restore s1
+	&xor	($s[3],&DWP(1,$te,$v1,8));		# s2>>24
+
+	&mov	($v1,$v0);
+	&and	($v0,0xFF);
+	&xor	($s[1],&DWP(0,$te,$v0,8));		# s1>>0
+	&movz	($v0,&HB($v1));
+	&shr	($v1,16);
+	&xor	($s[0],&DWP(3,$te,$v0,8));		# s1>>8
+	&movz	($v0,&HB($v1));
+	&and	($v1,0xFF);
+	&xor	($s[3],&DWP(2,$te,$v1,8));		# s1>>16
+	 &mov	($key,$__key);				# reincarnate v1 as key
+	&xor	($s[2],&DWP(1,$te,$v0,8));		# s1>>24
+}
+
+# Another experimental routine, which features "horizontal spin," but
+# eliminates one reference to stack. Strangely enough runs slower...
+sub enchoriz()
+{ my ($v0,$v1) = ($key,$acc);
+
+	&movz	($v0,&LB($s0));			#  3, 2, 1, 0*
+	&rotr	($s2,8);			#  8,11,10, 9
+	&mov	($v1,&DWP(0,$te,$v0,8));	#  0
+	&movz	($v0,&HB($s1));			#  7, 6, 5*, 4
+	&rotr	($s3,16);			# 13,12,15,14
+	&xor	($v1,&DWP(3,$te,$v0,8));	#  5
+	&movz	($v0,&HB($s2));			#  8,11,10*, 9
+	&rotr	($s0,16);			#  1, 0, 3, 2
+	&xor	($v1,&DWP(2,$te,$v0,8));	# 10
+	&movz	($v0,&HB($s3));			# 13,12,15*,14
+	&xor	($v1,&DWP(1,$te,$v0,8));	# 15, t[0] collected
+	&mov	($__s0,$v1);			# t[0] saved
+
+	&movz	($v0,&LB($s1));			#  7, 6, 5, 4*
+	&shr	($s1,16);			#  -, -, 7, 6
+	&mov	($v1,&DWP(0,$te,$v0,8));	#  4
+	&movz	($v0,&LB($s3));			# 13,12,15,14*
+	&xor	($v1,&DWP(2,$te,$v0,8));	# 14
+	&movz	($v0,&HB($s0));			#  1, 0, 3*, 2
+	&and	($s3,0xffff0000);		# 13,12, -, -
+	&xor	($v1,&DWP(1,$te,$v0,8));	#  3
+	&movz	($v0,&LB($s2));			#  8,11,10, 9*
+	&or	($s3,$s1);			# 13,12, 7, 6
+	&xor	($v1,&DWP(3,$te,$v0,8));	#  9, t[1] collected
+	&mov	($s1,$v1);			#  s[1]=t[1]
+
+	&movz	($v0,&LB($s0));			#  1, 0, 3, 2*
+	&shr	($s2,16);			#  -, -, 8,11
+	&mov	($v1,&DWP(2,$te,$v0,8));	#  2
+	&movz	($v0,&HB($s3));			# 13,12, 7*, 6
+	&xor	($v1,&DWP(1,$te,$v0,8));	#  7
+	&movz	($v0,&HB($s2));			#  -, -, 8*,11
+	&xor	($v1,&DWP(0,$te,$v0,8));	#  8
+	&mov	($v0,$s3);
+	&shr	($v0,24);			# 13
+	&xor	($v1,&DWP(3,$te,$v0,8));	# 13, t[2] collected
+
+	&movz	($v0,&LB($s2));			#  -, -, 8,11*
+	&shr	($s0,24);			#  1*
+	&mov	($s2,&DWP(1,$te,$v0,8));	# 11
+	&xor	($s2,&DWP(3,$te,$s0,8));	#  1
+	&mov	($s0,$__s0);			# s[0]=t[0]
+	&movz	($v0,&LB($s3));			# 13,12, 7, 6*
+	&shr	($s3,16);			#   ,  ,13,12
+	&xor	($s2,&DWP(2,$te,$v0,8));	#  6
+	&mov	($key,$__key);			# reincarnate v0 as key
+	&and	($s3,0xff);			#   ,  ,13,12*
+	&mov	($s3,&DWP(0,$te,$s3,8));	# 12
+	&xor	($s3,$s2);			# s[2]=t[3] collected
+	&mov	($s2,$v1);			# s[2]=t[2]
+}
+
+# More experimental code... SSE one... Even though this one eliminates
+# *all* references to stack, it's not faster...
+sub sse_encbody()
+{
+	&movz	($acc,&LB("eax"));		#  0
+	&mov	("ecx",&DWP(0,$tbl,$acc,8));	#  0
+	&pshufw	("mm2","mm0",0x0d);		#  7, 6, 3, 2
+	&movz	("edx",&HB("eax"));		#  1
+	&mov	("edx",&DWP(3,$tbl,"edx",8));	#  1
+	&shr	("eax",16);			#  5, 4
+
+	&movz	($acc,&LB("ebx"));		# 10
+	&xor	("ecx",&DWP(2,$tbl,$acc,8));	# 10
+	&pshufw	("mm6","mm4",0x08);		# 13,12, 9, 8
+	&movz	($acc,&HB("ebx"));		# 11
+	&xor	("edx",&DWP(1,$tbl,$acc,8));	# 11
+	&shr	("ebx",16);			# 15,14
+
+	&movz	($acc,&HB("eax"));		#  5
+	&xor	("ecx",&DWP(3,$tbl,$acc,8));	#  5
+	&movq	("mm3",QWP(16,$key));
+	&movz	($acc,&HB("ebx"));		# 15
+	&xor	("ecx",&DWP(1,$tbl,$acc,8));	# 15
+	&movd	("mm0","ecx");			# t[0] collected
+
+	&movz	($acc,&LB("eax"));		#  4
+	&mov	("ecx",&DWP(0,$tbl,$acc,8));	#  4
+	&movd	("eax","mm2");			#  7, 6, 3, 2
+	&movz	($acc,&LB("ebx"));		# 14
+	&xor	("ecx",&DWP(2,$tbl,$acc,8));	# 14
+	&movd	("ebx","mm6");			# 13,12, 9, 8
+
+	&movz	($acc,&HB("eax"));		#  3
+	&xor	("ecx",&DWP(1,$tbl,$acc,8));	#  3
+	&movz	($acc,&HB("ebx"));		#  9
+	&xor	("ecx",&DWP(3,$tbl,$acc,8));	#  9
+	&movd	("mm1","ecx");			# t[1] collected
+
+	&movz	($acc,&LB("eax"));		#  2
+	&mov	("ecx",&DWP(2,$tbl,$acc,8));	#  2
+	&shr	("eax",16);			#  7, 6
+	&punpckldq	("mm0","mm1");		# t[0,1] collected
+	&movz	($acc,&LB("ebx"));		#  8
+	&xor	("ecx",&DWP(0,$tbl,$acc,8));	#  8
+	&shr	("ebx",16);			# 13,12
+
+	&movz	($acc,&HB("eax"));		#  7
+	&xor	("ecx",&DWP(1,$tbl,$acc,8));	#  7
+	&pxor	("mm0","mm3");
+	&movz	("eax",&LB("eax"));		#  6
+	&xor	("edx",&DWP(2,$tbl,"eax",8));	#  6
+	&pshufw	("mm1","mm0",0x08);		#  5, 4, 1, 0
+	&movz	($acc,&HB("ebx"));		# 13
+	&xor	("ecx",&DWP(3,$tbl,$acc,8));	# 13
+	&xor	("ecx",&DWP(24,$key));		# t[2]
+	&movd	("mm4","ecx");			# t[2] collected
+	&movz	("ebx",&LB("ebx"));		# 12
+	&xor	("edx",&DWP(0,$tbl,"ebx",8));	# 12
+	&shr	("ecx",16);
+	&movd	("eax","mm1");			#  5, 4, 1, 0
+	&mov	("ebx",&DWP(28,$key));		# t[3]
+	&xor	("ebx","edx");
+	&movd	("mm5","ebx");			# t[3] collected
+	&and	("ebx",0xffff0000);
+	&or	("ebx","ecx");
+
+	&punpckldq	("mm4","mm5");		# t[2,3] collected
+}
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub enccompact()
+{ my $Fn = \&mov;
+  while ($#_>5) { pop(@_); $Fn=sub{}; }
+  my ($i,$te,@s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# $Fn is used in first compact round and its purpose is to
+	# void restoration of some values from stack, so that after
+	# 4xenccompact with extra argument $key value is left there...
+	if ($i==3)  {	&$Fn	($key,$__key);			}##%edx
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+	if ($i==1)  {	&shr	($s[0],16);			}#%ebx[1]
+	if ($i==2)  {	&shr	($s[0],24);			}#%ecx[2]
+			&movz	($out,&BP(-128,$te,$out,1));
+
+	if ($i==3)  {	$tmp=$s[1];				}##%eax
+			&movz	($tmp,&HB($s[1]));
+			&movz	($tmp,&BP(-128,$te,$tmp,1));
+			&shl	($tmp,8);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$__s0);		}##%ebx
+	else        {	&mov	($tmp,$s[2]);
+			&shr	($tmp,16);			}
+	if ($i==2)  {	&and	($s[1],0xFF);			}#%edx[2]
+			&and	($tmp,0xFF);
+			&movz	($tmp,&BP(-128,$te,$tmp,1));
+			&shl	($tmp,16);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}##%ecx
+	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
+	else        {	&mov	($tmp,$s[3]);
+			&shr	($tmp,24);			}
+			&movz	($tmp,&BP(-128,$te,$tmp,1));
+			&shl	($tmp,24);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$acc);			}
+	&comment();
+}
+
+sub enctransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+  my $i = shift;
+  my $tmp = $tbl;
+  my $r2  = $key ;
+
+	&and	($tmp,$s[$i]);
+	&lea	($r2,&DWP(0,$s[$i],$s[$i]));
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&and	($r2,0xfefefefe);
+	&sub	($acc,$tmp);
+	&mov	($tmp,$s[$i]);
+	&and	($acc,0x1b1b1b1b);
+	&rotr	($tmp,16);
+	&xor	($acc,$r2);	# r2
+	&mov	($r2,$s[$i]);
+
+	&xor	($s[$i],$acc);	# r0 ^ r2
+	&rotr	($r2,16+8);
+	&xor	($acc,$tmp);
+	&rotl	($s[$i],24);
+	&xor	($acc,$r2);
+	&mov	($tmp,0x80808080)	if ($i!=1);
+	&xor	($s[$i],$acc);	# ROTATE(r2^r0,24) ^ r2
+}
+
+&function_begin_B("_x86_AES_encrypt_compact");
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($__key,$key);			# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+	&lea	($acc,&DWP(-2,$acc,$acc));
+	&lea	($acc,&DWP(0,$key,$acc,8));
+	&mov	($__end,$acc);			# end of key schedule
+
+	# prefetch Te4
+	&mov	($key,&DWP(0-128,$tbl));
+	&mov	($acc,&DWP(32-128,$tbl));
+	&mov	($key,&DWP(64-128,$tbl));
+	&mov	($acc,&DWP(96-128,$tbl));
+	&mov	($key,&DWP(128-128,$tbl));
+	&mov	($acc,&DWP(160-128,$tbl));
+	&mov	($key,&DWP(192-128,$tbl));
+	&mov	($acc,&DWP(224-128,$tbl));
+
+	&set_label("loop",16);
+
+		&enccompact(0,$tbl,$s0,$s1,$s2,$s3,1);
+		&enccompact(1,$tbl,$s1,$s2,$s3,$s0,1);
+		&enccompact(2,$tbl,$s2,$s3,$s0,$s1,1);
+		&enccompact(3,$tbl,$s3,$s0,$s1,$s2,1);
+		&mov	($tbl,0x80808080);
+		&enctransform(2);
+		&enctransform(3);
+		&enctransform(0);
+		&enctransform(1);
+		&mov 	($key,$__key);
+		&mov	($tbl,$__tbl);
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+	&cmp	($key,$__end);
+	&mov	($__key,$key);
+	&jb	(&label("loop"));
+
+	&enccompact(0,$tbl,$s0,$s1,$s2,$s3);
+	&enccompact(1,$tbl,$s1,$s2,$s3,$s0);
+	&enccompact(2,$tbl,$s2,$s3,$s0,$s1);
+	&enccompact(3,$tbl,$s3,$s0,$s1,$s2);
+
+	&xor	($s0,&DWP(16,$key));
+	&xor	($s1,&DWP(20,$key));
+	&xor	($s2,&DWP(24,$key));
+	&xor	($s3,&DWP(28,$key));
+
+	&ret	();
+&function_end_B("_x86_AES_encrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+#
+# Performance is not actually extraordinary in comparison to pure
+# x86 code. In particular encrypt performance is virtually the same.
+# Decrypt performance on the other hand is 15-20% better on newer
+# µ-archs [but we're thankful for *any* improvement here], and ~50%
+# better on PIII:-) And additionally on the pros side this code
+# eliminates redundant references to stack and thus relieves/
+# minimizes the pressure on the memory bus.
+#
+# MMX register layout                           lsb
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |          mm4          |          mm0          |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |     s3    |     s2    |     s1    |     s0    |
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+# |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+# +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+#
+# Indexes translate as s[N/4]>>(8*(N%4)), e.g. 5 means s1>>8.
+# In this terms encryption and decryption "compact" permutation
+# matrices can be depicted as following:
+#
+# encryption              lsb	# decryption              lsb
+# +----++----+----+----+----+	# +----++----+----+----+----+
+# | t0 || 15 | 10 |  5 |  0 |	# | t0 ||  7 | 10 | 13 |  0 |
+# +----++----+----+----+----+	# +----++----+----+----+----+
+# | t1 ||  3 | 14 |  9 |  4 |	# | t1 || 11 | 14 |  1 |  4 |
+# +----++----+----+----+----+	# +----++----+----+----+----+
+# | t2 ||  7 |  2 | 13 |  8 |	# | t2 || 15 |  2 |  5 |  8 |
+# +----++----+----+----+----+	# +----++----+----+----+----+
+# | t3 || 11 |  6 |  1 | 12 |	# | t3 ||  3 |  6 |  9 | 12 |
+# +----++----+----+----+----+	# +----++----+----+----+----+
+#
+######################################################################
+# Why not xmm registers? Short answer. It was actually tested and
+# was not any faster, but *contrary*, most notably on Intel CPUs.
+# Longer answer. Main advantage of using mm registers is that movd
+# latency is lower, especially on Intel P4. While arithmetic
+# instructions are twice as many, they can be scheduled every cycle
+# and not every second one when they are operating on xmm register,
+# so that "arithmetic throughput" remains virtually the same. And
+# finally the code can be executed even on elder SSE-only CPUs:-)
+
+sub sse_enccompact()
+{
+	&pshufw	("mm1","mm0",0x08);		#  5, 4, 1, 0
+	&pshufw	("mm5","mm4",0x0d);		# 15,14,11,10
+	&movd	("eax","mm1");			#  5, 4, 1, 0
+	&movd	("ebx","mm5");			# 15,14,11,10
+	&mov	($__key,$key);
+
+	&movz	($acc,&LB("eax"));		#  0
+	&movz	("edx",&HB("eax"));		#  1
+	&pshufw	("mm2","mm0",0x0d);		#  7, 6, 3, 2
+	&movz	("ecx",&BP(-128,$tbl,$acc,1));	#  0
+	&movz	($key,&LB("ebx"));		# 10
+	&movz	("edx",&BP(-128,$tbl,"edx",1));	#  1
+	&shr	("eax",16);			#  5, 4
+	&shl	("edx",8);			#  1
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 10
+	&movz	($key,&HB("ebx"));		# 11
+	&shl	($acc,16);			# 10
+	&pshufw	("mm6","mm4",0x08);		# 13,12, 9, 8
+	&or	("ecx",$acc);			# 10
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 11
+	&movz	($key,&HB("eax"));		#  5
+	&shl	($acc,24);			# 11
+	&shr	("ebx",16);			# 15,14
+	&or	("edx",$acc);			# 11
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  5
+	&movz	($key,&HB("ebx"));		# 15
+	&shl	($acc,8);			#  5
+	&or	("ecx",$acc);			#  5
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 15
+	&movz	($key,&LB("eax"));		#  4
+	&shl	($acc,24);			# 15
+	&or	("ecx",$acc);			# 15
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  4
+	&movz	($key,&LB("ebx"));		# 14
+	&movd	("eax","mm2");			#  7, 6, 3, 2
+	&movd	("mm0","ecx");			# t[0] collected
+	&movz	("ecx",&BP(-128,$tbl,$key,1));	# 14
+	&movz	($key,&HB("eax"));		#  3
+	&shl	("ecx",16);			# 14
+	&movd	("ebx","mm6");			# 13,12, 9, 8
+	&or	("ecx",$acc);			# 14
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  3
+	&movz	($key,&HB("ebx"));		#  9
+	&shl	($acc,24);			#  3
+	&or	("ecx",$acc);			#  3
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  9
+	&movz	($key,&LB("ebx"));		#  8
+	&shl	($acc,8);			#  9
+	&shr	("ebx",16);			# 13,12
+	&or	("ecx",$acc);			#  9
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  8
+	&movz	($key,&LB("eax"));		#  2
+	&shr	("eax",16);			#  7, 6
+	&movd	("mm1","ecx");			# t[1] collected
+	&movz	("ecx",&BP(-128,$tbl,$key,1));	#  2
+	&movz	($key,&HB("eax"));		#  7
+	&shl	("ecx",16);			#  2
+	&and	("eax",0xff);			#  6
+	&or	("ecx",$acc);			#  2
+
+	&punpckldq	("mm0","mm1");		# t[0,1] collected
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  7
+	&movz	($key,&HB("ebx"));		# 13
+	&shl	($acc,24);			#  7
+	&and	("ebx",0xff);			# 12
+	&movz	("eax",&BP(-128,$tbl,"eax",1));	#  6
+	&or	("ecx",$acc);			#  7
+	&shl	("eax",16);			#  6
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 13
+	&or	("edx","eax");			#  6
+	&shl	($acc,8);			# 13
+	&movz	("ebx",&BP(-128,$tbl,"ebx",1));	# 12
+	&or	("ecx",$acc);			# 13
+	&or	("edx","ebx");			# 12
+	&mov	($key,$__key);
+	&movd	("mm4","ecx");			# t[2] collected
+	&movd	("mm5","edx");			# t[3] collected
+
+	&punpckldq	("mm4","mm5");		# t[2,3] collected
+}
+
+					if (!$x86only) {
+&function_begin_B("_sse_AES_encrypt_compact");
+	&pxor	("mm0",&QWP(0,$key));	#  7, 6, 5, 4, 3, 2, 1, 0
+	&pxor	("mm4",&QWP(8,$key));	# 15,14,13,12,11,10, 9, 8
+
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+	&lea	($acc,&DWP(-2,$acc,$acc));
+	&lea	($acc,&DWP(0,$key,$acc,8));
+	&mov	($__end,$acc);			# end of key schedule
+
+	&mov	($s0,0x1b1b1b1b);		# magic constant
+	&mov	(&DWP(8,"esp"),$s0);
+	&mov	(&DWP(12,"esp"),$s0);
+
+	# prefetch Te4
+	&mov	($s0,&DWP(0-128,$tbl));
+	&mov	($s1,&DWP(32-128,$tbl));
+	&mov	($s2,&DWP(64-128,$tbl));
+	&mov	($s3,&DWP(96-128,$tbl));
+	&mov	($s0,&DWP(128-128,$tbl));
+	&mov	($s1,&DWP(160-128,$tbl));
+	&mov	($s2,&DWP(192-128,$tbl));
+	&mov	($s3,&DWP(224-128,$tbl));
+
+	&set_label("loop",16);
+		&sse_enccompact();
+		&add	($key,16);
+		&cmp	($key,$__end);
+		&ja	(&label("out"));
+
+		&movq	("mm2",&QWP(8,"esp"));
+		&pxor	("mm3","mm3");		&pxor	("mm7","mm7");
+		&movq	("mm1","mm0");		&movq	("mm5","mm4");	# r0
+		&pcmpgtb("mm3","mm0");		&pcmpgtb("mm7","mm4");
+		&pand	("mm3","mm2");		&pand	("mm7","mm2");
+		&pshufw	("mm2","mm0",0xb1);	&pshufw	("mm6","mm4",0xb1);# ROTATE(r0,16)
+		&paddb	("mm0","mm0");		&paddb	("mm4","mm4");
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# = r2
+		&pshufw	("mm3","mm2",0xb1);	&pshufw	("mm7","mm6",0xb1);# r0
+		&pxor	("mm1","mm0");		&pxor	("mm5","mm4");	# r0^r2
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= ROTATE(r0,16)
+
+		&movq	("mm2","mm3");		&movq	("mm6","mm7");
+		&pslld	("mm3",8);		&pslld	("mm7",8);
+		&psrld	("mm2",24);		&psrld	("mm6",24);
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= r0<<8
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= r0>>24
+
+		&movq	("mm3","mm1");		&movq	("mm7","mm5");
+		&movq	("mm2",&QWP(0,$key));	&movq	("mm6",&QWP(8,$key));
+		&psrld	("mm1",8);		&psrld	("mm5",8);
+		&mov	($s0,&DWP(0-128,$tbl));
+		&pslld	("mm3",24);		&pslld	("mm7",24);
+		&mov	($s1,&DWP(64-128,$tbl));
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= (r2^r0)<<8
+		&mov	($s2,&DWP(128-128,$tbl));
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= (r2^r0)>>24
+		&mov	($s3,&DWP(192-128,$tbl));
+
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");
+	&jmp	(&label("loop"));
+
+	&set_label("out",16);
+	&pxor	("mm0",&QWP(0,$key));
+	&pxor	("mm4",&QWP(8,$key));
+
+	&ret	();
+&function_end_B("_sse_AES_encrypt_compact");
+					}
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub encstep()
+{ my ($i,$te,@s) = @_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# lines marked with #%e?x[i] denote "reordered" instructions...
+	if ($i==3)  {	&mov	($key,$__key);			}##%edx
+	else        {	&mov	($out,$s[0]);
+			&and	($out,0xFF);			}
+	if ($i==1)  {	&shr	($s[0],16);			}#%ebx[1]
+	if ($i==2)  {	&shr	($s[0],24);			}#%ecx[2]
+			&mov	($out,&DWP(0,$te,$out,8));
+
+	if ($i==3)  {	$tmp=$s[1];				}##%eax
+			&movz	($tmp,&HB($s[1]));
+			&xor	($out,&DWP(3,$te,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$__s0);		}##%ebx
+	else        {	&mov	($tmp,$s[2]);
+			&shr	($tmp,16);			}
+	if ($i==2)  {	&and	($s[1],0xFF);			}#%edx[2]
+			&and	($tmp,0xFF);
+			&xor	($out,&DWP(2,$te,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}##%ecx
+	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
+	else        {	&mov	($tmp,$s[3]);
+			&shr	($tmp,24)			}
+			&xor	($out,&DWP(1,$te,$tmp,8));
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$acc);			}
+			&comment();
+}
+
+sub enclast()
+{ my ($i,$te,@s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	if ($i==3)  {	&mov	($key,$__key);			}##%edx
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+	if ($i==1)  {	&shr	($s[0],16);			}#%ebx[1]
+	if ($i==2)  {	&shr	($s[0],24);			}#%ecx[2]
+			&mov	($out,&DWP(2,$te,$out,8));
+			&and	($out,0x000000ff);
+
+	if ($i==3)  {	$tmp=$s[1];				}##%eax
+			&movz	($tmp,&HB($s[1]));
+			&mov	($tmp,&DWP(0,$te,$tmp,8));
+			&and	($tmp,0x0000ff00);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$__s0);		}##%ebx
+	else        {	&mov	($tmp,$s[2]);
+			&shr	($tmp,16);			}
+	if ($i==2)  {	&and	($s[1],0xFF);			}#%edx[2]
+			&and	($tmp,0xFF);
+			&mov	($tmp,&DWP(0,$te,$tmp,8));
+			&and	($tmp,0x00ff0000);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}##%ecx
+	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
+	else        {	&mov	($tmp,$s[3]);
+			&shr	($tmp,24);			}
+			&mov	($tmp,&DWP(2,$te,$tmp,8));
+			&and	($tmp,0xff000000);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$acc);			}
+}
+
+&function_begin_B("_x86_AES_encrypt");
+	if ($vertical_spin) {
+		# I need high parts of volatile registers to be accessible...
+		&exch	($s1="edi",$key="ebx");
+		&mov	($s2="esi",$acc="ecx");
+	}
+
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($__key,$key);			# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+
+	if ($small_footprint) {
+	    &lea	($acc,&DWP(-2,$acc,$acc));
+	    &lea	($acc,&DWP(0,$key,$acc,8));
+	    &mov	($__end,$acc);		# end of key schedule
+
+	    &set_label("loop",16);
+		if ($vertical_spin) {
+		    &encvert($tbl,$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+		    &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+		    &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+		    &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+		}
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+	    &cmp	($key,$__end);
+	    &mov	($__key,$key);
+	    &jb		(&label("loop"));
+	}
+	else {
+	    &cmp	($acc,10);
+	    &jle	(&label("10rounds"));
+	    &cmp	($acc,12);
+	    &jle	(&label("12rounds"));
+
+	&set_label("14rounds",4);
+	    for ($i=1;$i<3;$i++) {
+		if ($vertical_spin) {
+		    &encvert($tbl,$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+		    &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+		    &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+		    &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	($__key,$key);		# advance rd_key
+	&set_label("12rounds",4);
+	    for ($i=1;$i<3;$i++) {
+		if ($vertical_spin) {
+		    &encvert($tbl,$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+		    &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+		    &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+		    &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	($__key,$key);		# advance rd_key
+	&set_label("10rounds",4);
+	    for ($i=1;$i<10;$i++) {
+		if ($vertical_spin) {
+		    &encvert($tbl,$s0,$s1,$s2,$s3);
+		} else {
+		    &encstep(0,$tbl,$s0,$s1,$s2,$s3);
+		    &encstep(1,$tbl,$s1,$s2,$s3,$s0);
+		    &encstep(2,$tbl,$s2,$s3,$s0,$s1);
+		    &encstep(3,$tbl,$s3,$s0,$s1,$s2);
+		}
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	}
+
+	if ($vertical_spin) {
+	    # "reincarnate" some registers for "horizontal" spin...
+	    &mov	($s1="ebx",$key="edi");
+	    &mov	($s2="ecx",$acc="esi");
+	}
+	&enclast(0,$tbl,$s0,$s1,$s2,$s3);
+	&enclast(1,$tbl,$s1,$s2,$s3,$s0);
+	&enclast(2,$tbl,$s2,$s3,$s0,$s1);
+	&enclast(3,$tbl,$s3,$s0,$s1,$s2);
+
+	&add	($key,$small_footprint?16:160);
+	&xor	($s0,&DWP(0,$key));
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&ret	();
+
+&set_label("AES_Te",64);	# Yes! I keep it in the code segment!
+	&_data_word(0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6);
+	&_data_word(0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591);
+	&_data_word(0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56);
+	&_data_word(0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec);
+	&_data_word(0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa);
+	&_data_word(0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb);
+	&_data_word(0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45);
+	&_data_word(0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b);
+	&_data_word(0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c);
+	&_data_word(0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83);
+	&_data_word(0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9);
+	&_data_word(0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a);
+	&_data_word(0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d);
+	&_data_word(0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f);
+	&_data_word(0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df);
+	&_data_word(0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea);
+	&_data_word(0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34);
+	&_data_word(0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b);
+	&_data_word(0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d);
+	&_data_word(0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413);
+	&_data_word(0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1);
+	&_data_word(0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6);
+	&_data_word(0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972);
+	&_data_word(0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85);
+	&_data_word(0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed);
+	&_data_word(0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511);
+	&_data_word(0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe);
+	&_data_word(0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b);
+	&_data_word(0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05);
+	&_data_word(0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1);
+	&_data_word(0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142);
+	&_data_word(0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf);
+	&_data_word(0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3);
+	&_data_word(0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e);
+	&_data_word(0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a);
+	&_data_word(0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6);
+	&_data_word(0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3);
+	&_data_word(0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b);
+	&_data_word(0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428);
+	&_data_word(0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad);
+	&_data_word(0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14);
+	&_data_word(0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8);
+	&_data_word(0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4);
+	&_data_word(0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2);
+	&_data_word(0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda);
+	&_data_word(0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949);
+	&_data_word(0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf);
+	&_data_word(0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810);
+	&_data_word(0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c);
+	&_data_word(0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697);
+	&_data_word(0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e);
+	&_data_word(0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f);
+	&_data_word(0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc);
+	&_data_word(0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c);
+	&_data_word(0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969);
+	&_data_word(0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27);
+	&_data_word(0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122);
+	&_data_word(0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433);
+	&_data_word(0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9);
+	&_data_word(0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5);
+	&_data_word(0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a);
+	&_data_word(0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0);
+	&_data_word(0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e);
+	&_data_word(0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c);
+
+#Te4	# four copies of Te4 to choose from to avoid L1 aliasing
+	&data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+	&data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+	&data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+	&data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+	&data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+	&data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+	&data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+	&data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+	&data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+	&data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+	&data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+	&data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+	&data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+	&data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+	&data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+	&data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+	&data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+	&data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+	&data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+	&data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+	&data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+	&data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+	&data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+	&data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+	&data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+	&data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+	&data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+	&data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+	&data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+	&data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+	&data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+	&data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+	&data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+	&data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+	&data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+	&data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+	&data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+	&data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+	&data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+	&data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+	&data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+	&data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+	&data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+	&data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+	&data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+	&data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+	&data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+	&data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+	&data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+	&data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+	&data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+	&data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+	&data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+	&data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+	&data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+	&data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+	&data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+	&data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+	&data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+	&data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+	&data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+	&data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+	&data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+	&data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+	&data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+	&data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+	&data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+	&data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+	&data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+	&data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+	&data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+	&data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+	&data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+	&data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+	&data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+	&data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+	&data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+	&data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+	&data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+	&data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+	&data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+	&data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+	&data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+	&data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+	&data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+	&data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+	&data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+	&data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+	&data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+	&data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+	&data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+	&data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+	&data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+	&data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+	&data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+	&data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+
+	&data_byte(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5);
+	&data_byte(0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76);
+	&data_byte(0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0);
+	&data_byte(0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0);
+	&data_byte(0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc);
+	&data_byte(0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15);
+	&data_byte(0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a);
+	&data_byte(0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75);
+	&data_byte(0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0);
+	&data_byte(0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84);
+	&data_byte(0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b);
+	&data_byte(0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf);
+	&data_byte(0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85);
+	&data_byte(0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8);
+	&data_byte(0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5);
+	&data_byte(0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2);
+	&data_byte(0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17);
+	&data_byte(0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73);
+	&data_byte(0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88);
+	&data_byte(0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb);
+	&data_byte(0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c);
+	&data_byte(0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79);
+	&data_byte(0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9);
+	&data_byte(0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08);
+	&data_byte(0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6);
+	&data_byte(0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a);
+	&data_byte(0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e);
+	&data_byte(0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e);
+	&data_byte(0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94);
+	&data_byte(0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf);
+	&data_byte(0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68);
+	&data_byte(0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16);
+#rcon:
+	&data_word(0x00000001, 0x00000002, 0x00000004, 0x00000008);
+	&data_word(0x00000010, 0x00000020, 0x00000040, 0x00000080);
+	&data_word(0x0000001b, 0x00000036, 0x00000000, 0x00000000);
+	&data_word(0x00000000, 0x00000000, 0x00000000, 0x00000000);
+&function_end_B("_x86_AES_encrypt");
+
+# void AES_encrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("AES_encrypt");
+	&mov	($acc,&wparam(0));		# load inp
+	&mov	($key,&wparam(2));		# load key
+
+	&mov	($s0,"esp");
+	&sub	("esp",36);
+	&and	("esp",-64);			# align to cache-line
+
+	# place stack frame just "above" the key schedule
+	&lea	($s1,&DWP(-64-63,$key));
+	&sub	($s1,"esp");
+	&neg	($s1);
+	&and	($s1,0x3C0);	# modulo 1024, but aligned to cache-line
+	&sub	("esp",$s1);
+	&add	("esp",4);	# 4 is reserved for caller's return address
+	&mov	($_esp,$s0);			# save stack pointer
+
+	&call   (&label("pic_point"));          # make it PIC!
+	&set_label("pic_point");
+	&blindpop($tbl);
+	&picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if (!$x86only);
+	&lea    ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+
+	# pick Te4 copy which can't "overlap" with stack frame or key schedule
+	&lea	($s1,&DWP(768-4,"esp"));
+	&sub	($s1,$tbl);
+	&and	($s1,0x300);
+	&lea	($tbl,&DWP(2048+128,$tbl,$s1));
+
+					if (!$x86only) {
+	&bt	(&DWP(0,$s0),25);	# check for SSE bit
+	&jnc	(&label("x86"));
+
+	&movq	("mm0",&QWP(0,$acc));
+	&movq	("mm4",&QWP(8,$acc));
+	&call	("_sse_AES_encrypt_compact");
+	&mov	("esp",$_esp);			# restore stack pointer
+	&mov	($acc,&wparam(1));		# load out
+	&movq	(&QWP(0,$acc),"mm0");		# write output data
+	&movq	(&QWP(8,$acc),"mm4");
+	&emms	();
+	&function_end_A();
+					}
+	&set_label("x86",16);
+	&mov	($_tbl,$tbl);
+	&mov	($s0,&DWP(0,$acc));		# load input data
+	&mov	($s1,&DWP(4,$acc));
+	&mov	($s2,&DWP(8,$acc));
+	&mov	($s3,&DWP(12,$acc));
+	&call	("_x86_AES_encrypt_compact");
+	&mov	("esp",$_esp);			# restore stack pointer
+	&mov	($acc,&wparam(1));		# load out
+	&mov	(&DWP(0,$acc),$s0);		# write output data
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+&function_end("AES_encrypt");
+
+#--------------------------------------------------------------------#
+
+######################################################################
+# "Compact" block function
+######################################################################
+
+sub deccompact()
+{ my $Fn = \&mov;
+  while ($#_>5) { pop(@_); $Fn=sub{}; }
+  my ($i,$td,@s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# $Fn is used in first compact round and its purpose is to
+	# void restoration of some values from stack, so that after
+	# 4xdeccompact with extra argument $key, $s0 and $s1 values
+	# are left there...
+	if($i==3)   {	&$Fn	($key,$__key);			}
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+			&movz	($out,&BP(-128,$td,$out,1));
+
+	if ($i==3)  {	$tmp=$s[1];				}
+			&movz	($tmp,&HB($s[1]));
+			&movz	($tmp,&BP(-128,$td,$tmp,1));
+			&shl	($tmp,8);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$acc);		}
+	else        {	mov	($tmp,$s[2]);			}
+			&shr	($tmp,16);
+			&and	($tmp,0xFF);
+			&movz	($tmp,&BP(-128,$td,$tmp,1));
+			&shl	($tmp,16);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &$Fn ($s[2],$__s1);		}
+	else        {	&mov	($tmp,$s[3]);			}
+			&shr	($tmp,24);
+			&movz	($tmp,&BP(-128,$td,$tmp,1));
+			&shl	($tmp,24);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&$Fn	($s[3],$__s0);			}
+}
+
+# must be called with 2,3,0,1 as argument sequence!!!
+sub dectransform()
+{ my @s = ($s0,$s1,$s2,$s3);
+  my $i = shift;
+  my $tmp = $key;
+  my $tp2 = @s[($i+2)%4]; $tp2 = @s[2] if ($i==1);
+  my $tp4 = @s[($i+3)%4]; $tp4 = @s[3] if ($i==1);
+  my $tp8 = $tbl;
+
+	&mov	($tmp,0x80808080);
+	&and	($tmp,$s[$i]);
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&lea	($tp2,&DWP(0,$s[$i],$s[$i]));
+	&sub	($acc,$tmp);
+	&and	($tp2,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	&xor	($tp2,$acc);
+	&mov	($tmp,0x80808080);
+
+	&and	($tmp,$tp2);
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&lea	($tp4,&DWP(0,$tp2,$tp2));
+	&sub	($acc,$tmp);
+	&and	($tp4,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	 &xor	($tp2,$s[$i]);	# tp2^tp1
+	&xor	($tp4,$acc);
+	&mov	($tmp,0x80808080);
+
+	&and	($tmp,$tp4);
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&lea	($tp8,&DWP(0,$tp4,$tp4));
+	&sub	($acc,$tmp);
+	&and	($tp8,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	 &xor	($tp4,$s[$i]);	# tp4^tp1
+	 &rotl	($s[$i],8);	# = ROTATE(tp1,8)
+	&xor	($tp8,$acc);
+
+	&xor	($s[$i],$tp2);
+	&xor	($tp2,$tp8);
+	&xor	($s[$i],$tp4);
+	&xor	($tp4,$tp8);
+	&rotl	($tp2,24);
+	&xor	($s[$i],$tp8);	# ^= tp8^(tp4^tp1)^(tp2^tp1)
+	&rotl	($tp4,16);
+	&xor	($s[$i],$tp2);	# ^= ROTATE(tp8^tp2^tp1,24)
+	&rotl	($tp8,8);
+	&xor	($s[$i],$tp4);	# ^= ROTATE(tp8^tp4^tp1,16)
+	 &mov	($s[0],$__s0)			if($i==2); #prefetch $s0
+	 &mov	($s[1],$__s1)			if($i==3); #prefetch $s1
+	 &mov	($s[2],$__s2)			if($i==1);
+	&xor	($s[$i],$tp8);	# ^= ROTATE(tp8,8)
+
+	&mov	($s[3],$__s3)			if($i==1);
+	&mov	(&DWP(4+4*$i,"esp"),$s[$i])	if($i>=2);
+}
+
+&function_begin_B("_x86_AES_decrypt_compact");
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($__key,$key);			# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+
+	&lea	($acc,&DWP(-2,$acc,$acc));
+	&lea	($acc,&DWP(0,$key,$acc,8));
+	&mov	($__end,$acc);			# end of key schedule
+
+	# prefetch Td4
+	&mov	($key,&DWP(0-128,$tbl));
+	&mov	($acc,&DWP(32-128,$tbl));
+	&mov	($key,&DWP(64-128,$tbl));
+	&mov	($acc,&DWP(96-128,$tbl));
+	&mov	($key,&DWP(128-128,$tbl));
+	&mov	($acc,&DWP(160-128,$tbl));
+	&mov	($key,&DWP(192-128,$tbl));
+	&mov	($acc,&DWP(224-128,$tbl));
+
+	&set_label("loop",16);
+
+		&deccompact(0,$tbl,$s0,$s3,$s2,$s1,1);
+		&deccompact(1,$tbl,$s1,$s0,$s3,$s2,1);
+		&deccompact(2,$tbl,$s2,$s1,$s0,$s3,1);
+		&deccompact(3,$tbl,$s3,$s2,$s1,$s0,1);
+		&dectransform(2);
+		&dectransform(3);
+		&dectransform(0);
+		&dectransform(1);
+		&mov 	($key,$__key);
+		&mov	($tbl,$__tbl);
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+	&cmp	($key,$__end);
+	&mov	($__key,$key);
+	&jb	(&label("loop"));
+
+	&deccompact(0,$tbl,$s0,$s3,$s2,$s1);
+	&deccompact(1,$tbl,$s1,$s0,$s3,$s2);
+	&deccompact(2,$tbl,$s2,$s1,$s0,$s3);
+	&deccompact(3,$tbl,$s3,$s2,$s1,$s0);
+
+	&xor	($s0,&DWP(16,$key));
+	&xor	($s1,&DWP(20,$key));
+	&xor	($s2,&DWP(24,$key));
+	&xor	($s3,&DWP(28,$key));
+
+	&ret	();
+&function_end_B("_x86_AES_decrypt_compact");
+
+######################################################################
+# "Compact" SSE block function.
+######################################################################
+
+sub sse_deccompact()
+{
+	&pshufw	("mm1","mm0",0x0c);		#  7, 6, 1, 0
+	&pshufw	("mm5","mm4",0x09);		# 13,12,11,10
+	&movd	("eax","mm1");			#  7, 6, 1, 0
+	&movd	("ebx","mm5");			# 13,12,11,10
+	&mov	($__key,$key);
+
+	&movz	($acc,&LB("eax"));		#  0
+	&movz	("edx",&HB("eax"));		#  1
+	&pshufw	("mm2","mm0",0x06);		#  3, 2, 5, 4
+	&movz	("ecx",&BP(-128,$tbl,$acc,1));	#  0
+	&movz	($key,&LB("ebx"));		# 10
+	&movz	("edx",&BP(-128,$tbl,"edx",1));	#  1
+	&shr	("eax",16);			#  7, 6
+	&shl	("edx",8);			#  1
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 10
+	&movz	($key,&HB("ebx"));		# 11
+	&shl	($acc,16);			# 10
+	&pshufw	("mm6","mm4",0x03);		# 9, 8,15,14
+	&or	("ecx",$acc);			# 10
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 11
+	&movz	($key,&HB("eax"));		#  7
+	&shl	($acc,24);			# 11
+	&shr	("ebx",16);			# 13,12
+	&or	("edx",$acc);			# 11
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  7
+	&movz	($key,&HB("ebx"));		# 13
+	&shl	($acc,24);			#  7
+	&or	("ecx",$acc);			#  7
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 13
+	&movz	($key,&LB("eax"));		#  6
+	&shl	($acc,8);			# 13
+	&movd	("eax","mm2");			#  3, 2, 5, 4
+	&or	("ecx",$acc);			# 13
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  6
+	&movz	($key,&LB("ebx"));		# 12
+	&shl	($acc,16);			#  6
+	&movd	("ebx","mm6");			#  9, 8,15,14
+	&movd	("mm0","ecx");			# t[0] collected
+	&movz	("ecx",&BP(-128,$tbl,$key,1));	# 12
+	&movz	($key,&LB("eax"));		#  4
+	&or	("ecx",$acc);			# 12
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  4
+	&movz	($key,&LB("ebx"));		# 14
+	&or	("edx",$acc);			#  4
+	&movz	($acc,&BP(-128,$tbl,$key,1));	# 14
+	&movz	($key,&HB("eax"));		#  5
+	&shl	($acc,16);			# 14
+	&shr	("eax",16);			#  3, 2
+	&or	("edx",$acc);			# 14
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  5
+	&movz	($key,&HB("ebx"));		# 15
+	&shr	("ebx",16);			#  9, 8
+	&shl	($acc,8);			#  5
+	&movd	("mm1","edx");			# t[1] collected
+	&movz	("edx",&BP(-128,$tbl,$key,1));	# 15
+	&movz	($key,&HB("ebx"));		#  9
+	&shl	("edx",24);			# 15
+	&and	("ebx",0xff);			#  8
+	&or	("edx",$acc);			# 15
+
+	&punpckldq	("mm0","mm1");		# t[0,1] collected
+
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  9
+	&movz	($key,&LB("eax"));		#  2
+	&shl	($acc,8);			#  9
+	&movz	("eax",&HB("eax"));		#  3
+	&movz	("ebx",&BP(-128,$tbl,"ebx",1));	#  8
+	&or	("ecx",$acc);			#  9
+	&movz	($acc,&BP(-128,$tbl,$key,1));	#  2
+	&or	("edx","ebx");			#  8
+	&shl	($acc,16);			#  2
+	&movz	("eax",&BP(-128,$tbl,"eax",1));	#  3
+	&or	("edx",$acc);			#  2
+	&shl	("eax",24);			#  3
+	&or	("ecx","eax");			#  3
+	&mov	($key,$__key);
+	&movd	("mm4","edx");			# t[2] collected
+	&movd	("mm5","ecx");			# t[3] collected
+
+	&punpckldq	("mm4","mm5");		# t[2,3] collected
+}
+
+					if (!$x86only) {
+&function_begin_B("_sse_AES_decrypt_compact");
+	&pxor	("mm0",&QWP(0,$key));	#  7, 6, 5, 4, 3, 2, 1, 0
+	&pxor	("mm4",&QWP(8,$key));	# 15,14,13,12,11,10, 9, 8
+
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+	&lea	($acc,&DWP(-2,$acc,$acc));
+	&lea	($acc,&DWP(0,$key,$acc,8));
+	&mov	($__end,$acc);			# end of key schedule
+
+	&mov	($s0,0x1b1b1b1b);		# magic constant
+	&mov	(&DWP(8,"esp"),$s0);
+	&mov	(&DWP(12,"esp"),$s0);
+
+	# prefetch Td4
+	&mov	($s0,&DWP(0-128,$tbl));
+	&mov	($s1,&DWP(32-128,$tbl));
+	&mov	($s2,&DWP(64-128,$tbl));
+	&mov	($s3,&DWP(96-128,$tbl));
+	&mov	($s0,&DWP(128-128,$tbl));
+	&mov	($s1,&DWP(160-128,$tbl));
+	&mov	($s2,&DWP(192-128,$tbl));
+	&mov	($s3,&DWP(224-128,$tbl));
+
+	&set_label("loop",16);
+		&sse_deccompact();
+		&add	($key,16);
+		&cmp	($key,$__end);
+		&ja	(&label("out"));
+
+		# ROTATE(x^y,N) == ROTATE(x,N)^ROTATE(y,N)
+		&movq	("mm3","mm0");		&movq	("mm7","mm4");
+		&movq	("mm2","mm0",1);	&movq	("mm6","mm4",1);
+		&movq	("mm1","mm0");		&movq	("mm5","mm4");
+		&pshufw	("mm0","mm0",0xb1);	&pshufw	("mm4","mm4",0xb1);# = ROTATE(tp0,16)
+		&pslld	("mm2",8);		&pslld	("mm6",8);
+		&psrld	("mm3",8);		&psrld	("mm7",8);
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= tp0<<8
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= tp0>>8
+		&pslld	("mm2",16);		&pslld	("mm6",16);
+		&psrld	("mm3",16);		&psrld	("mm7",16);
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= tp0<<24
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= tp0>>24
+
+		&movq	("mm3",&QWP(8,"esp"));
+		&pxor	("mm2","mm2");		&pxor	("mm6","mm6");
+		&pcmpgtb("mm2","mm1");		&pcmpgtb("mm6","mm5");
+		&pand	("mm2","mm3");		&pand	("mm6","mm3");
+		&paddb	("mm1","mm1");		&paddb	("mm5","mm5");
+		&pxor	("mm1","mm2");		&pxor	("mm5","mm6");	# tp2
+		&movq	("mm3","mm1");		&movq	("mm7","mm5");
+		&movq	("mm2","mm1");		&movq	("mm6","mm5");
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp2
+		&pslld	("mm3",24);		&pslld	("mm7",24);
+		&psrld	("mm2",8);		&psrld	("mm6",8);
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= tp2<<24
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= tp2>>8
+
+		&movq	("mm2",&QWP(8,"esp"));
+		&pxor	("mm3","mm3");		&pxor	("mm7","mm7");
+		&pcmpgtb("mm3","mm1");		&pcmpgtb("mm7","mm5");
+		&pand	("mm3","mm2");		&pand	("mm7","mm2");
+		&paddb	("mm1","mm1");		&paddb	("mm5","mm5");
+		&pxor	("mm1","mm3");		&pxor	("mm5","mm7");	# tp4
+		&pshufw	("mm3","mm1",0xb1);	&pshufw	("mm7","mm5",0xb1);
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp4
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= ROTATE(tp4,16)
+
+		&pxor	("mm3","mm3");		&pxor	("mm7","mm7");
+		&pcmpgtb("mm3","mm1");		&pcmpgtb("mm7","mm5");
+		&pand	("mm3","mm2");		&pand	("mm7","mm2");
+		&paddb	("mm1","mm1");		&paddb	("mm5","mm5");
+		&pxor	("mm1","mm3");		&pxor	("mm5","mm7");	# tp8
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp8
+		&movq	("mm3","mm1");		&movq	("mm7","mm5");
+		&pshufw	("mm2","mm1",0xb1);	&pshufw	("mm6","mm5",0xb1);
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");	# ^= ROTATE(tp8,16)
+		&pslld	("mm1",8);		&pslld	("mm5",8);
+		&psrld	("mm3",8);		&psrld	("mm7",8);
+		&movq	("mm2",&QWP(0,$key));	&movq	("mm6",&QWP(8,$key));
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp8<<8
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= tp8>>8
+		&mov	($s0,&DWP(0-128,$tbl));
+		&pslld	("mm1",16);		&pslld	("mm5",16);
+		&mov	($s1,&DWP(64-128,$tbl));
+		&psrld	("mm3",16);		&psrld	("mm7",16);
+		&mov	($s2,&DWP(128-128,$tbl));
+		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp8<<24
+		&mov	($s3,&DWP(192-128,$tbl));
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= tp8>>24
+
+		&pxor	("mm0","mm2");		&pxor	("mm4","mm6");
+	&jmp	(&label("loop"));
+
+	&set_label("out",16);
+	&pxor	("mm0",&QWP(0,$key));
+	&pxor	("mm4",&QWP(8,$key));
+
+	&ret	();
+&function_end_B("_sse_AES_decrypt_compact");
+					}
+
+######################################################################
+# Vanilla block function.
+######################################################################
+
+sub decstep()
+{ my ($i,$td,@s) = @_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	# no instructions are reordered, as performance appears
+	# optimal... or rather that all attempts to reorder didn't
+	# result in better performance [which by the way is not a
+	# bit lower than encryption].
+	if($i==3)   {	&mov	($key,$__key);			}
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+			&mov	($out,&DWP(0,$td,$out,8));
+
+	if ($i==3)  {	$tmp=$s[1];				}
+			&movz	($tmp,&HB($s[1]));
+			&xor	($out,&DWP(3,$td,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$acc);		}
+	else        {	&mov	($tmp,$s[2]);			}
+			&shr	($tmp,16);
+			&and	($tmp,0xFF);
+			&xor	($out,&DWP(2,$td,$tmp,8));
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}
+	else        {	&mov	($tmp,$s[3]);			}
+			&shr	($tmp,24);
+			&xor	($out,&DWP(1,$td,$tmp,8));
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$__s0);			}
+			&comment();
+}
+
+sub declast()
+{ my ($i,$td,@s)=@_;
+  my $tmp = $key;
+  my $out = $i==3?$s[0]:$acc;
+
+	if($i==0)   {	&lea	($td,&DWP(2048+128,$td));
+			&mov	($tmp,&DWP(0-128,$td));
+			&mov	($acc,&DWP(32-128,$td));
+			&mov	($tmp,&DWP(64-128,$td));
+			&mov	($acc,&DWP(96-128,$td));
+			&mov	($tmp,&DWP(128-128,$td));
+			&mov	($acc,&DWP(160-128,$td));
+			&mov	($tmp,&DWP(192-128,$td));
+			&mov	($acc,&DWP(224-128,$td));
+			&lea	($td,&DWP(-128,$td));		}
+	if($i==3)   {	&mov	($key,$__key);			}
+	else        {	&mov	($out,$s[0]);			}
+			&and	($out,0xFF);
+			&movz	($out,&BP(0,$td,$out,1));
+
+	if ($i==3)  {	$tmp=$s[1];				}
+			&movz	($tmp,&HB($s[1]));
+			&movz	($tmp,&BP(0,$td,$tmp,1));
+			&shl	($tmp,8);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[2]; &mov ($s[1],$acc);		}
+	else        {	mov	($tmp,$s[2]);			}
+			&shr	($tmp,16);
+			&and	($tmp,0xFF);
+			&movz	($tmp,&BP(0,$td,$tmp,1));
+			&shl	($tmp,16);
+			&xor	($out,$tmp);
+
+	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}
+	else        {	&mov	($tmp,$s[3]);			}
+			&shr	($tmp,24);
+			&movz	($tmp,&BP(0,$td,$tmp,1));
+			&shl	($tmp,24);
+			&xor	($out,$tmp);
+	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
+	if ($i==3)  {	&mov	($s[3],$__s0);
+			&lea	($td,&DWP(-2048,$td));		}
+}
+
+&function_begin_B("_x86_AES_decrypt");
+	# note that caller is expected to allocate stack frame for me!
+	&mov	($__key,$key);			# save key
+
+	&xor	($s0,&DWP(0,$key));		# xor with key
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&mov	($acc,&DWP(240,$key));		# load key->rounds
+
+	if ($small_footprint) {
+	    &lea	($acc,&DWP(-2,$acc,$acc));
+	    &lea	($acc,&DWP(0,$key,$acc,8));
+	    &mov	($__end,$acc);		# end of key schedule
+	    &set_label("loop",16);
+		&decstep(0,$tbl,$s0,$s3,$s2,$s1);
+		&decstep(1,$tbl,$s1,$s0,$s3,$s2);
+		&decstep(2,$tbl,$s2,$s1,$s0,$s3);
+		&decstep(3,$tbl,$s3,$s2,$s1,$s0);
+		&add	($key,16);		# advance rd_key
+		&xor	($s0,&DWP(0,$key));
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+	    &cmp	($key,$__end);
+	    &mov	($__key,$key);
+	    &jb		(&label("loop"));
+	}
+	else {
+	    &cmp	($acc,10);
+	    &jle	(&label("10rounds"));
+	    &cmp	($acc,12);
+	    &jle	(&label("12rounds"));
+
+	&set_label("14rounds",4);
+	    for ($i=1;$i<3;$i++) {
+		&decstep(0,$tbl,$s0,$s3,$s2,$s1);
+		&decstep(1,$tbl,$s1,$s0,$s3,$s2);
+		&decstep(2,$tbl,$s2,$s1,$s0,$s3);
+		&decstep(3,$tbl,$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	($__key,$key);		# advance rd_key
+	&set_label("12rounds",4);
+	    for ($i=1;$i<3;$i++) {
+		&decstep(0,$tbl,$s0,$s3,$s2,$s1);
+		&decstep(1,$tbl,$s1,$s0,$s3,$s2);
+		&decstep(2,$tbl,$s2,$s1,$s0,$s3);
+		&decstep(3,$tbl,$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	    &add	($key,32);
+	    &mov	($__key,$key);		# advance rd_key
+	&set_label("10rounds",4);
+	    for ($i=1;$i<10;$i++) {
+		&decstep(0,$tbl,$s0,$s3,$s2,$s1);
+		&decstep(1,$tbl,$s1,$s0,$s3,$s2);
+		&decstep(2,$tbl,$s2,$s1,$s0,$s3);
+		&decstep(3,$tbl,$s3,$s2,$s1,$s0);
+		&xor	($s0,&DWP(16*$i+0,$key));
+		&xor	($s1,&DWP(16*$i+4,$key));
+		&xor	($s2,&DWP(16*$i+8,$key));
+		&xor	($s3,&DWP(16*$i+12,$key));
+	    }
+	}
+
+	&declast(0,$tbl,$s0,$s3,$s2,$s1);
+	&declast(1,$tbl,$s1,$s0,$s3,$s2);
+	&declast(2,$tbl,$s2,$s1,$s0,$s3);
+	&declast(3,$tbl,$s3,$s2,$s1,$s0);
+
+	&add	($key,$small_footprint?16:160);
+	&xor	($s0,&DWP(0,$key));
+	&xor	($s1,&DWP(4,$key));
+	&xor	($s2,&DWP(8,$key));
+	&xor	($s3,&DWP(12,$key));
+
+	&ret	();
+
+&set_label("AES_Td",64);	# Yes! I keep it in the code segment!
+	&_data_word(0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a);
+	&_data_word(0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b);
+	&_data_word(0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5);
+	&_data_word(0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5);
+	&_data_word(0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d);
+	&_data_word(0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b);
+	&_data_word(0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295);
+	&_data_word(0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e);
+	&_data_word(0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927);
+	&_data_word(0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d);
+	&_data_word(0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362);
+	&_data_word(0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9);
+	&_data_word(0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52);
+	&_data_word(0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566);
+	&_data_word(0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3);
+	&_data_word(0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed);
+	&_data_word(0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e);
+	&_data_word(0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4);
+	&_data_word(0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4);
+	&_data_word(0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd);
+	&_data_word(0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d);
+	&_data_word(0xb58d5491, 0x055dc471, 0x6fd40604, 0xff155060);
+	&_data_word(0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967);
+	&_data_word(0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879);
+	&_data_word(0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000);
+	&_data_word(0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c);
+	&_data_word(0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36);
+	&_data_word(0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624);
+	&_data_word(0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b);
+	&_data_word(0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c);
+	&_data_word(0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12);
+	&_data_word(0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14);
+	&_data_word(0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3);
+	&_data_word(0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b);
+	&_data_word(0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8);
+	&_data_word(0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684);
+	&_data_word(0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7);
+	&_data_word(0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177);
+	&_data_word(0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947);
+	&_data_word(0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322);
+	&_data_word(0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498);
+	&_data_word(0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f);
+	&_data_word(0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54);
+	&_data_word(0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382);
+	&_data_word(0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf);
+	&_data_word(0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb);
+	&_data_word(0x097826cd, 0xf418596e, 0x01b79aec, 0xa89a4f83);
+	&_data_word(0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef);
+	&_data_word(0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029);
+	&_data_word(0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235);
+	&_data_word(0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733);
+	&_data_word(0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117);
+	&_data_word(0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4);
+	&_data_word(0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546);
+	&_data_word(0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb);
+	&_data_word(0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d);
+	&_data_word(0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb);
+	&_data_word(0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a);
+	&_data_word(0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773);
+	&_data_word(0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478);
+	&_data_word(0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2);
+	&_data_word(0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff);
+	&_data_word(0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664);
+	&_data_word(0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0);
+
+#Td4:	# four copies of Td4 to choose from to avoid L1 aliasing
+	&data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+	&data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+	&data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+	&data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+	&data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+	&data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+	&data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+	&data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+	&data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+	&data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+	&data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+	&data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+	&data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+	&data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+	&data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+	&data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+	&data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+	&data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+	&data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+	&data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+	&data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+	&data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+	&data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+	&data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+	&data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+	&data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+	&data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+	&data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+	&data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+	&data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+	&data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+	&data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+	&data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+	&data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+	&data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+	&data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+	&data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+	&data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+	&data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+	&data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+	&data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+	&data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+	&data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+	&data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+	&data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+	&data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+	&data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+	&data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+	&data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+	&data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+	&data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+	&data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+	&data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+	&data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+	&data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+	&data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+	&data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+	&data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+	&data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+	&data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+	&data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+	&data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+	&data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+	&data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+	&data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+	&data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+	&data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+	&data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+	&data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+	&data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+	&data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+	&data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+	&data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+	&data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+	&data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+	&data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+	&data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+	&data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+	&data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+	&data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+	&data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+	&data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+	&data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+	&data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+	&data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+	&data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+	&data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+	&data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+	&data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+	&data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+	&data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+	&data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+	&data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+	&data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+	&data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+	&data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+
+	&data_byte(0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38);
+	&data_byte(0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb);
+	&data_byte(0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87);
+	&data_byte(0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb);
+	&data_byte(0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d);
+	&data_byte(0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e);
+	&data_byte(0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2);
+	&data_byte(0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25);
+	&data_byte(0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16);
+	&data_byte(0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92);
+	&data_byte(0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda);
+	&data_byte(0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84);
+	&data_byte(0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a);
+	&data_byte(0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06);
+	&data_byte(0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02);
+	&data_byte(0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b);
+	&data_byte(0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea);
+	&data_byte(0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73);
+	&data_byte(0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85);
+	&data_byte(0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e);
+	&data_byte(0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89);
+	&data_byte(0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b);
+	&data_byte(0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20);
+	&data_byte(0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4);
+	&data_byte(0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31);
+	&data_byte(0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f);
+	&data_byte(0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d);
+	&data_byte(0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef);
+	&data_byte(0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0);
+	&data_byte(0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61);
+	&data_byte(0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26);
+	&data_byte(0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d);
+&function_end_B("_x86_AES_decrypt");
+
+# void AES_decrypt (const void *inp,void *out,const AES_KEY *key);
+&function_begin("AES_decrypt");
+	&mov	($acc,&wparam(0));		# load inp
+	&mov	($key,&wparam(2));		# load key
+
+	&mov	($s0,"esp");
+	&sub	("esp",36);
+	&and	("esp",-64);			# align to cache-line
+
+	# place stack frame just "above" the key schedule
+	&lea	($s1,&DWP(-64-63,$key));
+	&sub	($s1,"esp");
+	&neg	($s1);
+	&and	($s1,0x3C0);	# modulo 1024, but aligned to cache-line
+	&sub	("esp",$s1);
+	&add	("esp",4);	# 4 is reserved for caller's return address
+	&mov	($_esp,$s0);	# save stack pointer
+
+	&call   (&label("pic_point"));          # make it PIC!
+	&set_label("pic_point");
+	&blindpop($tbl);
+	&picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+	&lea    ($tbl,&DWP(&label("AES_Td")."-".&label("pic_point"),$tbl));
+
+	# pick Td4 copy which can't "overlap" with stack frame or key schedule
+	&lea	($s1,&DWP(768-4,"esp"));
+	&sub	($s1,$tbl);
+	&and	($s1,0x300);
+	&lea	($tbl,&DWP(2048+128,$tbl,$s1));
+
+					if (!$x86only) {
+	&bt	(&DWP(0,$s0),25);	# check for SSE bit
+	&jnc	(&label("x86"));
+
+	&movq	("mm0",&QWP(0,$acc));
+	&movq	("mm4",&QWP(8,$acc));
+	&call	("_sse_AES_decrypt_compact");
+	&mov	("esp",$_esp);			# restore stack pointer
+	&mov	($acc,&wparam(1));		# load out
+	&movq	(&QWP(0,$acc),"mm0");		# write output data
+	&movq	(&QWP(8,$acc),"mm4");
+	&emms	();
+	&function_end_A();
+					}
+	&set_label("x86",16);
+	&mov	($_tbl,$tbl);
+	&mov	($s0,&DWP(0,$acc));		# load input data
+	&mov	($s1,&DWP(4,$acc));
+	&mov	($s2,&DWP(8,$acc));
+	&mov	($s3,&DWP(12,$acc));
+	&call	("_x86_AES_decrypt_compact");
+	&mov	("esp",$_esp);			# restore stack pointer
+	&mov	($acc,&wparam(1));		# load out
+	&mov	(&DWP(0,$acc),$s0);		# write output data
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+&function_end("AES_decrypt");
+
+# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
+#			size_t length, const AES_KEY *key,
+#			unsigned char *ivp,const int enc);
+{
+# stack frame layout
+#             -4(%esp)		# return address	 0(%esp)
+#              0(%esp)		# s0 backing store	 4(%esp)
+#              4(%esp)		# s1 backing store	 8(%esp)
+#              8(%esp)		# s2 backing store	12(%esp)
+#             12(%esp)		# s3 backing store	16(%esp)
+#             16(%esp)		# key backup		20(%esp)
+#             20(%esp)		# end of key schedule	24(%esp)
+#             24(%esp)		# %ebp backup		28(%esp)
+#             28(%esp)		# %esp backup
+my $_inp=&DWP(32,"esp");	# copy of wparam(0)
+my $_out=&DWP(36,"esp");	# copy of wparam(1)
+my $_len=&DWP(40,"esp");	# copy of wparam(2)
+my $_key=&DWP(44,"esp");	# copy of wparam(3)
+my $_ivp=&DWP(48,"esp");	# copy of wparam(4)
+my $_tmp=&DWP(52,"esp");	# volatile variable
+#
+my $ivec=&DWP(60,"esp");	# ivec[16]
+my $aes_key=&DWP(76,"esp");	# copy of aes_key
+my $mark=&DWP(76+240,"esp");	# copy of aes_key->rounds
+
+&function_begin("AES_cbc_encrypt");
+	&mov	($s2 eq "ecx"? $s2 : "",&wparam(2));	# load len
+	&cmp	($s2,0);
+	&je	(&label("drop_out"));
+
+	&call   (&label("pic_point"));		# make it PIC!
+	&set_label("pic_point");
+	&blindpop($tbl);
+	&picmeup($s0,"OPENSSL_ia32cap_P",$tbl,&label("pic_point")) if(!$x86only);
+
+	&cmp	(&wparam(5),0);
+	&lea    ($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+	&jne	(&label("picked_te"));
+	&lea	($tbl,&DWP(&label("AES_Td")."-".&label("AES_Te"),$tbl));
+	&set_label("picked_te");
+
+	# one can argue if this is required
+	&pushf	();
+	&cld	();
+
+	&cmp	($s2,$speed_limit);
+	&jb	(&label("slow_way"));
+	&test	($s2,15);
+	&jnz	(&label("slow_way"));
+					if (!$x86only) {
+	&bt	(&DWP(0,$s0),28);	# check for hyper-threading bit
+	&jc	(&label("slow_way"));
+					}
+	# pre-allocate aligned stack frame...
+	&lea	($acc,&DWP(-80-244,"esp"));
+	&and	($acc,-64);
+
+	# ... and make sure it doesn't alias with $tbl modulo 4096
+	&mov	($s0,$tbl);
+	&lea	($s1,&DWP(2048+256,$tbl));
+	&mov	($s3,$acc);
+	&and	($s0,0xfff);		# s = %ebp&0xfff
+	&and	($s1,0xfff);		# e = (%ebp+2048+256)&0xfff
+	&and	($s3,0xfff);		# p = %esp&0xfff
+
+	&cmp	($s3,$s1);		# if (p>=e) %esp =- (p-e);
+	&jb	(&label("tbl_break_out"));
+	&sub	($s3,$s1);
+	&sub	($acc,$s3);
+	&jmp	(&label("tbl_ok"));
+	&set_label("tbl_break_out",4);	# else %esp -= (p-s)&0xfff + framesz;
+	&sub	($s3,$s0);
+	&and	($s3,0xfff);
+	&add	($s3,384);
+	&sub	($acc,$s3);
+	&set_label("tbl_ok",4);
+
+	&lea	($s3,&wparam(0));	# obtain pointer to parameter block
+	&exch	("esp",$acc);		# allocate stack frame
+	&add	("esp",4);		# reserve for return address!
+	&mov	($_tbl,$tbl);		# save %ebp
+	&mov	($_esp,$acc);		# save %esp
+
+	&mov	($s0,&DWP(0,$s3));	# load inp
+	&mov	($s1,&DWP(4,$s3));	# load out
+	#&mov	($s2,&DWP(8,$s3));	# load len
+	&mov	($key,&DWP(12,$s3));	# load key
+	&mov	($acc,&DWP(16,$s3));	# load ivp
+	&mov	($s3,&DWP(20,$s3));	# load enc flag
+
+	&mov	($_inp,$s0);		# save copy of inp
+	&mov	($_out,$s1);		# save copy of out
+	&mov	($_len,$s2);		# save copy of len
+	&mov	($_key,$key);		# save copy of key
+	&mov	($_ivp,$acc);		# save copy of ivp
+
+	&mov	($mark,0);		# copy of aes_key->rounds = 0;
+	# do we copy key schedule to stack?
+	&mov	($s1 eq "ebx" ? $s1 : "",$key);
+	&mov	($s2 eq "ecx" ? $s2 : "",244/4);
+	&sub	($s1,$tbl);
+	&mov	("esi",$key);
+	&and	($s1,0xfff);
+	&lea	("edi",$aes_key);
+	&cmp	($s1,2048+256);
+	&jb	(&label("do_copy"));
+	&cmp	($s1,4096-244);
+	&jb	(&label("skip_copy"));
+	&set_label("do_copy",4);
+		&mov	($_key,"edi");
+		&data_word(0xA5F3F689);	# rep movsd
+	&set_label("skip_copy");
+
+	&mov	($key,16);
+	&set_label("prefetch_tbl",4);
+		&mov	($s0,&DWP(0,$tbl));
+		&mov	($s1,&DWP(32,$tbl));
+		&mov	($s2,&DWP(64,$tbl));
+		&mov	($acc,&DWP(96,$tbl));
+		&lea	($tbl,&DWP(128,$tbl));
+		&sub	($key,1);
+	&jnz	(&label("prefetch_tbl"));
+	&sub	($tbl,2048);
+
+	&mov	($acc,$_inp);
+	&mov	($key,$_ivp);
+
+	&cmp	($s3,0);
+	&je	(&label("fast_decrypt"));
+
+#----------------------------- ENCRYPT -----------------------------#
+	&mov	($s0,&DWP(0,$key));		# load iv
+	&mov	($s1,&DWP(4,$key));
+
+	&set_label("fast_enc_loop",16);
+		&mov	($s2,&DWP(8,$key));
+		&mov	($s3,&DWP(12,$key));
+
+		&xor	($s0,&DWP(0,$acc));	# xor input data
+		&xor	($s1,&DWP(4,$acc));
+		&xor	($s2,&DWP(8,$acc));
+		&xor	($s3,&DWP(12,$acc));
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_encrypt");
+
+		&mov	($acc,$_inp);		# load inp
+		&mov	($key,$_out);		# load out
+
+		&mov	(&DWP(0,$key),$s0);	# save output data
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($s2,$_len);		# load len
+		&mov	($_inp,$acc);		# save inp
+		&lea	($s3,&DWP(16,$key));	# advance out
+		&mov	($_out,$s3);		# save out
+		&sub	($s2,16);		# decrease len
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("fast_enc_loop"));
+	&mov	($acc,$_ivp);		# load ivp
+	&mov	($s2,&DWP(8,$key));	# restore last 2 dwords
+	&mov	($s3,&DWP(12,$key));
+	&mov	(&DWP(0,$acc),$s0);	# save ivec
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+
+	&cmp	($mark,0);		# was the key schedule copied?
+	&mov	("edi",$_key);
+	&je	(&label("skip_ezero"));
+	# zero copy of key schedule
+	&mov	("ecx",240/4);
+	&xor	("eax","eax");
+	&align	(4);
+	&data_word(0xABF3F689);		# rep stosd
+	&set_label("skip_ezero");
+	&mov	("esp",$_esp);
+	&popf	();
+    &set_label("drop_out");
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+#----------------------------- DECRYPT -----------------------------#
+&set_label("fast_decrypt",16);
+
+	&cmp	($acc,$_out);
+	&je	(&label("fast_dec_in_place"));	# in-place processing...
+
+	&mov	($_tmp,$key);
+
+	&align	(4);
+	&set_label("fast_dec_loop",16);
+		&mov	($s0,&DWP(0,$acc));	# read input
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_decrypt");
+
+		&mov	($key,$_tmp);		# load ivp
+		&mov	($acc,$_len);		# load len
+		&xor	($s0,&DWP(0,$key));	# xor iv
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+		&mov	($key,$_out);		# load out
+		&mov	($acc,$_inp);		# load inp
+
+		&mov	(&DWP(0,$key),$s0);	# write output
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($s2,$_len);		# load len
+		&mov	($_tmp,$acc);		# save ivp
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+		&lea	($key,&DWP(16,$key));	# advance out
+		&mov	($_out,$key);		# save out
+		&sub	($s2,16);		# decrease len
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("fast_dec_loop"));
+	&mov	($key,$_tmp);		# load temp ivp
+	&mov	($acc,$_ivp);		# load user ivp
+	&mov	($s0,&DWP(0,$key));	# load iv
+	&mov	($s1,&DWP(4,$key));
+	&mov	($s2,&DWP(8,$key));
+	&mov	($s3,&DWP(12,$key));
+	&mov	(&DWP(0,$acc),$s0);	# copy back to user
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+	&jmp	(&label("fast_dec_out"));
+
+    &set_label("fast_dec_in_place",16);
+	&set_label("fast_dec_in_place_loop");
+		&mov	($s0,&DWP(0,$acc));	# read input
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&lea	($key,$ivec);
+		&mov	(&DWP(0,$key),$s0);	# copy to temp
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_decrypt");
+
+		&mov	($key,$_ivp);		# load ivp
+		&mov	($acc,$_out);		# load out
+		&xor	($s0,&DWP(0,$key));	# xor iv
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+		&mov	(&DWP(0,$acc),$s0);	# write output
+		&mov	(&DWP(4,$acc),$s1);
+		&mov	(&DWP(8,$acc),$s2);
+		&mov	(&DWP(12,$acc),$s3);
+
+		&lea	($acc,&DWP(16,$acc));	# advance out
+		&mov	($_out,$acc);		# save out
+
+		&lea	($acc,$ivec);
+		&mov	($s0,&DWP(0,$acc));	# read temp
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	(&DWP(0,$key),$s0);	# copy iv
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($acc,$_inp);		# load inp
+		&mov	($s2,$_len);		# load len
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+		&sub	($s2,16);		# decrease len
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("fast_dec_in_place_loop"));
+
+    &set_label("fast_dec_out",4);
+	&cmp	($mark,0);		# was the key schedule copied?
+	&mov	("edi",$_key);
+	&je	(&label("skip_dzero"));
+	# zero copy of key schedule
+	&mov	("ecx",240/4);
+	&xor	("eax","eax");
+	&align	(4);
+	&data_word(0xABF3F689);		# rep stosd
+	&set_label("skip_dzero");
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+#--------------------------- SLOW ROUTINE ---------------------------#
+&set_label("slow_way",16);
+
+	&mov	($s0,&DWP(0,$s0)) if (!$x86only);# load OPENSSL_ia32cap
+	&mov	($key,&wparam(3));	# load key
+
+	# pre-allocate aligned stack frame...
+	&lea	($acc,&DWP(-80,"esp"));
+	&and	($acc,-64);
+
+	# ... and make sure it doesn't alias with $key modulo 1024
+	&lea	($s1,&DWP(-80-63,$key));
+	&sub	($s1,$acc);
+	&neg	($s1);
+	&and	($s1,0x3C0);	# modulo 1024, but aligned to cache-line
+	&sub	($acc,$s1);
+
+	# pick S-box copy which can't overlap with stack frame or $key
+	&lea	($s1,&DWP(768,$acc));
+	&sub	($s1,$tbl);
+	&and	($s1,0x300);
+	&lea	($tbl,&DWP(2048+128,$tbl,$s1));
+
+	&lea	($s3,&wparam(0));	# pointer to parameter block
+
+	&exch	("esp",$acc);
+	&add	("esp",4);		# reserve for return address!
+	&mov	($_tbl,$tbl);		# save %ebp
+	&mov	($_esp,$acc);		# save %esp
+	&mov	($_tmp,$s0);		# save OPENSSL_ia32cap
+
+	&mov	($s0,&DWP(0,$s3));	# load inp
+	&mov	($s1,&DWP(4,$s3));	# load out
+	#&mov	($s2,&DWP(8,$s3));	# load len
+	#&mov	($key,&DWP(12,$s3));	# load key
+	&mov	($acc,&DWP(16,$s3));	# load ivp
+	&mov	($s3,&DWP(20,$s3));	# load enc flag
+
+	&mov	($_inp,$s0);		# save copy of inp
+	&mov	($_out,$s1);		# save copy of out
+	&mov	($_len,$s2);		# save copy of len
+	&mov	($_key,$key);		# save copy of key
+	&mov	($_ivp,$acc);		# save copy of ivp
+
+	&mov	($key,$acc);
+	&mov	($acc,$s0);
+
+	&cmp	($s3,0);
+	&je	(&label("slow_decrypt"));
+
+#--------------------------- SLOW ENCRYPT ---------------------------#
+	&cmp	($s2,16);
+	&mov	($s3,$s1);
+	&jb	(&label("slow_enc_tail"));
+
+					if (!$x86only) {
+	&bt	($_tmp,25);		# check for SSE bit
+	&jnc	(&label("slow_enc_x86"));
+
+	&movq	("mm0",&QWP(0,$key));	# load iv
+	&movq	("mm4",&QWP(8,$key));
+
+	&set_label("slow_enc_loop_sse",16);
+		&pxor	("mm0",&QWP(0,$acc));	# xor input data
+		&pxor	("mm4",&QWP(8,$acc));
+
+		&mov	($key,$_key);
+		&call	("_sse_AES_encrypt_compact");
+
+		&mov	($acc,$_inp);		# load inp
+		&mov	($key,$_out);		# load out
+		&mov	($s2,$_len);		# load len
+
+		&movq	(&QWP(0,$key),"mm0");	# save output data
+		&movq	(&QWP(8,$key),"mm4");
+
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+		&lea	($s3,&DWP(16,$key));	# advance out
+		&mov	($_out,$s3);		# save out
+		&sub	($s2,16);		# decrease len
+		&cmp	($s2,16);
+		&mov	($_len,$s2);		# save len
+	&jae	(&label("slow_enc_loop_sse"));
+	&test	($s2,15);
+	&jnz	(&label("slow_enc_tail"));
+	&mov	($acc,$_ivp);		# load ivp
+	&movq	(&QWP(0,$acc),"mm0");	# save ivec
+	&movq	(&QWP(8,$acc),"mm4");
+	&emms	();
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+					}
+    &set_label("slow_enc_x86",16);
+	&mov	($s0,&DWP(0,$key));	# load iv
+	&mov	($s1,&DWP(4,$key));
+
+	&set_label("slow_enc_loop_x86",4);
+		&mov	($s2,&DWP(8,$key));
+		&mov	($s3,&DWP(12,$key));
+
+		&xor	($s0,&DWP(0,$acc));	# xor input data
+		&xor	($s1,&DWP(4,$acc));
+		&xor	($s2,&DWP(8,$acc));
+		&xor	($s3,&DWP(12,$acc));
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_encrypt_compact");
+
+		&mov	($acc,$_inp);		# load inp
+		&mov	($key,$_out);		# load out
+
+		&mov	(&DWP(0,$key),$s0);	# save output data
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($s2,$_len);		# load len
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+		&lea	($s3,&DWP(16,$key));	# advance out
+		&mov	($_out,$s3);		# save out
+		&sub	($s2,16);		# decrease len
+		&cmp	($s2,16);
+		&mov	($_len,$s2);		# save len
+	&jae	(&label("slow_enc_loop_x86"));
+	&test	($s2,15);
+	&jnz	(&label("slow_enc_tail"));
+	&mov	($acc,$_ivp);		# load ivp
+	&mov	($s2,&DWP(8,$key));	# restore last dwords
+	&mov	($s3,&DWP(12,$key));
+	&mov	(&DWP(0,$acc),$s0);	# save ivec
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+    &set_label("slow_enc_tail",16);
+	&emms	()	if (!$x86only);
+	&mov	($key eq "edi"? $key:"",$s3);	# load out to edi
+	&mov	($s1,16);
+	&sub	($s1,$s2);
+	&cmp	($key,$acc eq "esi"? $acc:"");	# compare with inp
+	&je	(&label("enc_in_place"));
+	&align	(4);
+	&data_word(0xA4F3F689);	# rep movsb	# copy input
+	&jmp	(&label("enc_skip_in_place"));
+    &set_label("enc_in_place");
+	&lea	($key,&DWP(0,$key,$s2));
+    &set_label("enc_skip_in_place");
+	&mov	($s2,$s1);
+	&xor	($s0,$s0);
+	&align	(4);
+	&data_word(0xAAF3F689);	# rep stosb	# zero tail
+
+	&mov	($key,$_ivp);			# restore ivp
+	&mov	($acc,$s3);			# output as input
+	&mov	($s0,&DWP(0,$key));
+	&mov	($s1,&DWP(4,$key));
+	&mov	($_len,16);			# len=16
+	&jmp	(&label("slow_enc_loop_x86"));	# one more spin...
+
+#--------------------------- SLOW DECRYPT ---------------------------#
+&set_label("slow_decrypt",16);
+					if (!$x86only) {
+	&bt	($_tmp,25);		# check for SSE bit
+	&jnc	(&label("slow_dec_loop_x86"));
+
+	&set_label("slow_dec_loop_sse",4);
+		&movq	("mm0",&QWP(0,$acc));	# read input
+		&movq	("mm4",&QWP(8,$acc));
+
+		&mov	($key,$_key);
+		&call	("_sse_AES_decrypt_compact");
+
+		&mov	($acc,$_inp);		# load inp
+		&lea	($s0,$ivec);
+		&mov	($s1,$_out);		# load out
+		&mov	($s2,$_len);		# load len
+		&mov	($key,$_ivp);		# load ivp
+
+		&movq	("mm1",&QWP(0,$acc));	# re-read input
+		&movq	("mm5",&QWP(8,$acc));
+
+		&pxor	("mm0",&QWP(0,$key));	# xor iv
+		&pxor	("mm4",&QWP(8,$key));
+
+		&movq	(&QWP(0,$key),"mm1");	# copy input to iv
+		&movq	(&QWP(8,$key),"mm5");
+
+		&sub	($s2,16);		# decrease len
+		&jc	(&label("slow_dec_partial_sse"));
+
+		&movq	(&QWP(0,$s1),"mm0");	# write output
+		&movq	(&QWP(8,$s1),"mm4");
+
+		&lea	($s1,&DWP(16,$s1));	# advance out
+		&mov	($_out,$s1);		# save out
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+		&mov	($_len,$s2);		# save len
+	&jnz	(&label("slow_dec_loop_sse"));
+	&emms	();
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+    &set_label("slow_dec_partial_sse",16);
+	&movq	(&QWP(0,$s0),"mm0");	# save output to temp
+	&movq	(&QWP(8,$s0),"mm4");
+	&emms	();
+
+	&add	($s2 eq "ecx" ? "ecx":"",16);
+	&mov	("edi",$s1);		# out
+	&mov	("esi",$s0);		# temp
+	&align	(4);
+	&data_word(0xA4F3F689);		# rep movsb # copy partial output
+
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+					}
+	&set_label("slow_dec_loop_x86",16);
+		&mov	($s0,&DWP(0,$acc));	# read input
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&lea	($key,$ivec);
+		&mov	(&DWP(0,$key),$s0);	# copy to temp
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($key,$_key);		# load key
+		&call	("_x86_AES_decrypt_compact");
+
+		&mov	($key,$_ivp);		# load ivp
+		&mov	($acc,$_len);		# load len
+		&xor	($s0,&DWP(0,$key));	# xor iv
+		&xor	($s1,&DWP(4,$key));
+		&xor	($s2,&DWP(8,$key));
+		&xor	($s3,&DWP(12,$key));
+
+		&sub	($acc,16);
+		&jc	(&label("slow_dec_partial_x86"));
+
+		&mov	($_len,$acc);		# save len
+		&mov	($acc,$_out);		# load out
+
+		&mov	(&DWP(0,$acc),$s0);	# write output
+		&mov	(&DWP(4,$acc),$s1);
+		&mov	(&DWP(8,$acc),$s2);
+		&mov	(&DWP(12,$acc),$s3);
+
+		&lea	($acc,&DWP(16,$acc));	# advance out
+		&mov	($_out,$acc);		# save out
+
+		&lea	($acc,$ivec);
+		&mov	($s0,&DWP(0,$acc));	# read temp
+		&mov	($s1,&DWP(4,$acc));
+		&mov	($s2,&DWP(8,$acc));
+		&mov	($s3,&DWP(12,$acc));
+
+		&mov	(&DWP(0,$key),$s0);	# copy it to iv
+		&mov	(&DWP(4,$key),$s1);
+		&mov	(&DWP(8,$key),$s2);
+		&mov	(&DWP(12,$key),$s3);
+
+		&mov	($acc,$_inp);		# load inp
+		&lea	($acc,&DWP(16,$acc));	# advance inp
+		&mov	($_inp,$acc);		# save inp
+	&jnz	(&label("slow_dec_loop_x86"));
+	&mov	("esp",$_esp);
+	&popf	();
+	&function_end_A();
+	&pushf	();			# kludge, never executed
+
+    &set_label("slow_dec_partial_x86",16);
+	&lea	($acc,$ivec);
+	&mov	(&DWP(0,$acc),$s0);	# save output to temp
+	&mov	(&DWP(4,$acc),$s1);
+	&mov	(&DWP(8,$acc),$s2);
+	&mov	(&DWP(12,$acc),$s3);
+
+	&mov	($acc,$_inp);
+	&mov	($s0,&DWP(0,$acc));	# re-read input
+	&mov	($s1,&DWP(4,$acc));
+	&mov	($s2,&DWP(8,$acc));
+	&mov	($s3,&DWP(12,$acc));
+
+	&mov	(&DWP(0,$key),$s0);	# copy it to iv
+	&mov	(&DWP(4,$key),$s1);
+	&mov	(&DWP(8,$key),$s2);
+	&mov	(&DWP(12,$key),$s3);
+
+	&mov	("ecx",$_len);
+	&mov	("edi",$_out);
+	&lea	("esi",$ivec);
+	&align	(4);
+	&data_word(0xA4F3F689);		# rep movsb # copy partial output
+
+	&mov	("esp",$_esp);
+	&popf	();
+&function_end("AES_cbc_encrypt");
+}
+
+#------------------------------------------------------------------#
+
+sub enckey()
+{
+	&movz	("esi",&LB("edx"));		# rk[i]>>0
+	&movz	("ebx",&BP(-128,$tbl,"esi",1));
+	&movz	("esi",&HB("edx"));		# rk[i]>>8
+	&shl	("ebx",24);
+	&xor	("eax","ebx");
+
+	&movz	("ebx",&BP(-128,$tbl,"esi",1));
+	&shr	("edx",16);
+	&movz	("esi",&LB("edx"));		# rk[i]>>16
+	&xor	("eax","ebx");
+
+	&movz	("ebx",&BP(-128,$tbl,"esi",1));
+	&movz	("esi",&HB("edx"));		# rk[i]>>24
+	&shl	("ebx",8);
+	&xor	("eax","ebx");
+
+	&movz	("ebx",&BP(-128,$tbl,"esi",1));
+	&shl	("ebx",16);
+	&xor	("eax","ebx");
+
+	&xor	("eax",&DWP(1024-128,$tbl,"ecx",4));	# rcon
+}
+
+&function_begin("_x86_AES_set_encrypt_key");
+	&mov	("esi",&wparam(1));		# user supplied key
+	&mov	("edi",&wparam(3));		# private key schedule
+
+	&test	("esi",-1);
+	&jz	(&label("badpointer"));
+	&test	("edi",-1);
+	&jz	(&label("badpointer"));
+
+	&call	(&label("pic_point"));
+	&set_label("pic_point");
+	&blindpop($tbl);
+	&lea	($tbl,&DWP(&label("AES_Te")."-".&label("pic_point"),$tbl));
+	&lea	($tbl,&DWP(2048+128,$tbl));
+
+	# prefetch Te4
+	&mov	("eax",&DWP(0-128,$tbl));
+	&mov	("ebx",&DWP(32-128,$tbl));
+	&mov	("ecx",&DWP(64-128,$tbl));
+	&mov	("edx",&DWP(96-128,$tbl));
+	&mov	("eax",&DWP(128-128,$tbl));
+	&mov	("ebx",&DWP(160-128,$tbl));
+	&mov	("ecx",&DWP(192-128,$tbl));
+	&mov	("edx",&DWP(224-128,$tbl));
+
+	&mov	("ecx",&wparam(2));		# number of bits in key
+	&cmp	("ecx",128);
+	&je	(&label("10rounds"));
+	&cmp	("ecx",192);
+	&je	(&label("12rounds"));
+	&cmp	("ecx",256);
+	&je	(&label("14rounds"));
+	&mov	("eax",-2);			# invalid number of bits
+	&jmp	(&label("exit"));
+
+    &set_label("10rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 4 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("10shortcut"));
+
+	&align	(4);
+	&set_label("10loop");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+		&mov	("edx",&DWP(12,"edi"));		# rk[3]
+	&set_label("10shortcut");
+		&enckey	();
+
+		&mov	(&DWP(16,"edi"),"eax");		# rk[4]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(20,"edi"),"eax");		# rk[5]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(24,"edi"),"eax");		# rk[6]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(28,"edi"),"eax");		# rk[7]
+		&inc	("ecx");
+		&add	("edi",16);
+		&cmp	("ecx",10);
+	&jl	(&label("10loop"));
+
+	&mov	(&DWP(80,"edi"),10);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+
+    &set_label("12rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 6 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+	&mov	("ecx",&DWP(16,"esi"));
+	&mov	("edx",&DWP(20,"esi"));
+	&mov	(&DWP(16,"edi"),"ecx");
+	&mov	(&DWP(20,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("12shortcut"));
+
+	&align	(4);
+	&set_label("12loop");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+		&mov	("edx",&DWP(20,"edi"));		# rk[5]
+	&set_label("12shortcut");
+		&enckey	();
+
+		&mov	(&DWP(24,"edi"),"eax");		# rk[6]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(28,"edi"),"eax");		# rk[7]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(32,"edi"),"eax");		# rk[8]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(36,"edi"),"eax");		# rk[9]
+
+		&cmp	("ecx",7);
+		&je	(&label("12break"));
+		&inc	("ecx");
+
+		&xor	("eax",&DWP(16,"edi"));
+		&mov	(&DWP(40,"edi"),"eax");		# rk[10]
+		&xor	("eax",&DWP(20,"edi"));
+		&mov	(&DWP(44,"edi"),"eax");		# rk[11]
+
+		&add	("edi",24);
+	&jmp	(&label("12loop"));
+
+	&set_label("12break");
+	&mov	(&DWP(72,"edi"),12);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+
+    &set_label("14rounds");
+	&mov	("eax",&DWP(0,"esi"));		# copy first 8 dwords
+	&mov	("ebx",&DWP(4,"esi"));
+	&mov	("ecx",&DWP(8,"esi"));
+	&mov	("edx",&DWP(12,"esi"));
+	&mov	(&DWP(0,"edi"),"eax");
+	&mov	(&DWP(4,"edi"),"ebx");
+	&mov	(&DWP(8,"edi"),"ecx");
+	&mov	(&DWP(12,"edi"),"edx");
+	&mov	("eax",&DWP(16,"esi"));
+	&mov	("ebx",&DWP(20,"esi"));
+	&mov	("ecx",&DWP(24,"esi"));
+	&mov	("edx",&DWP(28,"esi"));
+	&mov	(&DWP(16,"edi"),"eax");
+	&mov	(&DWP(20,"edi"),"ebx");
+	&mov	(&DWP(24,"edi"),"ecx");
+	&mov	(&DWP(28,"edi"),"edx");
+
+	&xor	("ecx","ecx");
+	&jmp	(&label("14shortcut"));
+
+	&align	(4);
+	&set_label("14loop");
+		&mov	("edx",&DWP(28,"edi"));		# rk[7]
+	&set_label("14shortcut");
+		&mov	("eax",&DWP(0,"edi"));		# rk[0]
+
+		&enckey	();
+
+		&mov	(&DWP(32,"edi"),"eax");		# rk[8]
+		&xor	("eax",&DWP(4,"edi"));
+		&mov	(&DWP(36,"edi"),"eax");		# rk[9]
+		&xor	("eax",&DWP(8,"edi"));
+		&mov	(&DWP(40,"edi"),"eax");		# rk[10]
+		&xor	("eax",&DWP(12,"edi"));
+		&mov	(&DWP(44,"edi"),"eax");		# rk[11]
+
+		&cmp	("ecx",6);
+		&je	(&label("14break"));
+		&inc	("ecx");
+
+		&mov	("edx","eax");
+		&mov	("eax",&DWP(16,"edi"));		# rk[4]
+		&movz	("esi",&LB("edx"));		# rk[11]>>0
+		&movz	("ebx",&BP(-128,$tbl,"esi",1));
+		&movz	("esi",&HB("edx"));		# rk[11]>>8
+		&xor	("eax","ebx");
+
+		&movz	("ebx",&BP(-128,$tbl,"esi",1));
+		&shr	("edx",16);
+		&shl	("ebx",8);
+		&movz	("esi",&LB("edx"));		# rk[11]>>16
+		&xor	("eax","ebx");
+
+		&movz	("ebx",&BP(-128,$tbl,"esi",1));
+		&movz	("esi",&HB("edx"));		# rk[11]>>24
+		&shl	("ebx",16);
+		&xor	("eax","ebx");
+
+		&movz	("ebx",&BP(-128,$tbl,"esi",1));
+		&shl	("ebx",24);
+		&xor	("eax","ebx");
+
+		&mov	(&DWP(48,"edi"),"eax");		# rk[12]
+		&xor	("eax",&DWP(20,"edi"));
+		&mov	(&DWP(52,"edi"),"eax");		# rk[13]
+		&xor	("eax",&DWP(24,"edi"));
+		&mov	(&DWP(56,"edi"),"eax");		# rk[14]
+		&xor	("eax",&DWP(28,"edi"));
+		&mov	(&DWP(60,"edi"),"eax");		# rk[15]
+
+		&add	("edi",32);
+	&jmp	(&label("14loop"));
+
+	&set_label("14break");
+	&mov	(&DWP(48,"edi"),14);		# setup number of rounds
+	&xor	("eax","eax");
+	&jmp	(&label("exit"));
+
+    &set_label("badpointer");
+	&mov	("eax",-1);
+    &set_label("exit");
+&function_end("_x86_AES_set_encrypt_key");
+
+# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+#                        AES_KEY *key)
+&function_begin_B("AES_set_encrypt_key");
+	&call	("_x86_AES_set_encrypt_key");
+	&ret	();
+&function_end_B("AES_set_encrypt_key");
+
+sub deckey()
+{ my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_;
+  my $tmp = $tbl;
+
+	&mov	($tmp,0x80808080);
+	&and	($tmp,$tp1);
+	&lea	($tp2,&DWP(0,$tp1,$tp1));
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&sub	($acc,$tmp);
+	&and	($tp2,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	&xor	($tp2,$acc);
+	&mov	($tmp,0x80808080);
+
+	&and	($tmp,$tp2);
+	&lea	($tp4,&DWP(0,$tp2,$tp2));
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	&sub	($acc,$tmp);
+	&and	($tp4,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	 &xor	($tp2,$tp1);	# tp2^tp1
+	&xor	($tp4,$acc);
+	&mov	($tmp,0x80808080);
+
+	&and	($tmp,$tp4);
+	&lea	($tp8,&DWP(0,$tp4,$tp4));
+	&mov	($acc,$tmp);
+	&shr	($tmp,7);
+	 &xor	($tp4,$tp1);	# tp4^tp1
+	&sub	($acc,$tmp);
+	&and	($tp8,0xfefefefe);
+	&and	($acc,0x1b1b1b1b);
+	 &rotl	($tp1,8);	# = ROTATE(tp1,8)
+	&xor	($tp8,$acc);
+
+	&mov	($tmp,&DWP(4*($i+1),$key));	# modulo-scheduled load
+
+	&xor	($tp1,$tp2);
+	&xor	($tp2,$tp8);
+	&xor	($tp1,$tp4);
+	&rotl	($tp2,24);
+	&xor	($tp4,$tp8);
+	&xor	($tp1,$tp8);	# ^= tp8^(tp4^tp1)^(tp2^tp1)
+	&rotl	($tp4,16);
+	&xor	($tp1,$tp2);	# ^= ROTATE(tp8^tp2^tp1,24)
+	&rotl	($tp8,8);
+	&xor	($tp1,$tp4);	# ^= ROTATE(tp8^tp4^tp1,16)
+	&mov	($tp2,$tmp);
+	&xor	($tp1,$tp8);	# ^= ROTATE(tp8,8)
+
+	&mov	(&DWP(4*$i,$key),$tp1);
+}
+
+# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+#                        AES_KEY *key)
+&function_begin_B("AES_set_decrypt_key");
+	&call	("_x86_AES_set_encrypt_key");
+	&cmp	("eax",0);
+	&je	(&label("proceed"));
+	&ret	();
+
+    &set_label("proceed");
+	&push	("ebp");
+	&push	("ebx");
+	&push	("esi");
+	&push	("edi");
+
+	&mov	("esi",&wparam(2));
+	&mov	("ecx",&DWP(240,"esi"));	# pull number of rounds
+	&lea	("ecx",&DWP(0,"","ecx",4));
+	&lea	("edi",&DWP(0,"esi","ecx",4));	# pointer to last chunk
+
+	&set_label("invert",4);			# invert order of chunks
+		&mov	("eax",&DWP(0,"esi"));
+		&mov	("ebx",&DWP(4,"esi"));
+		&mov	("ecx",&DWP(0,"edi"));
+		&mov	("edx",&DWP(4,"edi"));
+		&mov	(&DWP(0,"edi"),"eax");
+		&mov	(&DWP(4,"edi"),"ebx");
+		&mov	(&DWP(0,"esi"),"ecx");
+		&mov	(&DWP(4,"esi"),"edx");
+		&mov	("eax",&DWP(8,"esi"));
+		&mov	("ebx",&DWP(12,"esi"));
+		&mov	("ecx",&DWP(8,"edi"));
+		&mov	("edx",&DWP(12,"edi"));
+		&mov	(&DWP(8,"edi"),"eax");
+		&mov	(&DWP(12,"edi"),"ebx");
+		&mov	(&DWP(8,"esi"),"ecx");
+		&mov	(&DWP(12,"esi"),"edx");
+		&add	("esi",16);
+		&sub	("edi",16);
+		&cmp	("esi","edi");
+	&jne	(&label("invert"));
+
+	&mov	($key,&wparam(2));
+	&mov	($acc,&DWP(240,$key));		# pull number of rounds
+	&lea	($acc,&DWP(-2,$acc,$acc));
+	&lea	($acc,&DWP(0,$key,$acc,8));
+	&mov	(&wparam(2),$acc);
+
+	&mov	($s0,&DWP(16,$key));		# modulo-scheduled load
+	&set_label("permute",4);		# permute the key schedule
+		&add	($key,16);
+		&deckey	(0,$key,$s0,$s1,$s2,$s3);
+		&deckey	(1,$key,$s1,$s2,$s3,$s0);
+		&deckey	(2,$key,$s2,$s3,$s0,$s1);
+		&deckey	(3,$key,$s3,$s0,$s1,$s2);
+		&cmp	($key,&wparam(2));
+	&jb	(&label("permute"));
+
+	&xor	("eax","eax");			# return success
+&function_end("AES_set_decrypt_key");
+&asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
+
+close STDOUT or die "error closing STDOUT: $!";

+ 1061 - 0
libs/openssl/crypto/aes/asm/aes-riscv32-zkn.pl

@@ -0,0 +1,1061 @@
+#! /usr/bin/env perl
+# Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# $output is the last argument if it looks like a file (it has an extension)
+# $flavour is the first argument if it doesn't look like a file
+$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+
+$output and open STDOUT,">$output";
+
+################################################################################
+# Utility functions to help with keeping track of which registers to stack/
+# unstack when entering / exiting routines.
+################################################################################
+{
+    # Callee-saved registers
+    my @callee_saved = map("x$_",(2,8,9,18..27));
+    # Caller-saved registers
+    my @caller_saved = map("x$_",(1,5..7,10..17,28..31));
+    my @must_save;
+    sub use_reg {
+        my $reg = shift;
+        if (grep(/^$reg$/, @callee_saved)) {
+            push(@must_save, $reg);
+        } elsif (!grep(/^$reg$/, @caller_saved)) {
+            # Register is not usable!
+            die("Unusable register ".$reg);
+        }
+        return $reg;
+    }
+    sub use_regs {
+        return map(use_reg("x$_"), @_);
+    }
+    sub save_regs {
+        my $ret = '';
+        my $stack_reservation = ($#must_save + 1) * 8;
+        my $stack_offset = $stack_reservation;
+        if ($stack_reservation % 16) {
+            $stack_reservation += 8;
+        }
+        $ret.="    addi    sp,sp,-$stack_reservation\n";
+        foreach (@must_save) {
+            $stack_offset -= 8;
+            $ret.="    sw      $_,$stack_offset(sp)\n";
+        }
+        return $ret;
+    }
+    sub load_regs {
+        my $ret = '';
+        my $stack_reservation = ($#must_save + 1) * 8;
+        my $stack_offset = $stack_reservation;
+        if ($stack_reservation % 16) {
+            $stack_reservation += 8;
+        }
+        foreach (@must_save) {
+            $stack_offset -= 8;
+            $ret.="    lw      $_,$stack_offset(sp)\n";
+        }
+        $ret.="    addi    sp,sp,$stack_reservation\n";
+        return $ret;
+    }
+    sub clear_regs {
+        @must_save = ();
+    }
+}
+
+################################################################################
+# util for encoding scalar crypto extension instructions
+################################################################################
+
+my @regs = map("x$_",(0..31));
+my %reglookup;
+@reglookup{@regs} = @regs;
+
+# Takes a register name, possibly an alias, and converts it to a register index
+# from 0 to 31
+sub read_reg {
+    my $reg = lc shift;
+    if (!exists($reglookup{$reg})) {
+        die("Unknown register ".$reg);
+    }
+    my $regstr = $reglookup{$reg};
+    if (!($regstr =~ /^x([0-9]+)$/)) {
+        die("Could not process register ".$reg);
+    }
+    return $1;
+}
+
+sub aes32dsi {
+    # Encoding for aes32dsi rd, rs1, rs2, bs instruction on RV32
+    #                bs_XXXXX_ rs2 _ rs1 _XXX_ rd  _XXXXXXX
+    my $template = 0b00_10101_00000_00000_000_00000_0110011;
+    my $rd = read_reg shift;
+    my $rs1 = read_reg shift;
+    my $rs2 = read_reg shift;
+    my $bs = shift;
+
+    return ".word ".($template | ($bs << 30) | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
+}
+
+sub aes32dsmi {
+    # Encoding for aes32dsmi rd, rs1, rs2, bs instruction on RV32
+    #                bs_XXXXX_ rs2 _ rs1 _XXX_ rd  _XXXXXXX
+    my $template = 0b00_10111_00000_00000_000_00000_0110011;
+    my $rd = read_reg shift;
+    my $rs1 = read_reg shift;
+    my $rs2 = read_reg shift;
+    my $bs = shift;
+
+    return ".word ".($template | ($bs << 30) | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
+}
+
+sub aes32esi {
+    # Encoding for aes32esi rd, rs1, rs2, bs instruction on RV32
+    #                bs_XXXXX_ rs2 _ rs1 _XXX_ rd  _XXXXXXX
+    my $template = 0b00_10001_00000_00000_000_00000_0110011;
+    my $rd = read_reg shift;
+    my $rs1 = read_reg shift;
+    my $rs2 = read_reg shift;
+    my $bs = shift;
+
+    return ".word ".($template | ($bs << 30) | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
+}
+
+sub aes32esmi {
+    # Encoding for aes32esmi rd, rs1, rs2, bs instruction on RV32
+    #                bs_XXXXX_ rs2 _ rs1 _XXX_ rd  _XXXXXXX
+    my $template = 0b00_10011_00000_00000_000_00000_0110011;
+    my $rd = read_reg shift;
+    my $rs1 = read_reg shift;
+    my $rs2 = read_reg shift;
+    my $bs = shift;
+
+    return ".word ".($template | ($bs << 30) | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
+}
+
+sub rori {
+    # Encoding for ror rd, rs1, imm instruction on RV64
+    #                XXXXXXX_shamt_ rs1 _XXX_ rd  _XXXXXXX
+    my $template = 0b0110000_00000_00000_101_00000_0010011;
+    my $rd = read_reg shift;
+    my $rs1 = read_reg shift;
+    my $shamt = shift;
+
+    return ".word ".($template | ($shamt << 20) | ($rs1 << 15) | ($rd << 7));
+}
+
+################################################################################
+# Register assignment for rv32i_zkne_encrypt and rv32i_zknd_decrypt
+################################################################################
+
+# Registers initially to hold AES state (called s0-s3 or y0-y3 elsewhere)
+my ($Q0,$Q1,$Q2,$Q3) = use_regs(6..9);
+
+# Function arguments (x10-x12 are a0-a2 in the ABI)
+# Input block pointer, output block pointer, key pointer
+my ($INP,$OUTP,$KEYP) = use_regs(10..12);
+
+# Registers initially to hold Key
+my ($T0,$T1,$T2,$T3) = use_regs(13..16);
+
+# Loop counter
+my ($loopcntr) = use_regs(30);
+
+################################################################################
+# Utility for rv32i_zkne_encrypt and rv32i_zknd_decrypt
+################################################################################
+
+# outer product of whole state into one column of key
+sub outer {
+    my $inst = shift;
+    my $key = shift;
+    # state 0 to 3
+    my $s0 = shift;
+    my $s1 = shift;
+    my $s2 = shift;
+    my $s3 = shift;
+    my $ret = '';
+$ret .= <<___;
+    @{[$inst->($key,$key,$s0,0)]}
+    @{[$inst->($key,$key,$s1,1)]}
+    @{[$inst->($key,$key,$s2,2)]}
+    @{[$inst->($key,$key,$s3,3)]}
+___
+    return $ret;
+}
+
+sub aes32esmi4 {
+    return outer(\&aes32esmi, @_)
+}
+
+sub aes32esi4 {
+    return outer(\&aes32esi, @_)
+}
+
+sub aes32dsmi4 {
+    return outer(\&aes32dsmi, @_)
+}
+
+sub aes32dsi4 {
+    return outer(\&aes32dsi, @_)
+}
+
+################################################################################
+# void rv32i_zkne_encrypt(const unsigned char *in, unsigned char *out,
+#   const AES_KEY *key);
+################################################################################
+my $code .= <<___;
+.text
+.balign 16
+.globl rv32i_zkne_encrypt
+.type   rv32i_zkne_encrypt,\@function
+rv32i_zkne_encrypt:
+___
+
+$code .= save_regs();
+
+$code .= <<___;
+    # Load input to block cipher
+    lw      $Q0,0($INP)
+    lw      $Q1,4($INP)
+    lw      $Q2,8($INP)
+    lw      $Q3,12($INP)
+
+    # Load key
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    # Load number of rounds
+    lw      $loopcntr,240($KEYP)
+
+    # initial transformation
+    xor     $Q0,$Q0,$T0
+    xor     $Q1,$Q1,$T1
+    xor     $Q2,$Q2,$T2
+    xor     $Q3,$Q3,$T3
+
+    # The main loop only executes the first N-2 rounds, each loop consumes two rounds
+    add     $loopcntr,$loopcntr,-2
+    srli    $loopcntr,$loopcntr,1
+1:
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,16
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    @{[aes32esmi4 $T0,$Q0,$Q1,$Q2,$Q3]}
+    @{[aes32esmi4 $T1,$Q1,$Q2,$Q3,$Q0]}
+    @{[aes32esmi4 $T2,$Q2,$Q3,$Q0,$Q1]}
+    @{[aes32esmi4 $T3,$Q3,$Q0,$Q1,$Q2]}
+    # now T0~T3 hold the new state
+
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,16
+    lw      $Q0,0($KEYP)
+    lw      $Q1,4($KEYP)
+    lw      $Q2,8($KEYP)
+    lw      $Q3,12($KEYP)
+
+    @{[aes32esmi4 $Q0,$T0,$T1,$T2,$T3]}
+    @{[aes32esmi4 $Q1,$T1,$T2,$T3,$T0]}
+    @{[aes32esmi4 $Q2,$T2,$T3,$T0,$T1]}
+    @{[aes32esmi4 $Q3,$T3,$T0,$T1,$T2]}
+    # now Q0~Q3 hold the new state
+
+    add     $loopcntr,$loopcntr,-1
+    bgtz    $loopcntr,1b
+
+# final two rounds
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,16
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    @{[aes32esmi4 $T0,$Q0,$Q1,$Q2,$Q3]}
+    @{[aes32esmi4 $T1,$Q1,$Q2,$Q3,$Q0]}
+    @{[aes32esmi4 $T2,$Q2,$Q3,$Q0,$Q1]}
+    @{[aes32esmi4 $T3,$Q3,$Q0,$Q1,$Q2]}
+    # now T0~T3 hold the new state
+
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,16
+    lw      $Q0,0($KEYP)
+    lw      $Q1,4($KEYP)
+    lw      $Q2,8($KEYP)
+    lw      $Q3,12($KEYP)
+
+    # no mix column now
+    @{[aes32esi4 $Q0,$T0,$T1,$T2,$T3]}
+    @{[aes32esi4 $Q1,$T1,$T2,$T3,$T0]}
+    @{[aes32esi4 $Q2,$T2,$T3,$T0,$T1]}
+    @{[aes32esi4 $Q3,$T3,$T0,$T1,$T2]}
+    # now Q0~Q3 hold the new state
+
+    sw      $Q0,0($OUTP)
+    sw      $Q1,4($OUTP)
+    sw      $Q2,8($OUTP)
+    sw      $Q3,12($OUTP)
+
+    # Pop registers and return
+___
+
+$code .= load_regs();
+
+$code .= <<___;
+    ret
+___
+
+################################################################################
+# void rv32i_zknd_decrypt(const unsigned char *in, unsigned char *out,
+#   const AES_KEY *key);
+################################################################################
+$code .= <<___;
+.text
+.balign 16
+.globl rv32i_zknd_decrypt
+.type   rv32i_zknd_decrypt,\@function
+rv32i_zknd_decrypt:
+___
+
+$code .= save_regs();
+
+$code .= <<___;
+    # Load input to block cipher
+    lw      $Q0,0($INP)
+    lw      $Q1,4($INP)
+    lw      $Q2,8($INP)
+    lw      $Q3,12($INP)
+
+    # Load number of rounds
+    lw      $loopcntr,240($KEYP)
+
+    # Load the last key
+    # use T0 as temporary now
+    slli    $T0,$loopcntr,4
+    add     $KEYP,$KEYP,$T0
+    # Load key
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    # initial transformation
+    xor     $Q0,$Q0,$T0
+    xor     $Q1,$Q1,$T1
+    xor     $Q2,$Q2,$T2
+    xor     $Q3,$Q3,$T3
+
+    # The main loop only executes the first N-2 rounds, each loop consumes two rounds
+    add     $loopcntr,$loopcntr,-2
+    srli    $loopcntr,$loopcntr,1
+1:
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,-16
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    @{[aes32dsmi4 $T0,$Q0,$Q3,$Q2,$Q1]}
+    @{[aes32dsmi4 $T1,$Q1,$Q0,$Q3,$Q2]}
+    @{[aes32dsmi4 $T2,$Q2,$Q1,$Q0,$Q3]}
+    @{[aes32dsmi4 $T3,$Q3,$Q2,$Q1,$Q0]}
+    # now T0~T3 hold the new state
+
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,-16
+    lw      $Q0,0($KEYP)
+    lw      $Q1,4($KEYP)
+    lw      $Q2,8($KEYP)
+    lw      $Q3,12($KEYP)
+
+    @{[aes32dsmi4 $Q0,$T0,$T3,$T2,$T1]}
+    @{[aes32dsmi4 $Q1,$T1,$T0,$T3,$T2]}
+    @{[aes32dsmi4 $Q2,$T2,$T1,$T0,$T3]}
+    @{[aes32dsmi4 $Q3,$T3,$T2,$T1,$T0]}
+    # now Q0~Q3 hold the new state
+
+    add     $loopcntr,$loopcntr,-1
+    bgtz    $loopcntr,1b
+
+# final two rounds
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,-16
+    lw      $T0,0($KEYP)
+    lw      $T1,4($KEYP)
+    lw      $T2,8($KEYP)
+    lw      $T3,12($KEYP)
+
+    @{[aes32dsmi4 $T0,$Q0,$Q3,$Q2,$Q1]}
+    @{[aes32dsmi4 $T1,$Q1,$Q0,$Q3,$Q2]}
+    @{[aes32dsmi4 $T2,$Q2,$Q1,$Q0,$Q3]}
+    @{[aes32dsmi4 $T3,$Q3,$Q2,$Q1,$Q0]}
+    # now T0~T3 hold the new state
+
+    # Grab next key in schedule
+    add     $KEYP,$KEYP,-16
+    lw      $Q0,0($KEYP)
+    lw      $Q1,4($KEYP)
+    lw      $Q2,8($KEYP)
+    lw      $Q3,12($KEYP)
+
+    # no mix column now
+    @{[aes32dsi4 $Q0,$T0,$T3,$T2,$T1]}
+    @{[aes32dsi4 $Q1,$T1,$T0,$T3,$T2]}
+    @{[aes32dsi4 $Q2,$T2,$T1,$T0,$T3]}
+    @{[aes32dsi4 $Q3,$T3,$T2,$T1,$T0]}
+    # now Q0~Q3 hold the new state
+
+    sw      $Q0,0($OUTP)
+    sw      $Q1,4($OUTP)
+    sw      $Q2,8($OUTP)
+    sw      $Q3,12($OUTP)
+
+    # Pop registers and return
+___
+
+$code .= load_regs();
+
+$code .= <<___;
+    ret
+___
+
+clear_regs();
+
+################################################################################
+# Register assignment for rv32i_zkn[e/d]_set_[en/de]crypt
+################################################################################
+
+# Function arguments (x10-x12 are a0-a2 in the ABI)
+# Pointer to user key, number of bits in key, key pointer
+my ($UKEY,$BITS,$KEYP) = use_regs(10..12);
+
+# Temporaries
+my ($T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7,$T8) = use_regs(13..17,28..31);
+
+################################################################################
+# utility functions for rv32i_zkne_set_encrypt_key
+################################################################################
+
+my @rcon = (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36);
+
+# do 4 sbox on 4 bytes of rs, (possibly mix), then xor with rd
+sub sbox4 {
+    my $inst = shift;
+    my $rd = shift;
+    my $rs = shift;
+    my $ret = <<___;
+    @{[$inst->($rd,$rd,$rs,0)]}
+    @{[$inst->($rd,$rd,$rs,1)]}
+    @{[$inst->($rd,$rd,$rs,2)]}
+    @{[$inst->($rd,$rd,$rs,3)]}
+___
+    return $ret;
+}
+
+sub fwdsbox4 {
+    return sbox4(\&aes32esi, @_);
+}
+
+sub ke128enc {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+    while($rnum < 10) {
+$ret .= <<___;
+    # use T4 to store rcon
+    li      $T4,$rcon[$rnum]
+    # as xor is associative and commutative
+    # we fist xor T0 with RCON, then use T0 to
+    # xor the result of each SBOX result of T3
+    xor     $T0,$T0,$T4
+    # use T4 to store rotated T3
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T4,$T3,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T4,$T3,8
+    slli    $T5,$T3,24
+    or      $T4,$T4,$T5
+___
+        }
+$ret .= <<___;
+    # update T0
+    @{[fwdsbox4 $T0,$T4]}
+
+    # update new T1~T3
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+
+    add     $KEYP,$KEYP,16
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+        $rnum++;
+    }
+    return $ret;
+}
+
+sub ke192enc {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+    lw      $T4,16($UKEY)
+    lw      $T5,20($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+    sw      $T4,16($KEYP)
+    sw      $T5,20($KEYP)
+___
+    while($rnum < 8) {
+$ret .= <<___;
+    # see the comment in ke128enc
+    li      $T6,$rcon[$rnum]
+    xor     $T0,$T0,$T6
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T6,$T5,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T6,$T5,8
+    slli    $T7,$T5,24
+    or      $T6,$T6,$T7
+___
+        }
+$ret .= <<___;
+    @{[fwdsbox4 $T0,$T6]}
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+___
+        if ($rnum != 7) {
+        # note that (8+1)*24 = 216, (12+1)*16 = 208
+        # thus the last 8 bytes can be dropped
+$ret .= <<___;
+    xor     $T4,$T4,$T3
+    xor     $T5,$T5,$T4
+___
+        }
+$ret .= <<___;
+    add     $KEYP,$KEYP,24
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+        if ($rnum != 7) {
+$ret .= <<___;
+    sw      $T4,16($KEYP)
+    sw      $T5,20($KEYP)
+___
+        }
+        $rnum++;
+    }
+    return $ret;
+}
+
+sub ke256enc {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+    lw      $T4,16($UKEY)
+    lw      $T5,20($UKEY)
+    lw      $T6,24($UKEY)
+    lw      $T7,28($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+    sw      $T4,16($KEYP)
+    sw      $T5,20($KEYP)
+    sw      $T6,24($KEYP)
+    sw      $T7,28($KEYP)
+___
+    while($rnum < 7) {
+$ret .= <<___;
+    # see the comment in ke128enc
+    li      $T8,$rcon[$rnum]
+    xor     $T0,$T0,$T8
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T8,$T7,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T8,$T7,8
+    slli    $BITS,$T7,24
+    or      $T8,$T8,$BITS
+___
+        }
+$ret .= <<___;
+    @{[fwdsbox4 $T0,$T8]}
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+
+    add     $KEYP,$KEYP,32
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+        if ($rnum != 6) {
+        # note that (7+1)*32 = 256, (14+1)*16 = 240
+        # thus the last 16 bytes can be dropped
+$ret .= <<___;
+    # for aes256, T3->T4 needs 4sbox but no rotate/rcon
+    @{[fwdsbox4 $T4,$T3]}
+    xor     $T5,$T5,$T4
+    xor     $T6,$T6,$T5
+    xor     $T7,$T7,$T6
+    sw      $T4,16($KEYP)
+    sw      $T5,20($KEYP)
+    sw      $T6,24($KEYP)
+    sw      $T7,28($KEYP)
+___
+        }
+        $rnum++;
+    }
+    return $ret;
+}
+
+################################################################################
+# void rv32i_zkne_set_encrypt_key(const unsigned char *userKey, const int bits,
+#   AES_KEY *key)
+################################################################################
+sub AES_set_common {
+    my ($ke128, $ke192, $ke256) = @_;
+    my $ret = '';
+$ret .= <<___;
+    bnez    $UKEY,1f        # if (!userKey || !key) return -1;
+    bnez    $KEYP,1f
+    li      a0,-1
+    ret
+1:
+    # Determine number of rounds from key size in bits
+    li      $T0,128
+    bne     $BITS,$T0,1f
+    li      $T1,10          # key->rounds = 10 if bits == 128
+    sw      $T1,240($KEYP)  # store key->rounds
+$ke128
+    j       4f
+1:
+    li      $T0,192
+    bne     $BITS,$T0,2f
+    li      $T1,12          # key->rounds = 12 if bits == 192
+    sw      $T1,240($KEYP)  # store key->rounds
+$ke192
+    j       4f
+2:
+    li      $T1,14          # key->rounds = 14 if bits == 256
+    li      $T0,256
+    beq     $BITS,$T0,3f
+    li      a0,-2           # If bits != 128, 192, or 256, return -2
+    j       5f
+3:
+    sw      $T1,240($KEYP)  # store key->rounds
+$ke256
+4:  # return 0
+    li      a0,0
+5:  # return a0
+___
+    return $ret;
+}
+$code .= <<___;
+.text
+.balign 16
+.globl rv32i_zkne_set_encrypt_key
+.type rv32i_zkne_set_encrypt_key,\@function
+rv32i_zkne_set_encrypt_key:
+___
+
+$code .= save_regs();
+$code .= AES_set_common(ke128enc(0), ke192enc(0),ke256enc(0));
+$code .= load_regs();
+$code .= <<___;
+    ret
+___
+
+################################################################################
+# void rv32i_zbkb_zkne_set_encrypt_key(const unsigned char *userKey,
+#   const int bits, AES_KEY *key)
+################################################################################
+$code .= <<___;
+.text
+.balign 16
+.globl rv32i_zbkb_zkne_set_encrypt_key
+.type rv32i_zbkb_zkne_set_encrypt_key,\@function
+rv32i_zbkb_zkne_set_encrypt_key:
+___
+
+$code .= save_regs();
+$code .= AES_set_common(ke128enc(1), ke192enc(1),ke256enc(1));
+$code .= load_regs();
+$code .= <<___;
+    ret
+___
+
+################################################################################
+# utility functions for rv32i_zknd_zkne_set_decrypt_key
+################################################################################
+
+sub invm4 {
+    # fwd sbox then inv sbox then mix column
+    # the result is only mix column
+    # this simulates aes64im T0
+    my $rd = shift;
+    my $tmp = shift;
+    my $rs = shift;
+    my $ret = <<___;
+    li      $tmp,0
+    li      $rd,0
+    @{[fwdsbox4 $tmp,$rs]}
+    @{[sbox4(\&aes32dsmi, $rd,$tmp)]}
+___
+    return $ret;
+}
+
+sub ke128dec {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+    while($rnum < 10) {
+$ret .= <<___;
+    # see comments in ke128enc
+    li      $T4,$rcon[$rnum]
+    xor     $T0,$T0,$T4
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T4,$T3,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T4,$T3,8
+    slli    $T5,$T3,24
+    or      $T4,$T4,$T5
+___
+        }
+$ret .= <<___;
+    @{[fwdsbox4 $T0,$T4]}
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+    add     $KEYP,$KEYP,16
+___
+    # need to mixcolumn only for [1:N-1] round keys
+    # this is from the fact that aes32dsmi subwords first then mix column
+    # intuitively decryption needs to first mix column then subwords
+    # however, for merging datapaths (encryption first subwords then mix column)
+    # aes32dsmi chooses to inverse the order of them, thus
+    # transform should then be done on the round key
+        if ($rnum < 9) {
+$ret .= <<___;
+    # T4 and T5 are temp variables
+    @{[invm4 $T5,$T4,$T0]}
+    sw      $T5,0($KEYP)
+    @{[invm4 $T5,$T4,$T1]}
+    sw      $T5,4($KEYP)
+    @{[invm4 $T5,$T4,$T2]}
+    sw      $T5,8($KEYP)
+    @{[invm4 $T5,$T4,$T3]}
+    sw      $T5,12($KEYP)
+___
+        } else {
+$ret .= <<___;
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+        }
+        $rnum++;
+    }
+    return $ret;
+}
+
+sub ke192dec {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+    lw      $T4,16($UKEY)
+    lw      $T5,20($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+    # see the comment in ke128dec
+    # T7 and T6 are temp variables
+    @{[invm4 $T7,$T6,$T4]}
+    sw      $T7,16($KEYP)
+    @{[invm4 $T7,$T6,$T5]}
+    sw      $T7,20($KEYP)
+___
+    while($rnum < 8) {
+$ret .= <<___;
+    # see the comment in ke128enc
+    li      $T6,$rcon[$rnum]
+    xor     $T0,$T0,$T6
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T6,$T5,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T6,$T5,8
+    slli    $T7,$T5,24
+    or      $T6,$T6,$T7
+___
+        }
+$ret .= <<___;
+    @{[fwdsbox4 $T0,$T6]}
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+
+    add     $KEYP,$KEYP,24
+___
+        if ($rnum < 7) {
+$ret .= <<___;
+    xor     $T4,$T4,$T3
+    xor     $T5,$T5,$T4
+
+    # see the comment in ke128dec
+    # T7 and T6 are temp variables
+    @{[invm4 $T7,$T6,$T0]}
+    sw      $T7,0($KEYP)
+    @{[invm4 $T7,$T6,$T1]}
+    sw      $T7,4($KEYP)
+    @{[invm4 $T7,$T6,$T2]}
+    sw      $T7,8($KEYP)
+    @{[invm4 $T7,$T6,$T3]}
+    sw      $T7,12($KEYP)
+    @{[invm4 $T7,$T6,$T4]}
+    sw      $T7,16($KEYP)
+    @{[invm4 $T7,$T6,$T5]}
+    sw      $T7,20($KEYP)
+___
+        } else { # rnum == 7
+$ret .= <<___;
+    # the reason for dropping T4/T5 is in ke192enc
+    # the reason for not invm4 is in ke128dec
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+___
+        }
+        $rnum++;
+    }
+    return $ret;
+}
+
+sub ke256dec {
+    my $zbkb = shift;
+    my $rnum = 0;
+    my $ret = '';
+$ret .= <<___;
+    lw      $T0,0($UKEY)
+    lw      $T1,4($UKEY)
+    lw      $T2,8($UKEY)
+    lw      $T3,12($UKEY)
+    lw      $T4,16($UKEY)
+    lw      $T5,20($UKEY)
+    lw      $T6,24($UKEY)
+    lw      $T7,28($UKEY)
+
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+    # see the comment in ke128dec
+    # BITS and T8 are temp variables
+    # BITS are not used anymore
+    @{[invm4 $T8,$BITS,$T4]}
+    sw      $T8,16($KEYP)
+    @{[invm4 $T8,$BITS,$T5]}
+    sw      $T8,20($KEYP)
+    @{[invm4 $T8,$BITS,$T6]}
+    sw      $T8,24($KEYP)
+    @{[invm4 $T8,$BITS,$T7]}
+    sw      $T8,28($KEYP)
+___
+    while($rnum < 7) {
+$ret .= <<___;
+    # see the comment in ke128enc
+    li      $T8,$rcon[$rnum]
+    xor     $T0,$T0,$T8
+___
+        # right rotate by 8
+        if ($zbkb) {
+$ret .= <<___;
+    @{[rori    $T8,$T7,8]}
+___
+        } else {
+$ret .= <<___;
+    srli    $T8,$T7,8
+    slli    $BITS,$T7,24
+    or      $T8,$T8,$BITS
+___
+        }
+$ret .= <<___;
+    @{[fwdsbox4 $T0,$T8]}
+    xor     $T1,$T1,$T0
+    xor     $T2,$T2,$T1
+    xor     $T3,$T3,$T2
+
+    add     $KEYP,$KEYP,32
+___
+        if ($rnum < 6) {
+$ret .= <<___;
+    # for aes256, T3->T4 needs 4sbox but no rotate/rcon
+    @{[fwdsbox4 $T4,$T3]}
+    xor     $T5,$T5,$T4
+    xor     $T6,$T6,$T5
+    xor     $T7,$T7,$T6
+
+    # see the comment in ke128dec
+    # T8 and BITS are temp variables
+    @{[invm4 $T8,$BITS,$T0]}
+    sw      $T8,0($KEYP)
+    @{[invm4 $T8,$BITS,$T1]}
+    sw      $T8,4($KEYP)
+    @{[invm4 $T8,$BITS,$T2]}
+    sw      $T8,8($KEYP)
+    @{[invm4 $T8,$BITS,$T3]}
+    sw      $T8,12($KEYP)
+    @{[invm4 $T8,$BITS,$T4]}
+    sw      $T8,16($KEYP)
+    @{[invm4 $T8,$BITS,$T5]}
+    sw      $T8,20($KEYP)
+    @{[invm4 $T8,$BITS,$T6]}
+    sw      $T8,24($KEYP)
+    @{[invm4 $T8,$BITS,$T7]}
+    sw      $T8,28($KEYP)
+___
+        } else {
+$ret .= <<___;
+    sw      $T0,0($KEYP)
+    sw      $T1,4($KEYP)
+    sw      $T2,8($KEYP)
+    sw      $T3,12($KEYP)
+    # last 16 bytes are dropped
+    # see the comment in ke256enc
+___
+        }
+        $rnum++;
+    }
+    return $ret;
+}
+
+################################################################################
+# void rv32i_zknd_zkne_set_decrypt_key(const unsigned char *userKey, const int bits,
+#   AES_KEY *key)
+################################################################################
+# a note on naming: set_decrypt_key needs aes32esi thus add zkne on name
+$code .= <<___;
+.text
+.balign 16
+.globl rv32i_zknd_zkne_set_decrypt_key
+.type   rv32i_zknd_zkne_set_decrypt_key,\@function
+rv32i_zknd_zkne_set_decrypt_key:
+___
+$code .= save_regs();
+$code .= AES_set_common(ke128dec(0), ke192dec(0),ke256dec(0));
+$code .= load_regs();
+$code .= <<___;
+    ret
+___
+
+################################################################################
+# void rv32i_zbkb_zknd_zkne_set_decrypt_key(const unsigned char *userKey,
+#   const int bits, AES_KEY *key)
+################################################################################
+$code .= <<___;
+.text
+.balign 16
+.globl rv32i_zbkb_zknd_zkne_set_decrypt_key
+.type rv32i_zbkb_zknd_zkne_set_decrypt_key,\@function
+rv32i_zbkb_zknd_zkne_set_decrypt_key:
+___
+
+$code .= save_regs();
+$code .= AES_set_common(ke128dec(1), ke192dec(1),ke256dec(1));
+$code .= load_regs();
+$code .= <<___;
+    ret
+___
+
+
+
+print $code;
+close STDOUT or die "error closing STDOUT: $!";

+ 2378 - 0
libs/openssl/crypto/aes/asm/bsaes-armv8.pl

@@ -0,0 +1,2378 @@
+#!/usr/bin/env perl
+# Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+use strict;
+
+my $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
+my $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef;
+my $xlate;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; my $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate  ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate ) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+my $code = data();
+print $code;
+
+close STDOUT or die "error closing STDOUT: $!"; # enforce flush
+
+sub data
+{
+    local $/;
+    return <DATA>;
+}
+
+__END__
+// Copyright 2021-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
+//
+// ====================================================================
+// Written by Ben Avison <[email protected]> for the OpenSSL
+// project. Rights for redistribution and usage in source and binary
+// forms are granted according to the OpenSSL license.
+// ====================================================================
+//
+// This implementation is a translation of bsaes-armv7 for AArch64.
+// No attempt has been made to carry across the build switches for
+// kernel targets, since the Linux kernel crypto support has moved on
+// from when it was based on OpenSSL.
+
+// A lot of hand-scheduling has been performed. Consequently, this code
+// doesn't factor out neatly into macros in the same way that the
+// AArch32 version did, and there is little to be gained by wrapping it
+// up in Perl, and it is presented as pure assembly.
+
+
+#include "crypto/arm_arch.h"
+
+.text
+
+.extern AES_cbc_encrypt
+.extern AES_encrypt
+.extern AES_decrypt
+
+.type   _bsaes_decrypt8,%function
+.align  4
+// On entry:
+//   x9 -> key (previously expanded using _bsaes_key_convert)
+//   x10 = number of rounds
+//   v0-v7 input data
+// On exit:
+//   x9-x11 corrupted
+//   other general-purpose registers preserved
+//   v0-v7 output data
+//   v11-v15 preserved
+//   other SIMD registers corrupted
+_bsaes_decrypt8:
+        ldr     q8, [x9], #16
+        adr     x11, .LM0ISR
+        movi    v9.16b, #0x55
+        ldr     q10, [x11], #16
+        movi    v16.16b, #0x33
+        movi    v17.16b, #0x0f
+        sub     x10, x10, #1
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v1.16b, v1.16b, v8.16b
+        eor     v2.16b, v2.16b, v8.16b
+        eor     v4.16b, v4.16b, v8.16b
+        eor     v3.16b, v3.16b, v8.16b
+        eor     v5.16b, v5.16b, v8.16b
+        tbl     v0.16b, {v0.16b}, v10.16b
+        tbl     v1.16b, {v1.16b}, v10.16b
+        tbl     v2.16b, {v2.16b}, v10.16b
+        tbl     v4.16b, {v4.16b}, v10.16b
+        eor     v6.16b, v6.16b, v8.16b
+        eor     v7.16b, v7.16b, v8.16b
+        tbl     v3.16b, {v3.16b}, v10.16b
+        tbl     v5.16b, {v5.16b}, v10.16b
+        tbl     v6.16b, {v6.16b}, v10.16b
+        ushr    v8.2d, v0.2d, #1
+        tbl     v7.16b, {v7.16b}, v10.16b
+        ushr    v10.2d, v4.2d, #1
+        ushr    v18.2d, v2.2d, #1
+        eor     v8.16b, v8.16b, v1.16b
+        ushr    v19.2d, v6.2d, #1
+        eor     v10.16b, v10.16b, v5.16b
+        eor     v18.16b, v18.16b, v3.16b
+        and     v8.16b, v8.16b, v9.16b
+        eor     v19.16b, v19.16b, v7.16b
+        and     v10.16b, v10.16b, v9.16b
+        and     v18.16b, v18.16b, v9.16b
+        eor     v1.16b, v1.16b, v8.16b
+        shl     v8.2d, v8.2d, #1
+        and     v9.16b, v19.16b, v9.16b
+        eor     v5.16b, v5.16b, v10.16b
+        shl     v10.2d, v10.2d, #1
+        eor     v3.16b, v3.16b, v18.16b
+        shl     v18.2d, v18.2d, #1
+        eor     v0.16b, v0.16b, v8.16b
+        shl     v8.2d, v9.2d, #1
+        eor     v7.16b, v7.16b, v9.16b
+        eor     v4.16b, v4.16b, v10.16b
+        eor     v2.16b, v2.16b, v18.16b
+        ushr    v9.2d, v1.2d, #2
+        eor     v6.16b, v6.16b, v8.16b
+        ushr    v8.2d, v0.2d, #2
+        ushr    v10.2d, v5.2d, #2
+        ushr    v18.2d, v4.2d, #2
+        eor     v9.16b, v9.16b, v3.16b
+        eor     v8.16b, v8.16b, v2.16b
+        eor     v10.16b, v10.16b, v7.16b
+        eor     v18.16b, v18.16b, v6.16b
+        and     v9.16b, v9.16b, v16.16b
+        and     v8.16b, v8.16b, v16.16b
+        and     v10.16b, v10.16b, v16.16b
+        and     v16.16b, v18.16b, v16.16b
+        eor     v3.16b, v3.16b, v9.16b
+        shl     v9.2d, v9.2d, #2
+        eor     v2.16b, v2.16b, v8.16b
+        shl     v8.2d, v8.2d, #2
+        eor     v7.16b, v7.16b, v10.16b
+        shl     v10.2d, v10.2d, #2
+        eor     v6.16b, v6.16b, v16.16b
+        shl     v16.2d, v16.2d, #2
+        eor     v1.16b, v1.16b, v9.16b
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v5.16b, v5.16b, v10.16b
+        eor     v4.16b, v4.16b, v16.16b
+        ushr    v8.2d, v3.2d, #4
+        ushr    v9.2d, v2.2d, #4
+        ushr    v10.2d, v1.2d, #4
+        ushr    v16.2d, v0.2d, #4
+        eor     v8.16b, v8.16b, v7.16b
+        eor     v9.16b, v9.16b, v6.16b
+        eor     v10.16b, v10.16b, v5.16b
+        eor     v16.16b, v16.16b, v4.16b
+        and     v8.16b, v8.16b, v17.16b
+        and     v9.16b, v9.16b, v17.16b
+        and     v10.16b, v10.16b, v17.16b
+        and     v16.16b, v16.16b, v17.16b
+        eor     v7.16b, v7.16b, v8.16b
+        shl     v8.2d, v8.2d, #4
+        eor     v6.16b, v6.16b, v9.16b
+        shl     v9.2d, v9.2d, #4
+        eor     v5.16b, v5.16b, v10.16b
+        shl     v10.2d, v10.2d, #4
+        eor     v4.16b, v4.16b, v16.16b
+        shl     v16.2d, v16.2d, #4
+        eor     v3.16b, v3.16b, v8.16b
+        eor     v2.16b, v2.16b, v9.16b
+        eor     v1.16b, v1.16b, v10.16b
+        eor     v0.16b, v0.16b, v16.16b
+        b       .Ldec_sbox
+.align  4
+.Ldec_loop:
+        ld1     {v16.16b, v17.16b, v18.16b, v19.16b}, [x9], #64
+        ldp     q8, q9, [x9], #32
+        eor     v0.16b, v16.16b, v0.16b
+        ldr     q10, [x9], #16
+        eor     v1.16b, v17.16b, v1.16b
+        ldr     q16, [x9], #16
+        eor     v2.16b, v18.16b, v2.16b
+        eor     v3.16b, v19.16b, v3.16b
+        eor     v4.16b, v8.16b, v4.16b
+        eor     v5.16b, v9.16b, v5.16b
+        eor     v6.16b, v10.16b, v6.16b
+        eor     v7.16b, v16.16b, v7.16b
+        tbl     v0.16b, {v0.16b}, v28.16b
+        tbl     v1.16b, {v1.16b}, v28.16b
+        tbl     v2.16b, {v2.16b}, v28.16b
+        tbl     v3.16b, {v3.16b}, v28.16b
+        tbl     v4.16b, {v4.16b}, v28.16b
+        tbl     v5.16b, {v5.16b}, v28.16b
+        tbl     v6.16b, {v6.16b}, v28.16b
+        tbl     v7.16b, {v7.16b}, v28.16b
+.Ldec_sbox:
+        eor     v1.16b, v1.16b, v4.16b
+        eor     v3.16b, v3.16b, v4.16b
+        subs    x10, x10, #1
+        eor     v4.16b, v4.16b, v7.16b
+        eor     v2.16b, v2.16b, v7.16b
+        eor     v1.16b, v1.16b, v6.16b
+        eor     v6.16b, v6.16b, v4.16b
+        eor     v2.16b, v2.16b, v5.16b
+        eor     v0.16b, v0.16b, v1.16b
+        eor     v7.16b, v7.16b, v6.16b
+        eor     v8.16b, v6.16b, v2.16b
+        and     v9.16b, v4.16b, v6.16b
+        eor     v10.16b, v2.16b, v6.16b
+        eor     v3.16b, v3.16b, v0.16b
+        eor     v5.16b, v5.16b, v0.16b
+        eor     v16.16b, v7.16b, v4.16b
+        eor     v17.16b, v4.16b, v0.16b
+        and     v18.16b, v0.16b, v2.16b
+        eor     v19.16b, v7.16b, v4.16b
+        eor     v1.16b, v1.16b, v3.16b
+        eor     v20.16b, v3.16b, v0.16b
+        eor     v21.16b, v5.16b, v2.16b
+        eor     v22.16b, v3.16b, v7.16b
+        and     v8.16b, v17.16b, v8.16b
+        orr     v17.16b, v3.16b, v5.16b
+        eor     v23.16b, v1.16b, v6.16b
+        eor     v24.16b, v20.16b, v16.16b
+        eor     v25.16b, v1.16b, v5.16b
+        orr     v26.16b, v20.16b, v21.16b
+        and     v20.16b, v20.16b, v21.16b
+        and     v27.16b, v7.16b, v1.16b
+        eor     v21.16b, v21.16b, v23.16b
+        orr     v28.16b, v16.16b, v23.16b
+        orr     v29.16b, v22.16b, v25.16b
+        eor     v26.16b, v26.16b, v8.16b
+        and     v16.16b, v16.16b, v23.16b
+        and     v22.16b, v22.16b, v25.16b
+        and     v21.16b, v24.16b, v21.16b
+        eor     v8.16b, v28.16b, v8.16b
+        eor     v23.16b, v5.16b, v2.16b
+        eor     v24.16b, v1.16b, v6.16b
+        eor     v16.16b, v16.16b, v22.16b
+        eor     v22.16b, v3.16b, v0.16b
+        eor     v25.16b, v29.16b, v21.16b
+        eor     v21.16b, v26.16b, v21.16b
+        eor     v8.16b, v8.16b, v20.16b
+        eor     v26.16b, v23.16b, v24.16b
+        eor     v16.16b, v16.16b, v20.16b
+        eor     v28.16b, v22.16b, v19.16b
+        eor     v20.16b, v25.16b, v20.16b
+        eor     v9.16b, v21.16b, v9.16b
+        eor     v8.16b, v8.16b, v18.16b
+        eor     v18.16b, v5.16b, v1.16b
+        eor     v21.16b, v16.16b, v17.16b
+        eor     v16.16b, v16.16b, v17.16b
+        eor     v17.16b, v20.16b, v27.16b
+        eor     v20.16b, v3.16b, v7.16b
+        eor     v25.16b, v9.16b, v8.16b
+        eor     v27.16b, v0.16b, v4.16b
+        and     v29.16b, v9.16b, v17.16b
+        eor     v30.16b, v8.16b, v29.16b
+        eor     v31.16b, v21.16b, v29.16b
+        eor     v29.16b, v21.16b, v29.16b
+        bsl     v30.16b, v17.16b, v21.16b
+        bsl     v31.16b, v9.16b, v8.16b
+        bsl     v16.16b, v30.16b, v29.16b
+        bsl     v21.16b, v29.16b, v30.16b
+        eor     v8.16b, v31.16b, v30.16b
+        and     v1.16b, v1.16b, v31.16b
+        and     v9.16b, v16.16b, v31.16b
+        and     v6.16b, v6.16b, v30.16b
+        eor     v16.16b, v17.16b, v21.16b
+        and     v4.16b, v4.16b, v30.16b
+        eor     v17.16b, v8.16b, v30.16b
+        and     v21.16b, v24.16b, v8.16b
+        eor     v9.16b, v9.16b, v25.16b
+        and     v19.16b, v19.16b, v8.16b
+        eor     v24.16b, v30.16b, v16.16b
+        eor     v25.16b, v30.16b, v16.16b
+        and     v7.16b, v7.16b, v17.16b
+        and     v10.16b, v10.16b, v16.16b
+        eor     v29.16b, v9.16b, v16.16b
+        eor     v30.16b, v31.16b, v9.16b
+        and     v0.16b, v24.16b, v0.16b
+        and     v9.16b, v18.16b, v9.16b
+        and     v2.16b, v25.16b, v2.16b
+        eor     v10.16b, v10.16b, v6.16b
+        eor     v18.16b, v29.16b, v16.16b
+        and     v5.16b, v30.16b, v5.16b
+        eor     v24.16b, v8.16b, v29.16b
+        and     v25.16b, v26.16b, v29.16b
+        and     v26.16b, v28.16b, v29.16b
+        eor     v8.16b, v8.16b, v29.16b
+        eor     v17.16b, v17.16b, v18.16b
+        eor     v5.16b, v1.16b, v5.16b
+        and     v23.16b, v24.16b, v23.16b
+        eor     v21.16b, v21.16b, v25.16b
+        eor     v19.16b, v19.16b, v26.16b
+        eor     v0.16b, v4.16b, v0.16b
+        and     v3.16b, v17.16b, v3.16b
+        eor     v1.16b, v9.16b, v1.16b
+        eor     v9.16b, v25.16b, v23.16b
+        eor     v5.16b, v5.16b, v21.16b
+        eor     v2.16b, v6.16b, v2.16b
+        and     v6.16b, v8.16b, v22.16b
+        eor     v3.16b, v7.16b, v3.16b
+        and     v8.16b, v20.16b, v18.16b
+        eor     v10.16b, v10.16b, v9.16b
+        eor     v0.16b, v0.16b, v19.16b
+        eor     v9.16b, v1.16b, v9.16b
+        eor     v1.16b, v2.16b, v21.16b
+        eor     v3.16b, v3.16b, v19.16b
+        and     v16.16b, v27.16b, v16.16b
+        eor     v17.16b, v26.16b, v6.16b
+        eor     v6.16b, v8.16b, v7.16b
+        eor     v7.16b, v1.16b, v9.16b
+        eor     v1.16b, v5.16b, v3.16b
+        eor     v2.16b, v10.16b, v3.16b
+        eor     v4.16b, v16.16b, v4.16b
+        eor     v8.16b, v6.16b, v17.16b
+        eor     v5.16b, v9.16b, v3.16b
+        eor     v9.16b, v0.16b, v1.16b
+        eor     v6.16b, v7.16b, v1.16b
+        eor     v0.16b, v4.16b, v17.16b
+        eor     v4.16b, v8.16b, v7.16b
+        eor     v7.16b, v9.16b, v2.16b
+        eor     v8.16b, v3.16b, v0.16b
+        eor     v7.16b, v7.16b, v5.16b
+        eor     v3.16b, v4.16b, v7.16b
+        eor     v4.16b, v7.16b, v0.16b
+        eor     v7.16b, v8.16b, v3.16b
+        bcc     .Ldec_done
+        ext     v8.16b, v0.16b, v0.16b, #8
+        ext     v9.16b, v1.16b, v1.16b, #8
+        ldr     q28, [x11]                  // load from .LISR in common case (x10 > 0)
+        ext     v10.16b, v6.16b, v6.16b, #8
+        ext     v16.16b, v3.16b, v3.16b, #8
+        ext     v17.16b, v5.16b, v5.16b, #8
+        ext     v18.16b, v4.16b, v4.16b, #8
+        eor     v8.16b, v8.16b, v0.16b
+        eor     v9.16b, v9.16b, v1.16b
+        eor     v10.16b, v10.16b, v6.16b
+        eor     v16.16b, v16.16b, v3.16b
+        eor     v17.16b, v17.16b, v5.16b
+        ext     v19.16b, v2.16b, v2.16b, #8
+        ext     v20.16b, v7.16b, v7.16b, #8
+        eor     v18.16b, v18.16b, v4.16b
+        eor     v6.16b, v6.16b, v8.16b
+        eor     v8.16b, v2.16b, v10.16b
+        eor     v4.16b, v4.16b, v9.16b
+        eor     v2.16b, v19.16b, v2.16b
+        eor     v9.16b, v20.16b, v7.16b
+        eor     v0.16b, v0.16b, v16.16b
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v6.16b, v6.16b, v17.16b
+        eor     v8.16b, v8.16b, v16.16b
+        eor     v7.16b, v7.16b, v18.16b
+        eor     v4.16b, v4.16b, v16.16b
+        eor     v2.16b, v3.16b, v2.16b
+        eor     v1.16b, v1.16b, v17.16b
+        eor     v3.16b, v5.16b, v9.16b
+        eor     v5.16b, v8.16b, v17.16b
+        eor     v7.16b, v7.16b, v17.16b
+        ext     v8.16b, v0.16b, v0.16b, #12
+        ext     v9.16b, v6.16b, v6.16b, #12
+        ext     v10.16b, v4.16b, v4.16b, #12
+        ext     v16.16b, v1.16b, v1.16b, #12
+        ext     v17.16b, v5.16b, v5.16b, #12
+        ext     v18.16b, v7.16b, v7.16b, #12
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v6.16b, v6.16b, v9.16b
+        eor     v4.16b, v4.16b, v10.16b
+        ext     v19.16b, v2.16b, v2.16b, #12
+        ext     v20.16b, v3.16b, v3.16b, #12
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v5.16b, v5.16b, v17.16b
+        eor     v7.16b, v7.16b, v18.16b
+        eor     v2.16b, v2.16b, v19.16b
+        eor     v16.16b, v16.16b, v0.16b
+        eor     v3.16b, v3.16b, v20.16b
+        eor     v17.16b, v17.16b, v4.16b
+        eor     v10.16b, v10.16b, v6.16b
+        ext     v0.16b, v0.16b, v0.16b, #8
+        eor     v9.16b, v9.16b, v1.16b
+        ext     v1.16b, v1.16b, v1.16b, #8
+        eor     v8.16b, v8.16b, v3.16b
+        eor     v16.16b, v16.16b, v3.16b
+        eor     v18.16b, v18.16b, v5.16b
+        eor     v19.16b, v19.16b, v7.16b
+        ext     v21.16b, v5.16b, v5.16b, #8
+        ext     v5.16b, v7.16b, v7.16b, #8
+        eor     v7.16b, v20.16b, v2.16b
+        ext     v4.16b, v4.16b, v4.16b, #8
+        ext     v20.16b, v3.16b, v3.16b, #8
+        eor     v17.16b, v17.16b, v3.16b
+        ext     v2.16b, v2.16b, v2.16b, #8
+        eor     v3.16b, v10.16b, v3.16b
+        ext     v10.16b, v6.16b, v6.16b, #8
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v5.16b, v5.16b, v18.16b
+        eor     v3.16b, v3.16b, v4.16b
+        eor     v7.16b, v20.16b, v7.16b
+        eor     v6.16b, v2.16b, v19.16b
+        eor     v4.16b, v21.16b, v17.16b
+        eor     v2.16b, v10.16b, v9.16b
+        bne     .Ldec_loop
+        ldr     q28, [x11, #16]!            // load from .LISRM0 on last round (x10 == 0)
+        b       .Ldec_loop
+.align  4
+.Ldec_done:
+        ushr    v8.2d, v0.2d, #1
+        movi    v9.16b, #0x55
+        ldr     q10, [x9]
+        ushr    v16.2d, v2.2d, #1
+        movi    v17.16b, #0x33
+        ushr    v18.2d, v6.2d, #1
+        movi    v19.16b, #0x0f
+        eor     v8.16b, v8.16b, v1.16b
+        ushr    v20.2d, v3.2d, #1
+        eor     v16.16b, v16.16b, v7.16b
+        eor     v18.16b, v18.16b, v4.16b
+        and     v8.16b, v8.16b, v9.16b
+        eor     v20.16b, v20.16b, v5.16b
+        and     v16.16b, v16.16b, v9.16b
+        and     v18.16b, v18.16b, v9.16b
+        shl     v21.2d, v8.2d, #1
+        eor     v1.16b, v1.16b, v8.16b
+        and     v8.16b, v20.16b, v9.16b
+        eor     v7.16b, v7.16b, v16.16b
+        shl     v9.2d, v16.2d, #1
+        eor     v4.16b, v4.16b, v18.16b
+        shl     v16.2d, v18.2d, #1
+        eor     v0.16b, v0.16b, v21.16b
+        shl     v18.2d, v8.2d, #1
+        eor     v5.16b, v5.16b, v8.16b
+        eor     v2.16b, v2.16b, v9.16b
+        eor     v6.16b, v6.16b, v16.16b
+        ushr    v8.2d, v1.2d, #2
+        eor     v3.16b, v3.16b, v18.16b
+        ushr    v9.2d, v0.2d, #2
+        ushr    v16.2d, v7.2d, #2
+        ushr    v18.2d, v2.2d, #2
+        eor     v8.16b, v8.16b, v4.16b
+        eor     v9.16b, v9.16b, v6.16b
+        eor     v16.16b, v16.16b, v5.16b
+        eor     v18.16b, v18.16b, v3.16b
+        and     v8.16b, v8.16b, v17.16b
+        and     v9.16b, v9.16b, v17.16b
+        and     v16.16b, v16.16b, v17.16b
+        and     v17.16b, v18.16b, v17.16b
+        eor     v4.16b, v4.16b, v8.16b
+        shl     v8.2d, v8.2d, #2
+        eor     v6.16b, v6.16b, v9.16b
+        shl     v9.2d, v9.2d, #2
+        eor     v5.16b, v5.16b, v16.16b
+        shl     v16.2d, v16.2d, #2
+        eor     v3.16b, v3.16b, v17.16b
+        shl     v17.2d, v17.2d, #2
+        eor     v1.16b, v1.16b, v8.16b
+        eor     v0.16b, v0.16b, v9.16b
+        eor     v7.16b, v7.16b, v16.16b
+        eor     v2.16b, v2.16b, v17.16b
+        ushr    v8.2d, v4.2d, #4
+        ushr    v9.2d, v6.2d, #4
+        ushr    v16.2d, v1.2d, #4
+        ushr    v17.2d, v0.2d, #4
+        eor     v8.16b, v8.16b, v5.16b
+        eor     v9.16b, v9.16b, v3.16b
+        eor     v16.16b, v16.16b, v7.16b
+        eor     v17.16b, v17.16b, v2.16b
+        and     v8.16b, v8.16b, v19.16b
+        and     v9.16b, v9.16b, v19.16b
+        and     v16.16b, v16.16b, v19.16b
+        and     v17.16b, v17.16b, v19.16b
+        eor     v5.16b, v5.16b, v8.16b
+        shl     v8.2d, v8.2d, #4
+        eor     v3.16b, v3.16b, v9.16b
+        shl     v9.2d, v9.2d, #4
+        eor     v7.16b, v7.16b, v16.16b
+        shl     v16.2d, v16.2d, #4
+        eor     v2.16b, v2.16b, v17.16b
+        shl     v17.2d, v17.2d, #4
+        eor     v4.16b, v4.16b, v8.16b
+        eor     v6.16b, v6.16b, v9.16b
+        eor     v7.16b, v7.16b, v10.16b
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v2.16b, v2.16b, v10.16b
+        eor     v0.16b, v0.16b, v17.16b
+        eor     v4.16b, v4.16b, v10.16b
+        eor     v6.16b, v6.16b, v10.16b
+        eor     v3.16b, v3.16b, v10.16b
+        eor     v5.16b, v5.16b, v10.16b
+        eor     v1.16b, v1.16b, v10.16b
+        eor     v0.16b, v0.16b, v10.16b
+        ret
+.size   _bsaes_decrypt8,.-_bsaes_decrypt8
+
+.type   _bsaes_const,%object
+.align  6
+_bsaes_const:
+// InvShiftRows constants
+// Used in _bsaes_decrypt8, which assumes contiguity
+// .LM0ISR used with round 0 key
+// .LISR   used with middle round keys
+// .LISRM0 used with final round key
+.LM0ISR:
+.quad   0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISR:
+.quad   0x0504070602010003, 0x0f0e0d0c080b0a09
+.LISRM0:
+.quad   0x01040b0e0205080f, 0x0306090c00070a0d
+
+// ShiftRows constants
+// Used in _bsaes_encrypt8, which assumes contiguity
+// .LM0SR used with round 0 key
+// .LSR   used with middle round keys
+// .LSRM0 used with final round key
+.LM0SR:
+.quad   0x0a0e02060f03070b, 0x0004080c05090d01
+.LSR:
+.quad   0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+.quad   0x0304090e00050a0f, 0x01060b0c0207080d
+
+.LM0_bigendian:
+.quad   0x02060a0e03070b0f, 0x0004080c0105090d
+.LM0_littleendian:
+.quad   0x0105090d0004080c, 0x03070b0f02060a0e
+
+// Used in ossl_bsaes_ctr32_encrypt_blocks, prior to dropping into
+// _bsaes_encrypt8_alt, for round 0 key in place of .LM0SR
+.LREVM0SR:
+.quad   0x090d01050c000408, 0x03070b0f060a0e02
+
+.align  6
+.size   _bsaes_const,.-_bsaes_const
+
+.type   _bsaes_encrypt8,%function
+.align  4
+// On entry:
+//   x9 -> key (previously expanded using _bsaes_key_convert)
+//   x10 = number of rounds
+//   v0-v7 input data
+// On exit:
+//   x9-x11 corrupted
+//   other general-purpose registers preserved
+//   v0-v7 output data
+//   v11-v15 preserved
+//   other SIMD registers corrupted
+_bsaes_encrypt8:
+        ldr     q8, [x9], #16
+        adr     x11, .LM0SR
+        ldr     q9, [x11], #16
+_bsaes_encrypt8_alt:
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v1.16b, v1.16b, v8.16b
+        sub     x10, x10, #1
+        eor     v2.16b, v2.16b, v8.16b
+        eor     v4.16b, v4.16b, v8.16b
+        eor     v3.16b, v3.16b, v8.16b
+        eor     v5.16b, v5.16b, v8.16b
+        tbl     v0.16b, {v0.16b}, v9.16b
+        tbl     v1.16b, {v1.16b}, v9.16b
+        tbl     v2.16b, {v2.16b}, v9.16b
+        tbl     v4.16b, {v4.16b}, v9.16b
+        eor     v6.16b, v6.16b, v8.16b
+        eor     v7.16b, v7.16b, v8.16b
+        tbl     v3.16b, {v3.16b}, v9.16b
+        tbl     v5.16b, {v5.16b}, v9.16b
+        tbl     v6.16b, {v6.16b}, v9.16b
+        ushr    v8.2d, v0.2d, #1
+        movi    v10.16b, #0x55
+        tbl     v7.16b, {v7.16b}, v9.16b
+        ushr    v9.2d, v4.2d, #1
+        movi    v16.16b, #0x33
+        ushr    v17.2d, v2.2d, #1
+        eor     v8.16b, v8.16b, v1.16b
+        movi    v18.16b, #0x0f
+        ushr    v19.2d, v6.2d, #1
+        eor     v9.16b, v9.16b, v5.16b
+        eor     v17.16b, v17.16b, v3.16b
+        and     v8.16b, v8.16b, v10.16b
+        eor     v19.16b, v19.16b, v7.16b
+        and     v9.16b, v9.16b, v10.16b
+        and     v17.16b, v17.16b, v10.16b
+        eor     v1.16b, v1.16b, v8.16b
+        shl     v8.2d, v8.2d, #1
+        and     v10.16b, v19.16b, v10.16b
+        eor     v5.16b, v5.16b, v9.16b
+        shl     v9.2d, v9.2d, #1
+        eor     v3.16b, v3.16b, v17.16b
+        shl     v17.2d, v17.2d, #1
+        eor     v0.16b, v0.16b, v8.16b
+        shl     v8.2d, v10.2d, #1
+        eor     v7.16b, v7.16b, v10.16b
+        eor     v4.16b, v4.16b, v9.16b
+        eor     v2.16b, v2.16b, v17.16b
+        ushr    v9.2d, v1.2d, #2
+        eor     v6.16b, v6.16b, v8.16b
+        ushr    v8.2d, v0.2d, #2
+        ushr    v10.2d, v5.2d, #2
+        ushr    v17.2d, v4.2d, #2
+        eor     v9.16b, v9.16b, v3.16b
+        eor     v8.16b, v8.16b, v2.16b
+        eor     v10.16b, v10.16b, v7.16b
+        eor     v17.16b, v17.16b, v6.16b
+        and     v9.16b, v9.16b, v16.16b
+        and     v8.16b, v8.16b, v16.16b
+        and     v10.16b, v10.16b, v16.16b
+        and     v16.16b, v17.16b, v16.16b
+        eor     v3.16b, v3.16b, v9.16b
+        shl     v9.2d, v9.2d, #2
+        eor     v2.16b, v2.16b, v8.16b
+        shl     v8.2d, v8.2d, #2
+        eor     v7.16b, v7.16b, v10.16b
+        shl     v10.2d, v10.2d, #2
+        eor     v6.16b, v6.16b, v16.16b
+        shl     v16.2d, v16.2d, #2
+        eor     v1.16b, v1.16b, v9.16b
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v5.16b, v5.16b, v10.16b
+        eor     v4.16b, v4.16b, v16.16b
+        ushr    v8.2d, v3.2d, #4
+        ushr    v9.2d, v2.2d, #4
+        ushr    v10.2d, v1.2d, #4
+        ushr    v16.2d, v0.2d, #4
+        eor     v8.16b, v8.16b, v7.16b
+        eor     v9.16b, v9.16b, v6.16b
+        eor     v10.16b, v10.16b, v5.16b
+        eor     v16.16b, v16.16b, v4.16b
+        and     v8.16b, v8.16b, v18.16b
+        and     v9.16b, v9.16b, v18.16b
+        and     v10.16b, v10.16b, v18.16b
+        and     v16.16b, v16.16b, v18.16b
+        eor     v7.16b, v7.16b, v8.16b
+        shl     v8.2d, v8.2d, #4
+        eor     v6.16b, v6.16b, v9.16b
+        shl     v9.2d, v9.2d, #4
+        eor     v5.16b, v5.16b, v10.16b
+        shl     v10.2d, v10.2d, #4
+        eor     v4.16b, v4.16b, v16.16b
+        shl     v16.2d, v16.2d, #4
+        eor     v3.16b, v3.16b, v8.16b
+        eor     v2.16b, v2.16b, v9.16b
+        eor     v1.16b, v1.16b, v10.16b
+        eor     v0.16b, v0.16b, v16.16b
+        b       .Lenc_sbox
+.align  4
+.Lenc_loop:
+        ld1     {v16.16b, v17.16b, v18.16b, v19.16b}, [x9], #64
+        ldp     q8, q9, [x9], #32
+        eor     v0.16b, v16.16b, v0.16b
+        ldr     q10, [x9], #16
+        eor     v1.16b, v17.16b, v1.16b
+        ldr     q16, [x9], #16
+        eor     v2.16b, v18.16b, v2.16b
+        eor     v3.16b, v19.16b, v3.16b
+        eor     v4.16b, v8.16b, v4.16b
+        eor     v5.16b, v9.16b, v5.16b
+        eor     v6.16b, v10.16b, v6.16b
+        eor     v7.16b, v16.16b, v7.16b
+        tbl     v0.16b, {v0.16b}, v28.16b
+        tbl     v1.16b, {v1.16b}, v28.16b
+        tbl     v2.16b, {v2.16b}, v28.16b
+        tbl     v3.16b, {v3.16b}, v28.16b
+        tbl     v4.16b, {v4.16b}, v28.16b
+        tbl     v5.16b, {v5.16b}, v28.16b
+        tbl     v6.16b, {v6.16b}, v28.16b
+        tbl     v7.16b, {v7.16b}, v28.16b
+.Lenc_sbox:
+        eor     v5.16b, v5.16b, v6.16b
+        eor     v3.16b, v3.16b, v0.16b
+        subs    x10, x10, #1
+        eor     v2.16b, v2.16b, v1.16b
+        eor     v5.16b, v5.16b, v0.16b
+        eor     v8.16b, v3.16b, v7.16b
+        eor     v6.16b, v6.16b, v2.16b
+        eor     v7.16b, v7.16b, v5.16b
+        eor     v8.16b, v8.16b, v4.16b
+        eor     v3.16b, v6.16b, v3.16b
+        eor     v4.16b, v4.16b, v5.16b
+        eor     v6.16b, v1.16b, v5.16b
+        eor     v2.16b, v2.16b, v7.16b
+        eor     v1.16b, v8.16b, v1.16b
+        eor     v8.16b, v7.16b, v4.16b
+        eor     v9.16b, v3.16b, v0.16b
+        eor     v10.16b, v7.16b, v6.16b
+        eor     v16.16b, v5.16b, v3.16b
+        eor     v17.16b, v6.16b, v2.16b
+        eor     v18.16b, v5.16b, v1.16b
+        eor     v19.16b, v2.16b, v4.16b
+        eor     v20.16b, v1.16b, v0.16b
+        orr     v21.16b, v8.16b, v9.16b
+        orr     v22.16b, v10.16b, v16.16b
+        eor     v23.16b, v8.16b, v17.16b
+        eor     v24.16b, v9.16b, v18.16b
+        and     v19.16b, v19.16b, v20.16b
+        orr     v20.16b, v17.16b, v18.16b
+        and     v8.16b, v8.16b, v9.16b
+        and     v9.16b, v17.16b, v18.16b
+        and     v17.16b, v23.16b, v24.16b
+        and     v10.16b, v10.16b, v16.16b
+        eor     v16.16b, v21.16b, v19.16b
+        eor     v18.16b, v20.16b, v19.16b
+        and     v19.16b, v2.16b, v1.16b
+        and     v20.16b, v6.16b, v5.16b
+        eor     v21.16b, v22.16b, v17.16b
+        eor     v9.16b, v9.16b, v10.16b
+        eor     v10.16b, v16.16b, v17.16b
+        eor     v16.16b, v18.16b, v8.16b
+        and     v17.16b, v4.16b, v0.16b
+        orr     v18.16b, v7.16b, v3.16b
+        eor     v21.16b, v21.16b, v8.16b
+        eor     v8.16b, v9.16b, v8.16b
+        eor     v9.16b, v10.16b, v19.16b
+        eor     v10.16b, v3.16b, v0.16b
+        eor     v16.16b, v16.16b, v17.16b
+        eor     v17.16b, v5.16b, v1.16b
+        eor     v19.16b, v21.16b, v20.16b
+        eor     v20.16b, v8.16b, v18.16b
+        eor     v8.16b, v8.16b, v18.16b
+        eor     v18.16b, v7.16b, v4.16b
+        eor     v21.16b, v9.16b, v16.16b
+        eor     v22.16b, v6.16b, v2.16b
+        and     v23.16b, v9.16b, v19.16b
+        eor     v24.16b, v10.16b, v17.16b
+        eor     v25.16b, v0.16b, v1.16b
+        eor     v26.16b, v7.16b, v6.16b
+        eor     v27.16b, v18.16b, v22.16b
+        eor     v28.16b, v3.16b, v5.16b
+        eor     v29.16b, v16.16b, v23.16b
+        eor     v30.16b, v20.16b, v23.16b
+        eor     v23.16b, v20.16b, v23.16b
+        eor     v31.16b, v4.16b, v2.16b
+        bsl     v29.16b, v19.16b, v20.16b
+        bsl     v30.16b, v9.16b, v16.16b
+        bsl     v8.16b, v29.16b, v23.16b
+        bsl     v20.16b, v23.16b, v29.16b
+        eor     v9.16b, v30.16b, v29.16b
+        and     v5.16b, v5.16b, v30.16b
+        and     v8.16b, v8.16b, v30.16b
+        and     v1.16b, v1.16b, v29.16b
+        eor     v16.16b, v19.16b, v20.16b
+        and     v2.16b, v2.16b, v29.16b
+        eor     v19.16b, v9.16b, v29.16b
+        and     v17.16b, v17.16b, v9.16b
+        eor     v8.16b, v8.16b, v21.16b
+        and     v20.16b, v22.16b, v9.16b
+        eor     v21.16b, v29.16b, v16.16b
+        eor     v22.16b, v29.16b, v16.16b
+        and     v23.16b, v25.16b, v16.16b
+        and     v6.16b, v6.16b, v19.16b
+        eor     v25.16b, v8.16b, v16.16b
+        eor     v29.16b, v30.16b, v8.16b
+        and     v4.16b, v21.16b, v4.16b
+        and     v8.16b, v28.16b, v8.16b
+        and     v0.16b, v22.16b, v0.16b
+        eor     v21.16b, v23.16b, v1.16b
+        eor     v22.16b, v9.16b, v25.16b
+        eor     v9.16b, v9.16b, v25.16b
+        eor     v23.16b, v25.16b, v16.16b
+        and     v3.16b, v29.16b, v3.16b
+        and     v24.16b, v24.16b, v25.16b
+        and     v25.16b, v27.16b, v25.16b
+        and     v10.16b, v22.16b, v10.16b
+        and     v9.16b, v9.16b, v18.16b
+        eor     v18.16b, v19.16b, v23.16b
+        and     v19.16b, v26.16b, v23.16b
+        eor     v3.16b, v5.16b, v3.16b
+        eor     v17.16b, v17.16b, v24.16b
+        eor     v10.16b, v24.16b, v10.16b
+        and     v16.16b, v31.16b, v16.16b
+        eor     v20.16b, v20.16b, v25.16b
+        eor     v9.16b, v25.16b, v9.16b
+        eor     v4.16b, v2.16b, v4.16b
+        and     v7.16b, v18.16b, v7.16b
+        eor     v18.16b, v19.16b, v6.16b
+        eor     v5.16b, v8.16b, v5.16b
+        eor     v0.16b, v1.16b, v0.16b
+        eor     v1.16b, v21.16b, v10.16b
+        eor     v8.16b, v3.16b, v17.16b
+        eor     v2.16b, v16.16b, v2.16b
+        eor     v3.16b, v6.16b, v7.16b
+        eor     v6.16b, v18.16b, v9.16b
+        eor     v4.16b, v4.16b, v20.16b
+        eor     v10.16b, v5.16b, v10.16b
+        eor     v0.16b, v0.16b, v17.16b
+        eor     v9.16b, v2.16b, v9.16b
+        eor     v3.16b, v3.16b, v20.16b
+        eor     v7.16b, v6.16b, v1.16b
+        eor     v5.16b, v8.16b, v4.16b
+        eor     v6.16b, v10.16b, v1.16b
+        eor     v2.16b, v4.16b, v0.16b
+        eor     v4.16b, v3.16b, v10.16b
+        eor     v9.16b, v9.16b, v7.16b
+        eor     v3.16b, v0.16b, v5.16b
+        eor     v0.16b, v1.16b, v4.16b
+        eor     v1.16b, v4.16b, v8.16b
+        eor     v4.16b, v9.16b, v5.16b
+        eor     v6.16b, v6.16b, v3.16b
+        bcc     .Lenc_done
+        ext     v8.16b, v0.16b, v0.16b, #12
+        ext     v9.16b, v4.16b, v4.16b, #12
+        ldr     q28, [x11]
+        ext     v10.16b, v6.16b, v6.16b, #12
+        ext     v16.16b, v1.16b, v1.16b, #12
+        ext     v17.16b, v3.16b, v3.16b, #12
+        ext     v18.16b, v7.16b, v7.16b, #12
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v4.16b, v4.16b, v9.16b
+        eor     v6.16b, v6.16b, v10.16b
+        ext     v19.16b, v2.16b, v2.16b, #12
+        ext     v20.16b, v5.16b, v5.16b, #12
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v3.16b, v3.16b, v17.16b
+        eor     v7.16b, v7.16b, v18.16b
+        eor     v2.16b, v2.16b, v19.16b
+        eor     v16.16b, v16.16b, v0.16b
+        eor     v5.16b, v5.16b, v20.16b
+        eor     v17.16b, v17.16b, v6.16b
+        eor     v10.16b, v10.16b, v4.16b
+        ext     v0.16b, v0.16b, v0.16b, #8
+        eor     v9.16b, v9.16b, v1.16b
+        ext     v1.16b, v1.16b, v1.16b, #8
+        eor     v8.16b, v8.16b, v5.16b
+        eor     v16.16b, v16.16b, v5.16b
+        eor     v18.16b, v18.16b, v3.16b
+        eor     v19.16b, v19.16b, v7.16b
+        ext     v3.16b, v3.16b, v3.16b, #8
+        ext     v7.16b, v7.16b, v7.16b, #8
+        eor     v20.16b, v20.16b, v2.16b
+        ext     v6.16b, v6.16b, v6.16b, #8
+        ext     v21.16b, v5.16b, v5.16b, #8
+        eor     v17.16b, v17.16b, v5.16b
+        ext     v2.16b, v2.16b, v2.16b, #8
+        eor     v10.16b, v10.16b, v5.16b
+        ext     v22.16b, v4.16b, v4.16b, #8
+        eor     v0.16b, v0.16b, v8.16b
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v5.16b, v7.16b, v18.16b
+        eor     v4.16b, v3.16b, v17.16b
+        eor     v3.16b, v6.16b, v10.16b
+        eor     v7.16b, v21.16b, v20.16b
+        eor     v6.16b, v2.16b, v19.16b
+        eor     v2.16b, v22.16b, v9.16b
+        bne     .Lenc_loop
+        ldr     q28, [x11, #16]!            // load from .LSRM0 on last round (x10 == 0)
+        b       .Lenc_loop
+.align  4
+.Lenc_done:
+        ushr    v8.2d, v0.2d, #1
+        movi    v9.16b, #0x55
+        ldr     q10, [x9]
+        ushr    v16.2d, v3.2d, #1
+        movi    v17.16b, #0x33
+        ushr    v18.2d, v4.2d, #1
+        movi    v19.16b, #0x0f
+        eor     v8.16b, v8.16b, v1.16b
+        ushr    v20.2d, v2.2d, #1
+        eor     v16.16b, v16.16b, v7.16b
+        eor     v18.16b, v18.16b, v6.16b
+        and     v8.16b, v8.16b, v9.16b
+        eor     v20.16b, v20.16b, v5.16b
+        and     v16.16b, v16.16b, v9.16b
+        and     v18.16b, v18.16b, v9.16b
+        shl     v21.2d, v8.2d, #1
+        eor     v1.16b, v1.16b, v8.16b
+        and     v8.16b, v20.16b, v9.16b
+        eor     v7.16b, v7.16b, v16.16b
+        shl     v9.2d, v16.2d, #1
+        eor     v6.16b, v6.16b, v18.16b
+        shl     v16.2d, v18.2d, #1
+        eor     v0.16b, v0.16b, v21.16b
+        shl     v18.2d, v8.2d, #1
+        eor     v5.16b, v5.16b, v8.16b
+        eor     v3.16b, v3.16b, v9.16b
+        eor     v4.16b, v4.16b, v16.16b
+        ushr    v8.2d, v1.2d, #2
+        eor     v2.16b, v2.16b, v18.16b
+        ushr    v9.2d, v0.2d, #2
+        ushr    v16.2d, v7.2d, #2
+        ushr    v18.2d, v3.2d, #2
+        eor     v8.16b, v8.16b, v6.16b
+        eor     v9.16b, v9.16b, v4.16b
+        eor     v16.16b, v16.16b, v5.16b
+        eor     v18.16b, v18.16b, v2.16b
+        and     v8.16b, v8.16b, v17.16b
+        and     v9.16b, v9.16b, v17.16b
+        and     v16.16b, v16.16b, v17.16b
+        and     v17.16b, v18.16b, v17.16b
+        eor     v6.16b, v6.16b, v8.16b
+        shl     v8.2d, v8.2d, #2
+        eor     v4.16b, v4.16b, v9.16b
+        shl     v9.2d, v9.2d, #2
+        eor     v5.16b, v5.16b, v16.16b
+        shl     v16.2d, v16.2d, #2
+        eor     v2.16b, v2.16b, v17.16b
+        shl     v17.2d, v17.2d, #2
+        eor     v1.16b, v1.16b, v8.16b
+        eor     v0.16b, v0.16b, v9.16b
+        eor     v7.16b, v7.16b, v16.16b
+        eor     v3.16b, v3.16b, v17.16b
+        ushr    v8.2d, v6.2d, #4
+        ushr    v9.2d, v4.2d, #4
+        ushr    v16.2d, v1.2d, #4
+        ushr    v17.2d, v0.2d, #4
+        eor     v8.16b, v8.16b, v5.16b
+        eor     v9.16b, v9.16b, v2.16b
+        eor     v16.16b, v16.16b, v7.16b
+        eor     v17.16b, v17.16b, v3.16b
+        and     v8.16b, v8.16b, v19.16b
+        and     v9.16b, v9.16b, v19.16b
+        and     v16.16b, v16.16b, v19.16b
+        and     v17.16b, v17.16b, v19.16b
+        eor     v5.16b, v5.16b, v8.16b
+        shl     v8.2d, v8.2d, #4
+        eor     v2.16b, v2.16b, v9.16b
+        shl     v9.2d, v9.2d, #4
+        eor     v7.16b, v7.16b, v16.16b
+        shl     v16.2d, v16.2d, #4
+        eor     v3.16b, v3.16b, v17.16b
+        shl     v17.2d, v17.2d, #4
+        eor     v6.16b, v6.16b, v8.16b
+        eor     v4.16b, v4.16b, v9.16b
+        eor     v7.16b, v7.16b, v10.16b
+        eor     v1.16b, v1.16b, v16.16b
+        eor     v3.16b, v3.16b, v10.16b
+        eor     v0.16b, v0.16b, v17.16b
+        eor     v6.16b, v6.16b, v10.16b
+        eor     v4.16b, v4.16b, v10.16b
+        eor     v2.16b, v2.16b, v10.16b
+        eor     v5.16b, v5.16b, v10.16b
+        eor     v1.16b, v1.16b, v10.16b
+        eor     v0.16b, v0.16b, v10.16b
+        ret
+.size   _bsaes_encrypt8,.-_bsaes_encrypt8
+
+.type   _bsaes_key_convert,%function
+.align  4
+// On entry:
+//   x9 -> input key (big-endian)
+//   x10 = number of rounds
+//   x17 -> output key (native endianness)
+// On exit:
+//   x9, x10 corrupted
+//   x11 -> .LM0_bigendian
+//   x17 -> last quadword of output key
+//   other general-purpose registers preserved
+//   v2-v6 preserved
+//   v7.16b[] = 0x63
+//   v8-v14 preserved
+//   v15 = last round key (converted to native endianness)
+//   other SIMD registers corrupted
+_bsaes_key_convert:
+#ifdef __AARCH64EL__
+        adr     x11, .LM0_littleendian
+#else
+        adr     x11, .LM0_bigendian
+#endif
+        ldr     q0, [x9], #16               // load round 0 key
+        ldr     q1, [x11]                   // .LM0
+        ldr     q15, [x9], #16              // load round 1 key
+
+        movi    v7.16b, #0x63               // compose .L63
+        movi    v16.16b, #0x01              // bit masks
+        movi    v17.16b, #0x02
+        movi    v18.16b, #0x04
+        movi    v19.16b, #0x08
+        movi    v20.16b, #0x10
+        movi    v21.16b, #0x20
+        movi    v22.16b, #0x40
+        movi    v23.16b, #0x80
+
+#ifdef __AARCH64EL__
+        rev32   v0.16b, v0.16b
+#endif
+        sub     x10, x10, #1
+        str     q0, [x17], #16              // save round 0 key
+
+.align  4
+.Lkey_loop:
+        tbl     v0.16b, {v15.16b}, v1.16b
+        ldr     q15, [x9], #16              // load next round key
+
+        eor     v0.16b, v0.16b, v7.16b
+        cmtst   v24.16b, v0.16b, v16.16b
+        cmtst   v25.16b, v0.16b, v17.16b
+        cmtst   v26.16b, v0.16b, v18.16b
+        cmtst   v27.16b, v0.16b, v19.16b
+        cmtst   v28.16b, v0.16b, v20.16b
+        cmtst   v29.16b, v0.16b, v21.16b
+        cmtst   v30.16b, v0.16b, v22.16b
+        cmtst   v31.16b, v0.16b, v23.16b
+        sub     x10, x10, #1
+        st1     {v24.16b-v27.16b}, [x17], #64 // write bit-sliced round key
+        st1     {v28.16b-v31.16b}, [x17], #64
+        cbnz    x10, .Lkey_loop
+
+        // don't save last round key
+#ifdef __AARCH64EL__
+        rev32   v15.16b, v15.16b
+        adr     x11, .LM0_bigendian
+#endif
+        ret
+.size   _bsaes_key_convert,.-_bsaes_key_convert
+
+.globl  ossl_bsaes_cbc_encrypt
+.type   ossl_bsaes_cbc_encrypt,%function
+.align  4
+// On entry:
+//   x0 -> input ciphertext
+//   x1 -> output plaintext
+//   x2 = size of ciphertext and plaintext in bytes (assumed a multiple of 16)
+//   x3 -> key
+//   x4 -> 128-bit initialisation vector (or preceding 128-bit block of ciphertext if continuing after an earlier call)
+//   w5 must be == 0
+// On exit:
+//   Output plaintext filled in
+//   Initialisation vector overwritten with last quadword of ciphertext
+//   No output registers, usual AAPCS64 register preservation
+ossl_bsaes_cbc_encrypt:
+        cmp     x2, #128
+        bhs     .Lcbc_do_bsaes
+        b       AES_cbc_encrypt
+.Lcbc_do_bsaes:
+
+        // it is up to the caller to make sure we are called with enc == 0
+
+        stp     x29, x30, [sp, #-48]!
+        stp     d8, d9, [sp, #16]
+        stp     d10, d15, [sp, #32]
+        lsr     x2, x2, #4                  // len in 16 byte blocks
+
+        ldr     w15, [x3, #240]             // get # of rounds
+        mov     x14, sp
+
+        // allocate the key schedule on the stack
+        add     x17, sp, #96
+        sub     x17, x17, x15, lsl #7       // 128 bytes per inner round key, less 96 bytes
+
+        // populate the key schedule
+        mov     x9, x3                      // pass key
+        mov     x10, x15                    // pass # of rounds
+        mov     sp, x17                     // sp is sp
+        bl      _bsaes_key_convert
+        ldr     q6,  [sp]
+        str     q15, [x17]                  // save last round key
+        eor     v6.16b, v6.16b, v7.16b      // fix up round 0 key (by XORing with 0x63)
+        str     q6, [sp]
+
+        ldr     q15, [x4]                   // load IV
+        b       .Lcbc_dec_loop
+
+.align  4
+.Lcbc_dec_loop:
+        subs    x2, x2, #0x8
+        bmi     .Lcbc_dec_loop_finish
+
+        ldr     q0, [x0], #16               // load input
+        mov     x9, sp                      // pass the key
+        ldr     q1, [x0], #16
+        mov     x10, x15
+        ldr     q2, [x0], #16
+        ldr     q3, [x0], #16
+        ldr     q4, [x0], #16
+        ldr     q5, [x0], #16
+        ldr     q6, [x0], #16
+        ldr     q7, [x0], #-7*16
+
+        bl      _bsaes_decrypt8
+
+        ldr     q16, [x0], #16              // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        eor     v1.16b, v1.16b, v16.16b
+        str     q0, [x1], #16               // write output
+        ldr     q0, [x0], #16
+        str     q1, [x1], #16
+        ldr     q1, [x0], #16
+        eor     v1.16b, v4.16b, v1.16b
+        ldr     q4, [x0], #16
+        eor     v2.16b, v2.16b, v4.16b
+        eor     v0.16b, v6.16b, v0.16b
+        ldr     q4, [x0], #16
+        str     q0, [x1], #16
+        str     q1, [x1], #16
+        eor     v0.16b, v7.16b, v4.16b
+        ldr     q1, [x0], #16
+        str     q2, [x1], #16
+        ldr     q2, [x0], #16
+        ldr     q15, [x0], #16
+        str     q0, [x1], #16
+        eor     v0.16b, v5.16b, v2.16b
+        eor     v1.16b, v3.16b, v1.16b
+        str     q1, [x1], #16
+        str     q0, [x1], #16
+
+        b       .Lcbc_dec_loop
+
+.Lcbc_dec_loop_finish:
+        adds    x2, x2, #8
+        beq     .Lcbc_dec_done
+
+        ldr     q0, [x0], #16               // load input
+        cmp     x2, #2
+        blo     .Lcbc_dec_one
+        ldr     q1, [x0], #16
+        mov     x9, sp                      // pass the key
+        mov     x10, x15
+        beq     .Lcbc_dec_two
+        ldr     q2, [x0], #16
+        cmp     x2, #4
+        blo     .Lcbc_dec_three
+        ldr     q3, [x0], #16
+        beq     .Lcbc_dec_four
+        ldr     q4, [x0], #16
+        cmp     x2, #6
+        blo     .Lcbc_dec_five
+        ldr     q5, [x0], #16
+        beq     .Lcbc_dec_six
+        ldr     q6, [x0], #-6*16
+
+        bl      _bsaes_decrypt8
+
+        ldr     q5, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q8, [x0], #16
+        ldr     q9, [x0], #16
+        ldr     q10, [x0], #16
+        str     q0, [x1], #16               // write output
+        ldr     q0, [x0], #16
+        eor     v1.16b, v1.16b, v5.16b
+        ldr     q5, [x0], #16
+        eor     v6.16b, v6.16b, v8.16b
+        ldr     q15, [x0]
+        eor     v4.16b, v4.16b, v9.16b
+        eor     v2.16b, v2.16b, v10.16b
+        str     q1, [x1], #16
+        eor     v0.16b, v7.16b, v0.16b
+        str     q6, [x1], #16
+        eor     v1.16b, v3.16b, v5.16b
+        str     q4, [x1], #16
+        str     q2, [x1], #16
+        str     q0, [x1], #16
+        str     q1, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_six:
+        sub     x0, x0, #0x60
+        bl      _bsaes_decrypt8
+        ldr     q3, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q5, [x0], #16
+        ldr     q8, [x0], #16
+        ldr     q9, [x0], #16
+        str     q0, [x1], #16               // write output
+        ldr     q0, [x0], #16
+        eor     v1.16b, v1.16b, v3.16b
+        ldr     q15, [x0]
+        eor     v3.16b, v6.16b, v5.16b
+        eor     v4.16b, v4.16b, v8.16b
+        eor     v2.16b, v2.16b, v9.16b
+        str     q1, [x1], #16
+        eor     v0.16b, v7.16b, v0.16b
+        str     q3, [x1], #16
+        str     q4, [x1], #16
+        str     q2, [x1], #16
+        str     q0, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_five:
+        sub     x0, x0, #0x50
+        bl      _bsaes_decrypt8
+        ldr     q3, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q5, [x0], #16
+        ldr     q7, [x0], #16
+        ldr     q8, [x0], #16
+        str     q0, [x1], #16               // write output
+        ldr     q15, [x0]
+        eor     v0.16b, v1.16b, v3.16b
+        eor     v1.16b, v6.16b, v5.16b
+        eor     v3.16b, v4.16b, v7.16b
+        str     q0, [x1], #16
+        eor     v0.16b, v2.16b, v8.16b
+        str     q1, [x1], #16
+        str     q3, [x1], #16
+        str     q0, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_four:
+        sub     x0, x0, #0x40
+        bl      _bsaes_decrypt8
+        ldr     q2, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q3, [x0], #16
+        ldr     q5, [x0], #16
+        str     q0, [x1], #16               // write output
+        ldr     q15, [x0]
+        eor     v0.16b, v1.16b, v2.16b
+        eor     v1.16b, v6.16b, v3.16b
+        eor     v2.16b, v4.16b, v5.16b
+        str     q0, [x1], #16
+        str     q1, [x1], #16
+        str     q2, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_three:
+        sub     x0, x0, #0x30
+        bl      _bsaes_decrypt8
+        ldr     q2, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q3, [x0], #16
+        ldr     q15, [x0]
+        str     q0, [x1], #16               // write output
+        eor     v0.16b, v1.16b, v2.16b
+        eor     v1.16b, v6.16b, v3.16b
+        str     q0, [x1], #16
+        str     q1, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_two:
+        sub     x0, x0, #0x20
+        bl      _bsaes_decrypt8
+        ldr     q2, [x0], #16               // reload input
+        eor     v0.16b, v0.16b, v15.16b     // ^= IV
+        ldr     q15, [x0]
+        str     q0, [x1], #16               // write output
+        eor     v0.16b, v1.16b, v2.16b
+        str     q0, [x1]
+        b       .Lcbc_dec_done
+.align  4
+.Lcbc_dec_one:
+        sub     x0, x0, #0x10
+        stp     x1, x4, [sp, #-32]!
+        str     x14, [sp, #16]
+        mov     v8.16b, v15.16b
+        mov     v15.16b, v0.16b
+        mov     x2, x3
+        bl      AES_decrypt
+        ldr     x14, [sp, #16]
+        ldp     x1, x4, [sp], #32
+        ldr     q0, [x1]                    // load result
+        eor     v0.16b, v0.16b, v8.16b      // ^= IV
+        str     q0, [x1]                    // write output
+
+.align  4
+.Lcbc_dec_done:
+        movi    v0.16b, #0
+        movi    v1.16b, #0
+.Lcbc_dec_bzero:// wipe key schedule [if any]
+        stp     q0, q1, [sp], #32
+        cmp     sp, x14
+        bne     .Lcbc_dec_bzero
+        str     q15, [x4]                   // return IV
+        ldp     d8, d9, [sp, #16]
+        ldp     d10, d15, [sp, #32]
+        ldp     x29, x30, [sp], #48
+        ret
+.size   ossl_bsaes_cbc_encrypt,.-ossl_bsaes_cbc_encrypt
+
+.globl  ossl_bsaes_ctr32_encrypt_blocks
+.type   ossl_bsaes_ctr32_encrypt_blocks,%function
+.align  4
+// On entry:
+//   x0 -> input text (whole 16-byte blocks)
+//   x1 -> output text (whole 16-byte blocks)
+//   x2 = number of 16-byte blocks to encrypt/decrypt (> 0)
+//   x3 -> key
+//   x4 -> initial value of 128-bit counter (stored big-endian) which increments, modulo 2^32, for each block
+// On exit:
+//   Output text filled in
+//   No output registers, usual AAPCS64 register preservation
+ossl_bsaes_ctr32_encrypt_blocks:
+
+        cmp     x2, #8                      // use plain AES for
+        blo     .Lctr_enc_short             // small sizes
+
+        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]
+
+        ldr     w15, [x3, #240]             // get # of rounds
+        mov     x14, sp
+
+        // allocate the key schedule on the stack
+        add     x17, sp, #96
+        sub     x17, x17, x15, lsl #7       // 128 bytes per inner round key, less 96 bytes
+
+        // populate the key schedule
+        mov     x9, x3                      // pass key
+        mov     x10, x15                    // pass # of rounds
+        mov     sp, x17                     // sp is sp
+        bl      _bsaes_key_convert
+        eor     v7.16b, v7.16b, v15.16b     // fix up last round key
+        str     q7, [x17]                   // save last round key
+
+        ldr     q0, [x4]                    // load counter
+        add     x13, x11, #.LREVM0SR-.LM0_bigendian
+        ldr     q4, [sp]                    // load round0 key
+
+        movi    v8.4s, #1                   // compose 1<<96
+        movi    v9.16b, #0
+        rev32   v15.16b, v0.16b
+        rev32   v0.16b, v0.16b
+        ext     v11.16b, v9.16b, v8.16b, #4
+        rev32   v4.16b, v4.16b
+        add     v12.4s, v11.4s, v11.4s      // compose 2<<96
+        str     q4, [sp]                    // save adjusted round0 key
+        add     v13.4s, v11.4s, v12.4s      // compose 3<<96
+        add     v14.4s, v12.4s, v12.4s      // compose 4<<96
+        b       .Lctr_enc_loop
+
+.align  4
+.Lctr_enc_loop:
+        // Intermix prologue from _bsaes_encrypt8 to use the opportunity
+        // to flip byte order in 32-bit counter
+
+        add     v1.4s, v15.4s, v11.4s       // +1
+        add     x9, sp, #0x10               // pass next round key
+        add     v2.4s, v15.4s, v12.4s       // +2
+        ldr     q9, [x13]                   // .LREVM0SR
+        ldr     q8, [sp]                    // load round0 key
+        add     v3.4s, v15.4s, v13.4s       // +3
+        mov     x10, x15                    // pass rounds
+        sub     x11, x13, #.LREVM0SR-.LSR   // pass constants
+        add     v6.4s, v2.4s, v14.4s
+        add     v4.4s, v15.4s, v14.4s       // +4
+        add     v7.4s, v3.4s, v14.4s
+        add     v15.4s, v4.4s, v14.4s       // next counter
+        add     v5.4s, v1.4s, v14.4s
+
+        bl      _bsaes_encrypt8_alt
+
+        subs    x2, x2, #8
+        blo     .Lctr_enc_loop_done
+
+        ldr     q16, [x0], #16
+        ldr     q17, [x0], #16
+        eor     v1.16b, v1.16b, v17.16b
+        ldr     q17, [x0], #16
+        eor     v0.16b, v0.16b, v16.16b
+        eor     v4.16b, v4.16b, v17.16b
+        str     q0, [x1], #16
+        ldr     q16, [x0], #16
+        str     q1, [x1], #16
+        mov     v0.16b, v15.16b
+        str     q4, [x1], #16
+        ldr     q1, [x0], #16
+        eor     v4.16b, v6.16b, v16.16b
+        eor     v1.16b, v3.16b, v1.16b
+        ldr     q3, [x0], #16
+        eor     v3.16b, v7.16b, v3.16b
+        ldr     q6, [x0], #16
+        eor     v2.16b, v2.16b, v6.16b
+        ldr     q6, [x0], #16
+        eor     v5.16b, v5.16b, v6.16b
+        str     q4, [x1], #16
+        str     q1, [x1], #16
+        str     q3, [x1], #16
+        str     q2, [x1], #16
+        str     q5, [x1], #16
+
+        bne     .Lctr_enc_loop
+        b       .Lctr_enc_done
+
+.align  4
+.Lctr_enc_loop_done:
+        add     x2, x2, #8
+        ldr     q16, [x0], #16              // load input
+        eor     v0.16b, v0.16b, v16.16b
+        str     q0, [x1], #16               // write output
+        cmp     x2, #2
+        blo     .Lctr_enc_done
+        ldr     q17, [x0], #16
+        eor     v1.16b, v1.16b, v17.16b
+        str     q1, [x1], #16
+        beq     .Lctr_enc_done
+        ldr     q18, [x0], #16
+        eor     v4.16b, v4.16b, v18.16b
+        str     q4, [x1], #16
+        cmp     x2, #4
+        blo     .Lctr_enc_done
+        ldr     q19, [x0], #16
+        eor     v6.16b, v6.16b, v19.16b
+        str     q6, [x1], #16
+        beq     .Lctr_enc_done
+        ldr     q20, [x0], #16
+        eor     v3.16b, v3.16b, v20.16b
+        str     q3, [x1], #16
+        cmp     x2, #6
+        blo     .Lctr_enc_done
+        ldr     q21, [x0], #16
+        eor     v7.16b, v7.16b, v21.16b
+        str     q7, [x1], #16
+        beq     .Lctr_enc_done
+        ldr     q22, [x0]
+        eor     v2.16b, v2.16b, v22.16b
+        str     q2, [x1], #16
+
+.Lctr_enc_done:
+        movi    v0.16b, #0
+        movi    v1.16b, #0
+.Lctr_enc_bzero: // wipe key schedule [if any]
+        stp     q0, q1, [sp], #32
+        cmp     sp, x14
+        bne     .Lctr_enc_bzero
+
+        ldp     d8, d9, [sp, #16]
+        ldp     d10, d11, [sp, #32]
+        ldp     d12, d13, [sp, #48]
+        ldp     d14, d15, [sp, #64]
+        ldp     x29, x30, [sp], #80
+        ret
+
+.Lctr_enc_short:
+        stp     x29, x30, [sp, #-96]!
+        stp     x19, x20, [sp, #16]
+        stp     x21, x22, [sp, #32]
+        str     x23, [sp, #48]
+
+        mov     x19, x0                     // copy arguments
+        mov     x20, x1
+        mov     x21, x2
+        mov     x22, x3
+        ldr     w23, [x4, #12]              // load counter .LSW
+        ldr     q1, [x4]                    // load whole counter value
+#ifdef __AARCH64EL__
+        rev     w23, w23
+#endif
+        str     q1, [sp, #80]               // copy counter value
+
+.Lctr_enc_short_loop:
+        add     x0, sp, #80                 // input counter value
+        add     x1, sp, #64                 // output on the stack
+        mov     x2, x22                     // key
+
+        bl      AES_encrypt
+
+        ldr     q0, [x19], #16              // load input
+        ldr     q1, [sp, #64]               // load encrypted counter
+        add     x23, x23, #1
+#ifdef __AARCH64EL__
+        rev     w0, w23
+        str     w0, [sp, #80+12]            // next counter value
+#else
+        str     w23, [sp, #80+12]           // next counter value
+#endif
+        eor     v0.16b, v0.16b, v1.16b
+        str     q0, [x20], #16              // store output
+        subs    x21, x21, #1
+        bne     .Lctr_enc_short_loop
+
+        movi    v0.16b, #0
+        movi    v1.16b, #0
+        stp     q0, q1, [sp, #64]
+
+        ldr     x23, [sp, #48]
+        ldp     x21, x22, [sp, #32]
+        ldp     x19, x20, [sp, #16]
+        ldp     x29, x30, [sp], #96
+        ret
+.size   ossl_bsaes_ctr32_encrypt_blocks,.-ossl_bsaes_ctr32_encrypt_blocks
+
+.globl  ossl_bsaes_xts_encrypt
+.type   ossl_bsaes_xts_encrypt,%function
+.align  4
+// On entry:
+//   x0 -> input plaintext
+//   x1 -> output ciphertext
+//   x2 -> length of text in bytes (must be at least 16)
+//   x3 -> key1 (used to encrypt the XORed plaintext blocks)
+//   x4 -> key2 (used to encrypt the initial vector to yield the initial tweak)
+//   x5 -> 16-byte initial vector (typically, sector number)
+// On exit:
+//   Output ciphertext filled in
+//   No output registers, usual AAPCS64 register preservation
+ossl_bsaes_xts_encrypt:
+        // Stack layout:
+        // sp ->
+        //        nrounds*128-96 bytes: key schedule
+        // x19 ->
+        //        16 bytes: frame record
+        //        4*16 bytes: tweak storage across _bsaes_encrypt8
+        //        6*8 bytes: storage for 5 callee-saved general-purpose registers
+        //        8*8 bytes: storage for 8 callee-saved SIMD registers
+        stp     x29, x30, [sp, #-192]!
+        stp     x19, x20, [sp, #80]
+        stp     x21, x22, [sp, #96]
+        str     x23, [sp, #112]
+        stp     d8, d9, [sp, #128]
+        stp     d10, d11, [sp, #144]
+        stp     d12, d13, [sp, #160]
+        stp     d14, d15, [sp, #176]
+
+        mov     x19, sp
+        mov     x20, x0
+        mov     x21, x1
+        mov     x22, x2
+        mov     x23, x3
+
+        // generate initial tweak
+        sub     sp, sp, #16
+        mov     x0, x5                      // iv[]
+        mov     x1, sp
+        mov     x2, x4                      // key2
+        bl      AES_encrypt
+        ldr     q11, [sp], #16
+
+        ldr     w1, [x23, #240]             // get # of rounds
+        // allocate the key schedule on the stack
+        add     x17, sp, #96
+        sub     x17, x17, x1, lsl #7        // 128 bytes per inner round key, less 96 bytes
+
+        // populate the key schedule
+        mov     x9, x23                     // pass key
+        mov     x10, x1                     // pass # of rounds
+        mov     sp, x17
+        bl      _bsaes_key_convert
+        eor     v15.16b, v15.16b, v7.16b    // fix up last round key
+        str     q15, [x17]                  // save last round key
+
+        subs    x22, x22, #0x80
+        blo     .Lxts_enc_short
+        b       .Lxts_enc_loop
+
+.align  4
+.Lxts_enc_loop:
+        ldr     q8, .Lxts_magic
+        mov     x10, x1                     // pass rounds
+        add     x2, x19, #16
+        ldr     q0, [x20], #16
+        sshr    v1.2d, v11.2d, #63
+        mov     x9, sp                      // pass key schedule
+        ldr     q6, .Lxts_magic+16
+        add     v2.2d, v11.2d, v11.2d
+        cmtst   v3.2d, v11.2d, v6.2d
+        and     v1.16b, v1.16b, v8.16b
+        ext     v1.16b, v1.16b, v1.16b, #8
+        and     v3.16b, v3.16b, v8.16b
+        ldr     q4, [x20], #16
+        eor     v12.16b, v2.16b, v1.16b
+        eor     v1.16b, v4.16b, v12.16b
+        eor     v0.16b, v0.16b, v11.16b
+        cmtst   v2.2d, v12.2d, v6.2d
+        add     v4.2d, v12.2d, v12.2d
+        add     x0, x19, #16
+        ext     v3.16b, v3.16b, v3.16b, #8
+        and     v2.16b, v2.16b, v8.16b
+        eor     v13.16b, v4.16b, v3.16b
+        ldr     q3, [x20], #16
+        ext     v4.16b, v2.16b, v2.16b, #8
+        eor     v2.16b, v3.16b, v13.16b
+        ldr     q3, [x20], #16
+        add     v5.2d, v13.2d, v13.2d
+        cmtst   v7.2d, v13.2d, v6.2d
+        and     v7.16b, v7.16b, v8.16b
+        ldr     q9, [x20], #16
+        ext     v7.16b, v7.16b, v7.16b, #8
+        ldr     q10, [x20], #16
+        eor     v14.16b, v5.16b, v4.16b
+        ldr     q16, [x20], #16
+        add     v4.2d, v14.2d, v14.2d
+        eor     v3.16b, v3.16b, v14.16b
+        eor     v15.16b, v4.16b, v7.16b
+        add     v5.2d, v15.2d, v15.2d
+        ldr     q7, [x20], #16
+        cmtst   v4.2d, v14.2d, v6.2d
+        and     v17.16b, v4.16b, v8.16b
+        cmtst   v18.2d, v15.2d, v6.2d
+        eor     v4.16b, v9.16b, v15.16b
+        ext     v9.16b, v17.16b, v17.16b, #8
+        eor     v9.16b, v5.16b, v9.16b
+        add     v17.2d, v9.2d, v9.2d
+        and     v18.16b, v18.16b, v8.16b
+        eor     v5.16b, v10.16b, v9.16b
+        str     q9, [x2], #16
+        ext     v10.16b, v18.16b, v18.16b, #8
+        cmtst   v9.2d, v9.2d, v6.2d
+        and     v9.16b, v9.16b, v8.16b
+        eor     v10.16b, v17.16b, v10.16b
+        cmtst   v17.2d, v10.2d, v6.2d
+        eor     v6.16b, v16.16b, v10.16b
+        str     q10, [x2], #16
+        ext     v9.16b, v9.16b, v9.16b, #8
+        add     v10.2d, v10.2d, v10.2d
+        eor     v9.16b, v10.16b, v9.16b
+        str     q9, [x2], #16
+        eor     v7.16b, v7.16b, v9.16b
+        add     v9.2d, v9.2d, v9.2d
+        and     v8.16b, v17.16b, v8.16b
+        ext     v8.16b, v8.16b, v8.16b, #8
+        eor     v8.16b, v9.16b, v8.16b
+        str     q8, [x2]                    // next round tweak
+
+        bl      _bsaes_encrypt8
+
+        ldr     q8, [x0], #16
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        ldr     q9, [x0], #16
+        eor     v4.16b, v4.16b, v13.16b
+        eor     v6.16b, v6.16b, v14.16b
+        ldr     q10, [x0], #16
+        eor     v3.16b, v3.16b, v15.16b
+        subs    x22, x22, #0x80
+        str     q0, [x21], #16
+        ldr     q11, [x0]                   // next round tweak
+        str     q1, [x21], #16
+        eor     v0.16b, v7.16b, v8.16b
+        eor     v1.16b, v2.16b, v9.16b
+        str     q4, [x21], #16
+        eor     v2.16b, v5.16b, v10.16b
+        str     q6, [x21], #16
+        str     q3, [x21], #16
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q2, [x21], #16
+        bpl     .Lxts_enc_loop
+
+.Lxts_enc_short:
+        adds    x22, x22, #0x70
+        bmi     .Lxts_enc_done
+
+        ldr     q8, .Lxts_magic
+        sshr    v1.2d, v11.2d, #63
+        add     v2.2d, v11.2d, v11.2d
+        ldr     q9, .Lxts_magic+16
+        subs    x22, x22, #0x10
+        ldr     q0, [x20], #16
+        and     v1.16b, v1.16b, v8.16b
+        cmtst   v3.2d, v11.2d, v9.2d
+        ext     v1.16b, v1.16b, v1.16b, #8
+        and     v3.16b, v3.16b, v8.16b
+        eor     v12.16b, v2.16b, v1.16b
+        ext     v1.16b, v3.16b, v3.16b, #8
+        add     v2.2d, v12.2d, v12.2d
+        cmtst   v3.2d, v12.2d, v9.2d
+        eor     v13.16b, v2.16b, v1.16b
+        and     v22.16b, v3.16b, v8.16b
+        bmi     .Lxts_enc_1
+
+        ext     v2.16b, v22.16b, v22.16b, #8
+        add     v3.2d, v13.2d, v13.2d
+        ldr     q1, [x20], #16
+        cmtst   v4.2d, v13.2d, v9.2d
+        subs    x22, x22, #0x10
+        eor     v14.16b, v3.16b, v2.16b
+        and     v23.16b, v4.16b, v8.16b
+        bmi     .Lxts_enc_2
+
+        ext     v3.16b, v23.16b, v23.16b, #8
+        add     v4.2d, v14.2d, v14.2d
+        ldr     q2, [x20], #16
+        cmtst   v5.2d, v14.2d, v9.2d
+        eor     v0.16b, v0.16b, v11.16b
+        subs    x22, x22, #0x10
+        eor     v15.16b, v4.16b, v3.16b
+        and     v24.16b, v5.16b, v8.16b
+        bmi     .Lxts_enc_3
+
+        ext     v4.16b, v24.16b, v24.16b, #8
+        add     v5.2d, v15.2d, v15.2d
+        ldr     q3, [x20], #16
+        cmtst   v6.2d, v15.2d, v9.2d
+        eor     v1.16b, v1.16b, v12.16b
+        subs    x22, x22, #0x10
+        eor     v16.16b, v5.16b, v4.16b
+        and     v25.16b, v6.16b, v8.16b
+        bmi     .Lxts_enc_4
+
+        ext     v5.16b, v25.16b, v25.16b, #8
+        add     v6.2d, v16.2d, v16.2d
+        add     x0, x19, #16
+        cmtst   v7.2d, v16.2d, v9.2d
+        ldr     q4, [x20], #16
+        eor     v2.16b, v2.16b, v13.16b
+        str     q16, [x0], #16
+        subs    x22, x22, #0x10
+        eor     v17.16b, v6.16b, v5.16b
+        and     v26.16b, v7.16b, v8.16b
+        bmi     .Lxts_enc_5
+
+        ext     v7.16b, v26.16b, v26.16b, #8
+        add     v18.2d, v17.2d, v17.2d
+        ldr     q5, [x20], #16
+        eor     v3.16b, v3.16b, v14.16b
+        str     q17, [x0], #16
+        subs    x22, x22, #0x10
+        eor     v18.16b, v18.16b, v7.16b
+        bmi     .Lxts_enc_6
+
+        ldr     q6, [x20], #16
+        eor     v4.16b, v4.16b, v15.16b
+        eor     v5.16b, v5.16b, v16.16b
+        str     q18, [x0]                   // next round tweak
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1
+        add     x0, x19, #16
+        sub     x22, x22, #0x10
+        eor     v6.16b, v6.16b, v17.16b
+
+        bl      _bsaes_encrypt8
+
+        ldr     q16, [x0], #16
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        ldr     q17, [x0], #16
+        eor     v4.16b, v4.16b, v13.16b
+        eor     v6.16b, v6.16b, v14.16b
+        eor     v3.16b, v3.16b, v15.16b
+        ldr     q11, [x0]                   // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        eor     v0.16b, v7.16b, v16.16b
+        eor     v1.16b, v2.16b, v17.16b
+        str     q4, [x21], #16
+        str     q6, [x21], #16
+        str     q3, [x21], #16
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_6:
+        eor     v4.16b, v4.16b, v15.16b
+        eor     v5.16b, v5.16b, v16.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_encrypt8
+
+        ldr     q16, [x0], #16
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v4.16b, v4.16b, v13.16b
+        eor     v6.16b, v6.16b, v14.16b
+        ldr     q11, [x0]                   // next round tweak
+        eor     v3.16b, v3.16b, v15.16b
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        eor     v0.16b, v7.16b, v16.16b
+        str     q4, [x21], #16
+        str     q6, [x21], #16
+        str     q3, [x21], #16
+        str     q0, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_5:
+        eor     v3.16b, v3.16b, v14.16b
+        eor     v4.16b, v4.16b, v15.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_encrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        ldr     q11, [x0]                   // next round tweak
+        eor     v4.16b, v4.16b, v13.16b
+        eor     v6.16b, v6.16b, v14.16b
+        eor     v3.16b, v3.16b, v15.16b
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q4, [x21], #16
+        str     q6, [x21], #16
+        str     q3, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_4:
+        eor     v2.16b, v2.16b, v13.16b
+        eor     v3.16b, v3.16b, v14.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_encrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v4.16b, v4.16b, v13.16b
+        eor     v6.16b, v6.16b, v14.16b
+        mov     v11.16b, v15.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q4, [x21], #16
+        str     q6, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_3:
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v2.16b, v2.16b, v13.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_encrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v4.16b, v4.16b, v13.16b
+        mov     v11.16b, v14.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q4, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_2:
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_encrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        mov     v11.16b, v13.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        b       .Lxts_enc_done
+
+.align  4
+.Lxts_enc_1:
+        eor     v0.16b, v0.16b, v11.16b
+        sub     x0, sp, #16
+        sub     x1, sp, #16
+        mov     x2, x23
+        mov     v13.d[0], v11.d[1]          // just in case AES_encrypt corrupts top half of callee-saved SIMD registers
+        mov     v14.d[0], v12.d[1]
+        str     q0, [sp, #-16]!
+
+        bl      AES_encrypt
+
+        ldr     q0, [sp], #16
+        trn1    v13.2d, v11.2d, v13.2d
+        trn1    v11.2d, v12.2d, v14.2d      // next round tweak
+        eor     v0.16b, v0.16b, v13.16b
+        str     q0, [x21], #16
+
+.Lxts_enc_done:
+        adds    x22, x22, #0x10
+        beq     .Lxts_enc_ret
+
+        sub     x6, x21, #0x10
+        // Penultimate plaintext block produces final ciphertext part-block
+        // plus remaining part of final plaintext block. Move ciphertext part
+        // to final position and re-use penultimate ciphertext block buffer to
+        // construct final plaintext block
+.Lxts_enc_steal:
+        ldrb    w0, [x20], #1
+        ldrb    w1, [x21, #-0x10]
+        strb    w0, [x21, #-0x10]
+        strb    w1, [x21], #1
+
+        subs    x22, x22, #1
+        bhi     .Lxts_enc_steal
+
+        // Finally encrypt the penultimate ciphertext block using the
+        // last tweak
+        ldr     q0, [x6]
+        eor     v0.16b, v0.16b, v11.16b
+        str     q0, [sp, #-16]!
+        mov     x0, sp
+        mov     x1, sp
+        mov     x2, x23
+        mov     x21, x6
+        mov     v13.d[0], v11.d[1]          // just in case AES_encrypt corrupts top half of callee-saved SIMD registers
+
+        bl      AES_encrypt
+
+        trn1    v11.2d, v11.2d, v13.2d
+        ldr     q0, [sp], #16
+        eor     v0.16b, v0.16b, v11.16b
+        str     q0, [x21]
+
+.Lxts_enc_ret:
+
+        movi    v0.16b, #0
+        movi    v1.16b, #0
+.Lxts_enc_bzero: // wipe key schedule
+        stp     q0, q1, [sp], #32
+        cmp     sp, x19
+        bne     .Lxts_enc_bzero
+
+        ldp     x19, x20, [sp, #80]
+        ldp     x21, x22, [sp, #96]
+        ldr     x23, [sp, #112]
+        ldp     d8, d9, [sp, #128]
+        ldp     d10, d11, [sp, #144]
+        ldp     d12, d13, [sp, #160]
+        ldp     d14, d15, [sp, #176]
+        ldp     x29, x30, [sp], #192
+        ret
+.size   ossl_bsaes_xts_encrypt,.-ossl_bsaes_xts_encrypt
+
+// The assembler doesn't seem capable of de-duplicating these when expressed
+// using `ldr qd,=` syntax, so assign a symbolic address
+.align  5
+.Lxts_magic:
+.quad   1, 0x87, 0x4000000000000000, 0x4000000000000000
+
+.globl  ossl_bsaes_xts_decrypt
+.type   ossl_bsaes_xts_decrypt,%function
+.align  4
+// On entry:
+//   x0 -> input ciphertext
+//   x1 -> output plaintext
+//   x2 -> length of text in bytes (must be at least 16)
+//   x3 -> key1 (used to decrypt the XORed ciphertext blocks)
+//   x4 -> key2 (used to encrypt the initial vector to yield the initial tweak)
+//   x5 -> 16-byte initial vector (typically, sector number)
+// On exit:
+//   Output plaintext filled in
+//   No output registers, usual AAPCS64 register preservation
+ossl_bsaes_xts_decrypt:
+        // Stack layout:
+        // sp ->
+        //        nrounds*128-96 bytes: key schedule
+        // x19 ->
+        //        16 bytes: frame record
+        //        4*16 bytes: tweak storage across _bsaes_decrypt8
+        //        6*8 bytes: storage for 5 callee-saved general-purpose registers
+        //        8*8 bytes: storage for 8 callee-saved SIMD registers
+        stp     x29, x30, [sp, #-192]!
+        stp     x19, x20, [sp, #80]
+        stp     x21, x22, [sp, #96]
+        str     x23, [sp, #112]
+        stp     d8, d9, [sp, #128]
+        stp     d10, d11, [sp, #144]
+        stp     d12, d13, [sp, #160]
+        stp     d14, d15, [sp, #176]
+
+        mov     x19, sp
+        mov     x20, x0
+        mov     x21, x1
+        mov     x22, x2
+        mov     x23, x3
+
+        // generate initial tweak
+        sub     sp, sp, #16
+        mov     x0, x5                      // iv[]
+        mov     x1, sp
+        mov     x2, x4                      // key2
+        bl      AES_encrypt
+        ldr     q11, [sp], #16
+
+        ldr     w1, [x23, #240]             // get # of rounds
+        // allocate the key schedule on the stack
+        add     x17, sp, #96
+        sub     x17, x17, x1, lsl #7        // 128 bytes per inner round key, less 96 bytes
+
+        // populate the key schedule
+        mov     x9, x23                     // pass key
+        mov     x10, x1                     // pass # of rounds
+        mov     sp, x17
+        bl      _bsaes_key_convert
+        ldr     q6,  [sp]
+        str     q15, [x17]                  // save last round key
+        eor     v6.16b, v6.16b, v7.16b      // fix up round 0 key (by XORing with 0x63)
+        str     q6, [sp]
+
+        sub     x30, x22, #0x10
+        tst     x22, #0xf                   // if not multiple of 16
+        csel    x22, x30, x22, ne           // subtract another 16 bytes
+        subs    x22, x22, #0x80
+
+        blo     .Lxts_dec_short
+        b       .Lxts_dec_loop
+
+.align  4
+.Lxts_dec_loop:
+        ldr     q8, .Lxts_magic
+        mov     x10, x1                     // pass rounds
+        add     x2, x19, #16
+        ldr     q0, [x20], #16
+        sshr    v1.2d, v11.2d, #63
+        mov     x9, sp                      // pass key schedule
+        ldr     q6, .Lxts_magic+16
+        add     v2.2d, v11.2d, v11.2d
+        cmtst   v3.2d, v11.2d, v6.2d
+        and     v1.16b, v1.16b, v8.16b
+        ext     v1.16b, v1.16b, v1.16b, #8
+        and     v3.16b, v3.16b, v8.16b
+        ldr     q4, [x20], #16
+        eor     v12.16b, v2.16b, v1.16b
+        eor     v1.16b, v4.16b, v12.16b
+        eor     v0.16b, v0.16b, v11.16b
+        cmtst   v2.2d, v12.2d, v6.2d
+        add     v4.2d, v12.2d, v12.2d
+        add     x0, x19, #16
+        ext     v3.16b, v3.16b, v3.16b, #8
+        and     v2.16b, v2.16b, v8.16b
+        eor     v13.16b, v4.16b, v3.16b
+        ldr     q3, [x20], #16
+        ext     v4.16b, v2.16b, v2.16b, #8
+        eor     v2.16b, v3.16b, v13.16b
+        ldr     q3, [x20], #16
+        add     v5.2d, v13.2d, v13.2d
+        cmtst   v7.2d, v13.2d, v6.2d
+        and     v7.16b, v7.16b, v8.16b
+        ldr     q9, [x20], #16
+        ext     v7.16b, v7.16b, v7.16b, #8
+        ldr     q10, [x20], #16
+        eor     v14.16b, v5.16b, v4.16b
+        ldr     q16, [x20], #16
+        add     v4.2d, v14.2d, v14.2d
+        eor     v3.16b, v3.16b, v14.16b
+        eor     v15.16b, v4.16b, v7.16b
+        add     v5.2d, v15.2d, v15.2d
+        ldr     q7, [x20], #16
+        cmtst   v4.2d, v14.2d, v6.2d
+        and     v17.16b, v4.16b, v8.16b
+        cmtst   v18.2d, v15.2d, v6.2d
+        eor     v4.16b, v9.16b, v15.16b
+        ext     v9.16b, v17.16b, v17.16b, #8
+        eor     v9.16b, v5.16b, v9.16b
+        add     v17.2d, v9.2d, v9.2d
+        and     v18.16b, v18.16b, v8.16b
+        eor     v5.16b, v10.16b, v9.16b
+        str     q9, [x2], #16
+        ext     v10.16b, v18.16b, v18.16b, #8
+        cmtst   v9.2d, v9.2d, v6.2d
+        and     v9.16b, v9.16b, v8.16b
+        eor     v10.16b, v17.16b, v10.16b
+        cmtst   v17.2d, v10.2d, v6.2d
+        eor     v6.16b, v16.16b, v10.16b
+        str     q10, [x2], #16
+        ext     v9.16b, v9.16b, v9.16b, #8
+        add     v10.2d, v10.2d, v10.2d
+        eor     v9.16b, v10.16b, v9.16b
+        str     q9, [x2], #16
+        eor     v7.16b, v7.16b, v9.16b
+        add     v9.2d, v9.2d, v9.2d
+        and     v8.16b, v17.16b, v8.16b
+        ext     v8.16b, v8.16b, v8.16b, #8
+        eor     v8.16b, v9.16b, v8.16b
+        str     q8, [x2]                    // next round tweak
+
+        bl      _bsaes_decrypt8
+
+        eor     v6.16b, v6.16b, v13.16b
+        eor     v0.16b, v0.16b, v11.16b
+        ldr     q8, [x0], #16
+        eor     v7.16b, v7.16b, v8.16b
+        str     q0, [x21], #16
+        eor     v0.16b, v1.16b, v12.16b
+        ldr     q1, [x0], #16
+        eor     v1.16b, v3.16b, v1.16b
+        subs    x22, x22, #0x80
+        eor     v2.16b, v2.16b, v15.16b
+        eor     v3.16b, v4.16b, v14.16b
+        ldr     q4, [x0], #16
+        str     q0, [x21], #16
+        ldr     q11, [x0]                   // next round tweak
+        eor     v0.16b, v5.16b, v4.16b
+        str     q6, [x21], #16
+        str     q3, [x21], #16
+        str     q2, [x21], #16
+        str     q7, [x21], #16
+        str     q1, [x21], #16
+        str     q0, [x21], #16
+        bpl     .Lxts_dec_loop
+
+.Lxts_dec_short:
+        adds    x22, x22, #0x70
+        bmi     .Lxts_dec_done
+
+        ldr     q8, .Lxts_magic
+        sshr    v1.2d, v11.2d, #63
+        add     v2.2d, v11.2d, v11.2d
+        ldr     q9, .Lxts_magic+16
+        subs    x22, x22, #0x10
+        ldr     q0, [x20], #16
+        and     v1.16b, v1.16b, v8.16b
+        cmtst   v3.2d, v11.2d, v9.2d
+        ext     v1.16b, v1.16b, v1.16b, #8
+        and     v3.16b, v3.16b, v8.16b
+        eor     v12.16b, v2.16b, v1.16b
+        ext     v1.16b, v3.16b, v3.16b, #8
+        add     v2.2d, v12.2d, v12.2d
+        cmtst   v3.2d, v12.2d, v9.2d
+        eor     v13.16b, v2.16b, v1.16b
+        and     v22.16b, v3.16b, v8.16b
+        bmi     .Lxts_dec_1
+
+        ext     v2.16b, v22.16b, v22.16b, #8
+        add     v3.2d, v13.2d, v13.2d
+        ldr     q1, [x20], #16
+        cmtst   v4.2d, v13.2d, v9.2d
+        subs    x22, x22, #0x10
+        eor     v14.16b, v3.16b, v2.16b
+        and     v23.16b, v4.16b, v8.16b
+        bmi     .Lxts_dec_2
+
+        ext     v3.16b, v23.16b, v23.16b, #8
+        add     v4.2d, v14.2d, v14.2d
+        ldr     q2, [x20], #16
+        cmtst   v5.2d, v14.2d, v9.2d
+        eor     v0.16b, v0.16b, v11.16b
+        subs    x22, x22, #0x10
+        eor     v15.16b, v4.16b, v3.16b
+        and     v24.16b, v5.16b, v8.16b
+        bmi     .Lxts_dec_3
+
+        ext     v4.16b, v24.16b, v24.16b, #8
+        add     v5.2d, v15.2d, v15.2d
+        ldr     q3, [x20], #16
+        cmtst   v6.2d, v15.2d, v9.2d
+        eor     v1.16b, v1.16b, v12.16b
+        subs    x22, x22, #0x10
+        eor     v16.16b, v5.16b, v4.16b
+        and     v25.16b, v6.16b, v8.16b
+        bmi     .Lxts_dec_4
+
+        ext     v5.16b, v25.16b, v25.16b, #8
+        add     v6.2d, v16.2d, v16.2d
+        add     x0, x19, #16
+        cmtst   v7.2d, v16.2d, v9.2d
+        ldr     q4, [x20], #16
+        eor     v2.16b, v2.16b, v13.16b
+        str     q16, [x0], #16
+        subs    x22, x22, #0x10
+        eor     v17.16b, v6.16b, v5.16b
+        and     v26.16b, v7.16b, v8.16b
+        bmi     .Lxts_dec_5
+
+        ext     v7.16b, v26.16b, v26.16b, #8
+        add     v18.2d, v17.2d, v17.2d
+        ldr     q5, [x20], #16
+        eor     v3.16b, v3.16b, v14.16b
+        str     q17, [x0], #16
+        subs    x22, x22, #0x10
+        eor     v18.16b, v18.16b, v7.16b
+        bmi     .Lxts_dec_6
+
+        ldr     q6, [x20], #16
+        eor     v4.16b, v4.16b, v15.16b
+        eor     v5.16b, v5.16b, v16.16b
+        str     q18, [x0]                   // next round tweak
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1
+        add     x0, x19, #16
+        sub     x22, x22, #0x10
+        eor     v6.16b, v6.16b, v17.16b
+
+        bl      _bsaes_decrypt8
+
+        ldr     q16, [x0], #16
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        ldr     q17, [x0], #16
+        eor     v6.16b, v6.16b, v13.16b
+        eor     v4.16b, v4.16b, v14.16b
+        eor     v2.16b, v2.16b, v15.16b
+        ldr     q11, [x0]                   // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        eor     v0.16b, v7.16b, v16.16b
+        eor     v1.16b, v3.16b, v17.16b
+        str     q6, [x21], #16
+        str     q4, [x21], #16
+        str     q2, [x21], #16
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_6:
+        eor     v4.16b, v4.16b, v15.16b
+        eor     v5.16b, v5.16b, v16.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_decrypt8
+
+        ldr     q16, [x0], #16
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v6.16b, v6.16b, v13.16b
+        eor     v4.16b, v4.16b, v14.16b
+        ldr     q11, [x0]                   // next round tweak
+        eor     v2.16b, v2.16b, v15.16b
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        eor     v0.16b, v7.16b, v16.16b
+        str     q6, [x21], #16
+        str     q4, [x21], #16
+        str     q2, [x21], #16
+        str     q0, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_5:
+        eor     v3.16b, v3.16b, v14.16b
+        eor     v4.16b, v4.16b, v15.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_decrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        ldr     q11, [x0]                   // next round tweak
+        eor     v6.16b, v6.16b, v13.16b
+        eor     v4.16b, v4.16b, v14.16b
+        eor     v2.16b, v2.16b, v15.16b
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q6, [x21], #16
+        str     q4, [x21], #16
+        str     q2, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_4:
+        eor     v2.16b, v2.16b, v13.16b
+        eor     v3.16b, v3.16b, v14.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_decrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v6.16b, v6.16b, v13.16b
+        eor     v4.16b, v4.16b, v14.16b
+        mov     v11.16b, v15.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q6, [x21], #16
+        str     q4, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_3:
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v2.16b, v2.16b, v13.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_decrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        eor     v6.16b, v6.16b, v13.16b
+        mov     v11.16b, v14.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        str     q6, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_2:
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        mov     x9, sp                      // pass key schedule
+        mov     x10, x1                     // pass rounds
+        add     x0, x19, #16
+
+        bl      _bsaes_decrypt8
+
+        eor     v0.16b, v0.16b, v11.16b
+        eor     v1.16b, v1.16b, v12.16b
+        mov     v11.16b, v13.16b            // next round tweak
+        str     q0, [x21], #16
+        str     q1, [x21], #16
+        b       .Lxts_dec_done
+
+.align  4
+.Lxts_dec_1:
+        eor     v0.16b, v0.16b, v11.16b
+        sub     x0, sp, #16
+        sub     x1, sp, #16
+        mov     x2, x23
+        mov     v13.d[0], v11.d[1]          // just in case AES_decrypt corrupts top half of callee-saved SIMD registers
+        mov     v14.d[0], v12.d[1]
+        str     q0, [sp, #-16]!
+
+        bl      AES_decrypt
+
+        ldr     q0, [sp], #16
+        trn1    v13.2d, v11.2d, v13.2d
+        trn1    v11.2d, v12.2d, v14.2d      // next round tweak
+        eor     v0.16b, v0.16b, v13.16b
+        str     q0, [x21], #16
+
+.Lxts_dec_done:
+        adds    x22, x22, #0x10
+        beq     .Lxts_dec_ret
+
+        // calculate one round of extra tweak for the stolen ciphertext
+        ldr     q8, .Lxts_magic
+        sshr    v6.2d, v11.2d, #63
+        and     v6.16b, v6.16b, v8.16b
+        add     v12.2d, v11.2d, v11.2d
+        ext     v6.16b, v6.16b, v6.16b, #8
+        eor     v12.16b, v12.16b, v6.16b
+
+        // perform the final decryption with the last tweak value
+        ldr     q0, [x20], #16
+        eor     v0.16b, v0.16b, v12.16b
+        str     q0, [sp, #-16]!
+        mov     x0, sp
+        mov     x1, sp
+        mov     x2, x23
+        mov     v13.d[0], v11.d[1]          // just in case AES_decrypt corrupts top half of callee-saved SIMD registers
+        mov     v14.d[0], v12.d[1]
+
+        bl      AES_decrypt
+
+        trn1    v12.2d, v12.2d, v14.2d
+        trn1    v11.2d, v11.2d, v13.2d
+        ldr     q0, [sp], #16
+        eor     v0.16b, v0.16b, v12.16b
+        str     q0, [x21]
+
+        mov     x6, x21
+        // Penultimate ciphertext block produces final plaintext part-block
+        // plus remaining part of final ciphertext block. Move plaintext part
+        // to final position and re-use penultimate plaintext block buffer to
+        // construct final ciphertext block
+.Lxts_dec_steal:
+        ldrb    w1, [x21]
+        ldrb    w0, [x20], #1
+        strb    w1, [x21, #0x10]
+        strb    w0, [x21], #1
+
+        subs    x22, x22, #1
+        bhi     .Lxts_dec_steal
+
+        // Finally decrypt the penultimate plaintext block using the
+        // penultimate tweak
+        ldr     q0, [x6]
+        eor     v0.16b, v0.16b, v11.16b
+        str     q0, [sp, #-16]!
+        mov     x0, sp
+        mov     x1, sp
+        mov     x2, x23
+        mov     x21, x6
+
+        bl      AES_decrypt
+
+        trn1    v11.2d, v11.2d, v13.2d
+        ldr     q0, [sp], #16
+        eor     v0.16b, v0.16b, v11.16b
+        str     q0, [x21]
+
+.Lxts_dec_ret:
+
+        movi    v0.16b, #0
+        movi    v1.16b, #0
+.Lxts_dec_bzero: // wipe key schedule
+        stp     q0, q1, [sp], #32
+        cmp     sp, x19
+        bne     .Lxts_dec_bzero
+
+        ldp     x19, x20, [sp, #80]
+        ldp     x21, x22, [sp, #96]
+        ldr     x23, [sp, #112]
+        ldp     d8, d9, [sp, #128]
+        ldp     d10, d11, [sp, #144]
+        ldp     d12, d13, [sp, #160]
+        ldp     d14, d15, [sp, #176]
+        ldp     x29, x30, [sp], #192
+        ret
+.size   ossl_bsaes_xts_decrypt,.-ossl_bsaes_xts_decrypt

+ 17 - 17
libs/openssl/crypto/aria/aria.c

@@ -1,8 +1,8 @@
 /*
- * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
  * Copyright (c) 2017, Oracle and/or its affiliates.  All rights reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -468,8 +468,8 @@ static const uint32_t X2[256] = {
         (Y) = (TMP2) ^ rotr32((TMP) ^ (TMP2), 16);  \
     } while(0)
 
-void aria_encrypt(const unsigned char *in, unsigned char *out,
-                  const ARIA_KEY *key)
+void ossl_aria_encrypt(const unsigned char *in, unsigned char *out,
+                       const ARIA_KEY *key)
 {
     register uint32_t reg0, reg1, reg2, reg3;
     int Nr;
@@ -535,8 +535,8 @@ void aria_encrypt(const unsigned char *in, unsigned char *out,
     PUT_U32_BE(out, 3, reg3);
 }
 
-int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
-                         ARIA_KEY *key)
+int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits,
+                              ARIA_KEY *key)
 {
     register uint32_t reg0, reg1, reg2, reg3;
     uint32_t w0[4], w1[4], w2[4], w3[4];
@@ -667,8 +667,8 @@ int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
     return 0;
 }
 
-int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
-                         ARIA_KEY *key)
+int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits,
+                              ARIA_KEY *key)
 {
     ARIA_u128 *rk_head;
     ARIA_u128 *rk_tail;
@@ -676,7 +676,7 @@ int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
     register uint32_t reg0, reg1, reg2, reg3;
     uint32_t s0, s1, s2, s3;
 
-    const int r = aria_set_encrypt_key(userKey, bits, key);
+    const int r = ossl_aria_set_encrypt_key(userKey, bits, key);
 
     if (r != 0) {
         return r;
@@ -1007,7 +1007,7 @@ static void sl2(ARIA_c128 o, const ARIA_u128 *x, const ARIA_u128 *y)
 {
     unsigned int i;
     for (i = 0; i < ARIA_BLOCK_SIZE; i += 4) {
-        o[i    ] = sb3[x->c[i	 ] ^ y->c[i    ]];
+        o[i    ] = sb3[x->c[i    ] ^ y->c[i    ]];
         o[i + 1] = sb4[x->c[i + 1] ^ y->c[i + 1]];
         o[i + 2] = sb1[x->c[i + 2] ^ y->c[i + 2]];
         o[i + 3] = sb2[x->c[i + 3] ^ y->c[i + 3]];
@@ -1106,8 +1106,8 @@ static void do_encrypt(unsigned char *o, const unsigned char *pin,
  * Encrypt a single block
  * in and out can overlap
  */
-void aria_encrypt(const unsigned char *in, unsigned char *out,
-                  const ARIA_KEY *key)
+void ossl_aria_encrypt(const unsigned char *in, unsigned char *out,
+                       const ARIA_KEY *key)
 {
     assert(in != NULL && out != NULL && key != NULL);
     do_encrypt(out, in, key->rounds, key->rd_key);
@@ -1119,8 +1119,8 @@ void aria_encrypt(const unsigned char *in, unsigned char *out,
  * We short circuit execution of the last two
  * or four rotations based on the key size.
  */
-int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
-                         ARIA_KEY *key)
+int ossl_aria_set_encrypt_key(const unsigned char *userKey, const int bits,
+                              ARIA_KEY *key)
 {
     const ARIA_u128 *ck1, *ck2, *ck3;
     ARIA_u128 kr, w0, w1, w2, w3;
@@ -1192,11 +1192,11 @@ int aria_set_encrypt_key(const unsigned char *userKey, const int bits,
 /*
  * Expand the cipher key into the decryption key schedule.
  */
-int aria_set_decrypt_key(const unsigned char *userKey, const int bits,
-                         ARIA_KEY *key)
+int ossl_aria_set_decrypt_key(const unsigned char *userKey, const int bits,
+                              ARIA_KEY *key)
 {
     ARIA_KEY ek;
-    const int r = aria_set_encrypt_key(userKey, bits, &ek);
+    const int r = ossl_aria_set_encrypt_key(userKey, bits, &ek);
     unsigned int i, rounds = ek.rounds;
 
     if (r == 0) {

+ 117 - 7
libs/openssl/crypto/arm_arch.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -21,11 +21,6 @@
 #  elif defined(__GNUC__)
 #   if   defined(__aarch64__)
 #    define __ARM_ARCH__ 8
-#    if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
-#     define __ARMEB__
-#    else
-#     define __ARMEL__
-#    endif
   /*
    * Why doesn't gcc define __ARM_ARCH__? Instead it defines
    * bunch of below macros. See all_architectures[] table in
@@ -71,6 +66,8 @@
 
 # ifndef __ASSEMBLER__
 extern unsigned int OPENSSL_armcap_P;
+extern unsigned int OPENSSL_arm_midr;
+extern unsigned int OPENSSL_armv8_rsa_neonized;
 # endif
 
 # define ARMV7_NEON      (1<<0)
@@ -80,5 +77,118 @@ extern unsigned int OPENSSL_armcap_P;
 # define ARMV8_SHA256    (1<<4)
 # define ARMV8_PMULL     (1<<5)
 # define ARMV8_SHA512    (1<<6)
+# define ARMV8_CPUID     (1<<7)
+# define ARMV8_RNG       (1<<8)
+# define ARMV8_SM3       (1<<9)
+# define ARMV8_SM4       (1<<10)
+# define ARMV8_SHA3      (1<<11)
+# define ARMV8_UNROLL8_EOR3      (1<<12)
+# define ARMV8_SVE       (1<<13)
+# define ARMV8_SVE2      (1<<14)
+
+/*
+ * MIDR_EL1 system register
+ *
+ * 63___ _ ___32_31___ _ ___24_23_____20_19_____16_15__ _ __4_3_______0
+ * |            |             |         |         |          |        |
+ * |RES0        | Implementer | Variant | Arch    | PartNum  |Revision|
+ * |____ _ _____|_____ _ _____|_________|_______ _|____ _ ___|________|
+ *
+ */
+
+# define ARM_CPU_IMP_ARM           0x41
+
+# define ARM_CPU_PART_CORTEX_A72   0xD08
+# define ARM_CPU_PART_N1           0xD0C
+# define ARM_CPU_PART_V1           0xD40
+# define ARM_CPU_PART_N2           0xD49
+
+# define MIDR_PARTNUM_SHIFT       4
+# define MIDR_PARTNUM_MASK        (0xfffU << MIDR_PARTNUM_SHIFT)
+# define MIDR_PARTNUM(midr)       \
+           (((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
+
+# define MIDR_IMPLEMENTER_SHIFT   24
+# define MIDR_IMPLEMENTER_MASK    (0xffU << MIDR_IMPLEMENTER_SHIFT)
+# define MIDR_IMPLEMENTER(midr)   \
+           (((midr) & MIDR_IMPLEMENTER_MASK) >> MIDR_IMPLEMENTER_SHIFT)
+
+# define MIDR_ARCHITECTURE_SHIFT  16
+# define MIDR_ARCHITECTURE_MASK   (0xfU << MIDR_ARCHITECTURE_SHIFT)
+# define MIDR_ARCHITECTURE(midr)  \
+           (((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
+
+# define MIDR_CPU_MODEL_MASK \
+           (MIDR_IMPLEMENTER_MASK | \
+            MIDR_PARTNUM_MASK     | \
+            MIDR_ARCHITECTURE_MASK)
+
+# define MIDR_CPU_MODEL(imp, partnum) \
+           (((imp)     << MIDR_IMPLEMENTER_SHIFT)  | \
+            (0xfU      << MIDR_ARCHITECTURE_SHIFT) | \
+            ((partnum) << MIDR_PARTNUM_SHIFT))
+
+# define MIDR_IS_CPU_MODEL(midr, imp, partnum) \
+           (((midr) & MIDR_CPU_MODEL_MASK) == MIDR_CPU_MODEL(imp, partnum))
+
+#if defined(__ASSEMBLER__)
+
+   /*
+    * Support macros for
+    *   - Armv8.3-A Pointer Authentication and
+    *   - Armv8.5-A Branch Target Identification
+    * features which require emitting a .note.gnu.property section with the
+    * appropriate architecture-dependent feature bits set.
+    * Read more: "ELF for the Arm® 64-bit Architecture"
+    */
+
+#  if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
+#   define GNU_PROPERTY_AARCH64_BTI (1 << 0)   /* Has Branch Target Identification */
+#   define AARCH64_VALID_CALL_TARGET hint #34  /* BTI 'c' */
+#  else
+#   define GNU_PROPERTY_AARCH64_BTI 0  /* No Branch Target Identification */
+#   define AARCH64_VALID_CALL_TARGET
+#  endif
+
+#  if defined(__ARM_FEATURE_PAC_DEFAULT) && \
+       (__ARM_FEATURE_PAC_DEFAULT & 1) == 1  /* Signed with A-key */
+#   define GNU_PROPERTY_AARCH64_POINTER_AUTH \
+     (1 << 1)                                       /* Has Pointer Authentication */
+#   define AARCH64_SIGN_LINK_REGISTER hint #25      /* PACIASP */
+#   define AARCH64_VALIDATE_LINK_REGISTER hint #29  /* AUTIASP */
+#  elif defined(__ARM_FEATURE_PAC_DEFAULT) && \
+       (__ARM_FEATURE_PAC_DEFAULT & 2) == 2  /* Signed with B-key */
+#   define GNU_PROPERTY_AARCH64_POINTER_AUTH \
+     (1 << 1)                                       /* Has Pointer Authentication */
+#   define AARCH64_SIGN_LINK_REGISTER hint #27      /* PACIBSP */
+#   define AARCH64_VALIDATE_LINK_REGISTER hint #31  /* AUTIBSP */
+#  else
+#   define GNU_PROPERTY_AARCH64_POINTER_AUTH 0  /* No Pointer Authentication */
+#   if GNU_PROPERTY_AARCH64_BTI != 0
+#    define AARCH64_SIGN_LINK_REGISTER AARCH64_VALID_CALL_TARGET
+#   else
+#    define AARCH64_SIGN_LINK_REGISTER
+#   endif
+#   define AARCH64_VALIDATE_LINK_REGISTER
+#  endif
+
+#  if GNU_PROPERTY_AARCH64_POINTER_AUTH != 0 || GNU_PROPERTY_AARCH64_BTI != 0
+    .pushsection .note.gnu.property, "a";
+    .balign 8;
+    .long 4;
+    .long 0x10;
+    .long 0x5;
+    .asciz "GNU";
+    .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+    .long 4;
+    .long (GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_BTI);
+    .long 0;
+    .popsection;
+#  endif
+
+# endif  /* defined __ASSEMBLER__ */
+
+# define IS_CPU_SUPPORT_UNROLL8_EOR3() \
+           (OPENSSL_armcap_P & ARMV8_UNROLL8_EOR3)
 
 #endif

+ 7 - 7
libs/openssl/crypto/asn1/a_bitstr.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -18,7 +18,7 @@ int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
     return ASN1_STRING_set(x, d, len);
 }
 
-int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
+int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
 {
     int ret, j, bits, len;
     unsigned char *p, *d;
@@ -76,8 +76,8 @@ int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
     return ret;
 }
 
-ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
-                                     const unsigned char **pp, long len)
+ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+                                          const unsigned char **pp, long len)
 {
     ASN1_BIT_STRING *ret = NULL;
     const unsigned char *p;
@@ -134,7 +134,7 @@ ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
     *pp = p;
     return ret;
  err:
-    ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
+    ERR_raise(ERR_LIB_ASN1, i);
     if ((a == NULL) || (*a != ret))
         ASN1_BIT_STRING_free(ret);
     return NULL;
@@ -164,7 +164,7 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
             return 1;         /* Don't need to set */
         c = OPENSSL_clear_realloc(a->data, a->length, w + 1);
         if (c == NULL) {
-            ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         if (w + 1 - a->length > 0)

+ 46 - 27
libs/openssl/crypto/asn1/a_d2i_fp.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -13,6 +13,7 @@
 #include "internal/numbers.h"
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
+#include "internal/asn1.h"
 #include "crypto/asn1.h"
 
 #ifndef NO_OLD_ASN1
@@ -24,7 +25,7 @@ void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
     void *ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
         return NULL;
     }
     BIO_set_fp(b, in, BIO_NOCLOSE);
@@ -54,39 +55,53 @@ void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
 
 #endif
 
-void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+void *ASN1_item_d2i_bio_ex(const ASN1_ITEM *it, BIO *in, void *x,
+                           OSSL_LIB_CTX *libctx, const char *propq)
 {
     BUF_MEM *b = NULL;
     const unsigned char *p;
     void *ret = NULL;
     int len;
 
+    if (in == NULL)
+        return NULL;
     len = asn1_d2i_read_bio(in, &b);
     if (len < 0)
         goto err;
 
     p = (const unsigned char *)b->data;
-    ret = ASN1_item_d2i(x, &p, len, it);
+    ret = ASN1_item_d2i_ex(x, &p, len, it, libctx, propq);
  err:
     BUF_MEM_free(b);
     return ret;
 }
 
+void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+{
+    return ASN1_item_d2i_bio_ex(it, in, x, NULL, NULL);
+}
+
 #ifndef OPENSSL_NO_STDIO
-void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+void *ASN1_item_d2i_fp_ex(const ASN1_ITEM *it, FILE *in, void *x,
+                          OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *b;
     char *ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
         return NULL;
     }
     BIO_set_fp(b, in, BIO_NOCLOSE);
-    ret = ASN1_item_d2i_bio(it, b, x);
+    ret = ASN1_item_d2i_bio_ex(it, b, x, libctx, propq);
     BIO_free(b);
     return ret;
 }
+
+void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+{
+    return ASN1_item_d2i_fp_ex(it, in, x, NULL, NULL);
+}
 #endif
 
 #define HEADER_SIZE   8
@@ -100,6 +115,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
     uint32_t eos = 0;
     size_t off = 0;
     size_t len = 0;
+    size_t diff;
 
     const unsigned char *q;
     long slen;
@@ -107,27 +123,28 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
 
     b = BUF_MEM_new();
     if (b == NULL) {
-        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return -1;
     }
 
-    ERR_clear_error();
+    ERR_set_mark();
     for (;;) {
-        if (want >= (len - off)) {
-            want -= (len - off);
+        diff = len - off;
+        if (want >= diff) {
+            want -= diff;
 
             if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
-                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
             i = BIO_read(in, &(b->data[len]), want);
-            if ((i < 0) && ((len - off) == 0)) {
-                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA);
+            if (i < 0 && diff == 0) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
                 goto err;
             }
             if (i > 0) {
                 if (len + i < len) {
-                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
                     goto err;
                 }
                 len += i;
@@ -137,15 +154,17 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
 
         p = (unsigned char *)&(b->data[off]);
         q = p;
-        inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
+        diff = len - off;
+        if (diff == 0)
+            goto err;
+        inf = ASN1_get_object(&q, &slen, &tag, &xclass, diff);
         if (inf & 0x80) {
             unsigned long e;
 
-            e = ERR_GET_REASON(ERR_peek_error());
+            e = ERR_GET_REASON(ERR_peek_last_error());
             if (e != ASN1_R_TOO_LONG)
                 goto err;
-            else
-                ERR_clear_error(); /* clear error */
+            ERR_pop_to_mark();
         }
         i = q - p;            /* header length */
         off += i;               /* end of data */
@@ -153,7 +172,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
         if (inf & 1) {
             /* no data body so go round again */
             if (eos == UINT32_MAX) {
-                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
                 goto err;
             }
             eos++;
@@ -174,7 +193,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
                 want -= (len - off);
                 if (want > INT_MAX /* BIO_read takes an int length */  ||
                     len + want < len) {
-                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
                     goto err;
                 }
                 while (want > 0) {
@@ -187,15 +206,14 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
                     size_t chunk = want > chunk_max ? chunk_max : want;
 
                     if (!BUF_MEM_grow_clean(b, len + chunk)) {
-                        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE);
+                        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                         goto err;
                     }
                     want -= chunk;
                     while (chunk > 0) {
                         i = BIO_read(in, &(b->data[len]), chunk);
                         if (i <= 0) {
-                            ASN1err(ASN1_F_ASN1_D2I_READ_BIO,
-                                    ASN1_R_NOT_ENOUGH_DATA);
+                            ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ENOUGH_DATA);
                             goto err;
                         }
                     /*
@@ -210,7 +228,7 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
                 }
             }
             if (off + slen < off) {
-                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
                 goto err;
             }
             off += slen;
@@ -222,13 +240,14 @@ int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
     }
 
     if (off > INT_MAX) {
-        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
         goto err;
     }
 
     *pb = b;
     return off;
  err:
+    ERR_clear_last_mark();
     BUF_MEM_free(b);
     return -1;
 }

+ 40 - 13
libs/openssl/crypto/asn1/a_digest.c

@@ -1,24 +1,29 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include <time.h>
 #include <sys/types.h>
 
 #include "internal/cryptlib.h"
 
+#include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/x509.h>
+#include "crypto/x509.h"
 
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 
 int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
                 unsigned char *md, unsigned int *len)
@@ -28,11 +33,11 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
 
     inl = i2d(data, NULL);
     if (inl <= 0) {
-        ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_INTERNAL_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
         return 0;
     }
     if ((str = OPENSSL_malloc(inl)) == NULL) {
-        ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     p = str;
@@ -48,20 +53,42 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
 
 #endif
 
-int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
-                     unsigned char *md, unsigned int *len)
+int ossl_asn1_item_digest_ex(const ASN1_ITEM *it, const EVP_MD *md, void *asn,
+                             unsigned char *data, unsigned int *len,
+                             OSSL_LIB_CTX *libctx, const char *propq)
 {
-    int i;
+    int i, ret = 0;
     unsigned char *str = NULL;
+    EVP_MD *fetched_md = (EVP_MD *)md;
 
     i = ASN1_item_i2d(asn, &str, it);
-    if (!str)
+    if (i < 0 || str == NULL)
         return 0;
 
-    if (!EVP_Digest(str, i, md, len, type, NULL)) {
-        OPENSSL_free(str);
-        return 0;
+    if (EVP_MD_get0_provider(md) == NULL) {
+#if !defined(OPENSSL_NO_ENGINE)
+        ENGINE *tmpeng = ENGINE_get_digest_engine(EVP_MD_get_type(md));
+
+        if (tmpeng != NULL)
+            ENGINE_finish(tmpeng);
+        else
+#endif
+            fetched_md = EVP_MD_fetch(libctx, EVP_MD_get0_name(md), propq);
     }
+    if (fetched_md == NULL)
+        goto err;
+
+    ret = EVP_Digest(str, i, data, len, fetched_md, NULL);
+err:
     OPENSSL_free(str);
-    return 1;
+    if (fetched_md != md)
+        EVP_MD_free(fetched_md);
+    return ret;
 }
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *md, void *asn,
+                     unsigned char *data, unsigned int *len)
+{
+    return ossl_asn1_item_digest_ex(it, md, asn, data, len, NULL, NULL);
+}
+

+ 38 - 9
libs/openssl/crypto/asn1/a_dup.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -9,11 +9,11 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
-#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
 
 #ifndef NO_OLD_ASN1
 
-void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
+void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, const void *x)
 {
     unsigned char *b, *p;
     const unsigned char *p2;
@@ -24,9 +24,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
         return NULL;
 
     i = i2d(x, NULL);
+    if (i <= 0)
+        return NULL;
+
     b = OPENSSL_malloc(i + 10);
     if (b == NULL) {
-        ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     p = b;
@@ -46,23 +49,49 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
  * decode.
  */
 
-void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
+void *ASN1_item_dup(const ASN1_ITEM *it, const void *x)
 {
+    ASN1_aux_cb *asn1_cb = NULL;
     unsigned char *b = NULL;
     const unsigned char *p;
     long i;
-    void *ret;
+    ASN1_VALUE *ret;
+    OSSL_LIB_CTX *libctx = NULL;
+    const char *propq = NULL;
 
     if (x == NULL)
         return NULL;
 
+    if (it->itype == ASN1_ITYPE_SEQUENCE || it->itype == ASN1_ITYPE_CHOICE
+        || it->itype == ASN1_ITYPE_NDEF_SEQUENCE) {
+        const ASN1_AUX *aux = it->funcs;
+
+        asn1_cb = aux != NULL ? aux->asn1_cb : NULL;
+    }
+
+    if (asn1_cb != NULL) {
+        if (!asn1_cb(ASN1_OP_DUP_PRE, (ASN1_VALUE **)&x, it, NULL)
+                || !asn1_cb(ASN1_OP_GET0_LIBCTX, (ASN1_VALUE **)&x, it, &libctx)
+                || !asn1_cb(ASN1_OP_GET0_PROPQ, (ASN1_VALUE **)&x, it, &propq))
+            goto auxerr;
+    }
+
     i = ASN1_item_i2d(x, &b, it);
     if (b == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     p = b;
-    ret = ASN1_item_d2i(NULL, &p, i, it);
+    ret = ASN1_item_d2i_ex(NULL, &p, i, it, libctx, propq);
     OPENSSL_free(b);
+
+    if (asn1_cb != NULL
+        && !asn1_cb(ASN1_OP_DUP_POST, &ret, it, (void *)x))
+        goto auxerr;
+
     return ret;
+
+ auxerr:
+    ERR_raise_data(ERR_LIB_ASN1, ASN1_R_AUX_ERROR, "Type=%s", it->sname);
+    return NULL;
 }

+ 10 - 6
libs/openssl/crypto/asn1/a_gentm.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -16,14 +16,18 @@
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include "asn1_local.h"
+#include <openssl/asn1t.h>
+
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_GENERALIZEDTIME)
 
 /* This is the primary function used to parse ASN1_GENERALIZEDTIME */
-int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
+static int asn1_generalizedtime_to_tm(struct tm *tm,
+                                      const ASN1_GENERALIZEDTIME *d)
 {
-    /* wrapper around asn1_time_to_tm */
+    /* wrapper around ossl_asn1_time_to_tm */
     if (d->type != V_ASN1_GENERALIZEDTIME)
         return 0;
-    return asn1_time_to_tm(tm, d);
+    return ossl_asn1_time_to_tm(tm, d);
 }
 
 int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
@@ -71,7 +75,7 @@ ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
             return NULL;
     }
 
-    return asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
+    return ossl_asn1_time_from_tm(s, ts, V_ASN1_GENERALIZEDTIME);
 }
 
 int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)

+ 28 - 10
libs/openssl/crypto/asn1/a_i2d_fp.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -15,13 +15,13 @@
 #ifndef NO_OLD_ASN1
 
 # ifndef OPENSSL_NO_STDIO
-int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
+int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, const void *x)
 {
     BIO *b;
     int ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
         return 0;
     }
     BIO_set_fp(b, out, BIO_NOCLOSE);
@@ -31,7 +31,7 @@ int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
 }
 # endif
 
-int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
+int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, const void *x)
 {
     char *b;
     unsigned char *p;
@@ -43,7 +43,7 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
 
     b = OPENSSL_malloc(n);
     if (b == NULL) {
-        ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -68,13 +68,13 @@ int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
 #endif
 
 #ifndef OPENSSL_NO_STDIO
-int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
+int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, const void *x)
 {
     BIO *b;
     int ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_BUF_LIB);
         return 0;
     }
     BIO_set_fp(b, out, BIO_NOCLOSE);
@@ -84,14 +84,14 @@ int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
 }
 #endif
 
-int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
+int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, const void *x)
 {
     unsigned char *b = NULL;
     int i, j = 0, n, ret = 1;
 
     n = ASN1_item_i2d(x, &b, it);
     if (b == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -109,3 +109,21 @@ int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
     OPENSSL_free(b);
     return ret;
 }
+
+BIO *ASN1_item_i2d_mem_bio(const ASN1_ITEM *it, const ASN1_VALUE *val)
+{
+    BIO *res;
+
+    if (it == NULL || val == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+
+    if ((res = BIO_new(BIO_s_mem())) == NULL)
+        return NULL;
+    if (ASN1_item_i2d_bio(it, res, val) <= 0) {
+        BIO_free(res);
+        res = NULL;
+    }
+    return res;
+}

+ 42 - 29
libs/openssl/crypto/asn1/a_int.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -79,8 +79,14 @@ static void twos_complement(unsigned char *dst, const unsigned char *src,
     unsigned int carry = pad & 1;
 
     /* Begin at the end of the encoding */
-    dst += len;
-    src += len;
+    if (len != 0) {
+        /*
+         * if len == 0 then src/dst could be NULL, and this would be undefined
+         * behaviour.
+         */
+        dst += len;
+        src += len;
+    }
     /* two's complement value: ~value + 1 */
     while (len-- != 0) {
         *(--dst) = (unsigned char)(carry += *(--src) ^ pad);
@@ -151,7 +157,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
     int neg, pad;
     /* Zero content length is illegal */
     if (plen == 0) {
-        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
         return 0;
     }
     neg = p[0] & 0x80;
@@ -184,7 +190,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
     }
     /* reject illegal padding: first two octets MSB can't match */
     if (pad && (neg == (p[1] & 0x80))) {
-        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING);
         return 0;
     }
 
@@ -198,7 +204,7 @@ static size_t c2i_ibuf(unsigned char *b, int *pneg,
     return plen;
 }
 
-int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
+int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
 {
     return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp);
 }
@@ -210,7 +216,7 @@ static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen)
     uint64_t r;
 
     if (blen > sizeof(*pr)) {
-        ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
         return 0;
     }
     if (b == NULL)
@@ -262,14 +268,14 @@ static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
              * on ones'-complement system. */
             *pr = (int64_t)(0 - r);
         } else {
-            ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
             return 0;
         }
     } else {
         if (r <= INT64_MAX) {
             *pr = (int64_t)r;
         } else {
-            ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
             return 0;
         }
     }
@@ -277,8 +283,8 @@ static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen,
 }
 
 /* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */
-ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
-                               long len)
+ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+                                    long len)
 {
     ASN1_INTEGER *ret = NULL;
     size_t r;
@@ -302,16 +308,18 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
 
     c2i_ibuf(ret->data, &neg, *pp, len);
 
-    if (neg)
+    if (neg != 0)
         ret->type |= V_ASN1_NEG;
+    else
+        ret->type &= ~V_ASN1_NEG;
 
     *pp += len;
     if (a != NULL)
         (*a) = ret;
     return ret;
  err:
-    ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
-    if ((a == NULL) || (*a != ret))
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+    if (a == NULL || *a != ret)
         ASN1_INTEGER_free(ret);
     return NULL;
 }
@@ -319,11 +327,11 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
 static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype)
 {
     if (a == NULL) {
-        ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
     if ((a->type & ~V_ASN1_NEG) != itype) {
-        ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
         return 0;
     }
     return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG);
@@ -354,15 +362,15 @@ static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a,
                                   int itype)
 {
     if (a == NULL) {
-        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
     if ((a->type & ~V_ASN1_NEG) != itype) {
-        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
         return 0;
     }
     if (a->type & V_ASN1_NEG) {
-        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
         return 0;
     }
     return asn1_get_uint64(pr, a->data, a->length);
@@ -390,7 +398,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
     ASN1_INTEGER *ret = NULL;
     const unsigned char *p;
     unsigned char *s;
-    long len;
+    long len = 0;
     int inf, tag, xclass;
     int i;
 
@@ -413,6 +421,10 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
         goto err;
     }
 
+    if (len < 0) {
+        i = ASN1_R_ILLEGAL_NEGATIVE_VALUE;
+        goto err;
+    }
     /*
      * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
      * a missing NULL parameter.
@@ -440,7 +452,7 @@ ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
     *pp = p;
     return ret;
  err:
-    ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i);
+    ERR_raise(ERR_LIB_ASN1, i);
     if ((a == NULL) || (*a != ret))
         ASN1_INTEGER_free(ret);
     return NULL;
@@ -460,7 +472,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
     }
 
     if (ret == NULL) {
-        ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
         goto err;
     }
 
@@ -473,7 +485,7 @@ static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai,
         len = 1;
 
     if (ASN1_STRING_set(ret, NULL, len) == 0) {
-        ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -496,13 +508,13 @@ static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn,
     BIGNUM *ret;
 
     if ((ai->type & ~V_ASN1_NEG) != itype) {
-        ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_INTEGER_TYPE);
         return NULL;
     }
 
     ret = BN_bin2bn(ai->data, ai->length, bn);
     if (ret == NULL) {
-        ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_BN_LIB);
         return NULL;
     }
     if (ai->type & V_ASN1_NEG)
@@ -603,7 +615,8 @@ BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
 }
 
 /* Internal functions used by x_int64.c */
-int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
+int ossl_c2i_uint64_int(uint64_t *ret, int *neg,
+                        const unsigned char **pp, long len)
 {
     unsigned char buf[sizeof(uint64_t)];
     size_t buflen;
@@ -612,14 +625,14 @@ int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len)
     if (buflen == 0)
         return 0;
     if (buflen > sizeof(uint64_t)) {
-        ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
         return 0;
     }
     (void)c2i_ibuf(buf, neg, *pp, len);
     return asn1_get_uint64(ret, buf, buflen);
 }
 
-int i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
+int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg)
 {
     unsigned char buf[sizeof(uint64_t)];
     size_t off;

+ 28 - 21
libs/openssl/crypto/asn1/a_mbstr.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include "crypto/ctype.h"
 #include "internal/cryptlib.h"
+#include "internal/unicode.h"
 #include <openssl/asn1.h>
 
 static int traverse_string(const unsigned char *p, int len, int inform,
@@ -49,20 +50,20 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
     ASN1_STRING *dest;
     unsigned char *p;
     int nchar;
-    char strbuf[32];
     int (*cpyfunc) (unsigned long, void *) = NULL;
     if (len == -1)
         len = strlen((const char *)in);
     if (!mask)
         mask = DIRSTRING_TYPE;
+    if (len < 0)
+        return -1;
 
     /* First do a string check and work out the number of characters */
     switch (inform) {
 
     case MBSTRING_BMP:
         if (len & 1) {
-            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
-                    ASN1_R_INVALID_BMPSTRING_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
             return -1;
         }
         nchar = len >> 1;
@@ -70,8 +71,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
 
     case MBSTRING_UNIV:
         if (len & 3) {
-            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY,
-                    ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
             return -1;
         }
         nchar = len >> 2;
@@ -82,7 +82,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
         /* This counts the characters and does utf8 syntax checking */
         ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
         if (ret < 0) {
-            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UTF8STRING);
             return -1;
         }
         break;
@@ -92,27 +92,25 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
         break;
 
     default:
-        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
         return -1;
     }
 
     if ((minsize > 0) && (nchar < minsize)) {
-        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT);
-        BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize);
-        ERR_add_error_data(2, "minsize=", strbuf);
+        ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_SHORT,
+                       "minsize=%ld", minsize);
         return -1;
     }
 
     if ((maxsize > 0) && (nchar > maxsize)) {
-        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG);
-        BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize);
-        ERR_add_error_data(2, "maxsize=", strbuf);
+        ERR_raise_data(ERR_LIB_ASN1, ASN1_R_STRING_TOO_LONG,
+                       "maxsize=%ld", maxsize);
         return -1;
     }
 
     /* Now work out minimal type (if any) */
     if (traverse_string(in, len, inform, type_str, &mask) < 0) {
-        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_CHARACTERS);
         return -1;
     }
 
@@ -149,7 +147,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
         free_out = 1;
         dest = ASN1_STRING_type_new(str_type);
         if (dest == NULL) {
-            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         *out = dest;
@@ -157,7 +155,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
     /* If both the same type just copy across */
     if (inform == outform) {
         if (!ASN1_STRING_set(dest, in, len)) {
-            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         return str_type;
@@ -189,7 +187,7 @@ int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
     if ((p = OPENSSL_malloc(outlen + 1)) == NULL) {
         if (free_out)
             ASN1_STRING_free(dest);
-        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return -1;
     }
     dest->length = outlen;
@@ -247,6 +245,9 @@ static int traverse_string(const unsigned char *p, int len, int inform,
 static int in_utf8(unsigned long value, void *arg)
 {
     int *nchar;
+
+    if (!is_unicode_valid(value))
+        return -2;
     nchar = arg;
     (*nchar)++;
     return 1;
@@ -256,9 +257,13 @@ static int in_utf8(unsigned long value, void *arg)
 
 static int out_utf8(unsigned long value, void *arg)
 {
-    int *outlen;
+    int *outlen, len;
+
+    len = UTF8_putc(NULL, -1, value);
+    if (len <= 0)
+        return len;
     outlen = arg;
-    *outlen += UTF8_putc(NULL, -1, value);
+    *outlen += len;
     return 1;
 }
 
@@ -283,6 +288,8 @@ static int type_str(unsigned long value, void *arg)
         types &= ~B_ASN1_T61STRING;
     if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
         types &= ~B_ASN1_BMPSTRING;
+    if ((types & B_ASN1_UTF8STRING) && !is_unicode_valid(value))
+        types &= ~B_ASN1_UTF8STRING;
     if (!types)
         return -1;
     *((unsigned long *)arg) = types;

+ 29 - 22
libs/openssl/crypto/asn1/a_object.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -32,7 +32,7 @@ int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
 
     if (*pp == NULL) {
         if ((p = allocated = OPENSSL_malloc(objsize)) == NULL) {
-            ASN1err(ASN1_F_I2D_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
     } else {
@@ -70,12 +70,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
     if ((c >= '0') && (c <= '2')) {
         first = c - '0';
     } else {
-        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
         goto err;
     }
 
     if (num <= 0) {
-        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_SECOND_NUMBER);
         goto err;
     }
     c = *(p++);
@@ -84,7 +84,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
         if (num <= 0)
             break;
         if ((c != '.') && (c != ' ')) {
-            ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SEPARATOR);
             goto err;
         }
         l = 0;
@@ -97,7 +97,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
             if ((c == ' ') || (c == '.'))
                 break;
             if (!ossl_isdigit(c)) {
-                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_DIGIT);
                 goto err;
             }
             if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
@@ -116,8 +116,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
         }
         if (len == 0) {
             if ((first < 2) && (l >= 40)) {
-                ASN1err(ASN1_F_A2D_ASN1_OBJECT,
-                        ASN1_R_SECOND_NUMBER_TOO_LARGE);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
                 goto err;
             }
             if (use_bn) {
@@ -136,8 +135,10 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
                     OPENSSL_free(tmp);
                 tmpsize = blsize + 32;
                 tmp = OPENSSL_malloc(tmpsize);
-                if (tmp == NULL)
+                if (tmp == NULL) {
+                    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                     goto err;
+                }
             }
             while (blsize--) {
                 BN_ULONG t = BN_div_word(bl, 0x80L);
@@ -157,7 +158,7 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
         }
         if (out != NULL) {
             if (len + i > olen) {
-                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_BUFFER_TOO_SMALL);
                 goto err;
             }
             while (--i > 0)
@@ -191,8 +192,12 @@ int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
         return BIO_write(bp, "NULL", 4);
     i = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
     if (i > (int)(sizeof(buf) - 1)) {
+        if (i > INT_MAX - 1) {  /* catch an integer overflow */
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_LENGTH_TOO_LONG);
+            return -1;
+        }
         if ((p = OPENSSL_malloc(i + 1)) == NULL) {
-            ASN1err(ASN1_F_I2A_ASN1_OBJECT, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         i2t_ASN1_OBJECT(p, i + 1, a);
@@ -227,17 +232,17 @@ ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
         i = ASN1_R_EXPECTING_AN_OBJECT;
         goto err;
     }
-    ret = c2i_ASN1_OBJECT(a, &p, len);
+    ret = ossl_c2i_ASN1_OBJECT(a, &p, len);
     if (ret)
         *pp = p;
     return ret;
  err:
-    ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
+    ERR_raise(ERR_LIB_ASN1, i);
     return NULL;
 }
 
-ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
-                             long len)
+ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+                                  long len)
 {
     ASN1_OBJECT *ret = NULL, tobj;
     const unsigned char *p;
@@ -251,7 +256,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
      */
     if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
         p[len - 1] & 0x80) {
-        ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
         return NULL;
     }
     /* Now 0 < len <= INT_MAX, so the cast is safe. */
@@ -281,7 +286,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
     }
     for (i = 0; i < length; i++, p++) {
         if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
-            ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
             return NULL;
         }
     }
@@ -329,7 +334,7 @@ ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
     *pp = p;
     return ret;
  err:
-    ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
+    ERR_raise(ERR_LIB_ASN1, i);
     if ((a == NULL) || (*a != ret))
         ASN1_OBJECT_free(ret);
     return NULL;
@@ -341,7 +346,7 @@ ASN1_OBJECT *ASN1_OBJECT_new(void)
 
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-        ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
@@ -353,9 +358,11 @@ void ASN1_OBJECT_free(ASN1_OBJECT *a)
     if (a == NULL)
         return;
     if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
-#ifndef CONST_STRICT            /* disable purely for compile-time strict
-                                 * const checking. Doing this on a "real"
-                                 * compile will cause memory leaks */
+#ifndef CONST_STRICT
+        /*
+         * Disable purely for compile-time strict const checking.  Doing this
+         * on a "real" compile will cause memory leaks
+         */
         OPENSSL_free((void*)a->sn);
         OPENSSL_free((void*)a->ln);
 #endif

+ 1 - 1
libs/openssl/crypto/asn1/a_octet.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 1 - 1
libs/openssl/crypto/asn1/a_print.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 108 - 48
libs/openssl/crypto/asn1/a_sign.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -18,10 +18,11 @@
 #include <openssl/x509.h>
 #include <openssl/objects.h>
 #include <openssl/buffer.h>
+#include <openssl/core_names.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
 
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 
 int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
               ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
@@ -34,7 +35,7 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
     X509_ALGOR *a;
 
     if (ctx == NULL) {
-        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     for (i = 0; i < 2; i++) {
@@ -61,27 +62,27 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
         ASN1_OBJECT_free(a->algorithm);
         a->algorithm = OBJ_nid2obj(type->pkey_type);
         if (a->algorithm == NULL) {
-            ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_OBJECT_TYPE);
             goto err;
         }
         if (a->algorithm->length == 0) {
-            ASN1err(ASN1_F_ASN1_SIGN,
-                    ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+            ERR_raise(ERR_LIB_ASN1,
+                      ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
             goto err;
         }
     }
     inl = i2d(data, NULL);
     if (inl <= 0) {
-        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_INTERNAL_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     inll = (size_t)inl;
     buf_in = OPENSSL_malloc(inll);
-    outll = outl = EVP_PKEY_size(pkey);
+    outll = outl = EVP_PKEY_get_size(pkey);
     buf_out = OPENSSL_malloc(outll);
     if (buf_in == NULL || buf_out == NULL) {
         outl = 0;
-        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     p = buf_in;
@@ -92,7 +93,7 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
         || !EVP_SignFinal(ctx, (unsigned char *)buf_out,
                           (unsigned int *)&outl, pkey)) {
         outl = 0;
-        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         goto err;
     }
     OPENSSL_free(signature->data);
@@ -114,54 +115,104 @@ int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
 
 #endif
 
-int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
-                   X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
-                   EVP_PKEY *pkey, const EVP_MD *type)
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+                   ASN1_BIT_STRING *signature, const void *data,
+                   EVP_PKEY *pkey, const EVP_MD *md)
 {
-    int rv;
-    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    return ASN1_item_sign_ex(it, algor1, algor2, signature, data, NULL, pkey,
+                             md, NULL, NULL);
+}
+
+int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1,
+                      X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+                      const void *data, const ASN1_OCTET_STRING *id,
+                      EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx,
+                      const char *propq)
+{
+    int rv = 0;
+    EVP_MD_CTX *ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq);
 
     if (ctx == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
-    if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) {
-        EVP_MD_CTX_free(ctx);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
+    /* We can use the non _ex variant here since the pkey is already setup */
+    if (!EVP_DigestSignInit(ctx, NULL, md, NULL, pkey))
+        goto err;
 
-    rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx);
+    rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, data, ctx);
 
+ err:
+    EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx));
     EVP_MD_CTX_free(ctx);
     return rv;
 }
 
-int ASN1_item_sign_ctx(const ASN1_ITEM *it,
-                       X509_ALGOR *algor1, X509_ALGOR *algor2,
-                       ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1,
+                       X509_ALGOR *algor2, ASN1_BIT_STRING *signature,
+                       const void *data, EVP_MD_CTX *ctx)
 {
-    const EVP_MD *type;
+    const EVP_MD *md;
     EVP_PKEY *pkey;
     unsigned char *buf_in = NULL, *buf_out = NULL;
     size_t inl = 0, outl = 0, outll = 0;
     int signid, paramtype, buf_len = 0;
-    int rv;
+    int rv, pkey_id;
 
-    type = EVP_MD_CTX_md(ctx);
-    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx));
+    md = EVP_MD_CTX_get0_md(ctx);
+    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
 
     if (pkey == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
         goto err;
     }
 
     if (pkey->ameth == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
-        goto err;
-    }
+        EVP_PKEY_CTX *pctx = EVP_MD_CTX_get_pkey_ctx(ctx);
+        OSSL_PARAM params[2];
+        unsigned char aid[128];
+        size_t aid_len = 0;
+
+        if (pctx == NULL
+            || !EVP_PKEY_CTX_IS_SIGNATURE_OP(pctx)) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
+            goto err;
+        }
 
-    if (pkey->ameth->item_sign) {
-        rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature);
+        params[0] =
+            OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID,
+                                              aid, sizeof(aid));
+        params[1] = OSSL_PARAM_construct_end();
+
+        if (EVP_PKEY_CTX_get_params(pctx, params) <= 0)
+            goto err;
+
+        if ((aid_len = params[0].return_size) == 0) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+            goto err;
+        }
+
+        if (algor1 != NULL) {
+            const unsigned char *pp = aid;
+
+            if (d2i_X509_ALGOR(&algor1, &pp, aid_len) == NULL) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+        }
+
+        if (algor2 != NULL) {
+            const unsigned char *pp = aid;
+
+            if (d2i_X509_ALGOR(&algor2, &pp, aid_len) == NULL) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+        }
+
+        rv = 3;
+    } else if (pkey->ameth->item_sign) {
+        rv = pkey->ameth->item_sign(ctx, it, data, algor1, algor2, signature);
         if (rv == 1)
             outl = signature->length;
         /*-
@@ -172,7 +223,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
          *   3: ASN1 method sets algorithm identifiers: just sign.
          */
         if (rv <= 0)
-            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         if (rv <= 1)
             goto err;
     } else {
@@ -180,15 +231,19 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
     }
 
     if (rv == 2) {
-        if (type == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
+        if (md == NULL) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
             goto err;
         }
-        if (!OBJ_find_sigid_by_algs(&signid,
-                                    EVP_MD_nid(type),
-                                    pkey->ameth->pkey_id)) {
-            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
-                    ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+
+        pkey_id =
+#ifndef OPENSSL_NO_SM2
+            EVP_PKEY_get_id(pkey) == NID_sm2 ? NID_sm2 :
+#endif
+            pkey->ameth->pkey_id;
+
+        if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(md), pkey_id)) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
             goto err;
         }
 
@@ -204,24 +259,29 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it,
 
     }
 
-    buf_len = ASN1_item_i2d(asn, &buf_in, it);
+    buf_len = ASN1_item_i2d(data, &buf_in, it);
     if (buf_len <= 0) {
         outl = 0;
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_INTERNAL_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     inl = buf_len;
-    outll = outl = EVP_PKEY_size(pkey);
+    if (!EVP_DigestSign(ctx, NULL, &outll, buf_in, inl)) {
+        outl = 0;
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+        goto err;
+    }
+    outl = outll;
     buf_out = OPENSSL_malloc(outll);
     if (buf_in == NULL || buf_out == NULL) {
         outl = 0;
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     if (!EVP_DigestSign(ctx, buf_out, &outl, buf_in, inl)) {
         outl = 0;
-        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         goto err;
     }
     OPENSSL_free(signature->data);

+ 5 - 5
libs/openssl/crypto/asn1/a_strex.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -32,7 +32,7 @@
                   ASN1_STRFLGS_ESC_MSB)
 
 /*
- * Three IO functions for sending data to memory, a BIO and and a FILE
+ * Three IO functions for sending data to memory, a BIO and a FILE
  * pointer.
  */
 static int send_bio_chars(void *arg, const void *buf, int len)
@@ -152,13 +152,13 @@ static int do_buf(unsigned char *buf, int buflen,
     switch (charwidth) {
     case 4:
         if (buflen & 3) {
-            ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
             return -1;
         }
         break;
     case 2:
         if (buflen & 1) {
-            ASN1err(ASN1_F_DO_BUF, ASN1_R_INVALID_BMPSTRING_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
             return -1;
         }
         break;
@@ -283,7 +283,7 @@ static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
     if (der_len <= 0)
         return -1;
     if ((der_buf = OPENSSL_malloc(der_len)) == NULL) {
-        ASN1err(ASN1_F_DO_DUMP, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return -1;
     }
     p = der_buf;

+ 8 - 5
libs/openssl/crypto/asn1/a_strnid.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -51,7 +51,7 @@ int ASN1_STRING_set_default_mask_asc(const char *p)
     char *end;
 
     if (strncmp(p, "MASK:", 5) == 0) {
-        if (!p[5])
+        if (p[5] == '\0')
             return 0;
         mask = strtoul(p + 5, &end, 0);
         if (*end)
@@ -129,6 +129,9 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
     int idx;
     ASN1_STRING_TABLE fnd;
 
+    /* "stable" can be impacted by config, so load the config file first */
+    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+
     fnd.nid = nid;
     if (stable) {
         idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
@@ -157,7 +160,7 @@ static ASN1_STRING_TABLE *stable_get(int nid)
     if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC)
         return tmp;
     if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) {
-        ASN1err(ASN1_F_STABLE_GET, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
@@ -187,7 +190,7 @@ int ASN1_STRING_TABLE_add(int nid,
 
     tmp = stable_get(nid);
     if (tmp == NULL) {
-        ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     if (minsize >= 0)

+ 60 - 27
libs/openssl/crypto/asn1/a_time.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <time.h>
+#include "crypto/asn1.h"
 #include "crypto/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
@@ -24,6 +25,7 @@
 IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
 
 IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_TIME)
 
 static int is_utc(const int year)
 {
@@ -71,7 +73,7 @@ static void determine_days(struct tm *tm)
     tm->tm_wday = (d + (13 * m) / 5 + y + y / 4 + c / 4 + 5 * c + 6) % 7;
 }
 
-int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
+int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
 {
     static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
     static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
@@ -90,7 +92,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
      *
      * 1. "seconds" is a 'MUST'
      * 2. "Zulu" timezone is a 'MUST'
-     * 3. "+|-" is not allowed to indicate a time zone
+     * 3. "+|-" is not allowed to indicate a timezone
      */
     if (d->type == V_ASN1_UTCTIME) {
         if (d->flags & ASN1_STRING_FLAG_X509_TIME) {
@@ -128,14 +130,14 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
             i++;
             break;
         }
-        if (!ascii_isdigit(a[o]))
+        if (!ossl_ascii_isdigit(a[o]))
             goto err;
         n = a[o] - num_zero;
         /* incomplete 2-digital number */
         if (++o == l)
             goto err;
 
-        if (!ascii_isdigit(a[o]))
+        if (!ossl_ascii_isdigit(a[o]))
             goto err;
         n = (n * 10) + a[o] - num_zero;
         /* no more bytes to read, but we haven't seen time-zone yet */
@@ -196,7 +198,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
         if (++o == l)
             goto err;
         i = o;
-        while ((o < l) && ascii_isdigit(a[o]))
+        while ((o < l) && ossl_ascii_isdigit(a[o]))
             o++;
         /* Must have at least one digit after decimal point */
         if (i == o)
@@ -227,11 +229,11 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
         if (o + 4 != l)
             goto err;
         for (i = end; i < end + 2; i++) {
-            if (!ascii_isdigit(a[o]))
+            if (!ossl_ascii_isdigit(a[o]))
                 goto err;
             n = a[o] - num_zero;
             o++;
-            if (!ascii_isdigit(a[o]))
+            if (!ossl_ascii_isdigit(a[o]))
                 goto err;
             n = (n * 10) + a[o] - num_zero;
             i2 = (d->type == V_ASN1_UTCTIME) ? i + 1 : i;
@@ -262,7 +264,7 @@ int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d)
     return 0;
 }
 
-ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
+ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type)
 {
     char* p;
     ASN1_TIME *tmps = NULL;
@@ -327,14 +329,14 @@ ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
 
     ts = OPENSSL_gmtime(&t, &data);
     if (ts == NULL) {
-        ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_GETTING_TIME);
         return NULL;
     }
     if (offset_day || offset_sec) {
         if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
             return NULL;
     }
-    return asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
+    return ossl_asn1_time_from_tm(s, ts, V_ASN1_UNDEF);
 }
 
 int ASN1_TIME_check(const ASN1_TIME *t)
@@ -359,7 +361,7 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t,
     if (out != NULL)
         ret = *out;
 
-    ret = asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
+    ret = ossl_asn1_time_from_tm(ret, &tm, V_ASN1_GENERALIZEDTIME);
 
     if (out != NULL && ret != NULL)
         *out = ret;
@@ -408,7 +410,7 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
      */
 
     if (s != NULL && t.type == V_ASN1_GENERALIZEDTIME) {
-        if (!asn1_time_to_tm(&tm, &t))
+        if (!ossl_asn1_time_to_tm(&tm, &t))
             goto out;
         if (is_utc(tm.tm_year)) {
             t.length -= 2;
@@ -418,8 +420,10 @@ int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
              * new t.data would be freed after ASN1_STRING_copy is done.
              */
             t.data = OPENSSL_zalloc(t.length + 1);
-            if (t.data == NULL)
+            if (t.data == NULL) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 goto out;
+            }
             memcpy(t.data, str + 2, t.length);
             t.type = V_ASN1_UTCTIME;
         }
@@ -446,7 +450,7 @@ int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
         return 0;
     }
 
-    return asn1_time_to_tm(tm, s);
+    return ossl_asn1_time_to_tm(tm, s);
 }
 
 int ASN1_TIME_diff(int *pday, int *psec,
@@ -466,17 +470,31 @@ static const char _asn1_mon[12][4] = {
     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
+/* prints the time with the default date format (RFC 822) */
 int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
+{
+    return ASN1_TIME_print_ex(bp, tm, ASN1_DTFLGS_RFC822);
+}
+
+/* returns 1 on success, 0 on BIO write error or parse failure */
+int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
+{
+    return ossl_asn1_time_print_ex(bp, tm, flags) > 0;
+}
+
+
+/* prints the time with the date format of ISO 8601 */
+/* returns 0 on BIO write error, else -1 in case of parse failure, else 1 */
+int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
 {
     char *v;
     int gmt = 0, l;
     struct tm stm;
     const char upper_z = 0x5A, period = 0x2E;
 
-    if (!asn1_time_to_tm(&stm, tm)) {
-        /* asn1_time_to_tm will check the time type */
-        goto err;
-    }
+    /* ossl_asn1_time_to_tm will check the time type */
+    if (!ossl_asn1_time_to_tm(&stm, tm))
+        return BIO_write(bp, "Bad time value", 14) ? -1 : 0;
 
     l = tm->length;
     v = (char *)tm->data;
@@ -494,23 +512,38 @@ int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
         if (tm->length > 15 && v[14] == period) {
             f = &v[14];
             f_len = 1;
-            while (14 + f_len < l && ascii_isdigit(f[f_len]))
+            while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
                 ++f_len;
         }
 
-        return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+        if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+            return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
+                          stm.tm_year + 1900, stm.tm_mon + 1,
+                          stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec, f_len, f,
+                          (gmt ? "Z" : "")) > 0;
+        }
+        else {
+            return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
                           _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
                           stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
                           (gmt ? " GMT" : "")) > 0;
+        }
     } else {
-        return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+        if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
+            return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
+                          stm.tm_year + 1900, stm.tm_mon + 1,
+                          stm.tm_mday, stm.tm_hour,
+                          stm.tm_min, stm.tm_sec,
+                          (gmt ? "Z" : "")) > 0;
+        }
+        else {
+            return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
                           _asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
                           stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
                           (gmt ? " GMT" : "")) > 0;
+        }
     }
- err:
-    BIO_write(bp, "Bad time value", 14);
-    return 0;
 }
 
 int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
@@ -541,7 +574,7 @@ int ASN1_TIME_normalize(ASN1_TIME *t)
     if (!ASN1_TIME_to_tm(t, &tm))
         return 0;
 
-    return asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
+    return ossl_asn1_time_from_tm(t, &tm, V_ASN1_UNDEF) != NULL;
 }
 
 int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b)

+ 3 - 3
libs/openssl/crypto/asn1/a_type.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -29,7 +29,7 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
             && a->type != V_ASN1_NULL
             && a->value.ptr != NULL) {
         ASN1_TYPE **tmp_a = &a;
-        asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
+        ossl_asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0);
     }
     a->type = type;
     if (type == V_ASN1_BOOLEAN)

+ 11 - 8
libs/openssl/crypto/asn1/a_utctm.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -12,19 +12,22 @@
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include "asn1_local.h"
+#include <openssl/asn1t.h>
+
+IMPLEMENT_ASN1_DUP_FUNCTION(ASN1_UTCTIME)
 
 /* This is the primary function used to parse ASN1_UTCTIME */
-int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
+int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
 {
-    /* wrapper around ans1_time_to_tm */
+    /* wrapper around ossl_asn1_time_to_tm */
     if (d->type != V_ASN1_UTCTIME)
         return 0;
-    return asn1_time_to_tm(tm, d);
+    return ossl_asn1_time_to_tm(tm, d);
 }
 
 int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
 {
-    return asn1_utctime_to_tm(NULL, d);
+    return ossl_asn1_utctime_to_tm(NULL, d);
 }
 
 /* Sets the string via simple copy without cleaning it up */
@@ -66,7 +69,7 @@ ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
             return NULL;
     }
 
-    return asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
+    return ossl_asn1_time_from_tm(s, ts, V_ASN1_UTCTIME);
 }
 
 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
@@ -74,7 +77,7 @@ int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
     struct tm stm, ttm;
     int day, sec;
 
-    if (!asn1_utctime_to_tm(&stm, s))
+    if (!ossl_asn1_utctime_to_tm(&stm, s))
         return -2;
 
     if (OPENSSL_gmtime(&t, &ttm) == NULL)

+ 13 - 64
libs/openssl/crypto/asn1/a_utf8.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -9,6 +9,7 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
+#include "internal/unicode.h"
 #include <openssl/asn1.h>
 
 /* UTF8 utilities */
@@ -58,6 +59,8 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
         value |= *p++ & 0x3f;
         if (value < 0x800)
             return -4;
+        if (is_unicode_surrogate(value))
+            return -2;
         ret = 3;
     } else if ((*p & 0xf8) == 0xf0) {
         if (len < 4)
@@ -73,40 +76,6 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
         if (value < 0x10000)
             return -4;
         ret = 4;
-    } else if ((*p & 0xfc) == 0xf8) {
-        if (len < 5)
-            return -1;
-        if (((p[1] & 0xc0) != 0x80)
-            || ((p[2] & 0xc0) != 0x80)
-            || ((p[3] & 0xc0) != 0x80)
-            || ((p[4] & 0xc0) != 0x80))
-            return -3;
-        value = ((unsigned long)(*p++ & 0x3)) << 24;
-        value |= ((unsigned long)(*p++ & 0x3f)) << 18;
-        value |= ((unsigned long)(*p++ & 0x3f)) << 12;
-        value |= (*p++ & 0x3f) << 6;
-        value |= *p++ & 0x3f;
-        if (value < 0x200000)
-            return -4;
-        ret = 5;
-    } else if ((*p & 0xfe) == 0xfc) {
-        if (len < 6)
-            return -1;
-        if (((p[1] & 0xc0) != 0x80)
-            || ((p[2] & 0xc0) != 0x80)
-            || ((p[3] & 0xc0) != 0x80)
-            || ((p[4] & 0xc0) != 0x80)
-            || ((p[5] & 0xc0) != 0x80))
-            return -3;
-        value = ((unsigned long)(*p++ & 0x1)) << 30;
-        value |= ((unsigned long)(*p++ & 0x3f)) << 24;
-        value |= ((unsigned long)(*p++ & 0x3f)) << 18;
-        value |= ((unsigned long)(*p++ & 0x3f)) << 12;
-        value |= (*p++ & 0x3f) << 6;
-        value |= *p++ & 0x3f;
-        if (value < 0x4000000)
-            return -4;
-        ret = 6;
     } else
         return -2;
     *val = value;
@@ -116,15 +85,15 @@ int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
 /*
  * This takes a character 'value' and writes the UTF8 encoded value in 'str'
  * where 'str' is a buffer containing 'len' characters. Returns the number of
- * characters written or -1 if 'len' is too small. 'str' can be set to NULL
- * in which case it just returns the number of characters. It will need at
- * most 6 characters.
+ * characters written, -1 if 'len' is too small or -2 if 'value' is out of
+ * range. 'str' can be set to NULL in which case it just returns the number of
+ * characters. It will need at most 4 characters.
  */
 
 int UTF8_putc(unsigned char *str, int len, unsigned long value)
 {
     if (!str)
-        len = 6;                /* Maximum we will need */
+        len = 4;                /* Maximum we will need */
     else if (len <= 0)
         return -1;
     if (value < 0x80) {
@@ -142,6 +111,8 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
         return 2;
     }
     if (value < 0x10000) {
+        if (is_unicode_surrogate(value))
+            return -2;
         if (len < 3)
             return -1;
         if (str) {
@@ -151,7 +122,7 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
         }
         return 3;
     }
-    if (value < 0x200000) {
+    if (value < UNICODE_LIMIT) {
         if (len < 4)
             return -1;
         if (str) {
@@ -162,27 +133,5 @@ int UTF8_putc(unsigned char *str, int len, unsigned long value)
         }
         return 4;
     }
-    if (value < 0x4000000) {
-        if (len < 5)
-            return -1;
-        if (str) {
-            *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
-            *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-            *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-            *str = (unsigned char)((value & 0x3f) | 0x80);
-        }
-        return 5;
-    }
-    if (len < 6)
-        return -1;
-    if (str) {
-        *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
-        *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
-        *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-        *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-        *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-        *str = (unsigned char)((value & 0x3f) | 0x80);
-    }
-    return 6;
+    return -2;
 }

+ 103 - 57
libs/openssl/crypto/asn1/a_verify.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -20,8 +20,9 @@
 #include <openssl/evp.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/rsa.h"
 
-#ifndef NO_ASN1_OLD
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 
 int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
                 char *data, EVP_PKEY *pkey)
@@ -32,29 +33,29 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
     int ret = -1, i, inl;
 
     if (ctx == NULL) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     i = OBJ_obj2nid(a->algorithm);
     type = EVP_get_digestbyname(OBJ_nid2sn(i));
     if (type == NULL) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
         goto err;
     }
 
     if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
         goto err;
     }
 
     inl = i2d(data, NULL);
     if (inl <= 0) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_INTERNAL_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     buf_in = OPENSSL_malloc((unsigned int)inl);
     if (buf_in == NULL) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     p = buf_in;
@@ -66,14 +67,14 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
     OPENSSL_clear_free(buf_in, (unsigned int)inl);
 
     if (!ret) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         goto err;
     }
     ret = -1;
 
     if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data,
                         (unsigned int)signature->length, pkey) <= 0) {
-        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         ret = 0;
         goto err;
     }
@@ -85,81 +86,127 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
 
 #endif
 
-int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
-                     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg,
+                     const ASN1_BIT_STRING *signature, const void *data,
+                     EVP_PKEY *pkey)
 {
-    EVP_MD_CTX *ctx = NULL;
+    return ASN1_item_verify_ex(it, alg, signature, data, NULL, pkey, NULL, NULL);
+}
+
+int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg,
+                        const ASN1_BIT_STRING *signature, const void *data,
+                        const ASN1_OCTET_STRING *id, EVP_PKEY *pkey,
+                        OSSL_LIB_CTX *libctx, const char *propq)
+{
+    EVP_MD_CTX *ctx;
+    int rv = -1;
+
+    if ((ctx = evp_md_ctx_new_ex(pkey, id, libctx, propq)) != NULL) {
+        rv = ASN1_item_verify_ctx(it, alg, signature, data, ctx);
+        EVP_PKEY_CTX_free(EVP_MD_CTX_get_pkey_ctx(ctx));
+        EVP_MD_CTX_free(ctx);
+    }
+    return rv;
+}
+
+int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg,
+                         const ASN1_BIT_STRING *signature, const void *data,
+                         EVP_MD_CTX *ctx)
+{
+    EVP_PKEY *pkey;
     unsigned char *buf_in = NULL;
     int ret = -1, inl = 0;
     int mdnid, pknid;
     size_t inll = 0;
 
-    if (!pkey) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER);
+    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(ctx));
+
+    if (pkey == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
         return -1;
     }
 
     if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
         return -1;
     }
 
-    ctx = EVP_MD_CTX_new();
-    if (ctx == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
-        goto err;
-    }
-
     /* Convert signature OID into digest and public key OIDs */
-    if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+    if (!OBJ_find_sigid_algs(OBJ_obj2nid(alg->algorithm), &mdnid, &pknid)) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
         goto err;
     }
-    if (mdnid == NID_undef) {
-        if (!pkey->ameth || !pkey->ameth->item_verify) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
-                    ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+
+    if (mdnid == NID_undef && evp_pkey_is_legacy(pkey)) {
+        if (pkey->ameth == NULL || pkey->ameth->item_verify == NULL) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
             goto err;
         }
-        ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey);
+        ret = pkey->ameth->item_verify(ctx, it, data, alg, signature, pkey);
         /*
-         * Return value of 2 means carry on, anything else means we exit
-         * straight away: either a fatal error of the underlying verification
-         * routine handles all verification.
+         * Return values meaning:
+         * <=0: error.
+         *   1: method does everything.
+         *   2: carry on as normal, method has called EVP_DigestVerifyInit()
          */
-        if (ret != 2)
+        if (ret <= 0)
+            ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+        if (ret <= 1)
             goto err;
-        ret = -1;
     } else {
-        const EVP_MD *type = EVP_get_digestbynid(mdnid);
-
-        if (type == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
-                    ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
-            goto err;
-        }
-
-        /* Check public key OID matches public key type */
-        if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
-            goto err;
-        }
+        const EVP_MD *type = NULL;
 
-        if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
-            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
-            ret = 0;
-            goto err;
+        /*
+         * We don't yet have the ability for providers to be able to handle
+         * X509_ALGOR style parameters. Fortunately the only one that needs this
+         * so far is RSA-PSS, so we just special case this for now. In some
+         * future version of OpenSSL we should push this to the provider.
+         */
+        if (mdnid == NID_undef && pknid == EVP_PKEY_RSA_PSS) {
+            if (!EVP_PKEY_is_a(pkey, "RSA") && !EVP_PKEY_is_a(pkey, "RSA-PSS")) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+                goto err;
+            }
+            /* This function also calls EVP_DigestVerifyInit */
+            if (ossl_rsa_pss_to_ctx(ctx, NULL, alg, pkey) <= 0) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+        } else {
+            /* Check public key OID matches public key type */
+            if (!EVP_PKEY_is_a(pkey, OBJ_nid2sn(pknid))) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+                goto err;
+            }
+
+            if (mdnid != NID_undef) {
+                type = EVP_get_digestbynid(mdnid);
+                if (type == NULL) {
+                    ERR_raise(ERR_LIB_ASN1,
+                              ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+                    goto err;
+                }
+            }
+
+            /*
+             * Note that some algorithms (notably Ed25519 and Ed448) may allow
+             * a NULL digest value.
+             */
+            if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+                ret = 0;
+                goto err;
+            }
         }
-
     }
 
-    inl = ASN1_item_i2d(asn, &buf_in, it);
+    inl = ASN1_item_i2d(data, &buf_in, it);
     if (inl <= 0) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_INTERNAL_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
         goto err;
     }
     if (buf_in == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     inll = inl;
@@ -167,12 +214,11 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
     ret = EVP_DigestVerify(ctx, signature->data, (size_t)signature->length,
                            buf_in, inl);
     if (ret <= 0) {
-        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         goto err;
     }
     ret = 1;
  err:
     OPENSSL_clear_free(buf_in, inll);
-    EVP_MD_CTX_free(ctx);
     return ret;
 }

+ 36 - 50
libs/openssl/crypto/asn1/ameth_lib.c

@@ -1,13 +1,15 @@
 /*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
-#include "e_os.h"               /* for strncasecmp */
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include "internal/cryptlib.h"
 #include <stdio.h>
 #include <openssl/asn1t.h>
@@ -56,6 +58,7 @@ static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
 {
     EVP_PKEY_ASN1_METHOD tmp;
     const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
+
     tmp.pkey_id = type;
     if (app_methods) {
         int idx;
@@ -64,7 +67,7 @@ static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
             return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
     }
     ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods));
-    if (!ret || !*ret)
+    if (ret == NULL || *ret == NULL)
         return NULL;
     return *ret;
 }
@@ -130,7 +133,7 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
         if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
             continue;
         if ((int)strlen(ameth->pem_str) == len
-            && strncasecmp(ameth->pem_str, str, len) == 0)
+            && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
             return ameth;
     }
     return NULL;
@@ -152,7 +155,7 @@ int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
            && (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0)
           || (ameth->pem_str != NULL
               && (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
-        EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, ERR_R_PASSED_INVALID_ARGUMENT);
+        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
         return 0;
     }
 
@@ -164,8 +167,8 @@ int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
 
     tmp.pkey_id = ameth->pkey_id;
     if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
-        EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0,
-               EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
+        ERR_raise(ERR_LIB_EVP,
+                  EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
         return 0;
     }
 
@@ -219,8 +222,10 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
 {
     EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
 
-    if (ameth == NULL)
+    if (ameth == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
+    }
 
     ameth->pkey_id = id;
     ameth->pkey_base_id = id;
@@ -228,13 +233,13 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
 
     if (info) {
         ameth->info = OPENSSL_strdup(info);
-        if (!ameth->info)
+        if (ameth->info == NULL)
             goto err;
     }
 
     if (pem_str) {
         ameth->pem_str = OPENSSL_strdup(pem_str);
-        if (!ameth->pem_str)
+        if (ameth->pem_str == NULL)
             goto err;
     }
 
@@ -242,46 +247,27 @@ EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
 
  err:
     EVP_PKEY_asn1_free(ameth);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
     return NULL;
-
 }
 
 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
                         const EVP_PKEY_ASN1_METHOD *src)
 {
-
-    dst->pub_decode = src->pub_decode;
-    dst->pub_encode = src->pub_encode;
-    dst->pub_cmp = src->pub_cmp;
-    dst->pub_print = src->pub_print;
-
-    dst->priv_decode = src->priv_decode;
-    dst->priv_encode = src->priv_encode;
-    dst->priv_print = src->priv_print;
-
-    dst->old_priv_encode = src->old_priv_encode;
-    dst->old_priv_decode = src->old_priv_decode;
-
-    dst->pkey_size = src->pkey_size;
-    dst->pkey_bits = src->pkey_bits;
-
-    dst->param_decode = src->param_decode;
-    dst->param_encode = src->param_encode;
-    dst->param_missing = src->param_missing;
-    dst->param_copy = src->param_copy;
-    dst->param_cmp = src->param_cmp;
-    dst->param_print = src->param_print;
-
-    dst->pkey_free = src->pkey_free;
-    dst->pkey_ctrl = src->pkey_ctrl;
-
-    dst->item_sign = src->item_sign;
-    dst->item_verify = src->item_verify;
-
-    dst->siginf_set = src->siginf_set;
-
-    dst->pkey_check = src->pkey_check;
-
+    int pkey_id = dst->pkey_id;
+    int pkey_base_id = dst->pkey_base_id;
+    unsigned long pkey_flags = dst->pkey_flags;
+    char *pem_str = dst->pem_str;
+    char *info = dst->info;
+
+    *dst = *src;
+
+    /* We only copy the function pointers so restore the other values */
+    dst->pkey_id = pkey_id;
+    dst->pkey_base_id = pkey_base_id;
+    dst->pkey_flags = pkey_flags;
+    dst->pem_str = pem_str;
+    dst->info = info;
 }
 
 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
@@ -295,7 +281,7 @@ void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
 
 void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
                               int (*pub_decode) (EVP_PKEY *pk,
-                                                 X509_PUBKEY *pub),
+                                                 const X509_PUBKEY *pub),
                               int (*pub_encode) (X509_PUBKEY *pub,
                                                  const EVP_PKEY *pk),
                               int (*pub_cmp) (const EVP_PKEY *a,
@@ -376,13 +362,13 @@ void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
 void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
                             int (*item_verify) (EVP_MD_CTX *ctx,
                                                 const ASN1_ITEM *it,
-                                                void *asn,
-                                                X509_ALGOR *a,
-                                                ASN1_BIT_STRING *sig,
+                                                const void *data,
+                                                const X509_ALGOR *a,
+                                                const ASN1_BIT_STRING *sig,
                                                 EVP_PKEY *pkey),
                             int (*item_sign) (EVP_MD_CTX *ctx,
                                               const ASN1_ITEM *it,
-                                              void *asn,
+                                              const void *data,
                                               X509_ALGOR *alg1,
                                               X509_ALGOR *alg2,
                                               ASN1_BIT_STRING *sig))

+ 7 - 147
libs/openssl/crypto/asn1/asn1_err.c

@@ -1,8 +1,8 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -10,150 +10,10 @@
 
 #include <openssl/err.h>
 #include <openssl/asn1err.h>
+#include "crypto/asn1err.h"
 
 #ifndef OPENSSL_NO_ERR
 
-static const ERR_STRING_DATA ASN1_str_functs[] = {
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2D_ASN1_OBJECT, 0), "a2d_ASN1_OBJECT"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_INTEGER, 0), "a2i_ASN1_INTEGER"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_A2I_ASN1_STRING, 0), "a2i_ASN1_STRING"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_APPEND_EXP, 0), "append_exp"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIO_INIT, 0), "asn1_bio_init"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_BIT_STRING_SET_BIT, 0),
-     "ASN1_BIT_STRING_set_bit"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CB, 0), "asn1_cb"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, 0), "asn1_check_tlen"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_COLLECT, 0), "asn1_collect"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_EX_PRIMITIVE, 0),
-     "asn1_d2i_ex_primitive"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_FP, 0), "ASN1_d2i_fp"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, 0), "asn1_d2i_read_bio"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DIGEST, 0), "ASN1_digest"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_ADB, 0), "asn1_do_adb"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DO_LOCK, 0), "asn1_do_lock"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_DUP, 0), "ASN1_dup"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ENC_SAVE, 0), "asn1_enc_save"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_EX_C2I, 0), "asn1_ex_c2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_FIND_END, 0), "asn1_find_end"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERALIZEDTIME_ADJ, 0),
-     "ASN1_GENERALIZEDTIME_adj"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GENERATE_V3, 0), "ASN1_generate_v3"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_INT64, 0), "asn1_get_int64"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, 0), "ASN1_get_object"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_UINT64, 0), "asn1_get_uint64"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_BIO, 0), "ASN1_i2d_bio"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_I2D_FP, 0), "ASN1_i2d_fp"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_D2I_FP, 0), "ASN1_item_d2i_fp"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_DUP, 0), "ASN1_item_dup"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_D2I, 0),
-     "asn1_item_embed_d2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EMBED_NEW, 0),
-     "asn1_item_embed_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_EX_I2D, 0), "ASN1_item_ex_i2d"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_FLAGS_I2D, 0),
-     "asn1_item_flags_i2d"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_BIO, 0), "ASN1_item_i2d_bio"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_I2D_FP, 0), "ASN1_item_i2d_fp"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_PACK, 0), "ASN1_item_pack"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN, 0), "ASN1_item_sign"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_SIGN_CTX, 0),
-     "ASN1_item_sign_ctx"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_UNPACK, 0), "ASN1_item_unpack"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_ITEM_VERIFY, 0), "ASN1_item_verify"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_MBSTRING_NCOPY, 0),
-     "ASN1_mbstring_ncopy"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OBJECT_NEW, 0), "ASN1_OBJECT_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_OUTPUT_DATA, 0), "asn1_output_data"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PCTX_NEW, 0), "ASN1_PCTX_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_PRIMITIVE_NEW, 0),
-     "asn1_primitive_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SCTX_NEW, 0), "ASN1_SCTX_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_SIGN, 0), "ASN1_sign"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STR2TYPE, 0), "asn1_str2type"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_INT64, 0),
-     "asn1_string_get_int64"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_GET_UINT64, 0),
-     "asn1_string_get_uint64"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_SET, 0), "ASN1_STRING_set"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TABLE_ADD, 0),
-     "ASN1_STRING_TABLE_add"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TO_BN, 0), "asn1_string_to_bn"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_STRING_TYPE_NEW, 0),
-     "ASN1_STRING_type_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_EX_D2I, 0),
-     "asn1_template_ex_d2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NEW, 0), "asn1_template_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, 0),
-     "asn1_template_noexp_d2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TIME_ADJ, 0), "ASN1_TIME_adj"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, 0),
-     "ASN1_TYPE_get_int_octetstring"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_TYPE_GET_OCTETSTRING, 0),
-     "ASN1_TYPE_get_octetstring"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_UTCTIME_ADJ, 0), "ASN1_UTCTIME_adj"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_VERIFY, 0), "ASN1_verify"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_READ_ASN1, 0), "b64_read_asn1"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_B64_WRITE_ASN1, 0), "B64_write_ASN1"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BIO_NEW_NDEF, 0), "BIO_new_NDEF"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BITSTR_CB, 0), "bitstr_cb"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_BN_TO_ASN1_STRING, 0), "bn_to_asn1_string"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_BIT_STRING, 0),
-     "c2i_ASN1_BIT_STRING"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_INTEGER, 0), "c2i_ASN1_INTEGER"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_ASN1_OBJECT, 0), "c2i_ASN1_OBJECT"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_IBUF, 0), "c2i_ibuf"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_C2I_UINT64_INT, 0), "c2i_uint64_int"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_COLLECT_DATA, 0), "collect_data"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_OBJECT, 0), "d2i_ASN1_OBJECT"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_ASN1_UINTEGER, 0), "d2i_ASN1_UINTEGER"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_AUTOPRIVATEKEY, 0),
-     "d2i_AutoPrivateKey"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PRIVATEKEY, 0), "d2i_PrivateKey"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_D2I_PUBLICKEY, 0), "d2i_PublicKey"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_BUF, 0), "do_buf"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_CREATE, 0), "do_create"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_DUMP, 0), "do_dump"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_DO_TCREATE, 0), "do_tcreate"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2A_ASN1_OBJECT, 0), "i2a_ASN1_OBJECT"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_BIO_STREAM, 0),
-     "i2d_ASN1_bio_stream"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_ASN1_OBJECT, 0), "i2d_ASN1_OBJECT"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PRIVATEKEY, 0), "i2d_PrivateKey"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_PUBLICKEY, 0), "i2d_PublicKey"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_I2D_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_LONG_C2I, 0), "long_c2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_PREFIX, 0), "ndef_prefix"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_NDEF_SUFFIX, 0), "ndef_suffix"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_OID_MODULE_INIT, 0), "oid_module_init"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PARSE_TAGGING, 0), "parse_tagging"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_IV, 0), "PKCS5_pbe2_set_iv"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE2_SET_SCRYPT, 0),
-     "PKCS5_pbe2_set_scrypt"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET, 0), "PKCS5_pbe_set"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBE_SET0_ALGOR, 0),
-     "PKCS5_pbe_set0_algor"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_PBKDF2_SET, 0), "PKCS5_pbkdf2_set"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_PKCS5_SCRYPT_SET, 0), "pkcs5_scrypt_set"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_READ_ASN1, 0), "SMIME_read_ASN1"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_SMIME_TEXT, 0), "SMIME_text"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STABLE_GET, 0), "stable_get"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_STBL_MODULE_INIT, 0), "stbl_module_init"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_C2I, 0), "uint32_c2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT32_NEW, 0), "uint32_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_C2I, 0), "uint64_c2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_UINT64_NEW, 0), "uint64_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_CRL_ADD0_REVOKED, 0),
-     "X509_CRL_add0_revoked"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_INFO_NEW, 0), "X509_INFO_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_ENCODE, 0), "x509_name_encode"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_D2I, 0), "x509_name_ex_d2i"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_NAME_EX_NEW, 0), "x509_name_ex_new"},
-    {ERR_PACK(ERR_LIB_ASN1, ASN1_F_X509_PKEY_NEW, 0), "X509_PKEY_new"},
-    {0, NULL}
-};
-
 static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ADDING_OBJECT), "adding object"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"},
@@ -249,6 +109,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_UTF8STRING),
     "invalid utf8string"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_INVALID_VALUE), "invalid value"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LENGTH_TOO_LONG), "length too long"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_LIST_ERROR), "list error"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_MIME_NO_CONTENT_TYPE),
     "mime no content type"},
@@ -313,6 +174,7 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNEXPECTED_EOC), "unexpected eoc"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH),
     "universalstring is wrong length"},
+    {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_DIGEST), "unknown digest"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_FORMAT), "unknown format"},
     {ERR_PACK(ERR_LIB_ASN1, 0, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM),
     "unknown message digest algorithm"},
@@ -340,13 +202,11 @@ static const ERR_STRING_DATA ASN1_str_reasons[] = {
 
 #endif
 
-int ERR_load_ASN1_strings(void)
+int ossl_err_load_ASN1_strings(void)
 {
 #ifndef OPENSSL_NO_ERR
-    if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
-        ERR_load_strings_const(ASN1_str_functs);
+    if (ERR_reason_error_string(ASN1_str_reasons[0].error) == NULL)
         ERR_load_strings_const(ASN1_str_reasons);
-    }
 #endif
     return 1;
 }

+ 36 - 39
libs/openssl/crypto/asn1/asn1_gen.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -91,7 +91,7 @@ ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
     int err = 0;
     ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err);
     if (err)
-        ASN1err(ASN1_F_ASN1_GENERATE_V3, err);
+        ERR_raise(ERR_LIB_ASN1, err);
     return ret;
 }
 
@@ -263,8 +263,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
     utype = asn1_str2tag(elem, len);
 
     if (utype == -1) {
-        ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_TAG);
-        ERR_add_error_data(2, "tag=", elem);
+        ERR_raise_data(ERR_LIB_ASN1, ASN1_R_UNKNOWN_TAG, "tag=%s", elem);
         return -1;
     }
 
@@ -274,7 +273,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
         arg->str = vstart;
         /* If no value and not end of string, error */
         if (!vstart && elem[len]) {
-            ASN1err(ASN1_F_ASN1_CB, ASN1_R_MISSING_VALUE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_VALUE);
             return -1;
         }
         return 0;
@@ -285,7 +284,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
     case ASN1_GEN_FLAG_IMP:
         /* Check for illegal multiple IMPLICIT tagging */
         if (arg->imp_tag != -1) {
-            ASN1err(ASN1_F_ASN1_CB, ASN1_R_ILLEGAL_NESTED_TAGGING);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
             return -1;
         }
         if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
@@ -322,7 +321,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
 
     case ASN1_GEN_FLAG_FORMAT:
         if (!vstart) {
-            ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
             return -1;
         }
         if (strncmp(vstart, "ASCII", 5) == 0)
@@ -334,7 +333,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
         else if (strncmp(vstart, "BITLIST", 7) == 0)
             arg->format = ASN1_GEN_FORMAT_BITLIST;
         else {
-            ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_FORMAT);
             return -1;
         }
         break;
@@ -347,7 +346,6 @@ static int asn1_cb(const char *elem, int len, void *bitstr)
 
 static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
 {
-    char erch[2];
     long tag_num;
     char *eptr;
     if (!vstart)
@@ -357,7 +355,7 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
     if (eptr && *eptr && (eptr > vstart + vlen))
         return 0;
     if (tag_num < 0) {
-        ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_NUMBER);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
         return 0;
     }
     *ptag = tag_num;
@@ -386,10 +384,8 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
             break;
 
         default:
-            erch[0] = *eptr;
-            erch[1] = 0;
-            ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER);
-            ERR_add_error_data(2, "Char=", erch);
+            ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MODIFIER,
+                           "Char=%c", *eptr);
             return 0;
 
         }
@@ -469,12 +465,12 @@ static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
     tag_exp_type *exp_tmp;
     /* Can only have IMPLICIT if permitted */
     if ((arg->imp_tag != -1) && !imp_ok) {
-        ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
         return 0;
     }
 
     if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
-        ASN1err(ASN1_F_APPEND_EXP, ASN1_R_DEPTH_EXCEEDED);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DEPTH_EXCEEDED);
         return 0;
     }
 
@@ -568,7 +564,8 @@ static int asn1_str2tag(const char *tagstr, int len)
 
     tntmp = tnst;
     for (i = 0; i < OSSL_NELEM(tnst); i++, tntmp++) {
-        if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0))
+        if ((len == tntmp->len)
+            && (OPENSSL_strncasecmp(tntmp->strnam, tagstr, len) == 0))
             return tntmp->tag;
     }
 
@@ -584,7 +581,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
     int no_unused = 1;
 
     if ((atmp = ASN1_TYPE_new()) == NULL) {
-        ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
@@ -595,21 +592,21 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
 
     case V_ASN1_NULL:
         if (str && *str) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
             goto bad_form;
         }
         break;
 
     case V_ASN1_BOOLEAN:
         if (format != ASN1_GEN_FORMAT_ASCII) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_NOT_ASCII_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NOT_ASCII_FORMAT);
             goto bad_form;
         }
         vtmp.name = NULL;
         vtmp.section = NULL;
         vtmp.value = (char *)str;
         if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BOOLEAN);
             goto bad_str;
         }
         break;
@@ -617,23 +614,23 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
     case V_ASN1_INTEGER:
     case V_ASN1_ENUMERATED:
         if (format != ASN1_GEN_FORMAT_ASCII) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
             goto bad_form;
         }
         if ((atmp->value.integer
                     = s2i_ASN1_INTEGER(NULL, str)) == NULL) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_INTEGER);
             goto bad_str;
         }
         break;
 
     case V_ASN1_OBJECT:
         if (format != ASN1_GEN_FORMAT_ASCII) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
             goto bad_form;
         }
         if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT);
             goto bad_str;
         }
         break;
@@ -641,20 +638,20 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
     case V_ASN1_UTCTIME:
     case V_ASN1_GENERALIZEDTIME:
         if (format != ASN1_GEN_FORMAT_ASCII) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
             goto bad_form;
         }
         if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto bad_str;
         }
         if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto bad_str;
         }
         atmp->value.asn1_string->type = utype;
         if (!ASN1_TIME_check(atmp->value.asn1_string)) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_TIME_VALUE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
             goto bad_str;
         }
 
@@ -674,13 +671,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
         else if (format == ASN1_GEN_FORMAT_UTF8)
             format = MBSTRING_UTF8;
         else {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_FORMAT);
             goto bad_form;
         }
 
         if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
                                -1, format, ASN1_tag2bit(utype)) <= 0) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto bad_str;
         }
 
@@ -689,13 +686,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
     case V_ASN1_BIT_STRING:
     case V_ASN1_OCTET_STRING:
         if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto bad_form;
         }
 
         if (format == ASN1_GEN_FORMAT_HEX) {
             if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) {
-                ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_HEX);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_HEX);
                 goto bad_str;
             }
             atmp->value.asn1_string->data = rdata;
@@ -707,13 +704,13 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
                  && (utype == V_ASN1_BIT_STRING)) {
             if (!CONF_parse_list
                 (str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
-                ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_LIST_ERROR);
                 goto bad_str;
             }
             no_unused = 0;
 
         } else {
-            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
             goto bad_form;
         }
 
@@ -726,7 +723,7 @@ static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
         break;
 
     default:
-        ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
         goto bad_str;
     }
 
@@ -752,11 +749,11 @@ static int bitstr_cb(const char *elem, int len, void *bitstr)
     if (eptr && *eptr && (eptr != elem + len))
         return 0;
     if (bitnum < 0) {
-        ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_NUMBER);
         return 0;
     }
     if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
-        ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     return 1;

+ 89 - 36
libs/openssl/crypto/asn1/asn1_lib.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -22,11 +22,13 @@ static int _asn1_check_infinite_end(const unsigned char **p, long len)
     /*
      * If there is 0 or 1 byte left, the length check should pick things up
      */
-    if (len <= 0)
-        return 1;
-    else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
-        (*p) += 2;
+    if (len <= 0) {
         return 1;
+    } else {
+        if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
+            (*p) += 2;
+            return 1;
+        }
     }
     return 0;
 }
@@ -45,13 +47,15 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
                     int *pclass, long omax)
 {
     int i, ret;
-    long l;
+    long len;
     const unsigned char *p = *pp;
     int tag, xclass, inf;
     long max = omax;
 
-    if (!max)
-        goto err;
+    if (omax <= 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+        return 0x80;
+    }
     ret = (*p & V_ASN1_CONSTRUCTED);
     xclass = (*p & V_ASN1_PRIVATE);
     i = *p & V_ASN1_PRIMITIVE_TAG;
@@ -59,18 +63,18 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
         p++;
         if (--max == 0)
             goto err;
-        l = 0;
+        len = 0;
         while (*p & 0x80) {
-            l <<= 7L;
-            l |= *(p++) & 0x7f;
+            len <<= 7L;
+            len |= *(p++) & 0x7f;
             if (--max == 0)
                 goto err;
-            if (l > (INT_MAX >> 7L))
+            if (len > (INT_MAX >> 7L))
                 goto err;
         }
-        l <<= 7L;
-        l |= *(p++) & 0x7f;
-        tag = (int)l;
+        len <<= 7L;
+        len |= *(p++) & 0x7f;
+        tag = (int)len;
         if (--max == 0)
             goto err;
     } else {
@@ -88,7 +92,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
         goto err;
 
     if (*plength > (omax - (p - *pp))) {
-        ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
         /*
          * Set this so that even if things are not long enough the values are
          * set correctly
@@ -98,7 +102,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
     *pp = p;
     return ret | inf;
  err:
-    ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_HEADER_TOO_LONG);
     return 0x80;
 }
 
@@ -141,8 +145,9 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
             }
             if (ret > LONG_MAX)
                 return 0;
-        } else
+        } else {
             ret = i;
+        }
     }
     *pp = p;
     *rl = (long)ret;
@@ -150,7 +155,7 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
 }
 
 /*
- * class 0 is constructed constructed == 2 for indefinite length constructed
+ * constructed == 2 for indefinite length constructed
  */
 void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
                      int xclass)
@@ -160,9 +165,9 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
 
     i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
     i |= (xclass & V_ASN1_PRIVATE);
-    if (tag < 31)
+    if (tag < 31) {
         *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
-    else {
+    } else {
         *(p++) = i | V_ASN1_PRIMITIVE_TAG;
         for (i = 0, ttag = tag; ttag > 0; i++)
             ttag >>= 7;
@@ -185,6 +190,7 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
 int ASN1_put_eoc(unsigned char **pp)
 {
     unsigned char *p = *pp;
+
     *p++ = 0;
     *p++ = 0;
     *pp = p;
@@ -194,20 +200,21 @@ int ASN1_put_eoc(unsigned char **pp)
 static void asn1_put_length(unsigned char **pp, int length)
 {
     unsigned char *p = *pp;
-    int i, l;
-    if (length <= 127)
+    int i, len;
+
+    if (length <= 127) {
         *(p++) = (unsigned char)length;
-    else {
-        l = length;
-        for (i = 0; l > 0; i++)
-            l >>= 8;
+    } else {
+        len = length;
+        for (i = 0; len > 0; i++)
+            len >>= 8;
         *(p++) = i | 0x80;
-        l = i;
+        len = i;
         while (i-- > 0) {
             p[i] = length & 0xff;
             length >>= 8;
         }
-        p += l;
+        p += len;
     }
     *pp = p;
 }
@@ -215,6 +222,7 @@ static void asn1_put_length(unsigned char **pp, int length)
 int ASN1_object_size(int constructed, int length, int tag)
 {
     int ret = 1;
+
     if (length < 0)
         return -1;
     if (tag >= 31) {
@@ -256,6 +264,7 @@ int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
 ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
 {
     ASN1_STRING *ret;
+
     if (!str)
         return NULL;
     ret = ASN1_STRING_new();
@@ -287,7 +296,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
      * '\0' terminator even though this isn't strictly necessary.
      */
     if (len > INT_MAX - 1) {
-        ASN1err(0, ASN1_R_TOO_LARGE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
         return 0;
     }
     if ((size_t)str->length <= len || str->data == NULL) {
@@ -299,7 +308,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
         str->data = OPENSSL_realloc(c, len + 1);
 #endif
         if (str->data == NULL) {
-            ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             str->data = c;
             return 0;
         }
@@ -340,14 +349,14 @@ ASN1_STRING *ASN1_STRING_type_new(int type)
 
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-        ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     ret->type = type;
     return ret;
 }
 
-void asn1_string_embed_free(ASN1_STRING *a, int embed)
+void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed)
 {
     if (a == NULL)
         return;
@@ -361,7 +370,7 @@ void ASN1_STRING_free(ASN1_STRING *a)
 {
     if (a == NULL)
         return;
-    asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
+    ossl_asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED);
 }
 
 void ASN1_STRING_clear_free(ASN1_STRING *a)
@@ -385,8 +394,9 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
             return a->type - b->type;
         else
             return i;
-    } else
+    } else {
         return i;
+    }
 }
 
 int ASN1_STRING_length(const ASN1_STRING *x)
@@ -394,10 +404,12 @@ int ASN1_STRING_length(const ASN1_STRING *x)
     return x->length;
 }
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 void ASN1_STRING_length_set(ASN1_STRING *x, int len)
 {
     x->length = len;
 }
+#endif
 
 int ASN1_STRING_type(const ASN1_STRING *x)
 {
@@ -409,9 +421,50 @@ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
     return x->data;
 }
 
-# if OPENSSL_API_COMPAT < 0x10100000L
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
 unsigned char *ASN1_STRING_data(ASN1_STRING *x)
 {
     return x->data;
 }
 #endif
+
+/* |max_len| excludes NUL terminator and may be 0 to indicate no restriction */
+char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,
+                                   const char *sep, size_t max_len)
+{
+    int i;
+    ASN1_UTF8STRING *current;
+    size_t length = 0, sep_len;
+    char *result = NULL;
+    char *p;
+
+    if (sep == NULL)
+        sep = "";
+    sep_len = strlen(sep);
+
+    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+        current = sk_ASN1_UTF8STRING_value(text, i);
+        if (i > 0)
+            length += sep_len;
+        length += ASN1_STRING_length(current);
+        if (max_len != 0 && length > max_len)
+            return NULL;
+    }
+    if ((result = OPENSSL_malloc(length + 1)) == NULL)
+        return NULL;
+
+    p = result;
+    for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+        current = sk_ASN1_UTF8STRING_value(text, i);
+        length = ASN1_STRING_length(current);
+        if (i > 0 && sep_len > 0) {
+            strncpy(p, sep, sep_len + 1); /* using + 1 to silence gcc warning */
+            p += sep_len;
+        }
+        strncpy(p, (const char *)ASN1_STRING_get0_data(current), length);
+        p += length;
+    }
+    *p = '\0';
+
+    return result;
+}

+ 44 - 33
libs/openssl/crypto/asn1/asn1_local.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2005-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -9,9 +9,11 @@
 
 /* Internal ASN1 structures and functions: not for application use */
 
-int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
-int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
-int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
+typedef const ASN1_VALUE const_ASN1_VALUE;
+SKM_DEFINE_STACK_OF(const_ASN1_VALUE, const ASN1_VALUE, ASN1_VALUE)
+
+int ossl_asn1_time_to_tm(struct tm *tm, const ASN1_TIME *d);
+int ossl_asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
 
 /* ASN1 scan context structure */
 
@@ -43,41 +45,50 @@ DEFINE_STACK_OF(MIME_PARAM)
 typedef struct mime_header_st MIME_HEADER;
 DEFINE_STACK_OF(MIME_HEADER)
 
-void asn1_string_embed_free(ASN1_STRING *a, int embed);
+void ossl_asn1_string_embed_free(ASN1_STRING *a, int embed);
 
-int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
-int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
-                             const ASN1_ITEM *it);
+int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval,
+                                        const ASN1_ITEM *it);
+int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value,
+                                  const ASN1_ITEM *it);
 
-ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval,
+                                                 const ASN1_TEMPLATE *tt);
 
-const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
-                                 int nullerr);
+const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val,
+                                      const ASN1_TEMPLATE *tt,
+                                      int nullerr);
 
-int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
+int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
 
-void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
-void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
-                     const ASN1_ITEM *it);
-int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
-                  const ASN1_ITEM *it);
+void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval,
+                          const ASN1_ITEM *it);
+int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+                       const ASN1_ITEM *it);
 
-void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
-void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
+void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed);
+void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
 
-ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
-                             long length);
-int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
-ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
-                                     const unsigned char **pp, long length);
-int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
-ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
-                               long length);
+ASN1_OBJECT *ossl_c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
+                                  long length);
+int ossl_i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
+ASN1_BIT_STRING *ossl_c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
+                                          const unsigned char **pp, long length);
+int ossl_i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
+ASN1_INTEGER *ossl_c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
+                                    long length);
 
 /* Internal functions used by x_int64.c */
-int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len);
-int i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
+int ossl_c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp,
+                        long len);
+int ossl_i2c_uint64_int(unsigned char *p, uint64_t r, int neg);
+
+ASN1_TIME *ossl_asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
 
-ASN1_TIME *asn1_time_from_tm(ASN1_TIME *s, struct tm *ts, int type);
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                 OSSL_LIB_CTX *libctx, const char *propq);

+ 44 - 37
libs/openssl/crypto/asn1/asn1_par.c → libs/openssl/crypto/asn1/asn1_parse.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -17,25 +17,47 @@
 #define ASN1_PARSE_MAXDEPTH 128
 #endif
 
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
-                           int indent);
 static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
                        int offset, int depth, int indent, int dump);
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
-                           int indent)
+static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
+                           int tag, int xclass, int constructed, int indent)
 {
-    static const char fmt[] = "%-18s";
     char str[128];
     const char *p;
+    int pop_f_prefix = 0;
+    long saved_indent = -1;
+    int i = 0;
+    BIO *bio = NULL;
 
     if (constructed & V_ASN1_CONSTRUCTED)
         p = "cons: ";
     else
         p = "prim: ";
-    if (BIO_write(bp, p, 6) < 6)
-        goto err;
-    BIO_indent(bp, indent, 128);
+    if (constructed != (V_ASN1_CONSTRUCTED | 1)) {
+        if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s",
+                         offset, depth, (long)hl, len, p) <= 0)
+            goto err;
+    } else {
+        if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf  %s",
+                         offset, depth, (long)hl, p) <= 0)
+            goto err;
+    }
+    if (bp != NULL) {
+        if (BIO_set_prefix(bp, str) <= 0) {
+            if ((bio = BIO_new(BIO_f_prefix())) == NULL
+                    || (bp = BIO_push(bio, bp)) == NULL)
+                goto err;
+            pop_f_prefix = 1;
+        }
+        saved_indent = BIO_get_indent(bp);
+        if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) <= 0)
+            goto err;
+    }
 
+    /*
+     * BIO_set_prefix made a copy of |str|, so we can safely use it for
+     * something else, ASN.1 tag printout.
+     */
     p = str;
     if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
         BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
@@ -48,11 +70,14 @@ static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
     else
         p = ASN1_tag2str(tag);
 
-    if (BIO_printf(bp, fmt, p) <= 0)
-        goto err;
-    return 1;
+    i = (BIO_printf(bp, "%-18s", p) > 0);
  err:
-    return 0;
+    if (saved_indent >= 0)
+        BIO_set_indent(bp, saved_indent);
+    if (pop_f_prefix)
+        BIO_pop(bp);
+    BIO_free(bio);
+    return i;
 }
 
 int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
@@ -92,9 +117,7 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
         op = p;
         j = ASN1_get_object(&p, &len, &tag, &xclass, length);
         if (j & 0x80) {
-            if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
-                goto end;
-            ret = 0;
+            BIO_puts(bp, "Error in encoding\n");
             goto end;
         }
         hl = (p - op);
@@ -102,19 +125,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
         /*
          * if j == 0x21 it is a constructed indefinite length object
          */
-        if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp))
-            <= 0)
-            goto end;
-
-        if (j != (V_ASN1_CONSTRUCTED | 1)) {
-            if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
-                           depth, (long)hl, len) <= 0)
-                goto end;
-        } else {
-            if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ", depth, (long)hl) <= 0)
-                goto end;
-        }
-        if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
+        if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth,
+                             hl, len, tag, xclass, j, (indent) ? depth : 0))
             goto end;
         if (j & V_ASN1_CONSTRUCTED) {
             const unsigned char *sp = p;
@@ -124,7 +136,6 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
                 goto end;
             if (len > length) {
                 BIO_printf(bp, "length is greater than %ld\n", length);
-                ret = 0;
                 goto end;
             }
             if ((j == 0x21) && (len == 0)) {
@@ -132,10 +143,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
                     r = asn1_parse2(bp, &p, (long)(tot - p),
                                     offset + (p - *pp), depth + 1,
                                     indent, dump);
-                    if (r == 0) {
-                        ret = 0;
+                    if (r == 0)
                         goto end;
-                    }
                     if ((r == 2) || (p >= tot)) {
                         len = p - sp;
                         break;
@@ -149,10 +158,8 @@ static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
                     r = asn1_parse2(bp, &p, tmp,
                                     offset + (p - *pp), depth + 1,
                                     indent, dump);
-                    if (r == 0) {
-                        ret = 0;
+                    if (r == 0)
                         goto end;
-                    }
                     tmp -= p - sp;
                 }
             }

+ 121 - 66
libs/openssl/crypto/asn1/asn_mime.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -14,6 +14,7 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/cms.h>
 #include "crypto/evp.h"
 #include "internal/bio.h"
 #include "asn1_local.h"
@@ -53,7 +54,7 @@ static int mime_param_cmp(const MIME_PARAM *const *a,
                           const MIME_PARAM *const *b);
 static void mime_param_free(MIME_PARAM *param);
 static int mime_bound_check(char *line, int linelen, const char *bound, int blen);
-static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret);
+static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret);
 static int strip_eol(char *linebuf, int *plen, int flags);
 static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name);
 static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name);
@@ -64,18 +65,24 @@ static void mime_hdr_free(MIME_HEADER *hdr);
 
 /* Output an ASN1 structure in BER format streaming if necessary */
 
+/* unfortunately cannot constify this due to CMS_stream() and PKCS7_stream() */
 int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
                         const ASN1_ITEM *it)
 {
+    int rv = 1;
+
     /* If streaming create stream BIO and copy all content through it */
     if (flags & SMIME_STREAM) {
         BIO *bio, *tbio;
         bio = BIO_new_NDEF(out, val, it);
         if (!bio) {
-            ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
-        SMIME_crlf_copy(in, bio, flags);
+        if (!SMIME_crlf_copy(in, bio, flags)) {
+            rv = 0;
+        }
+
         (void)BIO_flush(bio);
         /* Free up successive BIOs until we hit the old output BIO */
         do {
@@ -90,7 +97,7 @@ int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
      */
     else
         ASN1_item_i2d_bio(it, out, val);
-    return 1;
+    return rv;
 }
 
 /* Base 64 read and write of ASN1 structure */
@@ -102,7 +109,7 @@ static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
     int r;
     b64 = BIO_new(BIO_f_base64());
     if (b64 == NULL) {
-        ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     /*
@@ -128,19 +135,20 @@ int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
     return r;
 }
 
-static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x,
+                                 OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *b64;
     ASN1_VALUE *val;
 
     if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
-        ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     bio = BIO_push(b64, bio);
-    val = ASN1_item_d2i_bio(it, bio, NULL);
+    val = ASN1_item_d2i_bio_ex(it, bio, x, libctx, propq);
     if (!val)
-        ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
     (void)BIO_flush(bio);
     BIO_pop(bio);
     BIO_free(b64);
@@ -207,9 +215,9 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
             goto err;
 
         default:
-            if (have_unknown)
+            if (have_unknown) {
                 write_comma = 0;
-            else {
+            } else {
                 BIO_puts(out, "unknown");
                 have_unknown = 1;
             }
@@ -227,14 +235,16 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
 
 /* SMIME sender */
 
-int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
-                     int ctype_nid, int econt_nid,
-                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+int SMIME_write_ASN1_ex(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                        int ctype_nid, int econt_nid,
+                        STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
+                        OSSL_LIB_CTX *libctx, const char *propq)
 {
     char bound[33], c;
     int i;
     const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
     const char *msg_type = NULL;
+
     if (flags & SMIME_OLDMIME)
         mime_prefix = "application/x-pkcs7-";
     else
@@ -247,7 +257,7 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
     if ((flags & SMIME_DETACHED) && data) {
         /* We want multipart/signed */
         /* Generate a random boundary */
-        if (RAND_bytes((unsigned char *)bound, 32) <= 0)
+        if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32, 0) <= 0)
             return 0;
         for (i = 0; i < 32; i++) {
             c = bound[i] & 0xf;
@@ -288,9 +298,9 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
 
     /* Determine smime-type header */
 
-    if (ctype_nid == NID_pkcs7_enveloped)
+    if (ctype_nid == NID_pkcs7_enveloped) {
         msg_type = "enveloped-data";
-    else if (ctype_nid == NID_pkcs7_signed) {
+    } else if (ctype_nid == NID_pkcs7_signed) {
         if (econt_nid == NID_id_smime_ct_receipt)
             msg_type = "signed-receipt";
         else if (sk_X509_ALGOR_num(mdalgs) >= 0)
@@ -317,8 +327,17 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
     return 1;
 }
 
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                     int ctype_nid, int econt_nid,
+                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+{
+    return SMIME_write_ASN1_ex(bio, val, data, flags, ctype_nid, econt_nid,
+                               mdalgs, it, NULL, NULL);
+}
+
 /* Handle output of ASN1 data */
 
+/* cannot constify val because of CMS_dataFinal() */
 static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
                             const ASN1_ITEM *it)
 {
@@ -332,12 +351,11 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
      * set up to finalise when it is written through.
      */
     if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) {
-        SMIME_crlf_copy(data, out, flags);
-        return 1;
+        return SMIME_crlf_copy(data, out, flags);
     }
 
     if (!aux || !aux->asn1_cb) {
-        ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
         return 0;
     }
 
@@ -351,7 +369,8 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
         return 0;
 
     /* Copy data across, passing through filter BIOs for processing */
-    SMIME_crlf_copy(data, sarg.ndef_bio, flags);
+    if (!SMIME_crlf_copy(data, sarg.ndef_bio, flags))
+        rv = 0;
 
     /* Finalize structure */
     if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
@@ -375,7 +394,9 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
  * opaque this is set to NULL
  */
 
-ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, int flags, BIO **bcont,
+                               const ASN1_ITEM *it, ASN1_VALUE **x,
+                               OSSL_LIB_CTX *libctx, const char *propq)
 {
     BIO *asnin;
     STACK_OF(MIME_HEADER) *headers = NULL;
@@ -389,14 +410,14 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         *bcont = NULL;
 
     if ((headers = mime_parse_hdr(bio)) == NULL) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
         return NULL;
     }
 
     if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
         || hdr->value == NULL) {
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_CONTENT_TYPE);
         return NULL;
     }
 
@@ -405,15 +426,15 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
     if (strcmp(hdr->value, "multipart/signed") == 0) {
         /* Split into two parts */
         prm = mime_param_find(hdr, "boundary");
-        if (!prm || !prm->param_value) {
+        if (prm == NULL || prm->param_value == NULL) {
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
             return NULL;
         }
-        ret = multi_split(bio, prm->param_value, &parts);
+        ret = multi_split(bio, flags, prm->param_value, &parts);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         if (!ret || (sk_BIO_num(parts) != 2)) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -422,7 +443,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         asnin = sk_BIO_value(parts, 1);
 
         if ((headers = mime_parse_hdr(asnin)) == NULL) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -432,23 +453,23 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
             || hdr->value == NULL) {
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
 
         if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
             strcmp(hdr->value, "application/pkcs7-signature")) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE);
-            ERR_add_error_data(2, "type: ", hdr->value);
+            ERR_raise_data(ERR_LIB_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE,
+                           "type: %s", hdr->value);
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         /* Read in ASN1 */
-        if ((val = b64_read_asn1(asnin, it)) == NULL) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
+        if ((val = b64_read_asn1(asnin, it, x, libctx, propq)) == NULL) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -457,8 +478,9 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
             *bcont = sk_BIO_value(parts, 0);
             BIO_free(asnin);
             sk_BIO_free(parts);
-        } else
+        } else {
             sk_BIO_pop_free(parts, BIO_vfree);
+        }
         return val;
     }
 
@@ -466,20 +488,24 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
 
     if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
         strcmp(hdr->value, "application/pkcs7-mime")) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
-        ERR_add_error_data(2, "type: ", hdr->value);
+        ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
+                       "type: %s", hdr->value);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         return NULL;
     }
 
     sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
 
-    if ((val = b64_read_asn1(bio, it)) == NULL) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
+    if ((val = b64_read_asn1(bio, it, x, libctx, propq)) == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ASN1_PARSE_ERROR);
         return NULL;
     }
     return val;
+}
 
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+{
+    return SMIME_read_ASN1_ex(bio, 0, bcont, it, NULL, NULL, NULL);
 }
 
 /* Copy text from one BIO to another making the output CRLF at EOL */
@@ -495,8 +521,10 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
      * when streaming as we don't end up with one OCTET STRING per line.
      */
     bf = BIO_new(BIO_f_buffer());
-    if (bf == NULL)
+    if (bf == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
+    }
     out = BIO_push(bf, out);
     if (flags & SMIME_BINARY) {
         while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
@@ -507,7 +535,7 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
             BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
         while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
             eol = strip_eol(linebuf, &len, flags);
-            if (len) {
+            if (len > 0) {
                 /* Not EOF: write out all CRLF */
                 if (flags & SMIME_ASCIICRLF) {
                     int i;
@@ -518,10 +546,11 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                 BIO_write(out, linebuf, len);
                 if (eol)
                     BIO_write(out, "\r\n", 2);
-            } else if (flags & SMIME_ASCIICRLF)
+            } else if (flags & SMIME_ASCIICRLF) {
                 eolcnt++;
-            else if (eol)
+            } else if (eol) {
                 BIO_write(out, "\r\n", 2);
+            }
         }
     }
     ret = BIO_flush(out);
@@ -542,18 +571,18 @@ int SMIME_text(BIO *in, BIO *out)
     MIME_HEADER *hdr;
 
     if ((headers = mime_parse_hdr(in)) == NULL) {
-        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_PARSE_ERROR);
         return 0;
     }
     if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
         || hdr->value == NULL) {
-        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MIME_NO_CONTENT_TYPE);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         return 0;
     }
     if (strcmp(hdr->value, "text/plain")) {
-        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE);
-        ERR_add_error_data(2, "type: ", hdr->value);
+        ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_MIME_TYPE,
+                       "type: %s", hdr->value);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         return 0;
     }
@@ -570,7 +599,7 @@ int SMIME_text(BIO *in, BIO *out)
  * canonical parts in a STACK of bios
  */
 
-static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
+static int multi_split(BIO *bio, int flags, const char *bound, STACK_OF(BIO) **ret)
 {
     char linebuf[MAX_SMLEN];
     int len, blen;
@@ -587,7 +616,7 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
     *ret = parts;
     if (*ret == NULL)
         return 0;
-    while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+    while ((len = BIO_get_line(bio, linebuf, MAX_SMLEN)) > 0) {
         state = mime_bound_check(linebuf, len, bound, blen);
         if (state == 1) {
             first = 1;
@@ -598,9 +627,9 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
                 return 0;
             }
             return 1;
-        } else if (part) {
-            /* Strip CR+LF from linebuf */
-            next_eol = strip_eol(linebuf, &len, 0);
+        } else if (part != 0) {
+            /* Strip (possibly CR +) LF from linebuf */
+            next_eol = strip_eol(linebuf, &len, flags);
             if (first) {
                 first = 0;
                 if (bpart)
@@ -612,10 +641,20 @@ static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret)
                 if (bpart == NULL)
                     return 0;
                 BIO_set_mem_eof_return(bpart, 0);
-            } else if (eol)
-                BIO_write(bpart, "\r\n", 2);
+            } else if (eol) {
+                if (
+#ifndef OPENSSL_NO_CMS
+                    (flags & CMS_BINARY) == 0
+#else
+                    1
+#endif
+                        || (flags & SMIME_CRLFEOL) != 0)
+                    BIO_write(bpart, "\r\n", 2);
+                else
+                    BIO_write(bpart, "\n", 1);
+            }
             eol = next_eol;
-            if (len)
+            if (len > 0)
                 BIO_write(bpart, linebuf, len);
         }
     }
@@ -739,15 +778,16 @@ static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
                 goto err;
             mhdr = new_hdr;
             new_hdr = NULL;
-        } else if (state == MIME_VALUE)
+        } else if (state == MIME_VALUE) {
             mime_hdr_addparam(mhdr, ntmp, strip_ends(q));
+        }
         if (p == linebuf)
             break;              /* Blank line means end of headers */
     }
 
     return headers;
 
-err:
+ err:
     mime_hdr_free(new_hdr);
     sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
     return NULL;
@@ -762,7 +802,7 @@ static char *strip_ends(char *name)
 static char *strip_start(char *name)
 {
     char *p, c;
-    /* Look for first non white space or quote */
+    /* Look for first non whitespace or quote */
     for (p = name; (c = *p); p++) {
         if (c == '"') {
             /* Next char is start of string if non null */
@@ -783,7 +823,7 @@ static char *strip_end(char *name)
     char *p, c;
     if (!name)
         return NULL;
-    /* Look for first non white space or quote */
+    /* Look for first non whitespace or quote */
     for (p = name + strlen(name) - 1; p >= name; p--) {
         c = *p;
         if (c == '"') {
@@ -869,8 +909,8 @@ static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *va
 static int mime_hdr_cmp(const MIME_HEADER *const *a,
                         const MIME_HEADER *const *b)
 {
-    if (!(*a)->name || !(*b)->name)
-        return ! !(*a)->name - ! !(*b)->name;
+    if ((*a)->name == NULL || (*b)->name == NULL)
+        return ((*a)->name != NULL) - ((*b)->name != NULL);
 
     return strcmp((*a)->name, (*b)->name);
 }
@@ -878,8 +918,8 @@ static int mime_hdr_cmp(const MIME_HEADER *const *a,
 static int mime_param_cmp(const MIME_PARAM *const *a,
                           const MIME_PARAM *const *b)
 {
-    if (!(*a)->param_name || !(*b)->param_name)
-        return ! !(*a)->param_name - ! !(*b)->param_name;
+    if ((*a)->param_name == NULL || (*b)->param_name == NULL)
+        return ((*a)->param_name != NULL) - ((*b)->param_name != NULL);
     return strcmp((*a)->param_name, (*b)->param_name);
 }
 
@@ -959,11 +999,26 @@ static int strip_eol(char *linebuf, int *plen, int flags)
     char *p, c;
     int is_eol = 0;
 
+#ifndef OPENSSL_NO_CMS
+    if ((flags & CMS_BINARY) != 0) {
+        if (len <= 0 || linebuf[len - 1] != '\n')
+            return 0;
+        if ((flags & SMIME_CRLFEOL) != 0) {
+            if (len <= 1 || linebuf[len - 2] != '\r')
+                return 0;
+            len--;
+        }
+        len--;
+        *plen = len;
+        return 1;
+    }
+#endif
+
     for (p = linebuf + len - 1; len > 0; len--, p--) {
         c = *p;
         if (c == '\n') {
             is_eol = 1;
-        } else if (is_eol && flags & SMIME_ASCIICRLF && c == 32) {
+        } else if (is_eol && (flags & SMIME_ASCIICRLF) != 0 && c == 32) {
             /* Strip trailing space on a line; 32 == ASCII for ' ' */
             continue;
         } else if (c != '\r') {

+ 5 - 5
libs/openssl/crypto/asn1/asn_moid.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -29,13 +29,13 @@ static int oid_module_init(CONF_IMODULE *md, const CONF *cnf)
 
     oid_section = CONF_imodule_get_value(md);
     if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) {
-        ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION);
         return 0;
     }
     for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
         oval = sk_CONF_VALUE_value(sktmp, i);
         if (!do_create(oval->value, oval->name)) {
-            ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ADDING_OBJECT);
             return 0;
         }
     }
@@ -84,7 +84,7 @@ static int do_create(const char *value, const char *name)
         }
         p++;
         if ((lntmp = OPENSSL_malloc((p - ln) + 1)) == NULL) {
-            ASN1err(ASN1_F_DO_CREATE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         memcpy(lntmp, ln, p - ln);

+ 9 - 9
libs/openssl/crypto/asn1/asn_mstbl.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2012-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2012-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -26,13 +26,13 @@ static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf)
 
     stbl_section = CONF_imodule_get_value(md);
     if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) {
-        ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_LOADING_SECTION);
         return 0;
     }
     for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
         mval = sk_CONF_VALUE_value(sktmp, i);
         if (!do_tcreate(mval->value, mval->name)) {
-            ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_VALUE);
             return 0;
         }
     }
@@ -96,17 +96,17 @@ static int do_tcreate(const char *value, const char *name)
     rv = 1;
  err:
     if (rv == 0) {
-        ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE);
         if (cnf)
-            ERR_add_error_data(4, "field=", cnf->name,
-                               ", value=", cnf->value);
+            ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE,
+                           "field=%s, value=%s", cnf->name, cnf->value);
         else
-            ERR_add_error_data(4, "name=", name, ", value=", value);
+            ERR_raise_data(ERR_LIB_ASN1, ASN1_R_INVALID_STRING_TABLE_VALUE,
+                           "name=%s, value=%s", name, value);
     } else {
         rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max,
                                    tbl_mask, tbl_flags);
         if (!rv)
-            ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
     }
     sk_CONF_VALUE_pop_free(lst, X509V3_conf_free);
     return rv;

+ 7 - 7
libs/openssl/crypto/asn1/asn_pack.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -19,7 +19,7 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
 
      if (oct == NULL || *oct == NULL) {
         if ((octmp = ASN1_STRING_new()) == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return NULL;
         }
     } else {
@@ -29,12 +29,12 @@ ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
     OPENSSL_free(octmp->data);
     octmp->data = NULL;
 
-    if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) {
-        ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR);
+    if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) <= 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ENCODE_ERROR);
         goto err;
     }
     if (octmp->data == NULL) {
-        ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -57,6 +57,6 @@ void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
 
     p = oct->data;
     if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL)
-        ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DECODE_ERROR);
     return ret;
 }

+ 6 - 6
libs/openssl/crypto/asn1/bio_asn1.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -79,10 +79,8 @@ static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 static const BIO_METHOD methods_asn1 = {
     BIO_TYPE_ASN1,
     "asn1",
-    /* TODO: Convert to new style write function */
     bwrite_conv,
     asn1_bio_write,
-    /* TODO: Convert to new style read function */
     bread_conv,
     asn1_bio_read,
     asn1_bio_puts,
@@ -102,8 +100,10 @@ static int asn1_bio_new(BIO *b)
 {
     BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
 
-    if (ctx == NULL)
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
+    }
     if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
         OPENSSL_free(ctx);
         return 0;
@@ -116,8 +116,8 @@ static int asn1_bio_new(BIO *b)
 
 static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
 {
-    if ((ctx->buf = OPENSSL_malloc(size)) == NULL) {
-        ASN1err(ASN1_F_ASN1_BIO_INIT, ERR_R_MALLOC_FAILURE);
+    if (size <= 0 || (ctx->buf = OPENSSL_malloc(size)) == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     ctx->bufsize = size;

+ 12 - 10
libs/openssl/crypto/asn1/bio_ndef.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -64,7 +64,7 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
     BIO *pop_bio = NULL;
 
     if (!aux || !aux->asn1_cb) {
-        ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
         return NULL;
     }
     ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux));
@@ -132,7 +132,7 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
     unsigned char *p;
     int derlen;
 
-    if (!parg)
+    if (parg == NULL)
         return 0;
 
     ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -141,15 +141,15 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
     if (derlen < 0)
         return 0;
     if ((p = OPENSSL_malloc(derlen)) == NULL) {
-        ASN1err(ASN1_F_NDEF_PREFIX, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
     ndef_aux->derbuf = p;
     *pbuf = p;
-    derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
+    ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
 
-    if (!*ndef_aux->boundary)
+    if (*ndef_aux->boundary == NULL)
         return 0;
 
     *plen = *ndef_aux->boundary - *pbuf;
@@ -162,7 +162,7 @@ static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen,
 {
     NDEF_SUPPORT *ndef_aux;
 
-    if (!parg)
+    if (parg == NULL)
         return 0;
 
     ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -197,7 +197,7 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
     const ASN1_AUX *aux;
     ASN1_STREAM_ARG sarg;
 
-    if (!parg)
+    if (parg == NULL)
         return 0;
 
     ndef_aux = *(NDEF_SUPPORT **)parg;
@@ -213,8 +213,10 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
         return 0;
 
     derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
+    if (derlen < 0)
+        return 0;
     if ((p = OPENSSL_malloc(derlen)) == NULL) {
-        ASN1err(ASN1_F_NDEF_SUFFIX, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -222,7 +224,7 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
     *pbuf = p;
     derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
 
-    if (!*ndef_aux->boundary)
+    if (*ndef_aux->boundary == NULL)
         return 0;
     *pbuf = *ndef_aux->boundary;
     *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);

+ 2 - 2
libs/openssl/crypto/asn1/charmap.h

@@ -2,9 +2,9 @@
  * WARNING: do not edit!
  * Generated by crypto/asn1/charmap.pl
  *
- * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 65 - 0
libs/openssl/crypto/asn1/d2i_param.c

@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/asn1.h>
+#include "internal/asn1.h"
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+
+EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
+                        long length)
+{
+    EVP_PKEY *ret = NULL;
+
+    if ((a == NULL) || (*a == NULL)) {
+        if ((ret = EVP_PKEY_new()) == NULL)
+            return NULL;
+    } else
+        ret = *a;
+
+    if (type != EVP_PKEY_get_id(ret) && !EVP_PKEY_set_type(ret, type))
+        goto err;
+
+    if (ret->ameth == NULL || ret->ameth->param_decode == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+        goto err;
+    }
+
+    if (!ret->ameth->param_decode(ret, pp, length))
+        goto err;
+
+    if (a != NULL)
+        (*a) = ret;
+    return ret;
+err:
+    if (a == NULL || *a != ret)
+        EVP_PKEY_free(ret);
+    return NULL;
+}
+
+EVP_PKEY *d2i_KeyParams_bio(int type, EVP_PKEY **a, BIO *in)
+{
+    BUF_MEM *b = NULL;
+    const unsigned char *p;
+    void *ret = NULL;
+    int len;
+
+    len = asn1_d2i_read_bio(in, &b);
+    if (len < 0)
+        goto err;
+
+    p = (unsigned char *)b->data;
+    ret = d2i_KeyParams(type, a, &p, len);
+err:
+    BUF_MEM_free(b);
+    return ret;
+}

+ 142 - 61
libs/openssl/crypto/asn1/d2i_pr.c

@@ -1,32 +1,89 @@
 /*
  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/bn.h>
 #include <openssl/evp.h>
 #include <openssl/objects.h>
+#include <openssl/decoder.h>
 #include <openssl/engine.h>
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "internal/asn1.h"
 
-EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
-                         long length)
+static EVP_PKEY *
+d2i_PrivateKey_decoder(int keytype, EVP_PKEY **a, const unsigned char **pp,
+                       long length, OSSL_LIB_CTX *libctx, const char *propq)
+{
+    OSSL_DECODER_CTX *dctx = NULL;
+    size_t len = length;
+    EVP_PKEY *pkey = NULL, *bak_a = NULL;
+    EVP_PKEY **ppkey = &pkey;
+    const char *key_name = NULL;
+    const char *input_structures[] = { "type-specific", "PrivateKeyInfo", NULL };
+    int i, ret;
+
+    if (keytype != EVP_PKEY_NONE) {
+        key_name = evp_pkey_type2name(keytype);
+        if (key_name == NULL)
+            return NULL;
+    }
+
+    for (i = 0;  i < (int)OSSL_NELEM(input_structures); ++i) {
+        const unsigned char *p = *pp;
+
+        if (a != NULL && (bak_a = *a) != NULL)
+            ppkey = a;
+        dctx = OSSL_DECODER_CTX_new_for_pkey(ppkey, "DER",
+                                             input_structures[i], key_name,
+                                             EVP_PKEY_KEYPAIR, libctx, propq);
+        if (a != NULL)
+            *a = bak_a;
+        if (dctx == NULL)
+            continue;
+
+        ret = OSSL_DECODER_from_data(dctx, pp, &len);
+        OSSL_DECODER_CTX_free(dctx);
+        if (ret) {
+            if (*ppkey != NULL
+                && evp_keymgmt_util_has(*ppkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY)) {
+                if (a != NULL)
+                    *a = *ppkey;
+                return *ppkey;
+            }
+            *pp = p;
+            goto err;
+        }
+    }
+    /* Fall through to error if all decodes failed */
+err:
+    if (ppkey != a)
+        EVP_PKEY_free(*ppkey);
+    return NULL;
+}
+
+EVP_PKEY *
+ossl_d2i_PrivateKey_legacy(int keytype, EVP_PKEY **a, const unsigned char **pp,
+                           long length, OSSL_LIB_CTX *libctx, const char *propq)
 {
     EVP_PKEY *ret;
     const unsigned char *p = *pp;
 
-    if ((a == NULL) || (*a == NULL)) {
+    if (a == NULL || *a == NULL) {
         if ((ret = EVP_PKEY_new()) == NULL) {
-            ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
             return NULL;
         }
     } else {
@@ -37,35 +94,45 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
 #endif
     }
 
-    if (!EVP_PKEY_set_type(ret, type)) {
-        ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+    if (!EVP_PKEY_set_type(ret, keytype)) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
         goto err;
     }
 
+    ERR_set_mark();
     if (!ret->ameth->old_priv_decode ||
         !ret->ameth->old_priv_decode(ret, &p, length)) {
-        if (ret->ameth->priv_decode) {
+        if (ret->ameth->priv_decode != NULL
+                || ret->ameth->priv_decode_ex != NULL) {
             EVP_PKEY *tmp;
             PKCS8_PRIV_KEY_INFO *p8 = NULL;
             p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
-            if (!p8)
+            if (p8 == NULL) {
+                ERR_clear_last_mark();
                 goto err;
-            tmp = EVP_PKCS82PKEY(p8);
+            }
+            tmp = evp_pkcs82pkey_legacy(p8, libctx, propq);
             PKCS8_PRIV_KEY_INFO_free(p8);
-            if (tmp == NULL)
+            if (tmp == NULL) {
+                ERR_clear_last_mark();
                 goto err;
+            }
             EVP_PKEY_free(ret);
             ret = tmp;
-            if (EVP_PKEY_type(type) != EVP_PKEY_base_id(ret))
+            ERR_pop_to_mark();
+            if (EVP_PKEY_type(keytype) != EVP_PKEY_get_base_id(ret))
                 goto err;
         } else {
-            ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
+            ERR_clear_last_mark();
+            ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
             goto err;
         }
+    } else {
+      ERR_clear_last_mark();
     }
     *pp = p;
     if (a != NULL)
-        (*a) = ret;
+        *a = ret;
     return ret;
  err:
     if (a == NULL || *a != ret)
@@ -73,58 +140,36 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
     return NULL;
 }
 
-/*
- * This works like d2i_PrivateKey() except it automatically works out the
- * type
- */
-
-static EVP_PKEY *key_as_pkcs8(const unsigned char **pp, long length, int *carry_on)
+EVP_PKEY *d2i_PrivateKey_ex(int keytype, EVP_PKEY **a, const unsigned char **pp,
+                            long length, OSSL_LIB_CTX *libctx,
+                            const char *propq)
 {
-    const unsigned char *p = *pp;
-    PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
     EVP_PKEY *ret;
 
-    if (p8 == NULL)
-        return NULL;
-
-    ret = EVP_PKCS82PKEY(p8);
+    ret = d2i_PrivateKey_decoder(keytype, a, pp, length, libctx, propq);
+    /* try the legacy path if the decoder failed */
     if (ret == NULL)
-        *carry_on = 0;
-
-    PKCS8_PRIV_KEY_INFO_free(p8);
-
-    if (ret != NULL)
-        *pp = p;
-
+        ret = ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq);
     return ret;
 }
 
-EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
-                             long length)
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
+                         long length)
+{
+    return d2i_PrivateKey_ex(type, a, pp, length, NULL, NULL);
+}
+
+static EVP_PKEY *d2i_AutoPrivateKey_legacy(EVP_PKEY **a,
+                                           const unsigned char **pp,
+                                           long length,
+                                           OSSL_LIB_CTX *libctx,
+                                           const char *propq)
 {
     STACK_OF(ASN1_TYPE) *inkey;
     const unsigned char *p;
     int keytype;
-    EVP_PKEY *ret = NULL;
-    int carry_on = 1;
-
-    ERR_set_mark();
-    ret = key_as_pkcs8(pp, length, &carry_on);
-    if (ret != NULL) {
-        ERR_clear_last_mark();
-        if (a != NULL)
-            *a = ret;
-        return ret;
-    }
 
-    if (carry_on == 0) {
-        ERR_clear_last_mark();
-        ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY,
-                ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-        return NULL;
-    }
     p = *pp;
-
     /*
      * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by
      * analyzing it we can determine the passed structure: this assumes the
@@ -136,19 +181,55 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
      * Since we only need to discern "traditional format" RSA and DSA keys we
      * can just count the elements.
      */
-    if (sk_ASN1_TYPE_num(inkey) == 6)
+    if (sk_ASN1_TYPE_num(inkey) == 6) {
         keytype = EVP_PKEY_DSA;
-    else if (sk_ASN1_TYPE_num(inkey) == 4)
+    } else if (sk_ASN1_TYPE_num(inkey) == 4) {
         keytype = EVP_PKEY_EC;
-    else
+    } else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not
+                                              * traditional format */
+        PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
+        EVP_PKEY *ret;
+
+        sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+        if (p8 == NULL) {
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+            return NULL;
+        }
+        ret = evp_pkcs82pkey_legacy(p8, libctx, propq);
+        PKCS8_PRIV_KEY_INFO_free(p8);
+        if (ret == NULL)
+            return NULL;
+        *pp = p;
+        if (a != NULL) {
+            *a = ret;
+        }
+        return ret;
+    } else {
         keytype = EVP_PKEY_RSA;
+    }
     sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+    return ossl_d2i_PrivateKey_legacy(keytype, a, pp, length, libctx, propq);
+}
 
-    ret = d2i_PrivateKey(keytype, a, pp, length);
-    if (ret != NULL)
-        ERR_pop_to_mark();
-    else
-        ERR_clear_last_mark();
+/*
+ * This works like d2i_PrivateKey() except it passes the keytype as
+ * EVP_PKEY_NONE, which then figures out the type during decoding.
+ */
+EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
+                                long length, OSSL_LIB_CTX *libctx,
+                                const char *propq)
+{
+    EVP_PKEY *ret;
 
+    ret = d2i_PrivateKey_decoder(EVP_PKEY_NONE, a, pp, length, libctx, propq);
+    /* try the legacy path if the decoder failed */
+    if (ret == NULL)
+        ret = d2i_AutoPrivateKey_legacy(a, pp, length, libctx, propq);
     return ret;
 }
+
+EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+                             long length)
+{
+    return d2i_AutoPrivateKey_ex(a, pp, length, NULL, NULL);
+}

+ 35 - 14
libs/openssl/crypto/asn1/d2i_pu.c

@@ -1,12 +1,18 @@
 /*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+/*
+ * DSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/bn.h>
@@ -23,55 +29,70 @@ EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
                         long length)
 {
     EVP_PKEY *ret;
+    EVP_PKEY *copy = NULL;
 
     if ((a == NULL) || (*a == NULL)) {
         if ((ret = EVP_PKEY_new()) == NULL) {
-            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
             return NULL;
         }
-    } else
+    } else {
         ret = *a;
 
-    if (type != EVP_PKEY_id(ret) && !EVP_PKEY_set_type(ret, type)) {
-        ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB);
+#ifndef OPENSSL_NO_EC
+        if (evp_pkey_is_provided(ret)
+            && EVP_PKEY_get_base_id(ret) == EVP_PKEY_EC) {
+            if (!evp_pkey_copy_downgraded(&copy, ret))
+                goto err;
+        }
+#endif
+    }
+
+    if ((type != EVP_PKEY_get_id(ret) || copy != NULL)
+        && !EVP_PKEY_set_type(ret, type)) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
         goto err;
     }
 
-    switch (EVP_PKEY_id(ret)) {
-#ifndef OPENSSL_NO_RSA
+    switch (EVP_PKEY_get_base_id(ret)) {
     case EVP_PKEY_RSA:
         if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) {
-            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
             goto err;
         }
         break;
-#endif
 #ifndef OPENSSL_NO_DSA
     case EVP_PKEY_DSA:
-        /* TMP UGLY CAST */
         if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) {
-            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
             goto err;
         }
         break;
 #endif
 #ifndef OPENSSL_NO_EC
     case EVP_PKEY_EC:
+        if (copy != NULL) {
+            /* use downgraded parameters from copy */
+            ret->pkey.ec = copy->pkey.ec;
+            copy->pkey.ec = NULL;
+        }
         if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) {
-            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB);
             goto err;
         }
         break;
 #endif
     default:
-        ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
         goto err;
     }
     if (a != NULL)
         (*a) = ret;
+    EVP_PKEY_free(copy);
     return ret;
  err:
     if (a == NULL || *a != ret)
         EVP_PKEY_free(ret);
+    EVP_PKEY_free(copy);
     return NULL;
 }

+ 97 - 25
libs/openssl/crypto/asn1/evp_asn1.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -11,6 +11,7 @@
 #include "internal/cryptlib.h"
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include "crypto/asn1.h"
 
 int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
 {
@@ -26,14 +27,17 @@ int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
     return 1;
 }
 
-/* int max_len:  for returned value    */
+/* int max_len:  for returned value
+ * if passing NULL in data, nothing is copied but the necessary length
+ * for it is returned.
+ */
 int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
 {
     int ret, num;
     const unsigned char *p;
 
     if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) {
-        ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
         return -1;
     }
     p = ASN1_STRING_get0_data(a->value.octet_string);
@@ -42,7 +46,36 @@ int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_l
         num = ret;
     else
         num = max_len;
-    memcpy(data, p, num);
+    if (num > 0 && data != NULL)
+        memcpy(data, p, num);
+    return ret;
+}
+
+static ossl_inline void asn1_type_init_oct(ASN1_OCTET_STRING *oct,
+                                           unsigned char *data, int len)
+{
+    oct->data = data;
+    oct->type = V_ASN1_OCTET_STRING;
+    oct->length = len;
+    oct->flags = 0;
+}
+
+static int asn1_type_get_int_oct(ASN1_OCTET_STRING *oct, int32_t anum,
+                                 long *num, unsigned char *data, int max_len)
+{
+    int ret = ASN1_STRING_length(oct), n;
+
+    if (num != NULL)
+        *num = anum;
+
+    if (max_len > ret)
+        n = ret;
+    else
+        n = max_len;
+
+    if (data != NULL)
+        memcpy(data, ASN1_STRING_get0_data(oct), n);
+
     return ret;
 }
 
@@ -66,25 +99,18 @@ int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data,
 
     atmp.num = num;
     atmp.oct = &oct;
-    oct.data = data;
-    oct.type = V_ASN1_OCTET_STRING;
-    oct.length = len;
-    oct.flags = 0;
+    asn1_type_init_oct(&oct, data, len);
 
     if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a))
         return 1;
     return 0;
 }
 
-/*
- * we return the actual length...
- */
-/* int max_len:  for returned value    */
 int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
                                   unsigned char *data, int max_len)
 {
     asn1_int_oct *atmp = NULL;
-    int ret = -1, n;
+    int ret = -1;
 
     if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) {
         goto err;
@@ -95,21 +121,67 @@ int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num,
     if (atmp == NULL)
         goto err;
 
-    if (num != NULL)
-        *num = atmp->num;
+    ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len);
 
-    ret = ASN1_STRING_length(atmp->oct);
-    if (max_len > ret)
-        n = ret;
-    else
-        n = max_len;
-
-    if (data != NULL)
-        memcpy(data, ASN1_STRING_get0_data(atmp->oct), n);
     if (ret == -1) {
  err:
-        ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
     }
     M_ASN1_free_of(atmp, asn1_int_oct);
     return ret;
 }
+
+typedef struct {
+    ASN1_OCTET_STRING *oct;
+    int32_t num;
+} asn1_oct_int;
+
+/*
+ * Defined in RFC 5084 -
+ * Section 2. "Content-Authenticated Encryption Algorithms"
+ */
+ASN1_SEQUENCE(asn1_oct_int) = {
+        ASN1_SIMPLE(asn1_oct_int, oct, ASN1_OCTET_STRING),
+        ASN1_EMBED(asn1_oct_int, num, INT32)
+} static_ASN1_SEQUENCE_END(asn1_oct_int)
+
+DECLARE_ASN1_ITEM(asn1_oct_int)
+
+int ossl_asn1_type_set_octetstring_int(ASN1_TYPE *a, long num,
+                                       unsigned char *data, int len)
+{
+    asn1_oct_int atmp;
+    ASN1_OCTET_STRING oct;
+
+    atmp.num = num;
+    atmp.oct = &oct;
+    asn1_type_init_oct(&oct, data, len);
+
+    if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_oct_int), &atmp, &a))
+        return 1;
+    return 0;
+}
+
+int ossl_asn1_type_get_octetstring_int(const ASN1_TYPE *a, long *num,
+                                       unsigned char *data, int max_len)
+{
+    asn1_oct_int *atmp = NULL;
+    int ret = -1;
+
+    if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL))
+        goto err;
+
+    atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_oct_int), a);
+
+    if (atmp == NULL)
+        goto err;
+
+    ret = asn1_type_get_int_oct(atmp->oct, atmp->num, num, data, max_len);
+
+    if (ret == -1) {
+ err:
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_DATA_IS_WRONG);
+    }
+    M_ASN1_free_of(atmp, asn1_oct_int);
+    return ret;
+}

+ 6 - 7
libs/openssl/crypto/asn1/f_int.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -100,7 +100,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
         k = 0;
         i -= again;
         if (i % 2 != 0) {
-            ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
             OPENSSL_free(s);
             return 0;
         }
@@ -108,7 +108,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
         if (num + i > slen) {
             sp = OPENSSL_clear_realloc(s, slen, num + i * 2);
             if (sp == NULL) {
-                ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 OPENSSL_free(s);
                 return 0;
             }
@@ -119,8 +119,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
             for (n = 0; n < 2; n++) {
                 m = OPENSSL_hexchar2int(bufp[k + n]);
                 if (m < 0) {
-                    ASN1err(ASN1_F_A2I_ASN1_INTEGER,
-                            ASN1_R_NON_HEX_CHARACTERS);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
                     goto err;
                 }
                 s[num + j] <<= 4;
@@ -137,7 +136,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
     bs->data = s;
     return 1;
  err:
-    ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
     OPENSSL_free(s);
     return 0;
 }

+ 6 - 7
libs/openssl/crypto/asn1/f_string.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -91,7 +91,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
         k = 0;
         i -= again;
         if (i % 2 != 0) {
-            ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
             OPENSSL_free(s);
             return 0;
         }
@@ -99,7 +99,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
         if (num + i > slen) {
             sp = OPENSSL_realloc(s, (unsigned int)num + i * 2);
             if (sp == NULL) {
-                ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 OPENSSL_free(s);
                 return 0;
             }
@@ -110,8 +110,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
             for (n = 0; n < 2; n++) {
                 m = OPENSSL_hexchar2int(bufp[k + n]);
                 if (m < 0) {
-                    ASN1err(ASN1_F_A2I_ASN1_STRING,
-                            ASN1_R_NON_HEX_CHARACTERS);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_NON_HEX_CHARACTERS);
                     OPENSSL_free(s);
                     return 0;
                 }
@@ -130,7 +129,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
     return 1;
 
  err:
-    ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_SHORT_LINE);
     OPENSSL_free(s);
     return 0;
 }

+ 149 - 0
libs/openssl/crypto/asn1/i2d_evp.c

@@ -0,0 +1,149 @@
+/*
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/encoder.h>
+#include <openssl/buffer.h>
+#include <openssl/x509.h>
+#include <openssl/rsa.h>         /* For i2d_RSAPublicKey */
+#include <openssl/dsa.h>         /* For i2d_DSAPublicKey */
+#include <openssl/ec.h>          /* For i2o_ECPublicKey */
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+
+struct type_and_structure_st {
+    const char *output_type;
+    const char *output_structure;
+};
+
+static int i2d_provided(const EVP_PKEY *a, int selection,
+                        const struct type_and_structure_st *output_info,
+                        unsigned char **pp)
+{
+    OSSL_ENCODER_CTX *ctx = NULL;
+    int ret;
+
+    for (ret = -1;
+         ret == -1 && output_info->output_type != NULL;
+         output_info++) {
+        /*
+         * The i2d_ calls don't take a boundary length for *pp.  However,
+         * OSSL_ENCODER_to_data() needs one, so we make one up.  Because
+         * OSSL_ENCODER_to_data() decrements this number by the amount of
+         * bytes written, we need to calculate the length written further
+         * down, when pp != NULL.
+         */
+        size_t len = INT_MAX;
+        int pp_was_NULL = (pp == NULL || *pp == NULL);
+
+        ctx = OSSL_ENCODER_CTX_new_for_pkey(a, selection,
+                                            output_info->output_type,
+                                            output_info->output_structure,
+                                            NULL);
+        if (ctx == NULL)
+            return -1;
+        if (OSSL_ENCODER_to_data(ctx, pp, &len)) {
+            if (pp_was_NULL)
+                ret = (int)len;
+            else
+                ret = INT_MAX - (int)len;
+        }
+        OSSL_ENCODER_CTX_free(ctx);
+        ctx = NULL;
+    }
+
+    if (ret == -1)
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+    return ret;
+}
+
+int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp)
+{
+    if (evp_pkey_is_provided(a)) {
+        static const struct type_and_structure_st output_info[] = {
+            { "DER", "type-specific" },
+            { NULL, }
+        };
+
+        return i2d_provided(a, EVP_PKEY_KEY_PARAMETERS, output_info, pp);
+    }
+    if (a->ameth != NULL && a->ameth->param_encode != NULL)
+        return a->ameth->param_encode(a, pp);
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_TYPE);
+    return -1;
+}
+
+int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey)
+{
+    return ASN1_i2d_bio_of(EVP_PKEY, i2d_KeyParams, bp, pkey);
+}
+
+int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
+{
+    if (evp_pkey_is_provided(a)) {
+        static const struct type_and_structure_st output_info[] = {
+            { "DER", "type-specific" },
+            { "DER", "PrivateKeyInfo" },
+            { NULL, }
+        };
+
+        return i2d_provided(a, EVP_PKEY_KEYPAIR, output_info, pp);
+    }
+    if (a->ameth != NULL && a->ameth->old_priv_encode != NULL) {
+        return a->ameth->old_priv_encode(a, pp);
+    }
+    if (a->ameth != NULL && a->ameth->priv_encode != NULL) {
+        PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
+        int ret = 0;
+
+        if (p8 != NULL) {
+            ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
+            PKCS8_PRIV_KEY_INFO_free(p8);
+        }
+        return ret;
+    }
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+    return -1;
+}
+
+int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp)
+{
+    if (evp_pkey_is_provided(a)) {
+        static const struct type_and_structure_st output_info[] = {
+            { "DER", "type-specific" },
+            { "blob", NULL },    /* for EC */
+            { NULL, }
+        };
+
+        return i2d_provided(a, EVP_PKEY_PUBLIC_KEY, output_info, pp);
+    }
+    switch (EVP_PKEY_get_base_id(a)) {
+    case EVP_PKEY_RSA:
+        return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
+#ifndef OPENSSL_NO_DSA
+    case EVP_PKEY_DSA:
+        return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
+#endif
+#ifndef OPENSSL_NO_EC
+    case EVP_PKEY_EC:
+        return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
+#endif
+    default:
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+        return -1;
+    }
+}

+ 0 - 33
libs/openssl/crypto/asn1/i2d_pr.c

@@ -1,33 +0,0 @@
-/*
- * Copyright 1995-2016 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
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include "crypto/asn1.h"
-#include "crypto/evp.h"
-
-int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
-{
-    if (a->ameth && a->ameth->old_priv_encode) {
-        return a->ameth->old_priv_encode(a, pp);
-    }
-    if (a->ameth && a->ameth->priv_encode) {
-        PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
-        int ret = 0;
-        if (p8 != NULL) {
-            ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
-            PKCS8_PRIV_KEY_INFO_free(p8);
-        }
-        return ret;
-    }
-    ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-    return -1;
-}

+ 0 - 38
libs/openssl/crypto/asn1/i2d_pu.c

@@ -1,38 +0,0 @@
-/*
- * Copyright 1995-2016 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
- */
-
-#include <stdio.h>
-#include "internal/cryptlib.h"
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-#include <openssl/rsa.h>
-#include <openssl/dsa.h>
-#include <openssl/ec.h>
-
-int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
-{
-    switch (EVP_PKEY_id(a)) {
-#ifndef OPENSSL_NO_RSA
-    case EVP_PKEY_RSA:
-        return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp);
-#endif
-#ifndef OPENSSL_NO_DSA
-    case EVP_PKEY_DSA:
-        return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp);
-#endif
-#ifndef OPENSSL_NO_EC
-    case EVP_PKEY_EC:
-        return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp);
-#endif
-    default:
-        ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-        return -1;
-    }
-}

+ 22 - 26
libs/openssl/crypto/asn1/n_pkey.c

@@ -1,26 +1,26 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
-#include "openssl/opensslconf.h"
-#ifdef OPENSSL_NO_RSA
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
-# include "internal/cryptlib.h"
-# include <stdio.h>
-# include <openssl/rsa.h>
-# include <openssl/objects.h>
-# include <openssl/asn1t.h>
-# include <openssl/evp.h>
-# include <openssl/x509.h>
-
-# ifndef OPENSSL_NO_RC4
+#include <openssl/opensslconf.h>
+#include "internal/cryptlib.h"
+#include <stdio.h>
+#include <openssl/rsa.h>
+#include <openssl/objects.h>
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#define ASN1_BROKEN_SEQUENCE(tname) \
+        static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \
+        ASN1_SEQUENCE(tname)
+#define static_ASN1_BROKEN_SEQUENCE_END(stname) \
+        static_ASN1_SEQUENCE_END_ref(stname, stname)
 
 typedef struct netscape_pkey_st {
     int32_t version;
@@ -43,9 +43,9 @@ ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = {
         ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG)
 } static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY)
 
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY)
-IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY)
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_ENCRYPTED_PKEY, NETSCAPE_ENCRYPTED_PKEY)
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_ENCRYPTED_PKEY)
 
 ASN1_SEQUENCE(NETSCAPE_PKEY) = {
         ASN1_EMBED(NETSCAPE_PKEY, version, INT32),
@@ -53,10 +53,6 @@ ASN1_SEQUENCE(NETSCAPE_PKEY) = {
         ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING)
 } static_ASN1_SEQUENCE_END(NETSCAPE_PKEY)
 
-DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY)
-IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY)
-
-# endif                         /* OPENSSL_NO_RC4 */
-
-#endif
+DECLARE_ASN1_FUNCTIONS(NETSCAPE_PKEY)
+DECLARE_ASN1_ENCODE_FUNCTIONS_name(NETSCAPE_PKEY, NETSCAPE_PKEY)
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_PKEY)

+ 1 - 1
libs/openssl/crypto/asn1/nsseq.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 30 - 13
libs/openssl/crypto/asn1/p5_pbe.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -24,8 +24,9 @@ IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
 
 /* Set an algorithm identifier for a PKCS#5 PBE algorithm */
 
-int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
-                         const unsigned char *salt, int saltlen)
+int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+                            const unsigned char *salt, int saltlen,
+                            OSSL_LIB_CTX *ctx)
 {
     PBEPARAM *pbe = NULL;
     ASN1_STRING *pbe_str = NULL;
@@ -33,33 +34,35 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
 
     pbe = PBEPARAM_new();
     if (pbe == NULL) {
-        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (iter <= 0)
         iter = PKCS5_DEFAULT_ITER;
     if (!ASN1_INTEGER_set(pbe->iter, iter)) {
-        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (!saltlen)
         saltlen = PKCS5_SALT_LEN;
+    if (saltlen < 0)
+        goto err;
 
     sstr = OPENSSL_malloc(saltlen);
     if (sstr == NULL) {
-        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (salt)
         memcpy(sstr, salt, saltlen);
-    else if (RAND_bytes(sstr, saltlen) <= 0)
+    else if (RAND_bytes_ex(ctx, sstr, saltlen, 0) <= 0)
         goto err;
 
     ASN1_STRING_set0(pbe->salt, sstr, saltlen);
     sstr = NULL;
 
     if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) {
-        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -76,21 +79,35 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
     return 0;
 }
 
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+                         const unsigned char *salt, int saltlen)
+{
+    return PKCS5_pbe_set0_algor_ex(algor, alg, iter, salt, saltlen, NULL);
+}
+
 /* Return an algorithm identifier for a PKCS#5 PBE algorithm */
 
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
-                          const unsigned char *salt, int saltlen)
+X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+                             const unsigned char *salt, int saltlen,
+                             OSSL_LIB_CTX *ctx)
 {
     X509_ALGOR *ret;
     ret = X509_ALGOR_new();
     if (ret == NULL) {
-        ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
-    if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+    if (PKCS5_pbe_set0_algor_ex(ret, alg, iter, salt, saltlen, ctx))
         return ret;
 
     X509_ALGOR_free(ret);
     return NULL;
 }
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+                          const unsigned char *salt, int saltlen)
+{
+    return PKCS5_pbe_set_ex(alg, iter, salt, saltlen, NULL);
+}
+

+ 48 - 23
libs/openssl/crypto/asn1/p5_pbev2.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
 #include <openssl/x509.h>
 #include <openssl/rand.h>
 
@@ -37,20 +39,20 @@ IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
  * and IV.
  */
 
-X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
-                              unsigned char *salt, int saltlen,
-                              unsigned char *aiv, int prf_nid)
+X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+                                 unsigned char *salt, int saltlen,
+                                 unsigned char *aiv, int prf_nid,
+                                 OSSL_LIB_CTX *libctx)
 {
     X509_ALGOR *scheme = NULL, *ret = NULL;
-    int alg_nid, keylen;
+    int alg_nid, keylen, ivlen;
     EVP_CIPHER_CTX *ctx = NULL;
     unsigned char iv[EVP_MAX_IV_LENGTH];
     PBE2PARAM *pbe2 = NULL;
 
-    alg_nid = EVP_CIPHER_type(cipher);
+    alg_nid = EVP_CIPHER_get_type(cipher);
     if (alg_nid == NID_undef) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,
-                ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
         goto err;
     }
 
@@ -64,10 +66,11 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
         goto merr;
 
     /* Create random IV */
-    if (EVP_CIPHER_iv_length(cipher)) {
+    ivlen = EVP_CIPHER_get_iv_length(cipher);
+    if (ivlen > 0) {
         if (aiv)
-            memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
-        else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
+            memcpy(iv, aiv, ivlen);
+        else if (RAND_bytes_ex(libctx, iv, ivlen, 0) <= 0)
             goto err;
     }
 
@@ -79,25 +82,26 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
     if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0))
         goto err;
     if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
         goto err;
     }
     /*
      * If prf NID unspecified see if cipher has a preference. An error is OK
      * here: just means use default PRF.
      */
+    ERR_set_mark();
     if ((prf_nid == -1) &&
         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
-        ERR_clear_error();
         prf_nid = NID_hmacWithSHA256;
     }
+    ERR_pop_to_mark();
     EVP_CIPHER_CTX_free(ctx);
     ctx = NULL;
 
     /* If its RC2 then we'd better setup the key length */
 
     if (alg_nid == NID_rc2_cbc)
-        keylen = EVP_CIPHER_key_length(cipher);
+        keylen = EVP_CIPHER_get_key_length(cipher);
     else
         keylen = -1;
 
@@ -105,9 +109,10 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
 
     X509_ALGOR_free(pbe2->keyfunc);
 
-    pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
+    pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen,
+                                        libctx);
 
-    if (!pbe2->keyfunc)
+    if (pbe2->keyfunc == NULL)
         goto merr;
 
     /* Now set up top level AlgorithmIdentifier */
@@ -129,7 +134,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
     return ret;
 
  merr:
-    ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
 
  err:
     EVP_CIPHER_CTX_free(ctx);
@@ -140,14 +145,25 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
     return NULL;
 }
 
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+                              unsigned char *salt, int saltlen,
+                              unsigned char *aiv, int prf_nid)
+{
+    return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid,
+                                NULL);
+}
+
 X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
                            unsigned char *salt, int saltlen)
 {
-    return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
+    return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
+                                NULL);
 }
 
-X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
-                             int prf_nid, int keylen)
+
+X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+                                int prf_nid, int keylen,
+                                OSSL_LIB_CTX *libctx)
 {
     X509_ALGOR *keyfunc = NULL;
     PBKDF2PARAM *kdf = NULL;
@@ -161,6 +177,8 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
     kdf->salt->value.octet_string = osalt;
     kdf->salt->type = V_ASN1_OCTET_STRING;
 
+    if (saltlen < 0)
+        goto merr;
     if (saltlen == 0)
         saltlen = PKCS5_SALT_LEN;
     if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL)
@@ -170,7 +188,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
 
     if (salt)
         memcpy(osalt->data, salt, saltlen);
-    else if (RAND_bytes(osalt->data, saltlen) <= 0)
+    else if (RAND_bytes_ex(libctx, osalt->data, saltlen, 0) <= 0)
         goto merr;
 
     if (iter <= 0)
@@ -214,8 +232,15 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
     return keyfunc;
 
  merr:
-    ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
     PBKDF2PARAM_free(kdf);
     X509_ALGOR_free(keyfunc);
     return NULL;
 }
+
+X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+                             int prf_nid, int keylen)
+{
+    return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL);
+}
+

+ 43 - 31
libs/openssl/crypto/asn1/p5_scrypt.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -10,10 +10,12 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/core_names.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
 #include <openssl/rand.h>
+#include "crypto/evp.h"
 
 #ifndef OPENSSL_NO_SCRYPT
 /* PKCS#5 scrypt password based encryption structures */
@@ -49,20 +51,18 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
     PBE2PARAM *pbe2 = NULL;
 
     if (!cipher) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
         goto err;
     }
 
     if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
-                ASN1_R_INVALID_SCRYPT_PARAMETERS);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INVALID_SCRYPT_PARAMETERS);
         goto err;
     }
 
-    alg_nid = EVP_CIPHER_type(cipher);
+    alg_nid = EVP_CIPHER_get_type(cipher);
     if (alg_nid == NID_undef) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
-                ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
         goto err;
     }
 
@@ -79,10 +79,10 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
         goto merr;
 
     /* Create random IV */
-    if (EVP_CIPHER_iv_length(cipher)) {
+    if (EVP_CIPHER_get_iv_length(cipher)) {
         if (aiv)
-            memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
-        else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
+            memcpy(iv, aiv, EVP_CIPHER_get_iv_length(cipher));
+        else if (RAND_bytes(iv, EVP_CIPHER_get_iv_length(cipher)) <= 0)
             goto err;
     }
 
@@ -94,8 +94,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
     if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0)
         goto err;
     if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) <= 0) {
-        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT,
-                ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
         goto err;
     }
     EVP_CIPHER_CTX_free(ctx);
@@ -104,7 +103,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
     /* If its RC2 then we'd better setup the key length */
 
     if (alg_nid == NID_rc2_cbc)
-        keylen = EVP_CIPHER_key_length(cipher);
+        keylen = EVP_CIPHER_get_key_length(cipher);
 
     /* Setup keyfunc */
 
@@ -135,7 +134,7 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
     return ret;
 
  merr:
-    ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
 
  err:
     PBE2PARAM_free(pbe2);
@@ -202,26 +201,27 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
     return keyfunc;
 
  merr:
-    ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
  err:
     SCRYPT_PARAMS_free(sparam);
     X509_ALGOR_free(keyfunc);
     return NULL;
 }
 
-int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
-                             int passlen, ASN1_TYPE *param,
-                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                int passlen, ASN1_TYPE *param,
+                                const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+                                OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
     uint64_t p, r, N;
     size_t saltlen;
     size_t keylen = 0;
-    int rv = 0;
+    int t, rv = 0;
     SCRYPT_PARAMS *sparam = NULL;
 
-    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
-        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET);
+    if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
         goto err;
     }
 
@@ -230,11 +230,16 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param);
 
     if (sparam == NULL) {
-        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR);
+        ERR_raise(ERR_LIB_EVP, EVP_R_DECODE_ERROR);
         goto err;
     }
 
-    keylen = EVP_CIPHER_CTX_key_length(ctx);
+    t = EVP_CIPHER_CTX_get_key_length(ctx);
+    if (t < 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH);
+        goto err;
+    }
+    keylen = t;
 
     /* Now check the parameters of sparam */
 
@@ -242,8 +247,7 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
         uint64_t spkeylen;
         if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0)
             || (spkeylen != keylen)) {
-            EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
-                   EVP_R_UNSUPPORTED_KEYLENGTH);
+            ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEYLENGTH);
             goto err;
         }
     }
@@ -251,9 +255,9 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0
         || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0
         || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0
-        || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
-        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN,
-               EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
+        || EVP_PBE_scrypt_ex(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0,
+                             libctx, propq) == 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
         goto err;
     }
 
@@ -261,8 +265,8 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
 
     salt = sparam->salt->data;
     saltlen = sparam->salt->length;
-    if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen)
-        == 0)
+    if (EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, 0, key,
+                          keylen, libctx, propq) == 0)
         goto err;
     rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
  err:
@@ -271,4 +275,12 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     SCRYPT_PARAMS_free(sparam);
     return rv;
 }
+
+int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+                             int passlen, ASN1_TYPE *param,
+                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+{
+    return PKCS5_v2_scrypt_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL);
+}
+
 #endif /* OPENSSL_NO_SCRYPT */

+ 13 - 2
libs/openssl/crypto/asn1/p8_pkey.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -78,3 +78,14 @@ int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
         return 1;
     return 0;
 }
+
+int PKCS8_pkey_add1_attr_by_OBJ(PKCS8_PRIV_KEY_INFO *p8, const ASN1_OBJECT *obj, int type,
+                                const unsigned char *bytes, int len)
+{
+    return (X509at_add1_attr_by_OBJ(&p8->attributes, obj, type, bytes, len) != NULL);
+}
+
+int PKCS8_pkey_add1_attr(PKCS8_PRIV_KEY_INFO *p8, X509_ATTRIBUTE *attr)
+{
+    return (X509at_add1_attr(&p8->attributes, attr) != NULL);
+}

+ 18 - 32
libs/openssl/crypto/asn1/standard_methods.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -13,49 +13,35 @@
  * is used to search it.
  */
 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
-#ifndef OPENSSL_NO_RSA
-    &rsa_asn1_meths[0],
-    &rsa_asn1_meths[1],
-#endif
+    &ossl_rsa_asn1_meths[0],
+    &ossl_rsa_asn1_meths[1],
 #ifndef OPENSSL_NO_DH
-    &dh_asn1_meth,
+    &ossl_dh_asn1_meth,
 #endif
 #ifndef OPENSSL_NO_DSA
-    &dsa_asn1_meths[0],
-    &dsa_asn1_meths[1],
-    &dsa_asn1_meths[2],
-    &dsa_asn1_meths[3],
-    &dsa_asn1_meths[4],
+    &ossl_dsa_asn1_meths[0],
+    &ossl_dsa_asn1_meths[1],
+    &ossl_dsa_asn1_meths[2],
+    &ossl_dsa_asn1_meths[3],
+    &ossl_dsa_asn1_meths[4],
 #endif
 #ifndef OPENSSL_NO_EC
-    &eckey_asn1_meth,
-#endif
-    &hmac_asn1_meth,
-#ifndef OPENSSL_NO_CMAC
-    &cmac_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_RSA
-    &rsa_pss_asn1_meth,
+    &ossl_eckey_asn1_meth,
 #endif
+    &ossl_rsa_pss_asn1_meth,
 #ifndef OPENSSL_NO_DH
-    &dhx_asn1_meth,
+    &ossl_dhx_asn1_meth,
 #endif
 #ifndef OPENSSL_NO_EC
-    &ecx25519_asn1_meth,
-    &ecx448_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_POLY1305
-    &poly1305_asn1_meth,
-#endif
-#ifndef OPENSSL_NO_SIPHASH
-    &siphash_asn1_meth,
+    &ossl_ecx25519_asn1_meth,
+    &ossl_ecx448_asn1_meth,
 #endif
 #ifndef OPENSSL_NO_EC
-    &ed25519_asn1_meth,
-    &ed448_asn1_meth,
+    &ossl_ed25519_asn1_meth,
+    &ossl_ed448_asn1_meth,
 #endif
 #ifndef OPENSSL_NO_SM2
-    &sm2_asn1_meth,
+    &ossl_sm2_asn1_meth,
 #endif
 };
 

+ 1 - 1
libs/openssl/crypto/asn1/t_bitst.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 1 - 1
libs/openssl/crypto/asn1/t_pkey.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 2 - 2
libs/openssl/crypto/asn1/t_spki.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -30,7 +30,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
     BIO_printf(out, "  Public Key Algorithm: %s\n",
                (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
     pkey = X509_PUBKEY_get(spki->spkac->pubkey);
-    if (!pkey)
+    if (pkey == NULL)
         BIO_printf(out, "  Unable to load public key\n");
     else {
         EVP_PKEY_print_public(out, pkey, 4, NULL);

+ 192 - 149
libs/openssl/crypto/asn1/tasn_dec.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -17,7 +17,6 @@
 #include "internal/numbers.h"
 #include "asn1_local.h"
 
-
 /*
  * Constructed types with a recursive definition (such as can be found in PKCS7)
  * could eventually exceed the stack given malicious input with excessive
@@ -29,7 +28,8 @@
 static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                                long len, const ASN1_ITEM *it,
                                int tag, int aclass, char opt, ASN1_TLC *ctx,
-                               int depth);
+                               int depth, OSSL_LIB_CTX *libctx,
+                               const char *propq);
 
 static int asn1_check_eoc(const unsigned char **in, long len);
 static int asn1_find_end(const unsigned char **in, long len, char inf);
@@ -47,11 +47,13 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
 static int asn1_template_ex_d2i(ASN1_VALUE **pval,
                                 const unsigned char **in, long len,
                                 const ASN1_TEMPLATE *tt, char opt,
-                                ASN1_TLC *ctx, int depth);
+                                ASN1_TLC *ctx, int depth, OSSL_LIB_CTX *libctx,
+                                const char *propq);
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
                                    const unsigned char **in, long len,
                                    const ASN1_TEMPLATE *tt, char opt,
-                                   ASN1_TLC *ctx, int depth);
+                                   ASN1_TLC *ctx, int depth,
+                                   OSSL_LIB_CTX *libctx, const char *propq);
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
                                  const unsigned char **in, long len,
                                  const ASN1_ITEM *it,
@@ -67,7 +69,7 @@ static const unsigned long tag2bit[32] = {
     /* tags  4- 7 */
     B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,
     /* tags  8-11 */
-    B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,
+    B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, 0, B_ASN1_UNKNOWN,
     /* tags 12-15 */
     B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,
     /* tags 16-19 */
@@ -91,9 +93,9 @@ unsigned long ASN1_tag2bit(int tag)
 
 /* Macro to initialize and invalidate the cache */
 
-#define asn1_tlc_clear(c)       if (c) (c)->valid = 0
+#define asn1_tlc_clear(c)       do { if ((c) != NULL) (c)->valid = 0; } while (0)
 /* Version to avoid compiler warning about 'c' always non-NULL */
-#define asn1_tlc_clear_nc(c)    (c)->valid = 0
+#define asn1_tlc_clear_nc(c)    do {(c)->valid = 0; } while (0)
 
 /*
  * Decode an ASN1 item, this currently behaves just like a standard 'd2i'
@@ -102,29 +104,54 @@ unsigned long ASN1_tag2bit(int tag)
  * this will simply be a special case.
  */
 
-ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
-                          const unsigned char **in, long len,
-                          const ASN1_ITEM *it)
+static int asn1_item_ex_d2i_intern(ASN1_VALUE **pval, const unsigned char **in,
+                                   long len, const ASN1_ITEM *it, int tag,
+                                   int aclass, char opt, ASN1_TLC *ctx,
+                                   OSSL_LIB_CTX *libctx, const char *propq)
+{
+    int rv;
+
+    if (pval == NULL || it == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0,
+                             libctx, propq);
+    if (rv <= 0)
+        ASN1_item_ex_free(pval, it);
+    return rv;
+}
+
+int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
+                     const ASN1_ITEM *it,
+                     int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+    return asn1_item_ex_d2i_intern(pval, in, len, it, tag, aclass, opt, ctx,
+                                   NULL, NULL);
+}
+
+ASN1_VALUE *ASN1_item_d2i_ex(ASN1_VALUE **pval,
+                             const unsigned char **in, long len,
+                             const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+                             const char *propq)
 {
     ASN1_TLC c;
     ASN1_VALUE *ptmpval = NULL;
-    if (!pval)
+
+    if (pval == NULL)
         pval = &ptmpval;
     asn1_tlc_clear_nc(&c);
-    if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+    if (asn1_item_ex_d2i_intern(pval, in, len, it, -1, 0, 0, &c, libctx,
+                                propq) > 0)
         return *pval;
     return NULL;
 }
 
-int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
-                     const ASN1_ITEM *it,
-                     int tag, int aclass, char opt, ASN1_TLC *ctx)
+ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
+                          const unsigned char **in, long len,
+                          const ASN1_ITEM *it)
 {
-    int rv;
-    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0);
-    if (rv <= 0)
-        ASN1_item_ex_free(pval, it);
-    return rv;
+    return ASN1_item_d2i_ex(pval, in, len, it, NULL, NULL);
 }
 
 /*
@@ -135,11 +162,12 @@ int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
 static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                                long len, const ASN1_ITEM *it,
                                int tag, int aclass, char opt, ASN1_TLC *ctx,
-                               int depth)
+                               int depth, OSSL_LIB_CTX *libctx,
+                               const char *propq)
 {
     const ASN1_TEMPLATE *tt, *errtt = NULL;
     const ASN1_EXTERN_FUNCS *ef;
-    const ASN1_AUX *aux = it->funcs;
+    const ASN1_AUX *aux;
     ASN1_aux_cb *asn1_cb;
     const unsigned char *p = NULL, *q;
     unsigned char oclass;
@@ -149,15 +177,23 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
     int otag;
     int ret = 0;
     ASN1_VALUE **pchptr;
-    if (!pval)
+
+    if (pval == NULL || it == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
+    }
+    if (len <= 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+        return 0;
+    }
+    aux = it->funcs;
     if (aux && aux->asn1_cb)
         asn1_cb = aux->asn1_cb;
     else
         asn1_cb = 0;
 
     if (++depth > ASN1_MAX_CONSTRUCTED_NEST) {
-        ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_TOO_DEEP);
         goto err;
     }
 
@@ -171,12 +207,12 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
              * template in the template itself.
              */
             if ((tag != -1) || opt) {
-                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I,
-                        ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+                ERR_raise(ERR_LIB_ASN1,
+                          ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
                 goto err;
             }
-            return asn1_template_ex_d2i(pval, in, len,
-                                        it->templates, opt, ctx, depth);
+            return asn1_template_ex_d2i(pval, in, len, it->templates, opt, ctx,
+                                        depth, libctx, propq);
         }
         return asn1_d2i_ex_primitive(pval, in, len, it,
                                      tag, aclass, opt, ctx);
@@ -187,7 +223,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
          * if tag != -1, then this looks like an error in the template.
          */
         if (tag != -1) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
             goto err;
         }
 
@@ -196,7 +232,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
                               &p, len, -1, 0, 1, ctx);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
 
@@ -205,7 +241,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             /* If OPTIONAL, assume this is OK */
             if (opt)
                 return -1;
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
             goto err;
         }
 
@@ -214,7 +250,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             /* If OPTIONAL, assume this is OK */
             if (opt)
                 return -1;
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MSTRING_WRONG_TAG);
             goto err;
         }
         return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx);
@@ -222,6 +258,9 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
     case ASN1_ITYPE_EXTERN:
         /* Use new style d2i */
         ef = it->funcs;
+        if (ef->asn1_ex_d2i_ex != NULL)
+            return ef->asn1_ex_d2i_ex(pval, in, len, it, tag, aclass, opt, ctx,
+                                      libctx, propq);
         return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
 
     case ASN1_ITYPE_CHOICE:
@@ -230,7 +269,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
          * if tag != -1, then this looks like an error in the template.
          */
         if (tag != -1) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_BAD_TEMPLATE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
             goto err;
         }
 
@@ -238,25 +277,26 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             goto auxerr;
         if (*pval) {
             /* Free up and zero CHOICE value if initialised */
-            i = asn1_get_choice_selector(pval, it);
+            i = ossl_asn1_get_choice_selector(pval, it);
             if ((i >= 0) && (i < it->tcount)) {
                 tt = it->templates + i;
-                pchptr = asn1_get_field_ptr(pval, tt);
-                asn1_template_free(pchptr, tt);
-                asn1_set_choice_selector(pval, -1, it);
+                pchptr = ossl_asn1_get_field_ptr(pval, tt);
+                ossl_asn1_template_free(pchptr, tt);
+                ossl_asn1_set_choice_selector(pval, -1, it);
             }
-        } else if (!ASN1_item_ex_new(pval, it)) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+        } else if (!ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
         /* CHOICE type, try each possibility in turn */
         p = *in;
         for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
-            pchptr = asn1_get_field_ptr(pval, tt);
+            pchptr = ossl_asn1_get_field_ptr(pval, tt);
             /*
              * We mark field as OPTIONAL so its absence can be recognised.
              */
-            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth);
+            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth,
+                                       libctx, propq);
             /* If field not present, try the next one */
             if (ret == -1)
                 continue;
@@ -267,9 +307,9 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
              * Must be an ASN1 parsing error.
              * Free up any partial choice value
              */
-            asn1_template_free(pchptr, tt);
+            ossl_asn1_template_free(pchptr, tt);
             errtt = tt;
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
 
@@ -281,11 +321,11 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                 ASN1_item_ex_free(pval, it);
                 return -1;
             }
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
             goto err;
         }
 
-        asn1_set_choice_selector(pval, i, it);
+        ossl_asn1_set_choice_selector(pval, i, it);
 
         if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
             goto auxerr;
@@ -306,7 +346,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
                               &p, len, tag, aclass, opt, ctx);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         } else if (ret == -1)
             return -1;
@@ -318,12 +358,13 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         else
             seq_nolen = seq_eoc;
         if (!cst) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
             goto err;
         }
 
-        if (!*pval && !ASN1_item_ex_new(pval, it)) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR);
+        if (*pval == NULL
+                && !ossl_asn1_item_ex_new_intern(pval, it, libctx, propq)) {
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         }
 
@@ -335,11 +376,11 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
             if (tt->flags & ASN1_TFLG_ADB_MASK) {
                 const ASN1_TEMPLATE *seqtt;
                 ASN1_VALUE **pseqval;
-                seqtt = asn1_do_adb(pval, tt, 0);
+                seqtt = ossl_asn1_do_adb(*pval, tt, 0);
                 if (seqtt == NULL)
                     continue;
-                pseqval = asn1_get_field_ptr(pval, seqtt);
-                asn1_template_free(pseqval, seqtt);
+                pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+                ossl_asn1_template_free(pseqval, seqtt);
             }
         }
 
@@ -347,22 +388,21 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
             const ASN1_TEMPLATE *seqtt;
             ASN1_VALUE **pseqval;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            seqtt = ossl_asn1_do_adb(*pval, tt, 1);
             if (seqtt == NULL)
                 goto err;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
+            pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
             /* Have we ran out of data? */
             if (!len)
                 break;
             q = p;
             if (asn1_check_eoc(&p, len)) {
                 if (!seq_eoc) {
-                    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
                     goto err;
                 }
                 len -= p - q;
                 seq_eoc = 0;
-                q = p;
                 break;
             }
             /*
@@ -380,7 +420,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
              */
 
             ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx,
-                                       depth);
+                                       depth, libctx, propq);
             if (!ret) {
                 errtt = seqtt;
                 goto err;
@@ -388,7 +428,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
                 /*
                  * OPTIONAL component absent. Free and zero the field.
                  */
-                asn1_template_free(pseqval, seqtt);
+                ossl_asn1_template_free(pseqval, seqtt);
                 continue;
             }
             /* Update length */
@@ -397,12 +437,12 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
 
         /* Check for EOC if expecting one */
         if (seq_eoc && !asn1_check_eoc(&p, len)) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
             goto err;
         }
         /* Check all data read */
         if (!seq_nolen && len) {
-            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
             goto err;
         }
 
@@ -413,21 +453,21 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
          */
         for (; i < it->tcount; tt++, i++) {
             const ASN1_TEMPLATE *seqtt;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            seqtt = ossl_asn1_do_adb(*pval, tt, 1);
             if (seqtt == NULL)
                 goto err;
             if (seqtt->flags & ASN1_TFLG_OPTIONAL) {
                 ASN1_VALUE **pseqval;
-                pseqval = asn1_get_field_ptr(pval, seqtt);
-                asn1_template_free(pseqval, seqtt);
+                pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+                ossl_asn1_template_free(pseqval, seqtt);
             } else {
                 errtt = seqtt;
-                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_FIELD_MISSING);
                 goto err;
             }
         }
         /* Save encoding */
-        if (!asn1_enc_save(pval, *in, p - *in, it))
+        if (!ossl_asn1_enc_save(pval, *in, p - *in, it))
             goto auxerr;
         if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
             goto auxerr;
@@ -438,7 +478,7 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
         return 0;
     }
  auxerr:
-    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR);
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR);
  err:
     if (errtt)
         ERR_add_error_data(4, "Field=", errtt->field_name,
@@ -456,7 +496,8 @@ static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in,
 static int asn1_template_ex_d2i(ASN1_VALUE **val,
                                 const unsigned char **in, long inlen,
                                 const ASN1_TEMPLATE *tt, char opt,
-                                ASN1_TLC *ctx, int depth)
+                                ASN1_TLC *ctx, int depth,
+                                OSSL_LIB_CTX *libctx, const char *propq)
 {
     int flags, aclass;
     int ret;
@@ -481,19 +522,19 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
                               &p, inlen, tt->tag, aclass, opt, ctx);
         q = p;
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         } else if (ret == -1)
             return -1;
         if (!cst) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
-                    ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
             return 0;
         }
         /* We've found the field so it can't be OPTIONAL now */
-        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth);
+        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth, libctx,
+                                      propq);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         }
         /* We read the field in OK so update length */
@@ -501,7 +542,7 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
         if (exp_eoc) {
             /* If NDEF we must have an EOC here */
             if (!asn1_check_eoc(&p, len)) {
-                ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
                 goto err;
             }
         } else {
@@ -509,13 +550,13 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
              * Otherwise we must hit the EXPLICIT tag end or its an error
              */
             if (len) {
-                ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I,
-                        ASN1_R_EXPLICIT_LENGTH_MISMATCH);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
                 goto err;
             }
         }
     } else
-        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth);
+        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth,
+                                       libctx, propq);
 
     *in = p;
     return 1;
@@ -527,7 +568,8 @@ static int asn1_template_ex_d2i(ASN1_VALUE **val,
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
                                    const unsigned char **in, long len,
                                    const ASN1_TEMPLATE *tt, char opt,
-                                   ASN1_TLC *ctx, int depth)
+                                   ASN1_TLC *ctx, int depth,
+                                   OSSL_LIB_CTX *libctx, const char *propq)
 {
     int flags, aclass;
     int ret;
@@ -539,7 +581,6 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
     aclass = flags & ASN1_TFLG_TAG_CLASS;
 
     p = *in;
-    q = p;
 
     /*
      * If field is embedded then val needs fixing so it is a pointer to
@@ -569,11 +610,11 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
         ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
                               &p, len, sktag, skaclass, opt, ctx);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         } else if (ret == -1)
             return -1;
-        if (!*val)
+        if (*val == NULL)
             *val = (ASN1_VALUE *)sk_ASN1_VALUE_new_null();
         else {
             /*
@@ -587,8 +628,8 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
             }
         }
 
-        if (!*val) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE);
+        if (*val == NULL) {
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto err;
         }
 
@@ -599,8 +640,7 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
             /* See if EOC found */
             if (asn1_check_eoc(&p, len)) {
                 if (!sk_eoc) {
-                    ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
-                            ASN1_R_UNEXPECTED_EOC);
+                    ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
                     goto err;
                 }
                 len -= p - q;
@@ -608,42 +648,41 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val,
                 break;
             }
             skfield = NULL;
-            if (!asn1_item_embed_d2i(&skfield, &p, len,
+            if (asn1_item_embed_d2i(&skfield, &p, len,
                                      ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx,
-                                     depth)) {
-                ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I,
-                        ERR_R_NESTED_ASN1_ERROR);
+                                     depth, libctx, propq) <= 0) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
                 /* |skfield| may be partially allocated despite failure. */
                 ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item));
                 goto err;
             }
             len -= p - q;
             if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
-                ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item));
                 goto err;
             }
         }
         if (sk_eoc) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
             goto err;
         }
     } else if (flags & ASN1_TFLG_IMPTAG) {
         /* IMPLICIT tagging */
         ret = asn1_item_embed_d2i(val, &p, len,
                                   ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt,
-                                  ctx, depth);
+                                  ctx, depth, libctx, propq);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         } else if (ret == -1)
             return -1;
     } else {
         /* Nothing special */
         ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
-                                  -1, 0, opt, ctx, depth);
+                                  -1, 0, opt, ctx, depth, libctx, propq);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             goto err;
         } else if (ret == -1)
             return -1;
@@ -668,8 +707,9 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
     BUF_MEM buf = { 0, NULL, 0, 0 };
     const unsigned char *cont = NULL;
     long len;
-    if (!pval) {
-        ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL);
+
+    if (pval == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NULL);
         return 0;               /* Should never happen */
     }
 
@@ -683,19 +723,18 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
         /* If type is ANY need to figure out type from tag */
         unsigned char oclass;
         if (tag >= 0) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
             return 0;
         }
         if (opt) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
-                    ASN1_R_ILLEGAL_OPTIONAL_ANY);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
             return 0;
         }
         p = *in;
         ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
                               &p, inlen, -1, 0, 0, ctx);
         if (!ret) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         }
         if (oclass != V_ASN1_UNIVERSAL)
@@ -710,7 +749,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
     ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
                           &p, inlen, tag, aclass, opt, ctx);
     if (!ret) {
-        ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
         return 0;
     } else if (ret == -1)
         return -1;
@@ -727,8 +766,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
         }
         /* SEQUENCE and SET must be constructed */
         else if (!cst) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE,
-                    ASN1_R_TYPE_NOT_CONSTRUCTED);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
             return 0;
         }
 
@@ -746,7 +784,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
         if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
             || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
             || utype == V_ASN1_ENUMERATED) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
             return 0;
         }
 
@@ -764,7 +802,7 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
         len = buf.length;
         /* Append a final null to string */
         if (!BUF_MEM_grow_clean(&buf, len + 1)) {
-            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             goto err;
         }
         buf.data[len] = 0;
@@ -805,7 +843,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
         return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
     /* If ANY type clear type and set pointer to internal value */
     if (it->utype == V_ASN1_ANY) {
-        if (!*pval) {
+        if (*pval == NULL) {
             typ = ASN1_TYPE_new();
             if (typ == NULL)
                 goto err;
@@ -820,13 +858,13 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     }
     switch (utype) {
     case V_ASN1_OBJECT:
-        if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
+        if (!ossl_c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
             goto err;
         break;
 
     case V_ASN1_NULL:
         if (len) {
-            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
             goto err;
         }
         *pval = (ASN1_VALUE *)1;
@@ -834,7 +872,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
 
     case V_ASN1_BOOLEAN:
         if (len != 1) {
-            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
             goto err;
         } else {
             ASN1_BOOLEAN *tbool;
@@ -844,14 +882,14 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
         break;
 
     case V_ASN1_BIT_STRING:
-        if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
+        if (!ossl_c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
             goto err;
         break;
 
     case V_ASN1_INTEGER:
     case V_ASN1_ENUMERATED:
         tint = (ASN1_INTEGER **)pval;
-        if (!c2i_ASN1_INTEGER(tint, &cont, len))
+        if (!ossl_c2i_ASN1_INTEGER(tint, &cont, len))
             goto err;
         /* Fixup type to match the expected form */
         (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
@@ -876,19 +914,18 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     case V_ASN1_SEQUENCE:
     default:
         if (utype == V_ASN1_BMPSTRING && (len & 1)) {
-            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
             goto err;
         }
         if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) {
-            ASN1err(ASN1_F_ASN1_EX_C2I,
-                    ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
             goto err;
         }
         /* All based on ASN1_STRING and handled the same */
-        if (!*pval) {
+        if (*pval == NULL) {
             stmp = ASN1_STRING_type_new(utype);
             if (stmp == NULL) {
-                ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
             *pval = (ASN1_VALUE *)stmp;
@@ -904,7 +941,7 @@ static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
             *free_cont = 0;
         } else {
             if (!ASN1_STRING_set(stmp, cont, len)) {
-                ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 ASN1_STRING_free(stmp);
                 *pval = NULL;
                 goto err;
@@ -962,12 +999,12 @@ static int asn1_find_end(const unsigned char **in, long len, char inf)
         /* Just read in a header: only care about the length */
         if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
                              -1, 0, 0, NULL)) {
-            ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         }
         if (inf) {
             if (expected_eoc == UINT32_MAX) {
-                ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR);
+                ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
                 return 0;
             }
             expected_eoc++;
@@ -977,7 +1014,7 @@ static int asn1_find_end(const unsigned char **in, long len, char inf)
         len -= p - q;
     }
     if (expected_eoc) {
-        ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
         return 0;
     }
     *in = p;
@@ -1024,7 +1061,7 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
              * EOC is illegal outside indefinite length constructed form
              */
             if (!inf) {
-                ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_UNEXPECTED_EOC);
                 return 0;
             }
             inf = 0;
@@ -1033,14 +1070,14 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
 
         if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
                              len, tag, aclass, 0, NULL)) {
-            ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_NESTED_ASN1_ERROR);
             return 0;
         }
 
         /* If indefinite length constructed update max length */
         if (cst) {
             if (depth >= ASN1_MAX_STRING_NEST) {
-                ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING);
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_NESTED_ASN1_STRING);
                 return 0;
             }
             if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1))
@@ -1050,7 +1087,7 @@ static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
         len -= p - q;
     }
     if (inf) {
-        ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_MISSING_EOC);
         return 0;
     }
     *in = p;
@@ -1063,7 +1100,7 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
     if (buf) {
         len = buf->length;
         if (!BUF_MEM_grow_clean(buf, len + plen)) {
-            ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         memcpy(buf->data + len, *p, plen);
@@ -1077,10 +1114,11 @@ static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
 static int asn1_check_eoc(const unsigned char **in, long len)
 {
     const unsigned char *p;
+
     if (len < 2)
         return 0;
     p = *in;
-    if (!p[0] && !p[1]) {
+    if (p[0] == '\0' && p[1] == '\0') {
         *in += 2;
         return 1;
     }
@@ -1106,7 +1144,11 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
     p = *in;
     q = p;
 
-    if (ctx && ctx->valid) {
+    if (len <= 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
+        goto err;
+    }
+    if (ctx != NULL && ctx->valid) {
         i = ctx->ret;
         plen = ctx->plen;
         pclass = ctx->pclass;
@@ -1114,7 +1156,7 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
         p += ctx->hdrlen;
     } else {
         i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
-        if (ctx) {
+        if (ctx != NULL) {
             ctx->ret = i;
             ctx->plen = plen;
             ctx->pclass = pclass;
@@ -1125,29 +1167,26 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
              * If definite length, and no error, length + header can't exceed
              * total amount of data available.
              */
-            if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {
-                ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG);
-                asn1_tlc_clear(ctx);
-                return 0;
+            if ((i & 0x81) == 0 && (plen + ctx->hdrlen) > len) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LONG);
+                goto err;
             }
         }
     }
 
-    if (i & 0x80) {
-        ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER);
-        asn1_tlc_clear(ctx);
-        return 0;
+    if ((i & 0x80) != 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_OBJECT_HEADER);
+        goto err;
     }
     if (exptag >= 0) {
-        if ((exptag != ptag) || (expclass != pclass)) {
+        if (exptag != ptag || expclass != pclass) {
             /*
              * If type is OPTIONAL, not an error: indicate missing type.
              */
-            if (opt)
+            if (opt != 0)
                 return -1;
-            asn1_tlc_clear(ctx);
-            ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG);
-            return 0;
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_WRONG_TAG);
+            goto err;
         }
         /*
          * We have a tag and class match: assume we are going to do something
@@ -1156,24 +1195,28 @@ static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
         asn1_tlc_clear(ctx);
     }
 
-    if (i & 1)
+    if ((i & 1) != 0)
         plen = len - (p - q);
 
-    if (inf)
+    if (inf != NULL)
         *inf = i & 1;
 
-    if (cst)
+    if (cst != NULL)
         *cst = i & V_ASN1_CONSTRUCTED;
 
-    if (olen)
+    if (olen != NULL)
         *olen = plen;
 
-    if (oclass)
+    if (oclass != NULL)
         *oclass = pclass;
 
-    if (otag)
+    if (otag != NULL)
         *otag = ptag;
 
     *in = p;
     return 1;
+
+ err:
+    asn1_tlc_clear(ctx);
+    return 0;
 }

+ 93 - 72
libs/openssl/crypto/asn1/tasn_enc.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -16,16 +16,17 @@
 #include "crypto/asn1.h"
 #include "asn1_local.h"
 
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
                                  const ASN1_ITEM *it, int tag, int aclass);
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+                            unsigned char **out,
                             int skcontlen, const ASN1_ITEM *item,
                             int do_sort, int iclass);
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                                 const ASN1_TEMPLATE *tt, int tag, int aclass);
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
                                const ASN1_ITEM *it, int flags);
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
                        const ASN1_ITEM *it);
 
 /*
@@ -33,13 +34,13 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
  * indefinite length constructed encoding, where appropriate
  */
 
-int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
+int ASN1_item_ndef_i2d(const ASN1_VALUE *val, unsigned char **out,
                        const ASN1_ITEM *it)
 {
     return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
 }
 
-int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
+int ASN1_item_i2d(const ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
 {
     return asn1_item_flags_i2d(val, out, it, 0);
 }
@@ -51,10 +52,10 @@ int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
  * allocated and populated with the encoding.
  */
 
-static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
+static int asn1_item_flags_i2d(const ASN1_VALUE *val, unsigned char **out,
                                const ASN1_ITEM *it, int flags)
 {
-    if (out && !*out) {
+    if (out != NULL && *out == NULL) {
         unsigned char *p, *buf;
         int len;
 
@@ -62,7 +63,7 @@ static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
         if (len <= 0)
             return len;
         if ((buf = OPENSSL_malloc(len)) == NULL) {
-            ASN1err(ASN1_F_ASN1_ITEM_FLAGS_I2D, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         p = buf;
@@ -79,20 +80,22 @@ static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
  * performs the normal item handling: it can be used in external types.
  */
 
-int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+int ASN1_item_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                      const ASN1_ITEM *it, int tag, int aclass)
 {
     const ASN1_TEMPLATE *tt = NULL;
     int i, seqcontlen, seqlen, ndef = 1;
     const ASN1_EXTERN_FUNCS *ef;
     const ASN1_AUX *aux = it->funcs;
-    ASN1_aux_cb *asn1_cb = 0;
+    ASN1_aux_const_cb *asn1_cb = NULL;
 
-    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
         return 0;
 
-    if (aux && aux->asn1_cb)
-        asn1_cb = aux->asn1_cb;
+    if (aux != NULL) {
+        asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
+            : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
+    }
 
     switch (it->itype) {
 
@@ -108,7 +111,7 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
          * if tag != -1, then this looks like an error in the template.
          */
         if (tag != -1) {
-            ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
             return -1;
         }
         return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
@@ -119,17 +122,17 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
          * if tag != -1, then this looks like an error in the template.
          */
         if (tag != -1) {
-            ASN1err(ASN1_F_ASN1_ITEM_EX_I2D, ASN1_R_BAD_TEMPLATE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_BAD_TEMPLATE);
             return -1;
         }
         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
             return 0;
-        i = asn1_get_choice_selector(pval, it);
+        i = ossl_asn1_get_choice_selector_const(pval, it);
         if ((i >= 0) && (i < it->tcount)) {
-            ASN1_VALUE **pchval;
+            const ASN1_VALUE **pchval;
             const ASN1_TEMPLATE *chtt;
             chtt = it->templates + i;
-            pchval = asn1_get_field_ptr(pval, chtt);
+            pchval = ossl_asn1_get_const_field_ptr(pval, chtt);
             return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
         }
         /* Fixme: error condition if selector out of range */
@@ -149,7 +152,7 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         /* fall through */
 
     case ASN1_ITYPE_SEQUENCE:
-        i = asn1_enc_restore(&seqcontlen, out, pval, it);
+        i = ossl_asn1_enc_restore(&seqcontlen, out, pval, it);
         /* An error occurred */
         if (i < 0)
             return 0;
@@ -170,12 +173,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         /* First work out sequence content length */
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
             const ASN1_TEMPLATE *seqtt;
-            ASN1_VALUE **pseqval;
+            const ASN1_VALUE **pseqval;
             int tmplen;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            seqtt = ossl_asn1_do_adb(*pval, tt, 1);
             if (!seqtt)
                 return 0;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
+            pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
             tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
             if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
                 return -1;
@@ -189,11 +192,11 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
             const ASN1_TEMPLATE *seqtt;
-            ASN1_VALUE **pseqval;
-            seqtt = asn1_do_adb(pval, tt, 1);
+            const ASN1_VALUE **pseqval;
+            seqtt = ossl_asn1_do_adb(*pval, tt, 1);
             if (!seqtt)
                 return 0;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
+            pseqval = ossl_asn1_get_const_field_ptr(pval, seqtt);
             /* FIXME: check for errors in enhanced version */
             asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
         }
@@ -210,12 +213,12 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     return 0;
 }
 
-static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_template_ex_i2d(const ASN1_VALUE **pval, unsigned char **out,
                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
 {
-    int i, ret, flags, ttag, tclass, ndef;
-    ASN1_VALUE *tval;
-    flags = tt->flags;
+    const int flags = tt->flags;
+    int i, ret, ttag, tclass, ndef, len;
+    const ASN1_VALUE *tval;
 
     /*
      * If field is embedded then val needs fixing so it is a pointer to
@@ -266,12 +269,12 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 
     if (flags & ASN1_TFLG_SK_MASK) {
         /* SET OF, SEQUENCE OF */
-        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+        STACK_OF(const_ASN1_VALUE) *sk = (STACK_OF(const_ASN1_VALUE) *)*pval;
         int isset, sktag, skaclass;
         int skcontlen, sklen;
-        ASN1_VALUE *skitem;
+        const ASN1_VALUE *skitem;
 
-        if (!*pval)
+        if (*pval == NULL)
             return 0;
 
         if (flags & ASN1_TFLG_SET_OF) {
@@ -299,14 +302,17 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 
         /* Determine total length of items */
         skcontlen = 0;
-        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
-            int tmplen;
-            skitem = sk_ASN1_VALUE_value(sk, i);
-            tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
-                                      -1, iclass);
-            if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
+        for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
+            skitem = sk_const_ASN1_VALUE_value(sk, i);
+            len = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
+                                   -1, iclass);
+            if (len == -1 || (skcontlen > INT_MAX - len))
                 return -1;
-            skcontlen += tmplen;
+            if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+                return -1;
+            }
+            skcontlen += len;
         }
         sklen = ASN1_object_size(ndef, skcontlen, sktag);
         if (sklen == -1)
@@ -342,8 +348,13 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
         /* EXPLICIT tagging */
         /* Find length of tagged item */
         i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
-        if (!i)
+        if (i == 0) {
+            if ((tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+                ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+                return -1;
+            }
             return 0;
+        }
         /* Find length of EXPLICIT tag */
         ret = ASN1_object_size(ndef, i, ttag);
         if (out && ret != -1) {
@@ -357,9 +368,13 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     }
 
     /* Either normal or IMPLICIT tagging: combine class and flags */
-    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
-                            ttag, tclass | iclass);
-
+    len = ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
+                              ttag, tclass | iclass);
+    if (len == 0 && (tt->flags & ASN1_TFLG_OPTIONAL) == 0) {
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_ZERO_CONTENT);
+        return -1;
+    }
+    return len;
 }
 
 /* Temporary structure used to hold DER encoding of items for SET OF */
@@ -367,7 +382,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
 typedef struct {
     unsigned char *data;
     int length;
-    ASN1_VALUE *field;
+    const ASN1_VALUE *field;
 } DER_ENC;
 
 static int der_cmp(const void *a, const void *b)
@@ -383,34 +398,38 @@ static int der_cmp(const void *a, const void *b)
 
 /* Output the content octets of SET OF or SEQUENCE OF */
 
-static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
+static int asn1_set_seq_out(STACK_OF(const_ASN1_VALUE) *sk,
+                            unsigned char **out,
                             int skcontlen, const ASN1_ITEM *item,
                             int do_sort, int iclass)
 {
-    int i;
-    ASN1_VALUE *skitem;
+    int i, ret = 0;
+    const ASN1_VALUE *skitem;
     unsigned char *tmpdat = NULL, *p = NULL;
     DER_ENC *derlst = NULL, *tder;
+
     if (do_sort) {
         /* Don't need to sort less than 2 items */
-        if (sk_ASN1_VALUE_num(sk) < 2)
+        if (sk_const_ASN1_VALUE_num(sk) < 2)
             do_sort = 0;
         else {
-            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+            derlst = OPENSSL_malloc(sk_const_ASN1_VALUE_num(sk)
                                     * sizeof(*derlst));
-            if (derlst == NULL)
+            if (derlst == NULL) {
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
                 return 0;
+            }
             tmpdat = OPENSSL_malloc(skcontlen);
             if (tmpdat == NULL) {
-                OPENSSL_free(derlst);
-                return 0;
+                ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
+                goto err;
             }
         }
     }
     /* If not sorting just output each item */
     if (!do_sort) {
-        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
-            skitem = sk_ASN1_VALUE_value(sk, i);
+        for (i = 0; i < sk_const_ASN1_VALUE_num(sk); i++) {
+            skitem = sk_const_ASN1_VALUE_value(sk, i);
             ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
         }
         return 1;
@@ -418,33 +437,35 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
     p = tmpdat;
 
     /* Doing sort: build up a list of each member's DER encoding */
-    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
-        skitem = sk_ASN1_VALUE_value(sk, i);
+    for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
+        skitem = sk_const_ASN1_VALUE_value(sk, i);
         tder->data = p;
         tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
         tder->field = skitem;
     }
 
     /* Now sort them */
-    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
+    qsort(derlst, sk_const_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
     /* Output sorted DER encoding */
     p = *out;
-    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+    for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++) {
         memcpy(p, tder->data, tder->length);
         p += tder->length;
     }
     *out = p;
     /* If do_sort is 2 then reorder the STACK */
     if (do_sort == 2) {
-        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
-            (void)sk_ASN1_VALUE_set(sk, i, tder->field);
+        for (i = 0, tder = derlst; i < sk_const_ASN1_VALUE_num(sk); i++, tder++)
+            (void)sk_const_ASN1_VALUE_set(sk, i, tder->field);
     }
+    ret = 1;
+err:
     OPENSSL_free(derlst);
     OPENSSL_free(tmpdat);
-    return 1;
+    return ret;
 }
 
-static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+static int asn1_i2d_ex_primitive(const ASN1_VALUE **pval, unsigned char **out,
                                  const ASN1_ITEM *it, int tag, int aclass)
 {
     int len;
@@ -504,7 +525,7 @@ static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
 
 /* Produce content octets from a structure */
 
-static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+static int asn1_ex_i2c(const ASN1_VALUE **pval, unsigned char *cout, int *putype,
                        const ASN1_ITEM *it)
 {
     ASN1_BOOLEAN *tbool = NULL;
@@ -522,7 +543,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
     /* Should type be omitted? */
     if ((it->itype != ASN1_ITYPE_PRIMITIVE)
         || (it->utype != V_ASN1_BOOLEAN)) {
-        if (!*pval)
+        if (*pval == NULL)
             return -1;
     }
 
@@ -537,7 +558,7 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
         typ = (ASN1_TYPE *)*pval;
         utype = typ->type;
         *putype = utype;
-        pval = &typ->value.asn1_value;
+        pval = (const ASN1_VALUE **)&typ->value.asn1_value; /* actually is const */
     } else
         utype = *putype;
 
@@ -574,15 +595,15 @@ static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
         break;
 
     case V_ASN1_BIT_STRING:
-        return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
-                                   cout ? &cout : NULL);
+        return ossl_i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+                                        cout ? &cout : NULL);
 
     case V_ASN1_INTEGER:
     case V_ASN1_ENUMERATED:
         /*
          * These are all have the same content format as ASN1_INTEGER
          */
-        return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
+        return ossl_i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
 
     case V_ASN1_OCTET_STRING:
     case V_ASN1_NUMERICSTRING:

+ 27 - 27
libs/openssl/crypto/asn1/tasn_fre.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -17,15 +17,15 @@
 
 void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
 {
-    asn1_item_embed_free(&val, it, 0);
+    ossl_asn1_item_embed_free(&val, it, 0);
 }
 
 void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
-    asn1_item_embed_free(pval, it, 0);
+    ossl_asn1_item_embed_free(pval, it, 0);
 }
 
-void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+void ossl_asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 {
     const ASN1_TEMPLATE *tt = NULL, *seqtt;
     const ASN1_EXTERN_FUNCS *ef;
@@ -33,9 +33,9 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
     ASN1_aux_cb *asn1_cb;
     int i;
 
-    if (!pval)
+    if (pval == NULL)
         return;
-    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && *pval == NULL)
         return;
     if (aux && aux->asn1_cb)
         asn1_cb = aux->asn1_cb;
@@ -46,13 +46,13 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 
     case ASN1_ITYPE_PRIMITIVE:
         if (it->templates)
-            asn1_template_free(pval, it->templates);
+            ossl_asn1_template_free(pval, it->templates);
         else
-            asn1_primitive_free(pval, it, embed);
+            ossl_asn1_primitive_free(pval, it, embed);
         break;
 
     case ASN1_ITYPE_MSTRING:
-        asn1_primitive_free(pval, it, embed);
+        ossl_asn1_primitive_free(pval, it, embed);
         break;
 
     case ASN1_ITYPE_CHOICE:
@@ -61,13 +61,13 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             if (i == 2)
                 return;
         }
-        i = asn1_get_choice_selector(pval, it);
+        i = ossl_asn1_get_choice_selector(pval, it);
         if ((i >= 0) && (i < it->tcount)) {
             ASN1_VALUE **pchval;
 
             tt = it->templates + i;
-            pchval = asn1_get_field_ptr(pval, tt);
-            asn1_template_free(pchval, tt);
+            pchval = ossl_asn1_get_field_ptr(pval, tt);
+            ossl_asn1_template_free(pchval, tt);
         }
         if (asn1_cb)
             asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
@@ -85,14 +85,14 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 
     case ASN1_ITYPE_NDEF_SEQUENCE:
     case ASN1_ITYPE_SEQUENCE:
-        if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
+        if (ossl_asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */
             return;
         if (asn1_cb) {
             i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
             if (i == 2)
                 return;
         }
-        asn1_enc_free(pval, it);
+        ossl_asn1_enc_free(pval, it);
         /*
          * If we free up as normal we will invalidate any ANY DEFINED BY
          * field and we won't be able to determine the type of the field it
@@ -103,11 +103,11 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             ASN1_VALUE **pseqval;
 
             tt--;
-            seqtt = asn1_do_adb(pval, tt, 0);
+            seqtt = ossl_asn1_do_adb(*pval, tt, 0);
             if (!seqtt)
                 continue;
-            pseqval = asn1_get_field_ptr(pval, seqtt);
-            asn1_template_free(pseqval, seqtt);
+            pseqval = ossl_asn1_get_field_ptr(pval, seqtt);
+            ossl_asn1_template_free(pseqval, seqtt);
         }
         if (asn1_cb)
             asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
@@ -119,7 +119,7 @@ void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
     }
 }
 
-void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+void ossl_asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
 {
     int embed = tt->flags & ASN1_TFLG_EMBED;
     ASN1_VALUE *tval;
@@ -134,16 +134,16 @@ void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
         for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
             ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i);
 
-            asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
+            ossl_asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed);
         }
         sk_ASN1_VALUE_free(sk);
         *pval = NULL;
     } else {
-        asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
+        ossl_asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed);
     }
 }
 
-void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+void ossl_asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 {
     int utype;
 
@@ -168,15 +168,15 @@ void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
 
         utype = typ->type;
         pval = &typ->value.asn1_value;
-        if (!*pval)
+        if (*pval == NULL)
             return;
     } else if (it->itype == ASN1_ITYPE_MSTRING) {
         utype = -1;
-        if (!*pval)
+        if (*pval == NULL)
             return;
     } else {
         utype = it->utype;
-        if ((utype != V_ASN1_BOOLEAN) && !*pval)
+        if ((utype != V_ASN1_BOOLEAN) && *pval == NULL)
             return;
     }
 
@@ -196,12 +196,12 @@ void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
         break;
 
     case V_ASN1_ANY:
-        asn1_primitive_free(pval, NULL, 0);
+        ossl_asn1_primitive_free(pval, NULL, 0);
         OPENSSL_free(*pval);
         break;
 
     default:
-        asn1_string_embed_free((ASN1_STRING *)*pval, embed);
+        ossl_asn1_string_embed_free((ASN1_STRING *)*pval, embed);
         break;
     }
     *pval = NULL;

+ 48 - 49
libs/openssl/crypto/asn1/tasn_new.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -16,11 +16,13 @@
 #include "asn1_local.h"
 
 static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
-                               int embed);
+                               int embed, OSSL_LIB_CTX *libctx,
+                               const char *propq);
 static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
                               int embed);
 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
+                             OSSL_LIB_CTX *libctx, const char *propq);
 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
 
@@ -32,14 +34,31 @@ ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
     return NULL;
 }
 
+ASN1_VALUE *ASN1_item_new_ex(const ASN1_ITEM *it, OSSL_LIB_CTX *libctx,
+                             const char *propq)
+{
+    ASN1_VALUE *ret = NULL;
+    if (asn1_item_embed_new(&ret, it, 0, libctx, propq) > 0)
+        return ret;
+    return NULL;
+}
+
 /* Allocate an ASN1 structure */
 
+
+int ossl_asn1_item_ex_new_intern(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                 OSSL_LIB_CTX *libctx, const char *propq)
+{
+    return asn1_item_embed_new(pval, it, 0, libctx, propq);
+}
+
 int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
-    return asn1_item_embed_new(pval, it, 0);
+    return asn1_item_embed_new(pval, it, 0, NULL, NULL);
 }
 
-int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
+int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed,
+                        OSSL_LIB_CTX *libctx, const char *propq)
 {
     const ASN1_TEMPLATE *tt = NULL;
     const ASN1_EXTERN_FUNCS *ef;
@@ -52,23 +71,24 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
     else
         asn1_cb = 0;
 
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new");
-#endif
-
     switch (it->itype) {
 
     case ASN1_ITYPE_EXTERN:
         ef = it->funcs;
-        if (ef && ef->asn1_ex_new) {
-            if (!ef->asn1_ex_new(pval, it))
-                goto memerr;
+        if (ef != NULL) {
+            if (ef->asn1_ex_new_ex != NULL) {
+                if (!ef->asn1_ex_new_ex(pval, it, libctx, propq))
+                    goto memerr;
+            } else if (ef->asn1_ex_new != NULL) {
+                if (!ef->asn1_ex_new(pval, it))
+                    goto memerr;
+            }
         }
         break;
 
     case ASN1_ITYPE_PRIMITIVE:
         if (it->templates) {
-            if (!asn1_template_new(pval, it->templates))
+            if (!asn1_template_new(pval, it->templates, libctx, propq))
                 goto memerr;
         } else if (!asn1_primitive_new(pval, it, embed))
             goto memerr;
@@ -85,9 +105,6 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             if (!i)
                 goto auxerr;
             if (i == 2) {
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-                OPENSSL_mem_debug_pop();
-#endif
                 return 1;
             }
         }
@@ -98,7 +115,7 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             if (*pval == NULL)
                 goto memerr;
         }
-        asn1_set_choice_selector(pval, -1, it);
+        ossl_asn1_set_choice_selector(pval, -1, it);
         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
             goto auxerr2;
         break;
@@ -110,9 +127,6 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
             if (!i)
                 goto auxerr;
             if (i == 2) {
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-                OPENSSL_mem_debug_pop();
-#endif
                 return 1;
             }
         }
@@ -124,44 +138,35 @@ int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed)
                 goto memerr;
         }
         /* 0 : init. lock */
-        if (asn1_do_lock(pval, 0, it) < 0) {
+        if (ossl_asn1_do_lock(pval, 0, it) < 0) {
             if (!embed) {
                 OPENSSL_free(*pval);
                 *pval = NULL;
             }
             goto memerr;
         }
-        asn1_enc_init(pval, it);
+        ossl_asn1_enc_init(pval, it);
         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
-            pseqval = asn1_get_field_ptr(pval, tt);
-            if (!asn1_template_new(pseqval, tt))
+            pseqval = ossl_asn1_get_field_ptr(pval, tt);
+            if (!asn1_template_new(pseqval, tt, libctx, propq))
                 goto memerr2;
         }
         if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
             goto auxerr2;
         break;
     }
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_pop();
-#endif
     return 1;
 
  memerr2:
-    asn1_item_embed_free(pval, it, embed);
+    ossl_asn1_item_embed_free(pval, it, embed);
  memerr:
-    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE);
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_pop();
-#endif
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
     return 0;
 
  auxerr2:
-    asn1_item_embed_free(pval, it, embed);
+    ossl_asn1_item_embed_free(pval, it, embed);
  auxerr:
-    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR);
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_pop();
-#endif
+    ERR_raise(ERR_LIB_ASN1, ASN1_R_AUX_ERROR);
     return 0;
 
 }
@@ -199,7 +204,8 @@ static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
     }
 }
 
-static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
+                             OSSL_LIB_CTX *libctx, const char *propq)
 {
     const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
     int embed = tt->flags & ASN1_TFLG_EMBED;
@@ -219,16 +225,12 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
         *pval = NULL;
         return 1;
     }
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_push(tt->field_name
-            ? tt->field_name : "asn1_template_new");
-#endif
     /* If SET OF or SEQUENCE OF, its a STACK */
     if (tt->flags & ASN1_TFLG_SK_MASK) {
         STACK_OF(ASN1_VALUE) *skval;
         skval = sk_ASN1_VALUE_new_null();
         if (!skval) {
-            ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             ret = 0;
             goto done;
         }
@@ -237,11 +239,8 @@ static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
         goto done;
     }
     /* Otherwise pass it back to the item routine */
-    ret = asn1_item_embed_new(pval, it, embed);
+    ret = asn1_item_embed_new(pval, it, embed, libctx, propq);
  done:
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    OPENSSL_mem_debug_pop();
-#endif
     return ret;
 }
 
@@ -300,7 +299,7 @@ static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
 
     case V_ASN1_ANY:
         if ((typ = OPENSSL_malloc(sizeof(*typ))) == NULL) {
-            ASN1err(ASN1_F_ASN1_PRIMITIVE_NEW, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         typ->value.ptr = NULL;

+ 29 - 29
libs/openssl/crypto/asn1/tasn_prn.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -38,7 +38,7 @@ ASN1_PCTX *ASN1_PCTX_new(void)
 
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-        ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     return ret;
@@ -101,15 +101,15 @@ void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
 
 /* Main print routines */
 
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
                                const ASN1_ITEM *it,
                                const char *fname, const char *sname,
                                int nohdr, const ASN1_PCTX *pctx);
 
-static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
                             const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
 
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
+static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld,
                                 const ASN1_ITEM *it, int indent,
                                 const char *fname, const char *sname,
                                 const ASN1_PCTX *pctx);
@@ -118,7 +118,7 @@ static int asn1_print_fsname(BIO *out, int indent,
                              const char *fname, const char *sname,
                              const ASN1_PCTX *pctx);
 
-int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
+int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent,
                     const ASN1_ITEM *it, const ASN1_PCTX *pctx)
 {
     const char *sname;
@@ -131,25 +131,25 @@ int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
     return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx);
 }
 
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
                                const ASN1_ITEM *it,
                                const char *fname, const char *sname,
                                int nohdr, const ASN1_PCTX *pctx)
 {
     const ASN1_TEMPLATE *tt;
     const ASN1_EXTERN_FUNCS *ef;
-    ASN1_VALUE **tmpfld;
+    const ASN1_VALUE **tmpfld;
     const ASN1_AUX *aux = it->funcs;
-    ASN1_aux_cb *asn1_cb;
+    ASN1_aux_const_cb *asn1_cb = NULL;
     ASN1_PRINT_ARG parg;
     int i;
-    if (aux && aux->asn1_cb) {
+    if (aux != NULL) {
         parg.out = out;
         parg.indent = indent;
         parg.pctx = pctx;
-        asn1_cb = aux->asn1_cb;
-    } else
-        asn1_cb = 0;
+        asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb
+            : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */
+    }
 
    if (((it->itype != ASN1_ITYPE_PRIMITIVE)
        || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) {
@@ -195,7 +195,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
 
     case ASN1_ITYPE_CHOICE:
         /* CHOICE type, get selector */
-        i = asn1_get_choice_selector(fld, it);
+        i = ossl_asn1_get_choice_selector_const(fld, it);
         /* This should never happen... */
         if ((i < 0) || (i >= it->tcount)) {
             if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0)
@@ -203,7 +203,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
             return 1;
         }
         tt = it->templates + i;
-        tmpfld = asn1_get_field_ptr(fld, tt);
+        tmpfld = ossl_asn1_get_const_field_ptr(fld, tt);
         if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
             return 0;
         break;
@@ -233,10 +233,10 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
         /* Print each field entry */
         for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
             const ASN1_TEMPLATE *seqtt;
-            seqtt = asn1_do_adb(fld, tt, 1);
+            seqtt = ossl_asn1_do_adb(*fld, tt, 1);
             if (!seqtt)
                 return 0;
-            tmpfld = asn1_get_field_ptr(fld, seqtt);
+            tmpfld = ossl_asn1_get_const_field_ptr(fld, seqtt);
             if (!asn1_template_print_ctx(out, tmpfld,
                                          indent + 2, seqtt, pctx))
                 return 0;
@@ -261,12 +261,12 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
     return 1;
 }
 
-static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent,
                             const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
 {
     int i, flags;
     const char *sname, *fname;
-    ASN1_VALUE *tfld;
+    const ASN1_VALUE *tfld;
     flags = tt->flags;
     if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
         sname = ASN1_ITEM_ptr(tt->item)->sname;
@@ -282,14 +282,14 @@ static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
      * a pointer to a field.
      */
     if (flags & ASN1_TFLG_EMBED) {
-        tfld = (ASN1_VALUE *)fld;
+        tfld = (const ASN1_VALUE *)fld;
         fld = &tfld;
     }
 
     if (flags & ASN1_TFLG_SK_MASK) {
         char *tname;
-        ASN1_VALUE *skitem;
-        STACK_OF(ASN1_VALUE) *stack;
+        const ASN1_VALUE *skitem;
+        STACK_OF(const_ASN1_VALUE) *stack;
 
         /* SET OF, SEQUENCE OF */
         if (fname) {
@@ -304,12 +304,12 @@ static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
             } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0)
                 return 0;
         }
-        stack = (STACK_OF(ASN1_VALUE) *)*fld;
-        for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
+        stack = (STACK_OF(const_ASN1_VALUE) *)*fld;
+        for (i = 0; i < sk_const_ASN1_VALUE_num(stack); i++) {
             if ((i > 0) && (BIO_puts(out, "\n") <= 0))
                 return 0;
 
-            skitem = sk_ASN1_VALUE_value(stack, i);
+            skitem = sk_const_ASN1_VALUE_value(stack, i);
             if (!asn1_item_print_ctx(out, &skitem, indent + 2,
                                      ASN1_ITEM_ptr(tt->item), NULL, NULL, 1,
                                      pctx))
@@ -430,7 +430,7 @@ static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent)
     return 1;
 }
 
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
+static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld,
                                 const ASN1_ITEM *it, int indent,
                                 const char *fname, const char *sname,
                                 const ASN1_PCTX *pctx)
@@ -456,9 +456,9 @@ static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
             str = (ASN1_STRING *)*fld;
     }
     if (utype == V_ASN1_ANY) {
-        ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
+        const ASN1_TYPE *atype = (const ASN1_TYPE *)*fld;
         utype = atype->type;
-        fld = &atype->value.asn1_value;
+        fld = (const ASN1_VALUE **)&atype->value.asn1_value; /* actually is const */
         str = (ASN1_STRING *)*fld;
         if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
             pname = NULL;

+ 3 - 3
libs/openssl/crypto/asn1/tasn_typ.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -80,5 +80,5 @@ ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
         ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
 ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)

+ 78 - 45
libs/openssl/crypto/asn1/tasn_utl.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -26,9 +26,18 @@
  * Given an ASN1_ITEM CHOICE type return the selector value
  */
 
-int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
+int ossl_asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
     int *sel = offset2ptr(*pval, it->utype);
+
+    return *sel;
+}
+
+int ossl_asn1_get_choice_selector_const(const ASN1_VALUE **pval,
+                                        const ASN1_ITEM *it)
+{
+    int *sel = offset2ptr(*pval, it->utype);
+
     return *sel;
 }
 
@@ -36,10 +45,11 @@ int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
  * Given an ASN1_ITEM CHOICE type set the selector value, return old value.
  */
 
-int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
-                             const ASN1_ITEM *it)
+int ossl_asn1_set_choice_selector(ASN1_VALUE **pval, int value,
+                                  const ASN1_ITEM *it)
 {
     int *sel, ret;
+
     sel = offset2ptr(*pval, it->utype);
     ret = *sel;
     *sel = value;
@@ -55,7 +65,7 @@ int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
  * It returns -1 on initialisation error.
  * Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects
  */
-int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
+int ossl_asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
 {
     const ASN1_AUX *aux;
     CRYPTO_REF_COUNT *lck;
@@ -66,7 +76,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
         && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
         return 0;
     aux = it->funcs;
-    if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
+    if (aux == NULL || (aux->flags & ASN1_AFLG_REFCOUNT) == 0)
         return 0;
     lck = offset2ptr(*pval, aux->ref_offset);
     lock = offset2ptr(*pval, aux->ref_lock);
@@ -76,7 +86,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
         *lck = ret = 1;
         *lock = CRYPTO_THREAD_lock_new();
         if (*lock == NULL) {
-            ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE);
+            ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
             return -1;
         }
         break;
@@ -87,9 +97,7 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
     case -1:
         if (!CRYPTO_DOWN_REF(lck, &ret, *lock))
             return -1;  /* failed */
-#ifdef REF_PRINT
-        fprintf(stderr, "%p:%4d:%s\n", it, ret, it->sname);
-#endif
+        REF_PRINT_EX(it->sname, ret, (void *)it);
         REF_ASSERT_ISNT(ret < 0);
         if (ret == 0) {
             CRYPTO_THREAD_lock_free(*lock);
@@ -104,30 +112,44 @@ int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
 static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
     const ASN1_AUX *aux;
-    if (!pval || !*pval)
+
+    if (pval == NULL || *pval == NULL)
+        return NULL;
+    aux = it->funcs;
+    if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0)
+        return NULL;
+    return offset2ptr(*pval, aux->enc_offset);
+}
+
+static const ASN1_ENCODING *asn1_get_const_enc_ptr(const ASN1_VALUE **pval,
+                                                   const ASN1_ITEM *it)
+{
+    const ASN1_AUX *aux;
+
+    if (pval == NULL || *pval == NULL)
         return NULL;
     aux = it->funcs;
-    if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
+    if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0)
         return NULL;
     return offset2ptr(*pval, aux->enc_offset);
 }
 
-void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
+void ossl_asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
-    ASN1_ENCODING *enc;
-    enc = asn1_get_enc_ptr(pval, it);
-    if (enc) {
+    ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+    if (enc != NULL) {
         enc->enc = NULL;
         enc->len = 0;
         enc->modified = 1;
     }
 }
 
-void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+void ossl_asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
-    ASN1_ENCODING *enc;
-    enc = asn1_get_enc_ptr(pval, it);
-    if (enc) {
+    ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+    if (enc != NULL) {
         OPENSSL_free(enc->enc);
         enc->enc = NULL;
         enc->len = 0;
@@ -135,17 +157,19 @@ void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
     }
 }
 
-int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
-                  const ASN1_ITEM *it)
+int ossl_asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
+                       const ASN1_ITEM *it)
 {
-    ASN1_ENCODING *enc;
-    enc = asn1_get_enc_ptr(pval, it);
-    if (!enc)
+    ASN1_ENCODING *enc = asn1_get_enc_ptr(pval, it);
+
+    if (enc == NULL)
         return 1;
 
     OPENSSL_free(enc->enc);
+    if (inlen <= 0)
+        return 0;
     if ((enc->enc = OPENSSL_malloc(inlen)) == NULL) {
-        ASN1err(ASN1_F_ASN1_ENC_SAVE, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     memcpy(enc->enc, in, inlen);
@@ -155,27 +179,27 @@ int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
     return 1;
 }
 
-int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
-                     const ASN1_ITEM *it)
+int ossl_asn1_enc_restore(int *len, unsigned char **out, const ASN1_VALUE **pval,
+                          const ASN1_ITEM *it)
 {
-    ASN1_ENCODING *enc;
-    enc = asn1_get_enc_ptr(pval, it);
-    if (!enc || enc->modified)
+    const ASN1_ENCODING *enc = asn1_get_const_enc_ptr(pval, it);
+
+    if (enc == NULL || enc->modified)
         return 0;
     if (out) {
         memcpy(*out, enc->enc, enc->len);
         *out += enc->len;
     }
-    if (len)
+    if (len != NULL)
         *len = enc->len;
     return 1;
 }
 
 /* Given an ASN1_TEMPLATE get a pointer to a field */
-ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+ASN1_VALUE **ossl_asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
 {
-    ASN1_VALUE **pvaltmp;
-    pvaltmp = offset2ptr(*pval, tt->offset);
+    ASN1_VALUE **pvaltmp = offset2ptr(*pval, tt->offset);
+
     /*
      * NOTE for BOOLEAN types the field is just a plain int so we can't
      * return int **, so settle for (int *).
@@ -183,31 +207,40 @@ ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
     return pvaltmp;
 }
 
+/* Given an ASN1_TEMPLATE get a const pointer to a field */
+const ASN1_VALUE **ossl_asn1_get_const_field_ptr(const ASN1_VALUE **pval,
+                                                 const ASN1_TEMPLATE *tt)
+{
+    return offset2ptr(*pval, tt->offset);
+}
+
 /*
  * Handle ANY DEFINED BY template, find the selector, look up the relevant
  * ASN1_TEMPLATE in the table and return it.
  */
 
-const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
-                                 int nullerr)
+const ASN1_TEMPLATE *ossl_asn1_do_adb(const ASN1_VALUE *val,
+                                      const ASN1_TEMPLATE *tt,
+                                      int nullerr)
 {
     const ASN1_ADB *adb;
     const ASN1_ADB_TABLE *atbl;
     long selector;
-    ASN1_VALUE **sfld;
+    const ASN1_VALUE **sfld;
     int i;
-    if (!(tt->flags & ASN1_TFLG_ADB_MASK))
+
+    if ((tt->flags & ASN1_TFLG_ADB_MASK) == 0)
         return tt;
 
     /* Else ANY DEFINED BY ... get the table */
     adb = ASN1_ADB_ptr(tt->item);
 
     /* Get the selector field */
-    sfld = offset2ptr(*pval, adb->offset);
+    sfld = offset2ptr(val, adb->offset);
 
     /* Check if NULL */
     if (*sfld == NULL) {
-        if (!adb->null_tt)
+        if (adb->null_tt == NULL)
             goto err;
         return adb->null_tt;
     }
@@ -216,14 +249,14 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
      * Convert type to a long: NB: don't check for NID_undef here because it
      * might be a legitimate value in the table
      */
-    if (tt->flags & ASN1_TFLG_ADB_OID)
+    if ((tt->flags & ASN1_TFLG_ADB_OID) != 0)
         selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
     else
         selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
 
     /* Let application callback translate value */
     if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) {
-        ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
         return NULL;
     }
 
@@ -248,6 +281,6 @@ const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
  err:
     /* FIXME: should log the value or OID of unsupported type */
     if (nullerr)
-        ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
     return NULL;
 }

+ 4 - 3
libs/openssl/crypto/asn1/tbl_standard.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -56,6 +56,7 @@ static const ASN1_STRING_TABLE tbl_standard[] = {
     {NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
     {NID_countryCode3c, 3, 3, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
     {NID_countryCode3n, 3, 3, B_ASN1_NUMERICSTRING, STABLE_NO_MASK},
-    {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK}
+    {NID_dnsName, 0, -1, B_ASN1_UTF8STRING, STABLE_NO_MASK},
+    {NID_id_on_SmtpUTF8Mailbox, 1, ub_email_address, B_ASN1_UTF8STRING, STABLE_NO_MASK}
 };
 

+ 72 - 8
libs/openssl/crypto/asn1/x_algor.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -11,6 +11,8 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include "crypto/asn1.h"
 #include "crypto/evp.h"
 
 ASN1_SEQUENCE(X509_ALGOR) = {
@@ -78,7 +80,7 @@ void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
     else
         param_type = V_ASN1_NULL;
 
-    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_get_type(md)), param_type, NULL);
 
 }
 
@@ -96,7 +98,7 @@ int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
 int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
 {
     if (src == NULL || dest == NULL)
-	return 0;
+        return 0;
 
     if (dest->algorithm)
          ASN1_OBJECT_free(dest->algorithm);
@@ -108,9 +110,9 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
 
     if (src->algorithm)
         if ((dest->algorithm = OBJ_dup(src->algorithm)) == NULL)
-	    return 0;
+            return 0;
 
-    if (src->parameter) {
+    if (src->parameter != NULL) {
         dest->parameter = ASN1_TYPE_new();
         if (dest->parameter == NULL)
             return 0;
@@ -118,9 +120,71 @@ int X509_ALGOR_copy(X509_ALGOR *dest, const X509_ALGOR *src)
         /* Assuming this is also correct for a BOOL.
          * set does copy as a side effect.
          */
-        if (ASN1_TYPE_set1(dest->parameter, 
-                src->parameter->type, src->parameter->value.ptr) == 0)
+        if (ASN1_TYPE_set1(dest->parameter, src->parameter->type,
+                           src->parameter->value.ptr) == 0)
             return 0;
     }
+
+    return 1;
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+int ossl_x509_algor_new_from_md(X509_ALGOR **palg, const EVP_MD *md)
+{
+    /* Default is SHA1 so no need to create it - still success */
+    if (md == NULL || EVP_MD_is_a(md, "SHA1"))
+        return 1;
+    *palg = X509_ALGOR_new();
+    if (*palg == NULL)
+        return 0;
+    X509_ALGOR_set_md(*palg, md);
     return 1;
 }
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+const EVP_MD *ossl_x509_algor_get_md(X509_ALGOR *alg)
+{
+    const EVP_MD *md;
+
+    if (alg == NULL)
+        return EVP_sha1();
+    md = EVP_get_digestbyobj(alg->algorithm);
+    if (md == NULL)
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_UNKNOWN_DIGEST);
+    return md;
+}
+
+X509_ALGOR *ossl_x509_algor_mgf1_decode(X509_ALGOR *alg)
+{
+    if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
+        return NULL;
+    return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
+                                     alg->parameter);
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+int ossl_x509_algor_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
+{
+    X509_ALGOR *algtmp = NULL;
+    ASN1_STRING *stmp = NULL;
+
+    *palg = NULL;
+    if (mgf1md == NULL || EVP_MD_is_a(mgf1md, "SHA1"))
+        return 1;
+    /* need to embed algorithm ID inside another */
+    if (!ossl_x509_algor_new_from_md(&algtmp, mgf1md))
+        goto err;
+    if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
+         goto err;
+    *palg = X509_ALGOR_new();
+    if (*palg == NULL)
+        goto err;
+    X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+    stmp = NULL;
+ err:
+    ASN1_STRING_free(stmp);
+    X509_ALGOR_free(algtmp);
+    if (*palg != NULL)
+        return 1;
+    return 0;
+}

+ 6 - 6
libs/openssl/crypto/asn1/x_bignum.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -25,13 +25,13 @@ static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
 static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
 static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
 
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
                   const ASN1_ITEM *it);
 static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                   int utype, char *free_cont, const ASN1_ITEM *it);
 static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                          int utype, char *free_cont, const ASN1_ITEM *it);
-static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                     int indent, const ASN1_PCTX *pctx);
 
 static ASN1_PRIMITIVE_FUNCS bignum_pf = {
@@ -91,7 +91,7 @@ static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
     *pval = NULL;
 }
 
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int bn_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
                   const ASN1_ITEM *it)
 {
     BIGNUM *bn;
@@ -146,7 +146,7 @@ static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     return ret;
 }
 
-static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int bn_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                     int indent, const ASN1_PCTX *pctx)
 {
     if (!BN_print(out, *(BIGNUM **)pval))

+ 3 - 3
libs/openssl/crypto/asn1/x_info.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -19,7 +19,7 @@ X509_INFO *X509_INFO_new(void)
 
     ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL) {
-        ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 

+ 26 - 26
libs/openssl/crypto/asn1/x_int64.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -29,7 +29,7 @@
 static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
     if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t))) == NULL) {
-        ASN1err(ASN1_F_UINT64_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     return 1;
@@ -46,8 +46,8 @@ static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
     **(uint64_t **)pval = 0;
 }
 
-static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
-                    const ASN1_ITEM *it)
+static int uint64_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
+                      const ASN1_ITEM *it)
 {
     uint64_t utmp;
     int neg = 0;
@@ -62,16 +62,16 @@ static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
         return -1;
     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
         && (int64_t)utmp < 0) {
-        /* i2c_uint64_int() assumes positive values */
+        /* ossl_i2c_uint64_int() assumes positive values */
         utmp = 0 - utmp;
         neg = 1;
     }
 
-    return i2c_uint64_int(cont, utmp, neg);
+    return ossl_i2c_uint64_int(cont, utmp, neg);
 }
 
 static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-                    int utype, char *free_cont, const ASN1_ITEM *it)
+                      int utype, char *free_cont, const ASN1_ITEM *it)
 {
     uint64_t utmp = 0;
     char *cp;
@@ -91,19 +91,19 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     if (len == 0)
         goto long_compat;
 
-    if (!c2i_uint64_int(&utmp, &neg, &cont, len))
+    if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
         return 0;
     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
-        ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
         return 0;
     }
     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
             && !neg && utmp > INT64_MAX) {
-        ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
         return 0;
     }
     if (neg)
-        /* c2i_uint64_int() returns positive values */
+        /* ossl_c2i_uint64_int() returns positive values */
         utmp = 0 - utmp;
 
  long_compat:
@@ -111,7 +111,7 @@ static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     return 1;
 }
 
-static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int uint64_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                         int indent, const ASN1_PCTX *pctx)
 {
     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
@@ -124,7 +124,7 @@ static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
 static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
     if ((*pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t))) == NULL) {
-        ASN1err(ASN1_F_UINT32_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     return 1;
@@ -141,8 +141,8 @@ static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
     **(uint32_t **)pval = 0;
 }
 
-static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
-                    const ASN1_ITEM *it)
+static int uint32_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
+                      const ASN1_ITEM *it)
 {
     uint32_t utmp;
     int neg = 0;
@@ -157,12 +157,12 @@ static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
         return -1;
     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED
         && (int32_t)utmp < 0) {
-        /* i2c_uint64_int() assumes positive values */
+        /* ossl_i2c_uint64_int() assumes positive values */
         utmp = 0 - utmp;
         neg = 1;
     }
 
-    return i2c_uint64_int(cont, (uint64_t)utmp, neg);
+    return ossl_i2c_uint64_int(cont, (uint64_t)utmp, neg);
 }
 
 /*
@@ -173,7 +173,7 @@ static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
 #define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1)
 
 static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-                    int utype, char *free_cont, const ASN1_ITEM *it)
+                      int utype, char *free_cont, const ASN1_ITEM *it)
 {
     uint64_t utmp = 0;
     uint32_t utmp2 = 0;
@@ -194,22 +194,22 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     if (len == 0)
         goto long_compat;
 
-    if (!c2i_uint64_int(&utmp, &neg, &cont, len))
+    if (!ossl_c2i_uint64_int(&utmp, &neg, &cont, len))
         return 0;
     if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) {
-        ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_NEGATIVE_VALUE);
         return 0;
     }
     if (neg) {
         if (utmp > ABS_INT32_MIN) {
-            ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_SMALL);
             return 0;
         }
         utmp = 0 - utmp;
     } else {
         if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX)
             || ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) {
-            ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE);
+            ERR_raise(ERR_LIB_ASN1, ASN1_R_TOO_LARGE);
             return 0;
         }
     }
@@ -220,12 +220,12 @@ static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     return 1;
 }
 
-static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int uint32_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                         int indent, const ASN1_PCTX *pctx)
 {
     if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED)
-        return BIO_printf(out, "%d\n", **(int32_t **)pval);
-    return BIO_printf(out, "%u\n", **(uint32_t **)pval);
+        return BIO_printf(out, "%d\n", (int)**(int32_t **)pval);
+    return BIO_printf(out, "%u\n", (unsigned int)**(uint32_t **)pval);
 }
 
 

+ 10 - 15
libs/openssl/crypto/asn1/x_long.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -11,10 +11,6 @@
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
 
-#if !(OPENSSL_API_COMPAT < 0x10200000L)
-NON_EMPTY_TRANSLATION_UNIT
-#else
-
 #define COPY_SIZE(a, b) (sizeof(a) < sizeof(b) ? sizeof(a) : sizeof(b))
 
 /*
@@ -25,11 +21,11 @@ NON_EMPTY_TRANSLATION_UNIT
 static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
 static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
 
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
                     const ASN1_ITEM *it);
 static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                     int utype, char *free_cont, const ASN1_ITEM *it);
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                       int indent, const ASN1_PCTX *pctx);
 
 static ASN1_PRIMITIVE_FUNCS long_pf = {
@@ -86,7 +82,7 @@ static int num_bits_ulong(unsigned long value)
     return (int)ret;
 }
 
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
+static int long_i2c(const ASN1_VALUE **pval, unsigned char *cont, int *putype,
                     const ASN1_ITEM *it)
 {
     long ltmp;
@@ -156,7 +152,7 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
         }
     }
     if (len > (int)sizeof(long)) {
-        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
         return 0;
     }
 
@@ -167,7 +163,7 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
         else
             sign = 0;
     } else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */
-        ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_ILLEGAL_PADDING);
         return 0;
     }
     utmp = 0;
@@ -177,20 +173,20 @@ static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
     }
     ltmp = (long)utmp;
     if (ltmp < 0) {
-        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
         return 0;
     }
     if (sign)
         ltmp = -ltmp - 1;
     if (ltmp == it->size) {
-        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+        ERR_raise(ERR_LIB_ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
         return 0;
     }
     memcpy(pval, &ltmp, COPY_SIZE(*pval, ltmp));
     return 1;
 }
 
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+static int long_print(BIO *out, const ASN1_VALUE **pval, const ASN1_ITEM *it,
                       int indent, const ASN1_PCTX *pctx)
 {
     long l;
@@ -198,4 +194,3 @@ static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
     memcpy(&l, pval, COPY_SIZE(*pval, l));
     return BIO_printf(out, "%ld\n", l);
 }
-#endif

+ 3 - 3
libs/openssl/crypto/asn1/x_pkey.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -29,7 +29,7 @@ X509_PKEY *X509_PKEY_new(void)
     return ret;
 err:
     X509_PKEY_free(ret);
-    ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+    ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE);
     return NULL;
 }
 

+ 1 - 1
libs/openssl/crypto/asn1/x_sig.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 1 - 1
libs/openssl/crypto/asn1/x_spki.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 1 - 1
libs/openssl/crypto/asn1/x_val.c

@@ -1,7 +1,7 @@
 /*
  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 252 - 0
libs/openssl/crypto/asn1_dsa.c

@@ -0,0 +1,252 @@
+/*
+ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * A simple ASN.1 DER encoder/decoder for DSA-Sig-Value and ECDSA-Sig-Value.
+ *
+ * DSA-Sig-Value ::= SEQUENCE {
+ *  r  INTEGER,
+ *  s  INTEGER
+ * }
+ *
+ * ECDSA-Sig-Value ::= SEQUENCE {
+ *  r  INTEGER,
+ *  s  INTEGER
+ * }
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include "crypto/asn1_dsa.h"
+#include "internal/packet.h"
+
+#define ID_SEQUENCE 0x30
+#define ID_INTEGER 0x02
+
+/*
+ * Outputs the encoding of the length octets for a DER value with a content
+ * length of cont_len bytes to pkt. The maximum supported content length is
+ * 65535 (0xffff) bytes.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_length(WPACKET *pkt, size_t cont_len)
+{
+    if (cont_len > 0xffff)
+        return 0; /* Too large for supported length encodings */
+
+    if (cont_len > 0xff) {
+        if (!WPACKET_put_bytes_u8(pkt, 0x82)
+                || !WPACKET_put_bytes_u16(pkt, cont_len))
+            return 0;
+    } else {
+        if (cont_len > 0x7f
+                && !WPACKET_put_bytes_u8(pkt, 0x81))
+            return 0;
+        if (!WPACKET_put_bytes_u8(pkt, cont_len))
+            return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * Outputs the DER encoding of a positive ASN.1 INTEGER to pkt.
+ *
+ * Results in an error if n is negative or too large.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_integer(WPACKET *pkt, const BIGNUM *n)
+{
+    unsigned char *bnbytes;
+    size_t cont_len;
+
+    if (BN_is_negative(n))
+        return 0;
+
+    /*
+     * Calculate the ASN.1 INTEGER DER content length for n.
+     * This is the number of whole bytes required to represent n (i.e. rounded
+     * down), plus one.
+     * If n is zero then the content is a single zero byte (length = 1).
+     * If the number of bits of n is a multiple of 8 then an extra zero padding
+     * byte is included to ensure that the value is still treated as positive
+     * in the INTEGER two's complement representation.
+     */
+    cont_len = BN_num_bits(n) / 8 + 1;
+
+    if (!WPACKET_start_sub_packet(pkt)
+            || !WPACKET_put_bytes_u8(pkt, ID_INTEGER)
+            || !ossl_encode_der_length(pkt, cont_len)
+            || !WPACKET_allocate_bytes(pkt, cont_len, &bnbytes)
+            || !WPACKET_close(pkt))
+        return 0;
+
+    if (bnbytes != NULL
+            && BN_bn2binpad(n, bnbytes, (int)cont_len) != (int)cont_len)
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to pkt. pkt
+ * may be initialised with a NULL buffer which enables pkt to be used to
+ * calculate how many bytes would be needed.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int ossl_encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s)
+{
+    WPACKET tmppkt, *dummypkt;
+    size_t cont_len;
+    int isnull = WPACKET_is_null_buf(pkt);
+
+    if (!WPACKET_start_sub_packet(pkt))
+        return 0;
+
+    if (!isnull) {
+        if (!WPACKET_init_null(&tmppkt, 0))
+            return 0;
+        dummypkt = &tmppkt;
+    } else {
+        /* If the input packet has a NULL buffer, we don't need a dummy packet */
+        dummypkt = pkt;
+    }
+
+    /* Calculate the content length */
+    if (!ossl_encode_der_integer(dummypkt, r)
+            || !ossl_encode_der_integer(dummypkt, s)
+            || !WPACKET_get_length(dummypkt, &cont_len)
+            || (!isnull && !WPACKET_finish(dummypkt))) {
+        if (!isnull)
+            WPACKET_cleanup(dummypkt);
+        return 0;
+    }
+
+    /* Add the tag and length bytes */
+    if (!WPACKET_put_bytes_u8(pkt, ID_SEQUENCE)
+            || !ossl_encode_der_length(pkt, cont_len)
+               /*
+                * Really encode the integers. We already wrote to the main pkt
+                * if it had a NULL buffer, so don't do it again
+                */
+            || (!isnull && !ossl_encode_der_integer(pkt, r))
+            || (!isnull && !ossl_encode_der_integer(pkt, s))
+            || !WPACKET_close(pkt))
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Decodes the DER length octets in pkt and initialises subpkt with the
+ * following bytes of that length.
+ *
+ * Returns 1 on success or 0 on failure.
+ */
+int ossl_decode_der_length(PACKET *pkt, PACKET *subpkt)
+{
+    unsigned int byte;
+
+    if (!PACKET_get_1(pkt, &byte))
+        return 0;
+
+    if (byte < 0x80)
+        return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte);
+    if (byte == 0x81)
+        return PACKET_get_length_prefixed_1(pkt, subpkt);
+    if (byte == 0x82)
+        return PACKET_get_length_prefixed_2(pkt, subpkt);
+
+    /* Too large, invalid, or not DER. */
+    return 0;
+}
+
+/*
+ * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded,
+ * and updates n with the decoded value.
+ *
+ * The BIGNUM, n, must have already been allocated by calling BN_new().
+ * pkt must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns 1 on success or 0 on error.
+ *
+ * If the PACKET is supposed to only contain a single INTEGER value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+int ossl_decode_der_integer(PACKET *pkt, BIGNUM *n)
+{
+    PACKET contpkt, tmppkt;
+    unsigned int tag, tmp;
+
+    /* Check we have an integer and get the content bytes */
+    if (!PACKET_get_1(pkt, &tag)
+            || tag != ID_INTEGER
+            || !ossl_decode_der_length(pkt, &contpkt))
+        return 0;
+
+    /* Peek ahead at the first bytes to check for proper encoding */
+    tmppkt = contpkt;
+    /* The INTEGER must be positive */
+    if (!PACKET_get_1(&tmppkt, &tmp)
+            || (tmp & 0x80) != 0)
+        return 0;
+    /* If there a zero padding byte the next byte must have the msb set */
+    if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) {
+        if (!PACKET_get_1(&tmppkt, &tmp)
+                || (tmp & 0x80) == 0)
+            return 0;
+    }
+
+    if (BN_bin2bn(PACKET_data(&contpkt),
+                  (int)PACKET_remaining(&contpkt), n) == NULL)
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be
+ * DER encoded, updates r and s with the decoded values, and increments *ppin
+ * past the data that was consumed.
+ *
+ * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().
+ * ppin and *ppin must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns the number of bytes of input consumed or 0 if an error occurs.
+ *
+ * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+size_t ossl_decode_der_dsa_sig(BIGNUM *r, BIGNUM *s,
+                               const unsigned char **ppin, size_t len)
+{
+    size_t consumed;
+    PACKET pkt, contpkt;
+    unsigned int tag;
+
+    if (!PACKET_buf_init(&pkt, *ppin, len)
+            || !PACKET_get_1(&pkt, &tag)
+            || tag != ID_SEQUENCE
+            || !ossl_decode_der_length(&pkt, &contpkt)
+            || !ossl_decode_der_integer(&contpkt, r)
+            || !ossl_decode_der_integer(&contpkt, s)
+            || PACKET_remaining(&contpkt) != 0)
+        return 0;
+
+    consumed = PACKET_data(&pkt) - *ppin;
+    *ppin += consumed;
+    return consumed;
+}

+ 1 - 1
libs/openssl/crypto/async/arch/async_null.h

@@ -1,7 +1,7 @@
 /*
  * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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

+ 34 - 3
libs/openssl/crypto/async/arch/async_posix.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -25,17 +25,47 @@
 #  define ASYNC_POSIX
 #  define ASYNC_ARCH
 
+#  if defined(__CET__) || defined(__ia64__)
+/*
+ * When Intel CET is enabled, makecontext will create a different
+ * shadow stack for each context.  async_fibre_swapcontext cannot
+ * use _longjmp.  It must call swapcontext to swap shadow stack as
+ * well as normal stack.
+ * On IA64 the register stack engine is not saved across setjmp/longjmp. Here
+ * swapcontext() performs correctly.
+ */
+#   define USE_SWAPCONTEXT
+#  endif
+#  if defined(__aarch64__) && defined(__clang__) \
+    && defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
+/*
+ * setjmp/longjmp don't currently work with BTI on all libc implementations
+ * when compiled by clang. This is because clang doesn't put a BTI after the
+ * call to setjmp where it returns the second time. This then fails on libc
+ * implementations - notably glibc - which use an indirect jump to there.
+ * So use the swapcontext implementation, which does work.
+ * See https://github.com/llvm/llvm-project/issues/48888.
+ */
+#   define USE_SWAPCONTEXT
+#  endif
 #  include <ucontext.h>
-#  include <setjmp.h>
+#  ifndef USE_SWAPCONTEXT
+#   include <setjmp.h>
+#  endif
 
 typedef struct async_fibre_st {
     ucontext_t fibre;
+#  ifndef USE_SWAPCONTEXT
     jmp_buf env;
     int env_init;
+#  endif
 } async_fibre;
 
 static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
 {
+#  ifdef USE_SWAPCONTEXT
+    swapcontext(&o->fibre, &n->fibre);
+#  else
     o->env_init = 1;
 
     if (!r || !_setjmp(o->env)) {
@@ -44,6 +74,7 @@ static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, i
         else
             setcontext(&n->fibre);
     }
+#  endif
 
     return 1;
 }

+ 6 - 2
libs/openssl/crypto/async/arch/async_win.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -34,7 +34,11 @@ void async_local_cleanup(void)
 
 int async_fibre_init_dispatcher(async_fibre *fibre)
 {
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+    fibre->fibre = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH);
+# else
     fibre->fibre = ConvertThreadToFiber(NULL);
+# endif
     if (fibre->fibre == NULL) {
         fibre->converted = 0;
         fibre->fibre = GetCurrentFiber();

+ 11 - 3
libs/openssl/crypto/async/arch/async_win.h

@@ -1,7 +1,7 @@
 /*
- * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -26,8 +26,16 @@ typedef struct async_fibre_st {
 
 # define async_fibre_swapcontext(o,n,r) \
         (SwitchToFiber((n)->fibre), 1)
-# define async_fibre_makecontext(c) \
+
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+#   define async_fibre_makecontext(c) \
+        ((c)->fibre = CreateFiberEx(0, 0, FIBER_FLAG_FLOAT_SWITCH, \
+                                    async_start_func_win, 0))
+# else
+#   define async_fibre_makecontext(c) \
         ((c)->fibre = CreateFiber(0, async_start_func_win, 0))
+# endif
+
 # define async_fibre_free(f)             (DeleteFiber((f)->fibre))
 
 int async_fibre_init_dispatcher(async_fibre *fibre);

+ 57 - 21
libs/openssl/crypto/async/async.c

@@ -1,7 +1,7 @@
 /*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -30,16 +30,18 @@
 static CRYPTO_THREAD_LOCAL ctxkey;
 static CRYPTO_THREAD_LOCAL poolkey;
 
+static void async_delete_thread_state(void *arg);
+
 static async_ctx *async_ctx_new(void)
 {
     async_ctx *nctx;
 
-    if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+    if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state))
         return NULL;
 
     nctx = OPENSSL_malloc(sizeof(*nctx));
     if (nctx == NULL) {
-        ASYNCerr(ASYNC_F_ASYNC_CTX_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -81,7 +83,7 @@ static ASYNC_JOB *async_job_new(void)
 
     job = OPENSSL_zalloc(sizeof(*job));
     if (job == NULL) {
-        ASYNCerr(ASYNC_F_ASYNC_JOB_NEW, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
@@ -136,6 +138,10 @@ static void async_release_job(ASYNC_JOB *job) {
     async_pool *pool;
 
     pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+    if (pool == NULL) {
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+        return;
+    }
     OPENSSL_free(job->funcargs);
     job->funcargs = NULL;
     sk_ASYNC_JOB_push(pool->jobs, job);
@@ -146,6 +152,10 @@ void async_start_func(void)
     ASYNC_JOB *job;
     async_ctx *ctx = async_get_ctx();
 
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+        return;
+    }
     while (1) {
         /* Run the job */
         job = ctx->currjob;
@@ -159,7 +169,7 @@ void async_start_func(void)
              * Should not happen. Getting here will close the thread...can't do
              * much about it
              */
-            ASYNCerr(ASYNC_F_ASYNC_START_FUNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+            ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
         }
     }
 }
@@ -168,6 +178,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
                     int (*func)(void *), void *args, size_t size)
 {
     async_ctx *ctx;
+    OSSL_LIB_CTX *libctx;
 
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
         return ASYNC_ERR;
@@ -178,7 +189,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
     if (ctx == NULL)
         return ASYNC_ERR;
 
-    if (*job)
+    if (*job != NULL)
         ctx->currjob = *job;
 
     for (;;) {
@@ -200,19 +211,38 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
             }
 
             if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
+                if (*job == NULL)
+                    return ASYNC_ERR;
                 ctx->currjob = *job;
+
+                /*
+                 * Restore the default libctx to what it was the last time the
+                 * fibre ran
+                 */
+                libctx = OSSL_LIB_CTX_set0_default(ctx->currjob->libctx);
+                if (libctx == NULL) {
+                    /* Failed to set the default context */
+                    ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
+                    goto err;
+                }
                 /* Resume previous job */
                 if (!async_fibre_swapcontext(&ctx->dispatcher,
                         &ctx->currjob->fibrectx, 1)) {
-                    ASYNCerr(ASYNC_F_ASYNC_START_JOB,
-                             ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+                    ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
+                    ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
                     goto err;
                 }
+                /*
+                 * In case the fibre changed the default libctx we set it back
+                 * again to what it was originally, and remember what it had
+                 * been changed to.
+                 */
+                ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
                 continue;
             }
 
             /* Should not happen */
-            ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR);
+            ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR);
             async_release_job(ctx->currjob);
             ctx->currjob = NULL;
             *job = NULL;
@@ -226,7 +256,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
         if (args != NULL) {
             ctx->currjob->funcargs = OPENSSL_malloc(size);
             if (ctx->currjob->funcargs == NULL) {
-                ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE);
+                ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
                 async_release_job(ctx->currjob);
                 ctx->currjob = NULL;
                 return ASYNC_ERR;
@@ -238,11 +268,17 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
 
         ctx->currjob->func = func;
         ctx->currjob->waitctx = wctx;
+        libctx = ossl_lib_ctx_get_concrete(NULL);
         if (!async_fibre_swapcontext(&ctx->dispatcher,
                 &ctx->currjob->fibrectx, 1)) {
-            ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+            ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
             goto err;
         }
+        /*
+         * In case the fibre changed the default libctx we set it back again
+         * to what it was, and remember what it had been changed to.
+         */
+        ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx);
     }
 
 err:
@@ -272,7 +308,7 @@ int ASYNC_pause_job(void)
 
     if (!async_fibre_swapcontext(&job->fibrectx,
                                  &ctx->dispatcher, 1)) {
-        ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+        ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
         return 0;
     }
     /* Reset counts of added and deleted fds */
@@ -285,7 +321,7 @@ static void async_empty_pool(async_pool *pool)
 {
     ASYNC_JOB *job;
 
-    if (!pool || !pool->jobs)
+    if (pool == NULL || pool->jobs == NULL)
         return;
 
     do {
@@ -319,25 +355,25 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
     size_t curr_size = 0;
 
     if (init_size > max_size) {
-        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INVALID_POOL_SIZE);
+        ERR_raise(ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE);
         return 0;
     }
 
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
         return 0;
 
-    if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+    if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state))
         return 0;
 
     pool = OPENSSL_zalloc(sizeof(*pool));
     if (pool == NULL) {
-        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
     pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size);
     if (pool->jobs == NULL) {
-        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+        ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE);
         OPENSSL_free(pool);
         return 0;
     }
@@ -362,7 +398,7 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
     }
     pool->curr_size = curr_size;
     if (!CRYPTO_THREAD_set_local(&poolkey, pool)) {
-        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL);
+        ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL);
         goto err;
     }
 
@@ -374,7 +410,7 @@ err:
     return 0;
 }
 
-void async_delete_thread_state(void)
+static void async_delete_thread_state(void *arg)
 {
     async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
 
@@ -393,7 +429,7 @@ void ASYNC_cleanup_thread(void)
     if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
         return;
 
-    async_delete_thread_state();
+    async_delete_thread_state(NULL);
 }
 
 ASYNC_JOB *ASYNC_get_current_job(void)

+ 5 - 19
libs/openssl/crypto/async/async_err.c

@@ -1,8 +1,8 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not 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
@@ -10,22 +10,10 @@
 
 #include <openssl/err.h>
 #include <openssl/asyncerr.h>
+#include "crypto/asyncerr.h"
 
 #ifndef OPENSSL_NO_ERR
 
-static const ERR_STRING_DATA ASYNC_str_functs[] = {
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_CTX_NEW, 0), "async_ctx_new"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_INIT_THREAD, 0),
-     "ASYNC_init_thread"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_JOB_NEW, 0), "async_job_new"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_PAUSE_JOB, 0), "ASYNC_pause_job"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_FUNC, 0), "async_start_func"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_JOB, 0), "ASYNC_start_job"},
-    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, 0),
-     "ASYNC_WAIT_CTX_set_wait_fd"},
-    {0, NULL}
-};
-
 static const ERR_STRING_DATA ASYNC_str_reasons[] = {
     {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SET_POOL),
     "failed to set pool"},
@@ -39,13 +27,11 @@ static const ERR_STRING_DATA ASYNC_str_reasons[] = {
 
 #endif
 
-int ERR_load_ASYNC_strings(void)
+int ossl_err_load_ASYNC_strings(void)
 {
 #ifndef OPENSSL_NO_ERR
-    if (ERR_func_error_string(ASYNC_str_functs[0].error) == NULL) {
-        ERR_load_strings_const(ASYNC_str_functs);
+    if (ERR_reason_error_string(ASYNC_str_reasons[0].error) == NULL)
         ERR_load_strings_const(ASYNC_str_reasons);
-    }
 #endif
     return 1;
 }

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini