Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Feb 2023 22:40:53 GMT
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 0904c29a0a11 - stable/13 - OpenSSL: Merge OpenSSL 1.1.1t
Message-ID:  <202302072240.317MerM1046361@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by jkim:

URL: https://cgit.FreeBSD.org/src/commit/?id=0904c29a0a116eb7d67a2d35d926580a65f0ddfb

commit 0904c29a0a116eb7d67a2d35d926580a65f0ddfb
Author:     Jung-uk Kim <jkim@FreeBSD.org>
AuthorDate: 2023-02-07 18:51:38 +0000
Commit:     Jung-uk Kim <jkim@FreeBSD.org>
CommitDate: 2023-02-07 22:38:40 +0000

    OpenSSL: Merge OpenSSL 1.1.1t
    
    (cherry picked from commit 640242a5915761ce63205bdb0542fa3c1473c0ff)
---
 crypto/openssl/CHANGES                         |  76 ++-
 crypto/openssl/Configure                       |  18 +-
 crypto/openssl/NEWS                            |   7 +
 crypto/openssl/README                          |   2 +-
 crypto/openssl/crypto/asn1/asn_mime.c          |   6 +-
 crypto/openssl/crypto/asn1/bio_asn1.c          |   4 +-
 crypto/openssl/crypto/asn1/bio_ndef.c          |  41 +-
 crypto/openssl/crypto/bio/b_print.c            |  22 +-
 crypto/openssl/crypto/bn/bn_blind.c            |  16 +-
 crypto/openssl/crypto/bn/bn_err.c              |   4 +-
 crypto/openssl/crypto/bn/bn_exp.c              |  36 +-
 crypto/openssl/crypto/bn/bn_local.h            |  36 +-
 crypto/openssl/crypto/bn/bn_mont.c             |   4 +-
 crypto/openssl/crypto/bn/build.info            |   3 +-
 crypto/openssl/crypto/bn/rsa_sup_mul.c         | 614 +++++++++++++++++++++++++
 crypto/openssl/crypto/cms/cms_enc.c            |   5 +
 crypto/openssl/crypto/cms/cms_err.c            |   2 +
 crypto/openssl/crypto/err/openssl.txt          |   5 +-
 crypto/openssl/crypto/evp/bio_enc.c            |   9 +-
 crypto/openssl/crypto/pem/pem_lib.c            |   8 +-
 crypto/openssl/crypto/rsa/rsa_ameth.c          |   1 +
 crypto/openssl/crypto/rsa/rsa_ossl.c           |  19 +-
 crypto/openssl/crypto/txt_db/txt_db.c          |   4 +-
 crypto/openssl/crypto/x509/by_dir.c            |  18 +-
 crypto/openssl/crypto/x509/x_name.c            |   8 +-
 crypto/openssl/crypto/x509v3/v3_genn.c         |   4 +-
 crypto/openssl/engines/asm/e_padlock-x86.pl    |   4 +-
 crypto/openssl/engines/asm/e_padlock-x86_64.pl |   4 +-
 crypto/openssl/include/crypto/bn.h             |   7 +-
 crypto/openssl/include/openssl/bnerr.h         |   3 +-
 crypto/openssl/include/openssl/cmserr.h        |   1 +
 crypto/openssl/include/openssl/opensslv.h      |   4 +-
 crypto/openssl/include/openssl/x509v3.h        |   4 +-
 crypto/openssl/ssl/record/rec_layer_s3.c       |  26 +-
 crypto/openssl/ssl/record/ssl3_buffer.c        |   9 +-
 35 files changed, 938 insertions(+), 96 deletions(-)

diff --git a/crypto/openssl/CHANGES b/crypto/openssl/CHANGES
index 882dd2034efe..459605bf71b6 100644
--- a/crypto/openssl/CHANGES
+++ b/crypto/openssl/CHANGES
@@ -7,11 +7,85 @@
  https://github.com/openssl/openssl/commits/ and pick the appropriate
  release branch.
 
+ Changes between 1.1.1s and 1.1.1t [7 Feb 2023]
+
+  *) Fixed X.400 address type confusion in X.509 GeneralName.
+
+     There is a type confusion vulnerability relating to X.400 address processing
+     inside an X.509 GeneralName. X.400 addresses were parsed as an ASN1_STRING
+     but subsequently interpreted by GENERAL_NAME_cmp as an ASN1_TYPE. This
+     vulnerability may allow an attacker who can provide a certificate chain and
+     CRL (neither of which need have a valid signature) to pass arbitrary
+     pointers to a memcmp call, creating a possible read primitive, subject to
+     some constraints. Refer to the advisory for more information. Thanks to
+     David Benjamin for discovering this issue. (CVE-2023-0286)
+
+     This issue has been fixed by changing the public header file definition of
+     GENERAL_NAME so that x400Address reflects the implementation. It was not
+     possible for any existing application to successfully use the existing
+     definition; however, if any application references the x400Address field
+     (e.g. in dead code), note that the type of this field has changed. There is
+     no ABI change.
+     [Hugo Landau]
+
+  *) Fixed Use-after-free following BIO_new_NDEF.
+
+     The public API function BIO_new_NDEF is a helper function used for
+     streaming ASN.1 data via a BIO. It is primarily used internally to OpenSSL
+     to support the SMIME, CMS and PKCS7 streaming capabilities, but may also
+     be called directly by end user applications.
+
+     The function receives a BIO from the caller, prepends a new BIO_f_asn1
+     filter BIO onto the front of it to form a BIO chain, and then returns
+     the new head of the BIO chain to the caller. Under certain conditions,
+     for example if a CMS recipient public key is invalid, the new filter BIO
+     is freed and the function returns a NULL result indicating a failure.
+     However, in this case, the BIO chain is not properly cleaned up and the
+     BIO passed by the caller still retains internal pointers to the previously
+     freed filter BIO. If the caller then goes on to call BIO_pop() on the BIO
+     then a use-after-free will occur. This will most likely result in a crash.
+     (CVE-2023-0215)
+     [Viktor Dukhovni, Matt Caswell]
+
+  *) Fixed Double free after calling PEM_read_bio_ex.
+
+     The function PEM_read_bio_ex() reads a PEM file from a BIO and parses and
+     decodes the "name" (e.g. "CERTIFICATE"), any header data and the payload
+     data. If the function succeeds then the "name_out", "header" and "data"
+     arguments are populated with pointers to buffers containing the relevant
+     decoded data. The caller is responsible for freeing those buffers. It is
+     possible to construct a PEM file that results in 0 bytes of payload data.
+     In this case PEM_read_bio_ex() will return a failure code but will populate
+     the header argument with a pointer to a buffer that has already been freed.
+     If the caller also frees this buffer then a double free will occur. This
+     will most likely lead to a crash.
+
+     The functions PEM_read_bio() and PEM_read() are simple wrappers around
+     PEM_read_bio_ex() and therefore these functions are also directly affected.
+
+     These functions are also called indirectly by a number of other OpenSSL
+     functions including PEM_X509_INFO_read_bio_ex() and
+     SSL_CTX_use_serverinfo_file() which are also vulnerable. Some OpenSSL
+     internal uses of these functions are not vulnerable because the caller does
+     not free the header argument if PEM_read_bio_ex() returns a failure code.
+     (CVE-2022-4450)
+     [Kurt Roeckx, Matt Caswell]
+
+  *) Fixed Timing Oracle in RSA Decryption.
+
+     A timing based side channel exists in the OpenSSL RSA Decryption
+     implementation which could be sufficient to recover a plaintext across
+     a network in a Bleichenbacher style attack. To achieve a successful
+     decryption an attacker would have to be able to send a very large number
+     of trial messages for decryption. The vulnerability affects all RSA padding
+     modes: PKCS#1 v1.5, RSA-OEAP and RSASVE.
+     (CVE-2022-4304)
+     [Dmitry Belyavsky, Hubert Kario]
+
  Changes between 1.1.1r and 1.1.1s [1 Nov 2022]
 
   *) Fixed a regression introduced in 1.1.1r version not refreshing the
      certificate data to be signed before signing the certificate.
-
      [Gibeom Gwon]
 
  Changes between 1.1.1q and 1.1.1r [11 Oct 2022]
diff --git a/crypto/openssl/Configure b/crypto/openssl/Configure
index 92e59b9ce7a6..37a99d14715c 100755
--- a/crypto/openssl/Configure
+++ b/crypto/openssl/Configure
@@ -1,6 +1,6 @@
 #! /usr/bin/env perl
 # -*- mode: perl; -*-
-# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the OpenSSL license (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
@@ -1217,7 +1217,7 @@ $target{build_scheme} = [ $target{build_scheme} ]
 my ($builder, $builder_platform, @builder_opts) =
     @{$target{build_scheme}};
 
-foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
+foreach my $checker (($builder_platform."-".$config{build_file}."-checker.pm",
                       $builder_platform."-checker.pm")) {
     my $checker_path = catfile($srcdir, "Configurations", $checker);
     if (-f $checker_path) {
@@ -1741,8 +1741,8 @@ if ($builder eq "unified") {
     # Store the name of the template file we will build the build file from
     # in %config.  This may be useful for the build file itself.
     my @build_file_template_names =
-        ( $builder_platform."-".$target{build_file}.".tmpl",
-          $target{build_file}.".tmpl" );
+        ( $builder_platform."-".$config{build_file}.".tmpl",
+          $config{build_file}.".tmpl" );
     my @build_file_templates = ();
 
     # First, look in the user provided directory, if given
@@ -1966,8 +1966,8 @@ if ($builder eq "unified") {
                     }
                     next if @skip && $skip[$#skip] <= 0;
                     push @rawlines,  $_
-                        if ($target_kind eq $target{build_file}
-                            || $target_kind eq $target{build_file}."(".$builder_platform.")");
+                        if ($target_kind eq $config{build_file}
+                            || $target_kind eq $config{build_file}."(".$builder_platform.")");
                 }
             },
             qr/^\s*(?:#.*)?$/ => sub { },
@@ -2842,8 +2842,8 @@ if ($builder_platform eq 'unix') {
 
 my %builders = (
     unified => sub {
-        print 'Creating ',$target{build_file},"\n";
-        run_dofile(catfile($blddir, $target{build_file}),
+        print 'Creating ',$config{build_file},"\n";
+        run_dofile(catfile($blddir, $config{build_file}),
                    @{$config{build_file_templates}});
     },
     );
@@ -2897,7 +2897,7 @@ exit(0);
 #
 sub death_handler {
     die @_ if $^S;              # To prevent the added message in eval blocks
-    my $build_file = $target{build_file} // "build file";
+    my $build_file = $config{build_file} // "build file";
     my @message = ( <<"_____", @_ );
 
 Failure!  $build_file wasn't produced.
diff --git a/crypto/openssl/NEWS b/crypto/openssl/NEWS
index c9e63eea63a6..2724fc4d85ba 100644
--- a/crypto/openssl/NEWS
+++ b/crypto/openssl/NEWS
@@ -5,6 +5,13 @@
   This file gives a brief overview of the major changes between each OpenSSL
   release. For more details please read the CHANGES file.
 
+  Major changes between OpenSSL 1.1.1s and OpenSSL 1.1.1t [7 Feb 2023]
+
+      o Fixed X.400 address type confusion in X.509 GeneralName (CVE-2023-0286)
+      o Fixed Use-after-free following BIO_new_NDEF (CVE-2023-0215)
+      o Fixed Double free after calling PEM_read_bio_ex (CVE-2022-4450)
+      o Fixed Timing Oracle in RSA Decryption (CVE-2022-4304)
+
   Major changes between OpenSSL 1.1.1r and OpenSSL 1.1.1s [1 Nov 2022]
 
       o Fixed a regression introduced in OpenSSL 1.1.1r not refreshing the
diff --git a/crypto/openssl/README b/crypto/openssl/README
index 2f6d91c6337c..b2f806be3a44 100644
--- a/crypto/openssl/README
+++ b/crypto/openssl/README
@@ -1,5 +1,5 @@
 
- OpenSSL 1.1.1s 1 Nov 2022
+ OpenSSL 1.1.1t 7 Feb 2023
 
  Copyright (c) 1998-2022 The OpenSSL Project
  Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
diff --git a/crypto/openssl/crypto/asn1/asn_mime.c b/crypto/openssl/crypto/asn1/asn_mime.c
index 38735cd86f3e..36853612b69c 100644
--- a/crypto/openssl/crypto/asn1/asn_mime.c
+++ b/crypto/openssl/crypto/asn1/asn_mime.c
@@ -489,6 +489,7 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
     char eol;
     int len;
     char linebuf[MAX_SMLEN];
+    int ret;
     /*
      * Buffer output so we don't write one line at a time. This is useful
      * when streaming as we don't end up with one OCTET STRING per line.
@@ -523,9 +524,12 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
                 BIO_write(out, "\r\n", 2);
         }
     }
-    (void)BIO_flush(out);
+    ret = BIO_flush(out);
     BIO_pop(out);
     BIO_free(bf);
+    if (ret <= 0)
+        return 0;
+
     return 1;
 }
 
diff --git a/crypto/openssl/crypto/asn1/bio_asn1.c b/crypto/openssl/crypto/asn1/bio_asn1.c
index 914d77c866c6..17b0d1aa6cad 100644
--- a/crypto/openssl/crypto/asn1/bio_asn1.c
+++ b/crypto/openssl/crypto/asn1/bio_asn1.c
@@ -172,7 +172,7 @@ static int asn1_bio_write(BIO *b, const char *in, int inl)
         case ASN1_STATE_START:
             if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
                                    ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
-                return 0;
+                return -1;
             break;
 
             /* Copy any pre data first */
@@ -189,7 +189,7 @@ static int asn1_bio_write(BIO *b, const char *in, int inl)
         case ASN1_STATE_HEADER:
             ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
             if (!ossl_assert(ctx->buflen <= ctx->bufsize))
-                return 0;
+                return -1;
             p = ctx->buf;
             ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
             ctx->copylen = inl;
diff --git a/crypto/openssl/crypto/asn1/bio_ndef.c b/crypto/openssl/crypto/asn1/bio_ndef.c
index 760e4846a474..c8a776b482d0 100644
--- a/crypto/openssl/crypto/asn1/bio_ndef.c
+++ b/crypto/openssl/crypto/asn1/bio_ndef.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-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
@@ -49,12 +49,19 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
                             void *parg);
 
+/*
+ * On success, the returned BIO owns the input BIO as part of its BIO chain.
+ * On failure, NULL is returned and the input BIO is owned by the caller.
+ *
+ * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream()
+ */
 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
 {
     NDEF_SUPPORT *ndef_aux = NULL;
     BIO *asn_bio = NULL;
     const ASN1_AUX *aux = it->funcs;
     ASN1_STREAM_ARG sarg;
+    BIO *pop_bio = NULL;
 
     if (!aux || !aux->asn1_cb) {
         ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
@@ -69,21 +76,39 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
     out = BIO_push(asn_bio, out);
     if (out == NULL)
         goto err;
+    pop_bio = asn_bio;
 
-    BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
-    BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
+    if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0
+            || BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0
+            || BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0)
+        goto err;
 
     /*
-     * Now let callback prepends any digest, cipher etc BIOs ASN1 structure
-     * needs.
+     * Now let the callback prepend any digest, cipher, etc., that the BIO's
+     * ASN1 structure needs.
      */
 
     sarg.out = out;
     sarg.ndef_bio = NULL;
     sarg.boundary = NULL;
 
-    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
+    /*
+     * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the
+     * middle of some partially built, but not returned BIO chain.
+     */
+    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) {
+        /*
+         * ndef_aux is now owned by asn_bio so we must not free it in the err
+         * clean up block
+         */
+        ndef_aux = NULL;
         goto err;
+    }
+
+    /*
+     * We must not fail now because the callback has prepended additional
+     * BIOs to the chain
+     */
 
     ndef_aux->val = val;
     ndef_aux->it = it;
@@ -91,11 +116,11 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
     ndef_aux->boundary = sarg.boundary;
     ndef_aux->out = out;
 
-    BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
-
     return sarg.ndef_bio;
 
  err:
+    /* BIO_pop() is NULL safe */
+    (void)BIO_pop(pop_bio);
     BIO_free(asn_bio);
     OPENSSL_free(ndef_aux);
     return NULL;
diff --git a/crypto/openssl/crypto/bio/b_print.c b/crypto/openssl/crypto/bio/b_print.c
index 41b7f5e2f61d..45d4e9f004b1 100644
--- a/crypto/openssl/crypto/bio/b_print.c
+++ b/crypto/openssl/crypto/bio/b_print.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2020 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
  * this file except in compliance with the License.  You can obtain a copy
@@ -13,6 +13,7 @@
 #include "crypto/ctype.h"
 #include "internal/numbers.h"
 #include <openssl/bio.h>
+#include <openssl/opensslconf.h>
 
 /*
  * Copyright Patrick Powell 1995
@@ -31,8 +32,10 @@ static int fmtstr(char **, char **, size_t *, size_t *,
                   const char *, int, int, int);
 static int fmtint(char **, char **, size_t *, size_t *,
                   int64_t, int, int, int, int);
+#ifndef OPENSSL_SYS_UEFI
 static int fmtfp(char **, char **, size_t *, size_t *,
                  LDOUBLE, int, int, int, int);
+#endif
 static int doapr_outch(char **, char **, size_t *, size_t *, int);
 static int _dopr(char **sbuffer, char **buffer,
                  size_t *maxlen, size_t *retlen, int *truncated,
@@ -88,7 +91,9 @@ _dopr(char **sbuffer,
 {
     char ch;
     int64_t value;
+#ifndef OPENSSL_SYS_UEFI
     LDOUBLE fvalue;
+#endif
     char *strvalue;
     int min;
     int max;
@@ -259,6 +264,7 @@ _dopr(char **sbuffer,
                             min, max, flags))
                     return 0;
                 break;
+#ifndef OPENSSL_SYS_UEFI
             case 'f':
                 if (cflags == DP_C_LDOUBLE)
                     fvalue = va_arg(args, LDOUBLE);
@@ -292,6 +298,16 @@ _dopr(char **sbuffer,
                            flags, G_FORMAT))
                     return 0;
                 break;
+#else
+            case 'f':
+            case 'E':
+            case 'e':
+            case 'G':
+            case 'g':
+                /* not implemented for UEFI */
+                ERR_raise(ERR_LIB_BIO, ERR_R_UNSUPPORTED);
+                return 0;
+#endif
             case 'c':
                 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
                                  va_arg(args, int)))
@@ -512,6 +528,8 @@ fmtint(char **sbuffer,
     return 1;
 }
 
+#ifndef OPENSSL_SYS_UEFI
+
 static LDOUBLE abs_val(LDOUBLE value)
 {
     LDOUBLE result = value;
@@ -803,6 +821,8 @@ fmtfp(char **sbuffer,
     return 1;
 }
 
+#endif /* OPENSSL_SYS_UEFI */
+
 #define BUFFER_INC  1024
 
 static int
diff --git a/crypto/openssl/crypto/bn/bn_blind.c b/crypto/openssl/crypto/bn/bn_blind.c
index 76fc7ebcffc0..dd5beea7c93e 100644
--- a/crypto/openssl/crypto/bn/bn_blind.c
+++ b/crypto/openssl/crypto/bn/bn_blind.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1998-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
@@ -13,20 +13,6 @@
 
 #define BN_BLINDING_COUNTER     32
 
-struct bn_blinding_st {
-    BIGNUM *A;
-    BIGNUM *Ai;
-    BIGNUM *e;
-    BIGNUM *mod;                /* just a reference */
-    CRYPTO_THREAD_ID tid;
-    int counter;
-    unsigned long flags;
-    BN_MONT_CTX *m_ctx;
-    int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
-    CRYPTO_RWLOCK *lock;
-};
-
 BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
 {
     BN_BLINDING *ret = NULL;
diff --git a/crypto/openssl/crypto/bn/bn_err.c b/crypto/openssl/crypto/bn/bn_err.c
index dd87c152cf37..6f5464b54054 100644
--- a/crypto/openssl/crypto/bn/bn_err.c
+++ b/crypto/openssl/crypto/bn/bn_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 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
  * this file except in compliance with the License.  You can obtain a copy
@@ -73,6 +73,8 @@ static const ERR_STRING_DATA BN_str_functs[] = {
     {ERR_PACK(ERR_LIB_BN, BN_F_BN_SET_WORDS, 0), "bn_set_words"},
     {ERR_PACK(ERR_LIB_BN, BN_F_BN_STACK_PUSH, 0), "BN_STACK_push"},
     {ERR_PACK(ERR_LIB_BN, BN_F_BN_USUB, 0), "BN_usub"},
+    {ERR_PACK(ERR_LIB_BN, BN_F_OSSL_BN_RSA_DO_UNBLIND, 0),
+    "ossl_bn_rsa_do_unblind"},
     {0, NULL}
 };
 
diff --git a/crypto/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c
index e21dcff027c5..517e3c29fc70 100644
--- a/crypto/openssl/crypto/bn/bn_exp.c
+++ b/crypto/openssl/crypto/bn/bn_exp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -37,6 +37,15 @@ extern unsigned int OPENSSL_sparcv9cap_P[];
 /* maximum precomputation table size for *variable* sliding windows */
 #define TABLE_SIZE      32
 
+/*
+ * Beyond this limit the constant time code is disabled due to
+ * the possible overflow in the computation of powerbufLen in
+ * BN_mod_exp_mont_consttime.
+ * When this limit is exceeded, the computation will be done using
+ * non-constant time code, but it will take very long.
+ */
+#define BN_CONSTTIME_SIZE_LIMIT (INT_MAX / BN_BYTES / 256)
+
 /* this one works - simple but works */
 int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
 {
@@ -305,12 +314,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
     BIGNUM *val[TABLE_SIZE];
     BN_MONT_CTX *mont = NULL;
 
-    if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
-            || BN_get_flags(a, BN_FLG_CONSTTIME) != 0
-            || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) {
-        return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
-    }
-
     bn_check_top(a);
     bn_check_top(p);
     bn_check_top(m);
@@ -319,6 +322,14 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
         BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);
         return 0;
     }
+
+    if (m->top <= BN_CONSTTIME_SIZE_LIMIT
+        && (BN_get_flags(p, BN_FLG_CONSTTIME) != 0
+            || BN_get_flags(a, BN_FLG_CONSTTIME) != 0
+            || BN_get_flags(m, BN_FLG_CONSTTIME) != 0)) {
+        return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
+    }
+
     bits = BN_num_bits(p);
     if (bits == 0) {
         /* x**0 mod 1, or x**0 mod -1 is still zero. */
@@ -618,6 +629,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
 
     top = m->top;
 
+    if (top > BN_CONSTTIME_SIZE_LIMIT) {
+        /* Prevent overflowing the powerbufLen computation below */
+        return BN_mod_exp_mont(rr, a, p, m, ctx, in_mont);
+    }
+
     /*
      * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak
      * whether the top bits are zero.
@@ -697,7 +713,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
     else
 #endif
 #if defined(OPENSSL_BN_ASM_MONT5)
-    if (window >= 5) {
+    if (window >= 5 && top <= BN_SOFT_LIMIT) {
         window = 5;             /* ~5% improvement for RSA2048 sign, and even
                                  * for RSA4096 */
         /* reserve space for mont->N.d[] copy */
@@ -758,6 +774,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
     if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
         goto err;
 
+    if (top > BN_SOFT_LIMIT)
+        goto fallback;
+
 #if defined(SPARC_T4_MONT)
     if (t4) {
         typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np,
@@ -1029,6 +1048,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
     } else
 #endif
     {
+ fallback:
         if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, window))
             goto err;
         if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window))
diff --git a/crypto/openssl/crypto/bn/bn_local.h b/crypto/openssl/crypto/bn/bn_local.h
index 8ad69ccd3639..30b7614fdbb2 100644
--- a/crypto/openssl/crypto/bn/bn_local.h
+++ b/crypto/openssl/crypto/bn/bn_local.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2020 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
  * this file except in compliance with the License.  You can obtain a copy
@@ -35,6 +35,26 @@
 /* #define BN_DEBUG */
 /* #define BN_DEBUG_RAND */
 
+/*
+ * This should limit the stack usage due to alloca to about 4K.
+ * BN_SOFT_LIMIT is a soft limit equivalent to 2*OPENSSL_RSA_MAX_MODULUS_BITS.
+ * Beyond that size bn_mul_mont is no longer used, and the constant time
+ * assembler code is disabled, due to the blatant alloca and bn_mul_mont usage.
+ * Note that bn_mul_mont does an alloca that is hidden away in assembly.
+ * It is not recommended to do computations with numbers exceeding this limit,
+ * since the result will be highly version dependent:
+ * While the current OpenSSL version will use non-optimized, but safe code,
+ * previous versions will use optimized code, that may crash due to unexpected
+ * stack overflow, and future versions may very well turn this into a hard
+ * limit.
+ * Note however, that it is possible to override the size limit using
+ * "./config -DBN_SOFT_LIMIT=<limit>" if necessary, and the O/S specific
+ * stack limit is known and taken into consideration.
+ */
+# ifndef BN_SOFT_LIMIT
+#  define BN_SOFT_LIMIT         (4096 / BN_BYTES)
+# endif
+
 # ifndef OPENSSL_SMALL_FOOTPRINT
 #  define BN_MUL_COMBA
 #  define BN_SQR_COMBA
@@ -263,6 +283,20 @@ struct bn_gencb_st {
     } cb;
 };
 
+struct bn_blinding_st {
+    BIGNUM *A;
+    BIGNUM *Ai;
+    BIGNUM *e;
+    BIGNUM *mod;                /* just a reference */
+    CRYPTO_THREAD_ID tid;
+    int counter;
+    unsigned long flags;
+    BN_MONT_CTX *m_ctx;
+    int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+    CRYPTO_RWLOCK *lock;
+};
+
 /*-
  * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
  *
diff --git a/crypto/openssl/crypto/bn/bn_mont.c b/crypto/openssl/crypto/bn/bn_mont.c
index 1e5045a010bb..7617b0df5e70 100644
--- a/crypto/openssl/crypto/bn/bn_mont.c
+++ b/crypto/openssl/crypto/bn/bn_mont.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2018 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
  * this file except in compliance with the License.  You can obtain a copy
@@ -42,7 +42,7 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
     int num = mont->N.top;
 
 #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
-    if (num > 1 && a->top == num && b->top == num) {
+    if (num > 1 && num <= BN_SOFT_LIMIT && a->top == num && b->top == num) {
         if (bn_wexpand(r, num) == NULL)
             return 0;
         if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
diff --git a/crypto/openssl/crypto/bn/build.info b/crypto/openssl/crypto/bn/build.info
index b9ed5322fa68..c9fe2fdada69 100644
--- a/crypto/openssl/crypto/bn/build.info
+++ b/crypto/openssl/crypto/bn/build.info
@@ -5,7 +5,8 @@ SOURCE[../../libcrypto]=\
         bn_kron.c bn_sqrt.c bn_gcd.c bn_prime.c bn_err.c bn_sqr.c \
         {- $target{bn_asm_src} -} \
         bn_recp.c bn_mont.c bn_mpi.c bn_exp2.c bn_gf2m.c bn_nist.c \
-        bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c
+        bn_depr.c bn_const.c bn_x931p.c bn_intern.c bn_dh.c bn_srp.c \
+        rsa_sup_mul.c
 
 INCLUDE[bn_exp.o]=..
 
diff --git a/crypto/openssl/crypto/bn/rsa_sup_mul.c b/crypto/openssl/crypto/bn/rsa_sup_mul.c
new file mode 100644
index 000000000000..acafefd5febf
--- /dev/null
+++ b/crypto/openssl/crypto/bn/rsa_sup_mul.c
@@ -0,0 +1,614 @@
+#include <openssl/e_os2.h>
+#include <stddef.h>
+#include <sys/types.h>
+#include <string.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/rsaerr.h>
+#include "internal/numbers.h"
+#include "internal/constant_time.h"
+#include "bn_local.h"
+
+# if BN_BYTES == 8
+typedef uint64_t limb_t;
+#  if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16
+/* nonstandard; implemented by gcc on 64-bit platforms */
+typedef __uint128_t limb2_t;
+#   define HAVE_LIMB2_T
+#  endif
+#  define LIMB_BIT_SIZE 64
+#  define LIMB_BYTE_SIZE 8
+# elif BN_BYTES == 4
+typedef uint32_t limb_t;
+typedef uint64_t limb2_t;
+#  define LIMB_BIT_SIZE 32
+#  define LIMB_BYTE_SIZE 4
+#  define HAVE_LIMB2_T
+# else
+#  error "Not supported"
+# endif
+
+/*
+ * For multiplication we're using schoolbook multiplication,
+ * so if we have two numbers, each with 6 "digits" (words)
+ * the multiplication is calculated as follows:
+ *                        A B C D E F
+ *                     x  I J K L M N
+ *                     --------------
+ *                                N*F
+ *                              N*E
+ *                            N*D
+ *                          N*C
+ *                        N*B
+ *                      N*A
+ *                              M*F
+ *                            M*E
+ *                          M*D
+ *                        M*C
+ *                      M*B
+ *                    M*A
+ *                            L*F
+ *                          L*E
+ *                        L*D
+ *                      L*C
+ *                    L*B
+ *                  L*A
+ *                          K*F
+ *                        K*E
+ *                      K*D
+ *                    K*C
+ *                  K*B
+ *                K*A
+ *                        J*F
+ *                      J*E
+ *                    J*D
+ *                  J*C
+ *                J*B
+ *              J*A
+ *                      I*F
+ *                    I*E
+ *                  I*D
+ *                I*C
+ *              I*B
+ *         +  I*A
+ *         ==========================
+ *                        N*B N*D N*F
+ *                    + N*A N*C N*E
+ *                    + M*B M*D M*F
+ *                  + M*A M*C M*E
+ *                  + L*B L*D L*F
+ *                + L*A L*C L*E
+ *                + K*B K*D K*F
+ *              + K*A K*C K*E
+ *              + J*B J*D J*F
+ *            + J*A J*C J*E
+ *            + I*B I*D I*F
+ *          + I*A I*C I*E
+ *
+ *                1+1 1+3 1+5
+ *              1+0 1+2 1+4
+ *              0+1 0+3 0+5
+ *            0+0 0+2 0+4
+ *
+ *            0 1 2 3 4 5 6
+ * which requires n^2 multiplications and 2n full length additions
+ * as we can keep every other result of limb multiplication in two separate
+ * limbs
+ */
+
+#if defined HAVE_LIMB2_T
+static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
+{
+    limb2_t t;
+    /*
+     * this is idiomatic code to tell compiler to use the native mul
+     * those three lines will actually compile to single instruction
+     */
+
+    t = (limb2_t)a * b;
+    *hi = t >> LIMB_BIT_SIZE;
+    *lo = (limb_t)t;
+}
+#elif (BN_BYTES == 8) && (defined _MSC_VER)
+/* https://learn.microsoft.com/en-us/cpp/intrinsics/umul128?view=msvc-170 */
+#pragma intrinsic(_umul128)
+static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
+{
+    *lo = _umul128(a, b, hi);
+}
+#else
+/*
+ * if the compiler doesn't have either a 128bit data type nor a "return
+ * high 64 bits of multiplication"
+ */
+static ossl_inline void _mul_limb(limb_t *hi, limb_t *lo, limb_t a, limb_t b)
+{
+    limb_t a_low = (limb_t)(uint32_t)a;
+    limb_t a_hi = a >> 32;
+    limb_t b_low = (limb_t)(uint32_t)b;
+    limb_t b_hi = b >> 32;
+
+    limb_t p0 = a_low * b_low;
+    limb_t p1 = a_low * b_hi;
+    limb_t p2 = a_hi * b_low;
+    limb_t p3 = a_hi * b_hi;
+
+    uint32_t cy = (uint32_t)(((p0 >> 32) + (uint32_t)p1 + (uint32_t)p2) >> 32);
+
+    *lo = p0 + (p1 << 32) + (p2 << 32);
+    *hi = p3 + (p1 >> 32) + (p2 >> 32) + cy;
+}
+#endif
+
+/* add two limbs with carry in, return carry out */
+static ossl_inline limb_t _add_limb(limb_t *ret, limb_t a, limb_t b, limb_t carry)
+{
+    limb_t carry1, carry2, t;
+    /*
+     * `c = a + b; if (c < a)` is idiomatic code that makes compilers
+     * use add with carry on assembly level
+     */
+
+    *ret = a + carry;
+    if (*ret < a)
+        carry1 = 1;
+    else
+        carry1 = 0;
+
+    t = *ret;
+    *ret = t + b;
+    if (*ret < t)
+        carry2 = 1;
+    else
+        carry2 = 0;
+
+    return carry1 + carry2;
+}
+
+/*
+ * add two numbers of the same size, return overflow
+ *
+ * add a to b, place result in ret; all arrays need to be n limbs long
+ * return overflow from addition (0 or 1)
+ */
+static ossl_inline limb_t add(limb_t *ret, limb_t *a, limb_t *b, size_t n)
+{
+    limb_t c = 0;
+    ossl_ssize_t i;
+
+    for(i = n - 1; i > -1; i--)
+        c = _add_limb(&ret[i], a[i], b[i], c);
+
+    return c;
+}
+
+/*
+ * return number of limbs necessary for temporary values
+ * when multiplying numbers n limbs large
+ */
+static ossl_inline size_t mul_limb_numb(size_t n)
+{
+    return  2 * n * 2;
+}
+
+/*
+ * multiply two numbers of the same size
+ *
+ * multiply a by b, place result in ret; a and b need to be n limbs long
+ * ret needs to be 2*n limbs long, tmp needs to be mul_limb_numb(n) limbs
+ * long
+ */
+static void limb_mul(limb_t *ret, limb_t *a, limb_t *b, size_t n, limb_t *tmp)
+{
+    limb_t *r_odd, *r_even;
+    size_t i, j, k;
+
+    r_odd = tmp;
+    r_even = &tmp[2 * n];
+
+    memset(ret, 0, 2 * n * sizeof(limb_t));
+
+    for (i = 0; i < n; i++) {
+        for (k = 0; k < i + n + 1; k++) {
+            r_even[k] = 0;
+            r_odd[k] = 0;
+        }
+        for (j = 0; j < n; j++) {
+            /*
+             * place results from even and odd limbs in separate arrays so that
+             * we don't have to calculate overflow every time we get individual
+             * limb multiplication result
+             */
+            if (j % 2 == 0)
+                _mul_limb(&r_even[i + j], &r_even[i + j + 1], a[i], b[j]);
+            else
+                _mul_limb(&r_odd[i + j], &r_odd[i + j + 1], a[i], b[j]);
+        }
+        /*
+         * skip the least significant limbs when adding multiples of
+         * more significant limbs (they're zero anyway)
+         */
+        add(ret, ret, r_even, n + i + 1);
+        add(ret, ret, r_odd, n + i + 1);
+    }
+}
+
+/* modifies the value in place by performing a right shift by one bit */
+static ossl_inline void rshift1(limb_t *val, size_t n)
+{
+    limb_t shift_in = 0, shift_out = 0;
+    size_t i;
+
+    for (i = 0; i < n; i++) {
+        shift_out = val[i] & 1;
+        val[i] = shift_in << (LIMB_BIT_SIZE - 1) | (val[i] >> 1);
+        shift_in = shift_out;
+    }
+}
+
+/* extend the LSB of flag to all bits of limb */
+static ossl_inline limb_t mk_mask(limb_t flag)
+{
+    flag |= flag << 1;
+    flag |= flag << 2;
+    flag |= flag << 4;
+    flag |= flag << 8;
+    flag |= flag << 16;
+#if (LIMB_BYTE_SIZE == 8)
+    flag |= flag << 32;
+#endif
+    return flag;
+}
+
+/*
+ * copy from either a or b to ret based on flag
+ * when flag == 0, then copies from b
+ * when flag == 1, then copies from a
+ */
+static ossl_inline void cselect(limb_t flag, limb_t *ret, limb_t *a, limb_t *b, size_t n)
+{
+    /*
+     * would be more efficient with non volatile mask, but then gcc
+     * generates code with jumps
+     */
+    volatile limb_t mask;
+    size_t i;
+
+    mask = mk_mask(flag);
+    for (i = 0; i < n; i++) {
+#if (LIMB_BYTE_SIZE == 8)
+        ret[i] = constant_time_select_64(mask, a[i], b[i]);
+#else
+        ret[i] = constant_time_select_32(mask, a[i], b[i]);
+#endif
+    }
+}
+
*** 834 LINES SKIPPED ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302072240.317MerM1046361>