diff --git a/cmake/external_libs/openssl.cmake b/cmake/external_libs/openssl.cmake index b807fe73357..a545bb3dc0b 100644 --- a/cmake/external_libs/openssl.cmake +++ b/cmake/external_libs/openssl.cmake @@ -28,7 +28,15 @@ if(BUILD_LITE) CONFIGURE_COMMAND ./Configure android-arm64 -D__ANDROID_API__=29 no-zlib PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3711.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3712.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-4160.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-0778.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-1292.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2068.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2097.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4304.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4450.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0215.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0286.patch ) elseif(PLATFORM_ARM32 AND ANDROID_NDK_TOOLCHAIN_INCLUDED) set(ANDROID_NDK_ROOT $ENV{ANDROID_NDK}) @@ -44,7 +52,15 @@ if(BUILD_LITE) CONFIGURE_COMMAND ./Configure android-arm -D__ANDROID_API__=19 no-zlib PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3711.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3712.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-4160.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-0778.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-1292.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2068.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2097.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4304.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4450.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0215.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0286.patch ) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux" OR APPLE) mindspore_add_pkg(openssl @@ -55,7 +71,15 @@ if(BUILD_LITE) CONFIGURE_COMMAND ./config no-zlib PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3711.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3712.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-4160.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-0778.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-1292.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2068.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2097.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4304.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4450.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0215.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0286.patch ) else() MESSAGE(FATAL_ERROR "openssl does not support compilation for the current environment.") @@ -74,7 +98,15 @@ else() CONFIGURE_COMMAND ./config no-zlib no-shared PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3711.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-3712.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2021-4160.patch PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-0778.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-1292.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2068.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-2097.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4304.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2022-4450.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0215.patch + PATCHES ${OPENSSL_PATCH_ROOT}/CVE-2023-0286.patch ) include_directories(${openssl_INC}) add_library(mindspore::ssl ALIAS openssl::ssl) diff --git a/third_party/patch/openssl/CVE-2021-4160.patch b/third_party/patch/openssl/CVE-2021-4160.patch new file mode 100644 index 00000000000..c5773f5b9f1 --- /dev/null +++ b/third_party/patch/openssl/CVE-2021-4160.patch @@ -0,0 +1,78 @@ +diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl +index 95cb227dc5..91b7aac6e7 100644 +--- a/crypto/bn/asm/mips.pl ++++ b/crypto/bn/asm/mips.pl +@@ -1986,6 +1986,8 @@ $code.=<<___; + sltu $at,$c_2,$t_1 + $ADDU $c_3,$t_2,$at + $ST $c_2,$BNSZ($a0) ++ sltu $at,$c_3,$t_2 ++ $ADDU $c_1,$at + mflo ($t_1,$a_2,$a_0) + mfhi ($t_2,$a_2,$a_0) + ___ +@@ -2196,6 +2198,8 @@ $code.=<<___; + sltu $at,$c_2,$t_1 + $ADDU $c_3,$t_2,$at + $ST $c_2,$BNSZ($a0) ++ sltu $at,$c_3,$t_2 ++ $ADDU $c_1,$at + mflo ($t_1,$a_2,$a_0) + mfhi ($t_2,$a_2,$a_0) + ___ +diff --git a/test/bntest.c b/test/bntest.c +index 87e5c4065b..fa9fc07cef 100644 +--- a/test/bntest.c ++++ b/test/bntest.c +@@ -630,6 +630,51 @@ static int test_modexp_mont5(void) + if (!TEST_BN_eq(c, d)) + goto err; + ++ /* ++ * Regression test for overflow bug in bn_sqr_comba4/8 for ++ * mips-linux-gnu and mipsel-linux-gnu 32bit targets. ++ */ ++ { ++ static const char *ehex[] = { ++ "95564994a96c45954227b845a1e99cb939d5a1da99ee91acc962396ae999a9ee", ++ "38603790448f2f7694c242a875f0cad0aae658eba085f312d2febbbd128dd2b5", ++ "8f7d1149f03724215d704344d0d62c587ae3c5939cba4b9b5f3dc5e8e911ef9a", ++ "5ce1a5a749a4989d0d8368f6e1f8cdf3a362a6c97fb02047ff152b480a4ad985", ++ "2d45efdf0770542992afca6a0590d52930434bba96017afbc9f99e112950a8b1", ++ "a359473ec376f329bdae6a19f503be6d4be7393c4e43468831234e27e3838680", ++ "b949390d2e416a3f9759e5349ab4c253f6f29f819a6fe4cbfd27ada34903300e", ++ "da021f62839f5878a36f1bc3085375b00fd5fa3e68d316c0fdace87a97558465", ++ NULL}; ++ static const char *phex[] = { ++ "f95dc0f980fbd22e90caa5a387cc4a369f3f830d50dd321c40db8c09a7e1a241", ++ "a536e096622d3280c0c1ba849c1f4a79bf490f60006d081e8cf69960189f0d31", ++ "2cd9e17073a3fba7881b21474a13b334116cb2f5dbf3189a6de3515d0840f053", ++ "c776d3982d391b6d04d642dda5cc6d1640174c09875addb70595658f89efb439", ++ "dc6fbd55f903aadd307982d3f659207f265e1ec6271b274521b7a5e28e8fd7a5", ++ "5df089292820477802a43cf5b6b94e999e8c9944ddebb0d0e95a60f88cb7e813", ++ "ba110d20e1024774107dd02949031864923b3cb8c3f7250d6d1287b0a40db6a4", ++ "7bd5a469518eb65aa207ddc47d8c6e5fc8e0c105be8fc1d4b57b2e27540471d5", ++ NULL}; ++ static const char *mhex[] = { ++ "fef15d5ce4625f1bccfbba49fc8439c72bf8202af039a2259678941b60bb4a8f", ++ "2987e965d58fd8cf86a856674d519763d0e1211cc9f8596971050d56d9b35db3", ++ "785866cfbca17cfdbed6060be3629d894f924a89fdc1efc624f80d41a22f1900", ++ "9503fcc3824ef62ccb9208430c26f2d8ceb2c63488ec4c07437aa4c96c43dd8b", ++ "9289ed00a712ff66ee195dc71f5e4ead02172b63c543d69baf495f5fd63ba7bc", ++ "c633bd309c016e37736da92129d0b053d4ab28d21ad7d8b6fab2a8bbdc8ee647", ++ "d2fbcf2cf426cf892e6f5639e0252993965dfb73ccd277407014ea784aaa280c", ++ "b7b03972bc8b0baa72360bdb44b82415b86b2f260f877791cd33ba8f2d65229b", ++ NULL}; ++ ++ if (!TEST_true(parse_bigBN(&e, ehex)) ++ || !TEST_true(parse_bigBN(&p, phex)) ++ || !TEST_true(parse_bigBN(&m, mhex)) ++ || !TEST_true(BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) ++ || !TEST_true(BN_mod_exp_simple(a, e, p, m, ctx)) ++ || !TEST_BN_eq(a, d)) ++ goto err; ++ } ++ + /* Zero input */ + if (!TEST_true(BN_bntest_rand(p, 1024, 0, 0))) + goto err; \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2022-1292.patch b/third_party/patch/openssl/CVE-2022-1292.patch new file mode 100644 index 00000000000..d07162220b5 --- /dev/null +++ b/third_party/patch/openssl/CVE-2022-1292.patch @@ -0,0 +1,58 @@ +diff --git a/tools/c_rehash.in b/tools/c_rehash.in +index fa7c6c9fef..83c1cc80e0 100644 +--- a/tools/c_rehash.in ++++ b/tools/c_rehash.in +@@ -152,6 +152,23 @@ sub check_file { + return ($is_cert, $is_crl); + } + ++sub compute_hash { ++ my $fh; ++ if ( $^O eq "VMS" ) { ++ # VMS uses the open through shell ++ # The file names are safe there and list form is unsupported ++ if (!open($fh, "-|", join(' ', @_))) { ++ print STDERR "Cannot compute hash on '$fname'\n"; ++ return; ++ } ++ } else { ++ if (!open($fh, "-|", @_)) { ++ print STDERR "Cannot compute hash on '$fname'\n"; ++ return; ++ } ++ } ++ return (<$fh>, <$fh>); ++} + + # Link a certificate to its subject name hash value, each hash is of + # the form . where n is an integer. If the hash value already exists +@@ -161,10 +178,12 @@ sub check_file { + + sub link_hash_cert { + my $fname = $_[0]; +- $fname =~ s/\"/\\\"/g; +- my ($hash, $fprint) = `"$openssl" x509 $x509hash -fingerprint -noout -in "$fname"`; ++ my ($hash, $fprint) = compute_hash($openssl, "x509", $x509hash, ++ "-fingerprint", "-noout", ++ "-in", $fname); + chomp $hash; + chomp $fprint; ++ return if !$hash; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; +@@ -202,10 +221,12 @@ sub link_hash_cert { + + sub link_hash_crl { + my $fname = $_[0]; +- $fname =~ s/'/'\\''/g; +- my ($hash, $fprint) = `"$openssl" crl $crlhash -fingerprint -noout -in '$fname'`; ++ my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash, ++ "-fingerprint", "-noout", ++ "-in", $fname); + chomp $hash; + chomp $fprint; ++ return if !$hash; + $fprint =~ s/^.*=//; + $fprint =~ tr/://d; + my $suffix = 0; \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2022-2068.patch b/third_party/patch/openssl/CVE-2022-2068.patch new file mode 100644 index 00000000000..fde78b92782 --- /dev/null +++ b/third_party/patch/openssl/CVE-2022-2068.patch @@ -0,0 +1,241 @@ +diff --git a/tools/c_rehash.in b/tools/c_rehash.in +index cfd18f5da1..9d2a6f6db7 100644 +--- a/tools/c_rehash.in ++++ b/tools/c_rehash.in +@@ -104,52 +104,78 @@ foreach (@dirlist) { + } + exit($errorcount); + ++sub copy_file { ++ my ($src_fname, $dst_fname) = @_; ++ ++ if (open(my $in, "<", $src_fname)) { ++ if (open(my $out, ">", $dst_fname)) { ++ print $out $_ while (<$in>); ++ close $out; ++ } else { ++ warn "Cannot open $dst_fname for write, $!"; ++ } ++ close $in; ++ } else { ++ warn "Cannot open $src_fname for read, $!"; ++ } ++} ++ + sub hash_dir { +- my %hashlist; +- print "Doing $_[0]\n"; +- chdir $_[0]; +- opendir(DIR, "."); +- my @flist = sort readdir(DIR); +- closedir DIR; +- if ( $removelinks ) { +- # Delete any existing symbolic links +- foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { +- if (-l $_) { +- print "unlink $_" if $verbose; +- unlink $_ || warn "Can't unlink $_, $!\n"; +- } +- } +- } +- FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) { +- # Check to see if certificates and/or CRLs present. +- my ($cert, $crl) = check_file($fname); +- if (!$cert && !$crl) { +- print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; +- next; +- } +- link_hash_cert($fname) if ($cert); +- link_hash_crl($fname) if ($crl); +- } ++ my $dir = shift; ++ my %hashlist; ++ ++ print "Doing $dir\n"; ++ ++ if (!chdir $dir) { ++ print STDERR "WARNING: Cannot chdir to '$dir', $!\n"; ++ return; ++ } ++ ++ opendir(DIR, ".") || print STDERR "WARNING: Cannot opendir '.', $!\n"; ++ my @flist = sort readdir(DIR); ++ closedir DIR; ++ if ( $removelinks ) { ++ # Delete any existing symbolic links ++ foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) { ++ if (-l $_) { ++ print "unlink $_\n" if $verbose; ++ unlink $_ || warn "Can't unlink $_, $!\n"; ++ } ++ } ++ } ++ FILE: foreach $fname (grep {/\.(pem)|(crt)|(cer)|(crl)$/} @flist) { ++ # Check to see if certificates and/or CRLs present. ++ my ($cert, $crl) = check_file($fname); ++ if (!$cert && !$crl) { ++ print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n"; ++ next; ++ } ++ link_hash_cert($fname) if ($cert); ++ link_hash_crl($fname) if ($crl); ++ } ++ ++ chdir $pwd; + } + + sub check_file { +- my ($is_cert, $is_crl) = (0,0); +- my $fname = $_[0]; +- open IN, $fname; +- while() { +- if (/^-----BEGIN (.*)-----/) { +- my $hdr = $1; +- if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { +- $is_cert = 1; +- last if ($is_crl); +- } elsif ($hdr eq "X509 CRL") { +- $is_crl = 1; +- last if ($is_cert); +- } +- } +- } +- close IN; +- return ($is_cert, $is_crl); ++ my ($is_cert, $is_crl) = (0,0); ++ my $fname = $_[0]; ++ ++ open(my $in, "<", $fname); ++ while(<$in>) { ++ if (/^-----BEGIN (.*)-----/) { ++ my $hdr = $1; ++ if ($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) { ++ $is_cert = 1; ++ last if ($is_crl); ++ } elsif ($hdr eq "X509 CRL") { ++ $is_crl = 1; ++ last if ($is_cert); ++ } ++ } ++ } ++ close $in; ++ return ($is_cert, $is_crl); + } + + sub compute_hash { +@@ -177,76 +203,48 @@ sub compute_hash { + # certificate fingerprints + + sub link_hash_cert { +- my $fname = $_[0]; +- my ($hash, $fprint) = compute_hash($openssl, "x509", $x509hash, +- "-fingerprint", "-noout", +- "-in", $fname); +- chomp $hash; +- chomp $fprint; +- return if !$hash; +- $fprint =~ s/^.*=//; +- $fprint =~ tr/://d; +- my $suffix = 0; +- # Search for an unused hash filename +- while(exists $hashlist{"$hash.$suffix"}) { +- # Hash matches: if fingerprint matches its a duplicate cert +- if ($hashlist{"$hash.$suffix"} eq $fprint) { +- print STDERR "WARNING: Skipping duplicate certificate $fname\n"; +- return; +- } +- $suffix++; +- } +- $hash .= ".$suffix"; +- if ($symlink_exists) { +- print "link $fname -> $hash\n" if $verbose; +- symlink $fname, $hash || warn "Can't symlink, $!"; +- } else { +- print "copy $fname -> $hash\n" if $verbose; +- if (open($in, "<", $fname)) { +- if (open($out,">", $hash)) { +- print $out $_ while (<$in>); +- close $out; +- } else { +- warn "can't open $hash for write, $!"; +- } +- close $in; +- } else { +- warn "can't open $fname for read, $!"; +- } +- } +- $hashlist{$hash} = $fprint; ++ link_hash($_[0], 'cert'); + } + + # Same as above except for a CRL. CRL links are of the form .r + + sub link_hash_crl { +- my $fname = $_[0]; +- my ($hash, $fprint) = compute_hash($openssl, "crl", $crlhash, +- "-fingerprint", "-noout", +- "-in", $fname); +- chomp $hash; +- chomp $fprint; +- return if !$hash; +- $fprint =~ s/^.*=//; +- $fprint =~ tr/://d; +- my $suffix = 0; +- # Search for an unused hash filename +- while(exists $hashlist{"$hash.r$suffix"}) { +- # Hash matches: if fingerprint matches its a duplicate cert +- if ($hashlist{"$hash.r$suffix"} eq $fprint) { +- print STDERR "WARNING: Skipping duplicate CRL $fname\n"; +- return; +- } +- $suffix++; +- } +- $hash .= ".r$suffix"; +- if ($symlink_exists) { +- print "link $fname -> $hash\n" if $verbose; +- symlink $fname, $hash || warn "Can't symlink, $!"; +- } else { +- print "cp $fname -> $hash\n" if $verbose; +- system ("cp", $fname, $hash); +- warn "Can't copy, $!" if ($? >> 8) != 0; +- } +- $hashlist{$hash} = $fprint; ++ link_hash($_[0], 'crl'); ++} ++ ++sub link_hash { ++ my ($fname, $type) = @_; ++ my $is_cert = $type eq 'cert'; ++ ++ my ($hash, $fprint) = compute_hash($openssl, ++ $is_cert ? "x509" : "crl", ++ $is_cert ? $x509hash : $crlhash, ++ "-fingerprint", "-noout", ++ "-in", $fname); ++ chomp $hash; ++ chomp $fprint; ++ return if !$hash; ++ $fprint =~ s/^.*=//; ++ $fprint =~ tr/://d; ++ my $suffix = 0; ++ # Search for an unused hash filename ++ my $crlmark = $is_cert ? "" : "r"; ++ while(exists $hashlist{"$hash.$crlmark$suffix"}) { ++ # Hash matches: if fingerprint matches its a duplicate cert ++ if ($hashlist{"$hash.$crlmark$suffix"} eq $fprint) { ++ my $what = $is_cert ? 'certificate' : 'CRL'; ++ print STDERR "WARNING: Skipping duplicate $what $fname\n"; ++ return; ++ } ++ $suffix++; ++ } ++ $hash .= ".$crlmark$suffix"; ++ if ($symlink_exists) { ++ print "link $fname -> $hash\n" if $verbose; ++ symlink $fname, $hash || warn "Can't symlink, $!"; ++ } else { ++ print "copy $fname -> $hash\n" if $verbose; ++ copy_file($fname, $hash); ++ } ++ $hashlist{$hash} = $fprint; + } \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2022-2097.patch b/third_party/patch/openssl/CVE-2022-2097.patch new file mode 100644 index 00000000000..0bc4a3ab17b --- /dev/null +++ b/third_party/patch/openssl/CVE-2022-2097.patch @@ -0,0 +1,22 @@ +diff --git a/crypto/aes/asm/aesni-x86.pl b/crypto/aes/asm/aesni-x86.pl +index fe2b26542a..812758e02e 100644 +--- a/crypto/aes/asm/aesni-x86.pl ++++ b/crypto/aes/asm/aesni-x86.pl +@@ -2027,7 +2027,7 @@ my ($l_,$block,$i1,$i3,$i5) = ($rounds_,$key_,$rounds,$len,$out); + &movdqu (&QWP(-16*2,$out,$inp),$inout4); + &movdqu (&QWP(-16*1,$out,$inp),$inout5); + &cmp ($inp,$len); # done yet? +- &jb (&label("grandloop")); ++ &jbe (&label("grandloop")); + + &set_label("short"); + &add ($len,16*6); +@@ -2453,7 +2453,7 @@ my ($l_,$block,$i1,$i3,$i5) = ($rounds_,$key_,$rounds,$len,$out); + &pxor ($rndkey1,$inout5); + &movdqu (&QWP(-16*1,$out,$inp),$inout5); + &cmp ($inp,$len); # done yet? +- &jb (&label("grandloop")); ++ &jbe (&label("grandloop")); + + &set_label("short"); + &add ($len,16*6); \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2022-4304.patch b/third_party/patch/openssl/CVE-2022-4304.patch new file mode 100644 index 00000000000..b898a5073be --- /dev/null +++ b/third_party/patch/openssl/CVE-2022-4304.patch @@ -0,0 +1,771 @@ +diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c +index 76fc7ebcff..6e9d239321 100644 +--- a/crypto/bn/bn_blind.c ++++ b/crypto/bn/bn_blind.c +@@ -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/bn/bn_err.c b/crypto/bn/bn_err.c +index dd87c152cf..3dd8d9a568 100644 +--- a/crypto/bn/bn_err.c ++++ b/crypto/bn/bn_err.c +@@ -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/bn/bn_local.h b/crypto/bn/bn_local.h +index 62a969b134..4d8cb64675 100644 +--- a/crypto/bn/bn_local.h ++++ b/crypto/bn/bn_local.h +@@ -283,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/bn/build.info b/crypto/bn/build.info +index b9ed5322fa..c9fe2fdada 100644 +--- a/crypto/bn/build.info ++++ b/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/bn/rsa_sup_mul.c b/crypto/bn/rsa_sup_mul.c +new file mode 100644 +index 0000000000..acafefd5fe +--- /dev/null ++++ b/crypto/bn/rsa_sup_mul.c +@@ -0,0 +1,614 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 ++ } ++} ++ ++static limb_t _sub_limb(limb_t *ret, limb_t a, limb_t b, limb_t borrow) ++{ ++ limb_t borrow1, borrow2, t; ++ /* ++ * while it doesn't look constant-time, this is idiomatic code ++ * to tell compilers to use the carry bit from subtraction ++ */ ++ ++ *ret = a - borrow; ++ if (*ret > a) ++ borrow1 = 1; ++ else ++ borrow1 = 0; ++ ++ t = *ret; ++ *ret = t - b; ++ if (*ret > t) ++ borrow2 = 1; ++ else ++ borrow2 = 0; ++ ++ return borrow1 + borrow2; ++} ++ ++/* ++ * place the result of a - b into ret, return the borrow bit. ++ * All arrays need to be n limbs long ++ */ ++static limb_t sub(limb_t *ret, limb_t *a, limb_t *b, size_t n) ++{ ++ limb_t borrow = 0; ++ ossl_ssize_t i; ++ ++ for (i = n - 1; i > -1; i--) ++ borrow = _sub_limb(&ret[i], a[i], b[i], borrow); ++ ++ return borrow; ++} ++ ++/* return the number of limbs necessary to allocate for the mod() tmp operand */ ++static ossl_inline size_t mod_limb_numb(size_t anum, size_t modnum) ++{ ++ return (anum + modnum) * 3; ++} ++ ++/* ++ * calculate a % mod, place the result in ret ++ * size of a is defined by anum, size of ret and mod is modnum, ++ * size of tmp is returned by mod_limb_numb() ++ */ ++static void mod(limb_t *ret, limb_t *a, size_t anum, limb_t *mod, ++ size_t modnum, limb_t *tmp) ++{ ++ limb_t *atmp, *modtmp, *rettmp; ++ limb_t res; ++ size_t i; ++ ++ memset(tmp, 0, mod_limb_numb(anum, modnum) * LIMB_BYTE_SIZE); ++ ++ atmp = tmp; ++ modtmp = &tmp[anum + modnum]; ++ rettmp = &tmp[(anum + modnum) * 2]; ++ ++ for (i = modnum; i 0; i--, rp--) { ++ v = _mul_add_limb(rp, mod, modnum, rp[modnum - 1] * ni0, tmp2); ++ v = v + carry + rp[-1]; ++ carry |= (v != rp[-1]); ++ carry &= (v <= rp[-1]); ++ rp[-1] = v; ++ } ++ ++ /* perform the final reduction by mod... */ ++ carry -= sub(ret, rp, mod, modnum); ++ ++ /* ...conditionally */ ++ cselect(carry, ret, rp, ret, modnum); ++} ++ ++/* allocated buffer should be freed afterwards */ ++static void BN_to_limb(const BIGNUM *bn, limb_t *buf, size_t limbs) ++{ ++ int i; ++ int real_limbs = (BN_num_bytes(bn) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; ++ limb_t *ptr = buf + (limbs - real_limbs); ++ ++ for (i = 0; i < real_limbs; i++) ++ ptr[i] = bn->d[real_limbs - i - 1]; ++} ++ ++#if LIMB_BYTE_SIZE == 8 ++static ossl_inline uint64_t be64(uint64_t host) ++{ ++ const union { ++ long one; ++ char little; ++ } is_endian = { 1 }; ++ ++ if (is_endian.little) { ++ uint64_t big = 0; ++ ++ big |= (host & 0xff00000000000000) >> 56; ++ big |= (host & 0x00ff000000000000) >> 40; ++ big |= (host & 0x0000ff0000000000) >> 24; ++ big |= (host & 0x000000ff00000000) >> 8; ++ big |= (host & 0x00000000ff000000) << 8; ++ big |= (host & 0x0000000000ff0000) << 24; ++ big |= (host & 0x000000000000ff00) << 40; ++ big |= (host & 0x00000000000000ff) << 56; ++ return big; ++ } else { ++ return host; ++ } ++} ++ ++#else ++/* Not all platforms have htobe32(). */ ++static ossl_inline uint32_t be32(uint32_t host) ++{ ++ const union { ++ long one; ++ char little; ++ } is_endian = { 1 }; ++ ++ if (is_endian.little) { ++ uint32_t big = 0; ++ ++ big |= (host & 0xff000000) >> 24; ++ big |= (host & 0x00ff0000) >> 8; ++ big |= (host & 0x0000ff00) << 8; ++ big |= (host & 0x000000ff) << 24; ++ return big; ++ } else { ++ return host; ++ } ++} ++#endif ++ ++/* ++ * We assume that intermediate, possible_arg2, blinding, and ctx are used ++ * similar to BN_BLINDING_invert_ex() arguments. ++ * to_mod is RSA modulus. ++ * buf and num is the serialization buffer and its length. ++ * ++ * Here we use classic/Montgomery multiplication and modulo. After the calculation finished ++ * we serialize the new structure instead of BIGNUMs taking endianness into account. ++ */ ++int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate, ++ const BN_BLINDING *blinding, ++ const BIGNUM *possible_arg2, ++ const BIGNUM *to_mod, BN_CTX *ctx, ++ unsigned char *buf, int num) ++{ ++ limb_t *l_im = NULL, *l_mul = NULL, *l_mod = NULL; ++ limb_t *l_ret = NULL, *l_tmp = NULL, l_buf; ++ size_t l_im_count = 0, l_mul_count = 0, l_size = 0, l_mod_count = 0; ++ size_t l_tmp_count = 0; ++ int ret = 0; ++ size_t i; ++ unsigned char *tmp; ++ const BIGNUM *arg1 = intermediate; ++ const BIGNUM *arg2 = (possible_arg2 == NULL) ? blinding->Ai : possible_arg2; ++ ++ l_im_count = (BN_num_bytes(arg1) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; ++ l_mul_count = (BN_num_bytes(arg2) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; ++ l_mod_count = (BN_num_bytes(to_mod) + LIMB_BYTE_SIZE - 1) / LIMB_BYTE_SIZE; ++ ++ l_size = l_im_count > l_mul_count ? l_im_count : l_mul_count; ++ l_im = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); ++ l_mul = OPENSSL_zalloc(l_size * LIMB_BYTE_SIZE); ++ l_mod = OPENSSL_zalloc(l_mod_count * LIMB_BYTE_SIZE); ++ ++ if ((l_im == NULL) || (l_mul == NULL) || (l_mod == NULL)) ++ goto err; ++ ++ BN_to_limb(arg1, l_im, l_size); ++ BN_to_limb(arg2, l_mul, l_size); ++ BN_to_limb(to_mod, l_mod, l_mod_count); ++ ++ l_ret = OPENSSL_malloc(2 * l_size * LIMB_BYTE_SIZE); ++ ++ if (blinding->m_ctx != NULL) { ++ l_tmp_count = mul_limb_numb(l_size) > mod_montgomery_limb_numb(l_mod_count) ? ++ mul_limb_numb(l_size) : mod_montgomery_limb_numb(l_mod_count); ++ l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); ++ } else { ++ l_tmp_count = mul_limb_numb(l_size) > mod_limb_numb(2 * l_size, l_mod_count) ? ++ mul_limb_numb(l_size) : mod_limb_numb(2 * l_size, l_mod_count); ++ l_tmp = OPENSSL_malloc(l_tmp_count * LIMB_BYTE_SIZE); ++ } ++ ++ if ((l_ret == NULL) || (l_tmp == NULL)) ++ goto err; ++ ++ if (blinding->m_ctx != NULL) { ++ limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); ++ mod_montgomery(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, ++ blinding->m_ctx->n0[0], l_tmp); ++ } else { ++ limb_mul(l_ret, l_im, l_mul, l_size, l_tmp); ++ mod(l_ret, l_ret, 2 * l_size, l_mod, l_mod_count, l_tmp); ++ } ++ ++ /* modulus size in bytes can be equal to num but after limbs conversion it becomes bigger */ ++ if (num < BN_num_bytes(to_mod)) { ++ BNerr(BN_F_OSSL_BN_RSA_DO_UNBLIND, ERR_R_PASSED_INVALID_ARGUMENT); ++ goto err; ++ } ++ ++ memset(buf, 0, num); ++ tmp = buf + num - BN_num_bytes(to_mod); ++ for (i = 0; i < l_mod_count; i++) { ++#if LIMB_BYTE_SIZE == 8 ++ l_buf = be64(l_ret[i]); ++#else ++ l_buf = be32(l_ret[i]); ++#endif ++ if (i == 0) { ++ int delta = LIMB_BYTE_SIZE - ((l_mod_count * LIMB_BYTE_SIZE) - num); ++ ++ memcpy(tmp, ((char *)&l_buf) + LIMB_BYTE_SIZE - delta, delta); ++ tmp += delta; ++ } else { ++ memcpy(tmp, &l_buf, LIMB_BYTE_SIZE); ++ tmp += LIMB_BYTE_SIZE; ++ } ++ } ++ ret = num; ++ ++ err: ++ OPENSSL_free(l_im); ++ OPENSSL_free(l_mul); ++ OPENSSL_free(l_mod); ++ OPENSSL_free(l_tmp); ++ OPENSSL_free(l_ret); ++ ++ return ret; ++} +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index 9f91a4a811..ba3a46d5b9 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1,4 +1,4 @@ +-# Copyright 1999-2021 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 + # this file except in compliance with the License. You can obtain a copy +@@ -232,6 +232,7 @@ BN_F_BN_RSHIFT:146:BN_rshift + BN_F_BN_SET_WORDS:144:bn_set_words + BN_F_BN_STACK_PUSH:148:BN_STACK_push + BN_F_BN_USUB:115:BN_usub ++BN_F_OSSL_BN_RSA_DO_UNBLIND:151:ossl_bn_rsa_do_unblind + BUF_F_BUF_MEM_GROW:100:BUF_MEM_grow + BUF_F_BUF_MEM_GROW_CLEAN:105:BUF_MEM_grow_clean + BUF_F_BUF_MEM_NEW:101:BUF_MEM_new +diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c +index b52a66f6a6..6c3c0cf78d 100644 +--- a/crypto/rsa/rsa_ossl.c ++++ b/crypto/rsa/rsa_ossl.c +@@ -465,11 +465,20 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + BN_free(d); + } + +- if (blinding) +- if (!rsa_blinding_invert(blinding, ret, unblind, ctx)) ++ if (blinding) { ++ /* ++ * ossl_bn_rsa_do_unblind() combines blinding inversion and ++ * 0-padded BN BE serialization ++ */ ++ j = ossl_bn_rsa_do_unblind(ret, blinding, unblind, rsa->n, ctx, ++ buf, num); ++ if (j == 0) + goto err; +- +- j = BN_bn2binpad(ret, buf, num); ++ } else { ++ j = BN_bn2binpad(ret, buf, num); ++ if (j < 0) ++ goto err; ++ } + + switch (padding) { + case RSA_PKCS1_PADDING: +diff --git a/include/crypto/bn.h b/include/crypto/bn.h +index 60afda1dad..b5f36fb25a 100644 +--- a/include/crypto/bn.h ++++ b/include/crypto/bn.h +@@ -86,5 +86,10 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); + int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n); + int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + const BIGNUM *d, BN_CTX *ctx); ++int ossl_bn_rsa_do_unblind(const BIGNUM *intermediate, ++ const BN_BLINDING *blinding, ++ const BIGNUM *possible_arg2, ++ const BIGNUM *to_mod, BN_CTX *ctx, ++ unsigned char *buf, int num); + + #endif +diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h +index 9f3c7cfaab..a0752cea52 100644 +--- a/include/openssl/bnerr.h ++++ b/include/openssl/bnerr.h +@@ -72,6 +72,7 @@ int ERR_load_BN_strings(void); + # define BN_F_BN_SET_WORDS 144 + # define BN_F_BN_STACK_PUSH 148 + # define BN_F_BN_USUB 115 ++# define BN_F_OSSL_BN_RSA_DO_UNBLIND 151 + + /* + * BN reason codes. \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2022-4450.patch b/third_party/patch/openssl/CVE-2022-4450.patch new file mode 100644 index 00000000000..3364ea75a61 --- /dev/null +++ b/third_party/patch/openssl/CVE-2022-4450.patch @@ -0,0 +1,14 @@ +diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c +index d416d939ea..328c30cdbb 100644 +--- a/crypto/pem/pem_lib.c ++++ b/crypto/pem/pem_lib.c +@@ -957,7 +957,9 @@ int PEM_read_bio_ex(BIO *bp, char **name_out, char **header, + *data = pem_malloc(len, flags); + if (*header == NULL || *data == NULL) { + pem_free(*header, flags, 0); ++ *header = NULL; + pem_free(*data, flags, 0); ++ *data = NULL; + goto end; + } + BIO_read(headerB, *header, headerlen); \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2023-0215.patch b/third_party/patch/openssl/CVE-2023-0215.patch new file mode 100644 index 00000000000..26b5cde0a9e --- /dev/null +++ b/third_party/patch/openssl/CVE-2023-0215.patch @@ -0,0 +1,144 @@ +diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c +index 760e4846a4..f8d4b1b9aa 100644 +--- a/crypto/asn1/bio_ndef.c ++++ b/crypto/asn1/bio_ndef.c +@@ -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/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t +index 5dc6a3aebe..ec11bfc253 100644 +--- a/test/recipes/80-test_cms.t ++++ b/test/recipes/80-test_cms.t +@@ -13,7 +13,7 @@ use warnings; + use POSIX; + use File::Spec::Functions qw/catfile/; + use File::Compare qw/compare_text/; +-use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file/; ++use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file with/; + use OpenSSL::Test::Utils; + + setup("test_cms"); +@@ -27,7 +27,7 @@ my $smcont = srctop_file("test", "smcont.txt"); + my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) + = disabled qw/des dh dsa ec ec2m rc2 zlib/; + +-plan tests => 6; ++plan tests => 7; + + my @smime_pkcs7_tests = ( + +@@ -584,3 +584,14 @@ sub check_availability { + + return ""; + } ++ ++# Check that we get the expected failure return code ++with({ exit_checker => sub { return shift == 6; } }, ++ sub { ++ ok(run(app(['openssl', 'cms', '-encrypt', ++ '-in', srctop_file("test", "smcont.txt"), ++ '-stream', '-recip', ++ srctop_file("test/smime-certs", "badrsa.pem"), ++ ])), ++ "Check failure during BIO setup with -stream is handled correctly"); ++ }); +diff --git a/test/smime-certs/badrsa.pem b/test/smime-certs/badrsa.pem +new file mode 100644 +index 0000000000..f824fc2267 +--- /dev/null ++++ b/test/smime-certs/badrsa.pem +@@ -0,0 +1,18 @@ ++-----BEGIN CERTIFICATE----- ++MIIDbTCCAlWgAwIBAgIToTV4Z0iuK08vZP20oTh//hC8BDANBgkqhkiG9w0BAQ0FADAtMSswKQYD ++VfcDEyJTYW1wbGUgTEFNUFMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTE5MTEyMDA2NTQxOFoY ++DzIwNTIwOTI3MDY1NDE4WjAZMRcwFQYDVQQDEw5BbGljZSBMb3ZlbGFjZTCCASIwDQYJKoZIhvcN ++AQEBBQADggEPADCCAQoCggEBALT0iehYOBY+TZp/T5K2KNI05Hwr+E3wP6XTvyi6WWyTgBK9LCOw ++I2juwdRrjFBmXkk7pWpjXwsA3A5GOtz0FpfgyC7OxsVcF7q4WHWZWleYXFKlQHJD73nQwXP968+A ++/3rBX7PhO0DBbZnfitOLPgPEwjTtdg0VQQ6Wz+CRQ/YbHPKaw7aRphZO63dKvIKp4cQVtkWQHi6s ++yTjGsgkLcLNau5LZDQUdsGV+SAo3nBdWCRYV+I65x8Kf4hCxqqmjV3d/2NKRu0BXnDe/N+iDz3X0 ++zEoj0fqXgq4SWcC0nsG1lyyXt1TL270I6ATKRGJWiQVCCpDtc0NT6vdJ45bCSxgCAwEAAaOBlzCB ++lDAMBgNVHRMBAf8EAjAAMB4GA1UdEQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1wbGUwEwYDVR0lBAww ++CgYIKwYBBQUHAwQwDwYDVR0PAQH/BAUDAwfAADAdBgNVHQ4EFgQUu/bMsi0dBhIcl64papAQ0yBm ++ZnMwHwYDVR0jBBgwFoAUeF8OWnjYa+RUcD2z3ez38fL6wEcwDQYJKoZIhvcNAQENBQADggEBABbW ++eonR6TMTckehDKNOabwaCIcekahAIL6l9tTzUX5ew6ufiAPlC6I/zQlmUaU0iSyFDG1NW14kNbFt ++5CAokyLhMtE4ASHBIHbiOp/ZSbUBTVYJZB61ot7w1/ol5QECSs08b8zrxIncf+t2DHGuVEy/Qq1d ++rBz8d4ay8zpqAE1tUyL5Da6ZiKUfWwZQXSI/JlbjQFzYQqTRDnzHWrg1xPeMTO1P2/cplFaseTiv ++yk4cYwOp/W9UAWymOZXF8WcJYCIUXkdcG/nEZxr057KlScrJmFXOoh7Y+8ON4iWYYcAfiNgpUFo/ ++j8BAwrKKaFvdlZS9k1Ypb2+UQY75mKJE9Bg= ++-----END CERTIFICATE----- \ No newline at end of file diff --git a/third_party/patch/openssl/CVE-2023-0286.patch b/third_party/patch/openssl/CVE-2023-0286.patch new file mode 100644 index 00000000000..c3915edf128 --- /dev/null +++ b/third_party/patch/openssl/CVE-2023-0286.patch @@ -0,0 +1,44 @@ +diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c +index 87a5eff47c..e54ddc55c9 100644 +--- a/crypto/x509v3/v3_genn.c ++++ b/crypto/x509v3/v3_genn.c +@@ -98,7 +98,7 @@ int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) + return -1; + switch (a->type) { + case GEN_X400: +- result = ASN1_TYPE_cmp(a->d.x400Address, b->d.x400Address); ++ result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address); + break; + + case GEN_EDIPARTY: +diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h +index 90fa3592ce..e61c0f29d4 100644 +--- a/include/openssl/x509v3.h ++++ b/include/openssl/x509v3.h +@@ -136,7 +136,7 @@ typedef struct GENERAL_NAME_st { + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; +- ASN1_TYPE *x400Address; ++ ASN1_STRING *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; +diff --git a/test/v3nametest.c b/test/v3nametest.c +index d1852190b8..37819da8fd 100644 +--- a/test/v3nametest.c ++++ b/test/v3nametest.c +@@ -646,6 +646,14 @@ static struct gennamedata { + 0xb7, 0x09, 0x02, 0x02 + }, + 15 ++ }, { ++ /* ++ * Regression test for CVE-2023-0286. ++ */ ++ { ++ 0xa3, 0x00 ++ }, ++ 2 + } + };