diff --git a/backport-Add-negative-integer-check-when-using-ASN1_BIT_STRIN.patch b/backport-Add-negative-integer-check-when-using-ASN1_BIT_STRIN.patch new file mode 100755 index 0000000000000000000000000000000000000000..bf4fff42d1c82ad939eb95adee79bcff45e31e9b --- /dev/null +++ b/backport-Add-negative-integer-check-when-using-ASN1_BIT_STRIN.patch @@ -0,0 +1,47 @@ +From 8ddacec11481a37302c19f4454e23299af399f83 Mon Sep 17 00:00:00 2001 +From: mlitre +Date: Mon, 1 May 2023 11:07:21 +0200 +Subject: [PATCH] Add negative integer check when using ASN1_BIT_STRING + +The negative integer check is done to prevent potential overflow. +Fixes #20719. + +CLA: trivial + +Reviewed-by: Tomas Mraz +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20862) + +(cherry picked from commit 1258a8e4361320cd3cfaf9ede692492ce01034c8) + +--- + crypto/asn1/a_bitstr.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c +index f462dd1073..31a1e11359 100644 +--- a/crypto/asn1/a_bitstr.c ++++ b/crypto/asn1/a_bitstr.c +@@ -148,6 +148,9 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) + int w, v, iv; + unsigned char *c; + ++ if (n < 0) ++ return 0; ++ + w = n / 8; + v = 1 << (7 - (n & 0x07)); + iv = ~v; +@@ -182,6 +185,9 @@ int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) + { + int w, v; + ++ if (n < 0) ++ return 0; ++ + w = n / 8; + v = 1 << (7 - (n & 0x07)); + if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) +-- +2.27.0 + diff --git a/backport-CVE-2022-4304-Fix-Timing-Oracle-in-RSA-decryption.patch b/backport-CVE-2022-4304-Fix-Timing-Oracle-in-RSA-decryption.patch index 626bc784c46c03f386514557692719dbdec7e32f..ba4ccd1c797ee77caf5782ec65c4a1e511755f5b 100644 --- a/backport-CVE-2022-4304-Fix-Timing-Oracle-in-RSA-decryption.patch +++ b/backport-CVE-2022-4304-Fix-Timing-Oracle-in-RSA-decryption.patch @@ -1,799 +1,464 @@ -From 43d8f88511991533f53680a751e9326999a6a31f Mon Sep 17 00:00:00 2001 -From: Matt Caswell -Date: Fri, 20 Jan 2023 15:26:54 +0000 -Subject: [PATCH] Fix Timing Oracle in RSA decryption +From 3f499b24f3bcd66db022074f7e8b4f6ee266a3ae Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Mon, 13 Feb 2023 17:46:41 +0100 +Subject: [PATCH] Alternative fix for CVE-2022-4304 -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. +NOTE: This patch replaces the original patch for +CVE-2022-4304 (43d8f88511991533f53680a751e9326999a6a31f). -Patch written by Dmitry Belyavsky and Hubert Kario +This is about a timing leak in the topmost limb +of the internal result of RSA_private_decrypt, +before the padding check. -CVE-2022-4304 +There are in fact at least three bugs together that +caused the timing leak: -Reviewed-by: Dmitry Belyavskiy +First and probably most important is the fact that +the blinding did not use the constant time code path +at all when the RSA object was used for a private +decrypt, due to the fact that the Montgomery context +rsa->_method_mod_n was not set up early enough in +rsa_ossl_private_decrypt, when BN_BLINDING_create_param +needed it, and that was persisted as blinding->m_ctx, +although the RSA object creates the Montgomery context +just a bit later. + +Then the infamous bn_correct_top was used on the +secret value right after the blinding was removed. + +And finally the function BN_bn2binpad did not use +the constant-time code path since the BN_FLG_CONSTTIME +was not set on the secret value. + +In order to address the first problem, this patch +makes sure that the rsa->_method_mod_n is initialized +right before the blinding context. + +And to fix the second problem, we add a new utility +function bn_correct_top_consttime, a const-time +variant of bn_correct_top. + +Together with the fact, that BN_bn2binpad is already +constant time if the flag BN_FLG_CONSTTIME is set, +this should eliminate the timing oracle completely. + +In addition the no-asm variant may also have +branches that depend on secret values, because the last +invocation of bn_sub_words in bn_from_montgomery_word +had branches when the function is compiled by certain +gcc compiler versions, due to the clumsy coding style. + +So additionally this patch stream-lined the no-asm +C-code in order to avoid branches where possible and +improve the resulting code quality. + +Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20284) + --- - crypto/bn/bn_blind.c | 14 - - crypto/bn/bn_err.c | 2 + - crypto/bn/bn_local.h | 14 + - crypto/bn/build.info | 3 +- - crypto/bn/rsa_sup_mul.c | 614 ++++++++++++++++++++++++++++++++++++++++ - crypto/err/openssl.txt | 3 +- - crypto/rsa/rsa_ossl.c | 17 +- - include/crypto/bn.h | 5 + - include/openssl/bnerr.h | 1 + - 9 files changed, 653 insertions(+), 20 deletions(-) - create mode 100644 crypto/bn/rsa_sup_mul.c + CHANGES | 10 ++++ + crypto/bn/bn_asm.c | 106 +++++++++++++++++++++++------------------- + crypto/bn/bn_blind.c | 3 +- + crypto/bn/bn_lib.c | 22 +++++++++ + crypto/bn/bn_local.h | 26 +++++------ + crypto/rsa/rsa_ossl.c | 13 +++--- + 6 files changed, 111 insertions(+), 69 deletions(-) -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 @@ +diff --git a/crypto/bn/bn_asm.c b/crypto/bn/bn_asm.c +index 4d83a8cf11..177558c647 100644 +--- a/crypto/bn/bn_asm.c ++++ b/crypto/bn/bn_asm.c +@@ -381,25 +381,33 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + #ifndef OPENSSL_SMALL_FOOTPRINT + while (n & ~3) { + t1 = a[0]; +- t2 = b[0]; +- r[0] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[0]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[0] = t1; ++ c += (t1 > t2); + t1 = a[1]; +- t2 = b[1]; +- r[1] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[1]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[1] = t1; ++ c += (t1 > t2); + t1 = a[2]; +- t2 = b[2]; +- r[2] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[2]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[2] = t1; ++ c += (t1 > t2); + t1 = a[3]; +- t2 = b[3]; +- r[3] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[3]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[3] = t1; ++ c += (t1 > t2); + a += 4; + b += 4; + r += 4; +@@ -408,10 +416,12 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + #endif + while (n) { + t1 = a[0]; +- t2 = b[0]; +- r[0] = (t1 - t2 - c) & BN_MASK2; +- if (t1 != t2) +- c = (t1 < t2); ++ t2 = (t1 - c) & BN_MASK2; ++ c = (t2 > t1); ++ t1 = b[0]; ++ t1 = (t2 - t1) & BN_MASK2; ++ r[0] = t1; ++ c += (t1 > t2); + a++; + b++; + r++; +@@ -446,7 +456,7 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + t += c0; /* no carry */ \ + c0 = (BN_ULONG)Lw(t); \ + hi = (BN_ULONG)Hw(t); \ +- c1 = (c1+hi)&BN_MASK2; if (c1 -+#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 top = (int)(rtop & ~mask) | (ntop & mask); + n->flags |= (BN_FLG_FIXED_TOP & ~mask); + } +- ret = BN_mod_mul_montgomery(n, n, r, b->m_ctx, ctx); ++ ret = bn_mul_mont_fixed_top(n, n, r, b->m_ctx, ctx); ++ bn_correct_top_consttime(n); + } else { + ret = BN_mod_mul(n, n, r, b->mod, ctx); + } +diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c +index eb4a31849b..fe6fb0e40f 100644 +--- a/crypto/bn/bn_lib.c ++++ b/crypto/bn/bn_lib.c +@@ -1001,6 +1001,28 @@ BIGNUM *bn_wexpand(BIGNUM *a, int words) + return (words <= a->dmax) ? a : bn_expand2(a, words); + } + ++void bn_correct_top_consttime(BIGNUM *a) +{ -+ limb_t carry, v; -+ limb_t *res, *rp, *tmp2; -+ ossl_ssize_t i; -+ -+ res = tmp; -+ /* -+ * for intermediate result we need an integer twice as long as modulus -+ * but keep the input in the least significant limbs -+ */ -+ memset(res, 0, sizeof(limb_t) * (modnum * 2)); -+ memcpy(&res[modnum * 2 - anum], a, sizeof(limb_t) * anum); -+ rp = &res[modnum]; -+ tmp2 = &res[modnum * 2]; -+ -+ carry = 0; -+ -+ /* add multiples of the modulus to the value until R divides it cleanly */ -+ 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; ++ int j, atop; ++ BN_ULONG limb; ++ unsigned int mask; ++ ++ for (j = 0, atop = 0; j < a->dmax; j++) { ++ limb = a->d[j]; ++ limb |= 0 - limb; ++ limb >>= BN_BITS2 - 1; ++ limb = 0 - limb; ++ mask = (unsigned int)limb; ++ mask &= constant_time_msb(j - a->top); ++ atop = constant_time_select_int(mask, j + 1, atop); + } + -+ /* perform the final reduction by mod... */ -+ carry -= sub(ret, rp, mod, modnum); -+ -+ /* ...conditionally */ -+ cselect(carry, ret, rp, ret, modnum); ++ mask = constant_time_eq_int(atop, 0); ++ a->top = atop; ++ a->neg = constant_time_select_int(mask, 0, a->neg); ++ a->flags &= ~BN_FLG_FIXED_TOP; +} + -+/* 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 -@@ -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 + void bn_correct_top(BIGNUM *a) + { + BN_ULONG *ftl; +diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h +index ee6342b60c..818e34348e 100644 +--- a/crypto/bn/bn_local.h ++++ b/crypto/bn/bn_local.h +@@ -515,10 +515,10 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + ret = (r); \ + BN_UMULT_LOHI(low,high,w,tmp); \ + ret += (c); \ +- (c) = (ret<(c))?1:0; \ ++ (c) = (ret<(c)); \ + (c) += high; \ + ret += low; \ +- (c) += (ret>(BN_BITS4-1); \ + m =(m&BN_MASK2l)<<(BN_BITS4+1); \ +- l=(l+m)&BN_MASK2; if (l < m) h++; \ ++ l=(l+m)&BN_MASK2; h += (l < m); \ + (lo)=l; \ + (ho)=h; \ + } +@@ -623,9 +623,9 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ +- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ ++ l=(l+(c))&BN_MASK2; h += (l < (c)); \ + (c)=(r); \ +- l=(l+(c))&BN_MASK2; if (l < (c)) h++; \ ++ l=(l+(c))&BN_MASK2; h += (l < (c)); \ + (c)=h&BN_MASK2; \ + (r)=l; \ + } +@@ -639,7 +639,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, + mul64(l,h,(bl),(bh)); \ + \ + /* non-multiply part */ \ +- l+=(c); if ((l&BN_MASK2) < (c)) h++; \ ++ l+=(c); h += ((l&BN_MASK2) < (c)); \ + (c)=h&BN_MASK2; \ + (r)=l&BN_MASK2; \ + } +@@ -669,7 +669,7 @@ BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl); + int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, + const BN_ULONG *np, const BN_ULONG *n0, int num); +- ++void bn_correct_top_consttime(BIGNUM *a); + BIGNUM *int_bn_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, + int *noinv); diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c -index b52a66f6a6..6c3c0cf78d 100644 +index 53cf2d03c9..cf5a10ab43 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); +@@ -226,6 +226,7 @@ static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, + * will only read the modulus from BN_BLINDING. In both cases it's safe + * to access the blinding without a lock. + */ ++ BN_set_flags(f, BN_FLG_CONSTTIME); + return BN_BLINDING_invert_ex(f, unblind, b, ctx); + } + +@@ -412,6 +413,11 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, + goto err; } -- 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) ++ if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) ++ if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, ++ rsa->n, ctx)) ++ goto err; ++ + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); + if (blinding == NULL) { +@@ -449,13 +455,6 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, goto err; + } + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); - -- 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. +- if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) +- if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock, +- rsa->n, ctx)) { +- BN_free(d); +- goto err; +- } + if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx, + rsa->_method_mod_n)) { + BN_free(d); -- -2.17.1 +2.27.0 + diff --git a/backport-Fix-stack-corruption-in-ui_read.patch b/backport-Fix-stack-corruption-in-ui_read.patch new file mode 100755 index 0000000000000000000000000000000000000000..cbe986a50bb706e4ec7e2718ce448d65fc497b7e --- /dev/null +++ b/backport-Fix-stack-corruption-in-ui_read.patch @@ -0,0 +1,64 @@ +From 0f90c4de9f58070a423003ec6b34ef1a9a670ec9 Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Sat, 13 May 2023 09:04:18 +0200 +Subject: [PATCH] Fix stack corruption in ui_read + +This is an alternative to #20893 + +Additionally this fixes also a possible issue in UI_UTIL_read_pw: + +When UI_new returns NULL, the result code would still be zero +as if UI_UTIL_read_pw succeeded, but the password buffer is left +uninitialized, with subsequent possible stack corruption or worse. + +Reviewed-by: Richard Levitte +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20957) + +(cherry picked from commit a64c48cff88e032cf9513578493c4536df725a22) + +--- + crypto/ui/ui_lib.c | 4 ++++ + crypto/ui/ui_util.c | 4 +--- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c +index 49cc45057c..daf11c7a0d 100644 +--- a/crypto/ui/ui_lib.c ++++ b/crypto/ui/ui_lib.c +@@ -529,6 +529,10 @@ int UI_process(UI *ui) + ok = 0; + break; + } ++ } else { ++ ui->flags &= ~UI_FLAG_REDOABLE; ++ ok = -2; ++ goto err; + } + } + +diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c +index 32a3c4e38d..e582252da6 100644 +--- a/crypto/ui/ui_util.c ++++ b/crypto/ui/ui_util.c +@@ -32,7 +32,7 @@ int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify) + { +- int ok = 0; ++ int ok = -2; + UI *ui; + + if (size < 1) +@@ -47,8 +47,6 @@ int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + ok = UI_process(ui); + UI_free(ui); + } +- if (ok > 0) +- ok = 0; + return ok; + } + +-- +2.27.0 + diff --git a/backport-Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorre.patch b/backport-Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorre.patch new file mode 100644 index 0000000000000000000000000000000000000000..983e1fadb62778331cc1b48b58885955e71ffced --- /dev/null +++ b/backport-Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorre.patch @@ -0,0 +1,30 @@ +From 8daa2616bbe6f7994e0cdd796d3280118c51d8d8 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Thu, 20 Apr 2023 10:24:38 +0200 +Subject: [PATCH] Re-add BN_F_OSSL_BN_RSA_DO_UNBLIND which was incorrectly + removed + +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/20784) + +--- + include/openssl/bnerr.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/openssl/bnerr.h b/include/openssl/bnerr.h +index a703efc92b..5c83777f9f 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. +-- +2.27.0 + diff --git a/openssl.spec b/openssl.spec index f37657b0c44b4dd1856c72fd1875057579199cde..fe4f48946e5edd8f5eccc45e30aea1ef1b2faf4b 100644 --- a/openssl.spec +++ b/openssl.spec @@ -2,7 +2,7 @@ Name: openssl Epoch: 1 Version: 1.1.1m -Release: 25 +Release: 29 Summary: Cryptography and SSL/TLS Toolkit License: OpenSSL and SSLeay URL: https://www.openssl.org/ @@ -69,6 +69,10 @@ Patch58: Fix-FIPS-getenv-build-failure.patch Patch59: backport-A-null-pointer-dereference-occurs-when-memory-alloca.patch Patch60: backport-Make-DH_check-set-some-error-bits-in-recently-added-.patch Patch61: backport-CVE-2023-5678-Make-DH_check_pub_key-and-DH_generate_key-safer-yet.patch +Patch62: backport-Add-negative-integer-check-when-using-ASN1_BIT_STRIN.patch +Patch63: backport-Fix-stack-corruption-in-ui_read.patch +Patch64: backport-Re-add-BN_F_OSSL_BN_RSA_DO_UNBLIND-which-was-incorre.patch + BuildRequires: gcc perl make lksctp-tools-devel coreutils util-linux zlib-devel Requires: coreutils %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} @@ -271,6 +275,9 @@ make test || : %ldconfig_scriptlets libs %changelog +* Mon Nov 20 2023 wangcheng - 1:1.1.1m-29 +* backport some patches + * Tue Nov 14 2023 zhujianwei - 1:1.1.1m-25 - fix CVE-2023-5678