backport patch for performance improvements
This commit is contained in:
parent
b3de38ebbd
commit
a810abe620
265
backport-01-Improve-FIPS-RSA-keygen-performance.patch
Normal file
265
backport-01-Improve-FIPS-RSA-keygen-performance.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From dd1d7bcb69994d81662e709b0ad838880b943870 Mon Sep 17 00:00:00 2001
|
||||
From: slontis <shane.lontis@oracle.com>
|
||||
Date: Wed, 2 Nov 2022 12:01:34 +1000
|
||||
Subject: [PATCH] Improve FIPS RSA keygen performance.
|
||||
|
||||
FIPS 186-4 has 5 different algorithms for key generation,
|
||||
and all of them rely on testing GCD(a,n) == 1 many times.
|
||||
|
||||
Cachegrind was showing that during a RSA keygen operation,
|
||||
the function BN_gcd() was taking a considerable percentage
|
||||
of the total cycles.
|
||||
|
||||
The default provider uses multiprime keygen, which seemed to
|
||||
be much faster. This is because it uses BN_mod_inverse()
|
||||
instead.
|
||||
|
||||
For a 4096 bit key, the entropy of a key that was taking a
|
||||
long time to generate was recorded and fed back into subsequent
|
||||
runs. Roughly 40% of the cycle time was BN_gcd() with most of the
|
||||
remainder in the prime testing. Changing to use the inverse
|
||||
resulted in the cycle count being 96% in the prime testing.
|
||||
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/19578)
|
||||
---
|
||||
crypto/bn/bn_gcd.c | 31 +++++++++++++++++++++++++++++++
|
||||
crypto/bn/bn_rsa_fips186_4.c | 24 +++++++++++++++---------
|
||||
doc/man3/BN_cmp.pod | 14 +++++++++++++-
|
||||
include/openssl/bn.h | 1 +
|
||||
test/bntest.c | 26 ++++++++++++++++++++++++--
|
||||
util/libcrypto.num | 1 +
|
||||
6 files changed, 85 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c
|
||||
index 91ad76a161..519bb4e951 100644
|
||||
--- a/crypto/bn/bn_gcd.c
|
||||
+++ b/crypto/bn/bn_gcd.c
|
||||
@@ -534,6 +534,37 @@ BIGNUM *BN_mod_inverse(BIGNUM *in,
|
||||
return rv;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * The numbers a and b are coprime if the only positive integer that is a
|
||||
+ * divisor of both of them is 1.
|
||||
+ * i.e. gcd(a,b) = 1.
|
||||
+ *
|
||||
+ * Coprimes have the property: b has a multiplicative inverse modulo a
|
||||
+ * i.e there is some value x such that bx = 1 (mod a).
|
||||
+ *
|
||||
+ * Testing the modulo inverse is currently much faster than the constant
|
||||
+ * time version of BN_gcd().
|
||||
+ */
|
||||
+int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ BIGNUM *tmp;
|
||||
+
|
||||
+ BN_CTX_start(ctx);
|
||||
+ tmp = BN_CTX_get(ctx);
|
||||
+ if (tmp == NULL)
|
||||
+ goto end;
|
||||
+
|
||||
+ ERR_set_mark();
|
||||
+ BN_set_flags(a, BN_FLG_CONSTTIME);
|
||||
+ ret = (BN_mod_inverse(tmp, a, b, ctx) != NULL);
|
||||
+ /* Clear any errors (an error is returned if there is no inverse) */
|
||||
+ ERR_pop_to_mark();
|
||||
+end:
|
||||
+ BN_CTX_end(ctx);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
/*-
|
||||
* This function is based on the constant-time GCD work by Bernstein and Yang:
|
||||
* https://eprint.iacr.org/2019/266
|
||||
diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c
|
||||
index 770ae4d1fa..e3a2ad76af 100644
|
||||
--- a/crypto/bn/bn_rsa_fips186_4.c
|
||||
+++ b/crypto/bn/bn_rsa_fips186_4.c
|
||||
@@ -286,14 +286,20 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
goto err;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * (Step 1) GCD(2r1, r2) = 1.
|
||||
+ * Note: This algorithm was doing a gcd(2r1, r2)=1 test before doing an
|
||||
+ * mod_inverse(2r1, r2) which are effectively the same operation.
|
||||
+ * (The algorithm assumed that the gcd test would be faster). Since the
|
||||
+ * mod_inverse is currently faster than calling the constant time
|
||||
+ * BN_gcd(), the call to BN_gcd() has been omitted. The inverse result
|
||||
+ * is used further down.
|
||||
+ */
|
||||
if (!(BN_lshift1(r1x2, r1)
|
||||
- /* (Step 1) GCD(2r1, r2) = 1 */
|
||||
- && BN_gcd(tmp, r1x2, r2, ctx)
|
||||
- && BN_is_one(tmp)
|
||||
+ && (BN_mod_inverse(tmp, r1x2, r2, ctx) != NULL)
|
||||
/* (Step 2) R = ((r2^-1 mod 2r1) * r2) - ((2r1^-1 mod r2)*2r1) */
|
||||
- && BN_mod_inverse(R, r2, r1x2, ctx)
|
||||
+ && (BN_mod_inverse(R, r2, r1x2, ctx) != NULL)
|
||||
&& BN_mul(R, R, r2, ctx) /* R = (r2^-1 mod 2r1) * r2 */
|
||||
- && BN_mod_inverse(tmp, r1x2, r2, ctx)
|
||||
&& BN_mul(tmp, tmp, r1x2, ctx) /* tmp = (2r1^-1 mod r2)*2r1 */
|
||||
&& BN_sub(R, R, tmp)
|
||||
/* Calculate 2r1r2 */
|
||||
@@ -305,7 +311,8 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
|
||||
/*
|
||||
* In FIPS 186-4 imax was set to 5 * nlen/2.
|
||||
- * Analysis by Allen Roginsky (See https://csrc.nist.gov/CSRC/media/Publications/fips/186/4/final/documents/comments-received-fips186-4-december-2015.pdf
|
||||
+ * Analysis by Allen Roginsky
|
||||
+ * (See https://csrc.nist.gov/CSRC/media/Publications/fips/186/4/final/documents/comments-received-fips186-4-december-2015.pdf
|
||||
* page 68) indicates this has a 1 in 2 million chance of failure.
|
||||
* The number has been updated to 20 * nlen/2 as used in
|
||||
* FIPS186-5 Appendix B.9 Step 9.
|
||||
@@ -337,10 +344,9 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
|
||||
/* (Step 7) If GCD(Y-1) == 1 & Y is probably prime then return Y */
|
||||
if (BN_copy(y1, Y) == NULL
|
||||
- || !BN_sub_word(y1, 1)
|
||||
- || !BN_gcd(tmp, y1, e, ctx))
|
||||
+ || !BN_sub_word(y1, 1))
|
||||
goto err;
|
||||
- if (BN_is_one(tmp)) {
|
||||
+ if (BN_are_coprime(y1, e, ctx)) {
|
||||
int rv = BN_check_prime(Y, ctx, cb);
|
||||
|
||||
if (rv > 0)
|
||||
diff --git a/doc/man3/BN_cmp.pod b/doc/man3/BN_cmp.pod
|
||||
index f302818f21..e9ddf8fa2d 100644
|
||||
--- a/doc/man3/BN_cmp.pod
|
||||
+++ b/doc/man3/BN_cmp.pod
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
-BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd - BIGNUM comparison and test functions
|
||||
+BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd, BN_are_coprime
|
||||
+- BIGNUM comparison and test functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
@@ -17,6 +18,8 @@ BN_cmp, BN_ucmp, BN_is_zero, BN_is_one, BN_is_word, BN_abs_is_word, BN_is_odd -
|
||||
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w);
|
||||
int BN_is_odd(const BIGNUM *a);
|
||||
|
||||
+ int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||
+
|
||||
=head1 DESCRIPTION
|
||||
|
||||
BN_cmp() compares the numbers I<a> and I<b>. BN_ucmp() compares their
|
||||
@@ -26,6 +29,10 @@ BN_is_zero(), BN_is_one(), BN_is_word() and BN_abs_is_word() test if
|
||||
I<a> equals 0, 1, I<w>, or E<verbar>I<w>E<verbar> respectively.
|
||||
BN_is_odd() tests if I<a> is odd.
|
||||
|
||||
+BN_are_coprime() determines if B<a> and B<b> are coprime.
|
||||
+B<ctx> is used internally for storing temporary variables.
|
||||
+The values of B<a> and B<b> and B<ctx> must not be NULL.
|
||||
+
|
||||
=head1 RETURN VALUES
|
||||
|
||||
BN_cmp() returns -1 if I<a> E<lt> I<b>, 0 if I<a> == I<b> and 1 if
|
||||
@@ -35,11 +42,16 @@ of I<a> and I<b>.
|
||||
BN_is_zero(), BN_is_one() BN_is_word(), BN_abs_is_word() and
|
||||
BN_is_odd() return 1 if the condition is true, 0 otherwise.
|
||||
|
||||
+BN_are_coprime() returns 1 if the B<BIGNUM>'s are coprime, otherwise it
|
||||
+returns 0.
|
||||
+
|
||||
=head1 HISTORY
|
||||
|
||||
Prior to OpenSSL 1.1.0, BN_is_zero(), BN_is_one(), BN_is_word(),
|
||||
BN_abs_is_word() and BN_is_odd() were macros.
|
||||
|
||||
+The function BN_are_coprime() was added in OpenSSL 3.1.
|
||||
+
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
|
||||
index 333e201eae..ea706dca7f 100644
|
||||
--- a/include/openssl/bn.h
|
||||
+++ b/include/openssl/bn.h
|
||||
@@ -350,6 +350,7 @@ int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||
int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); /* returns
|
||||
* -2 for
|
||||
* error */
|
||||
+int BN_are_coprime(BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
|
||||
BIGNUM *BN_mod_inverse(BIGNUM *ret,
|
||||
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
|
||||
BIGNUM *BN_mod_sqrt(BIGNUM *ret,
|
||||
diff --git a/test/bntest.c b/test/bntest.c
|
||||
index 85445b701b..b35b53df7e 100644
|
||||
--- a/test/bntest.c
|
||||
+++ b/test/bntest.c
|
||||
@@ -41,6 +41,7 @@ typedef struct mpitest_st {
|
||||
|
||||
static const int NUM0 = 100; /* number of tests */
|
||||
static const int NUM1 = 50; /* additional tests for some functions */
|
||||
+static const int NUM_PRIME_TESTS = 20;
|
||||
static BN_CTX *ctx;
|
||||
|
||||
/*
|
||||
@@ -2722,6 +2723,25 @@ static int test_ctx_consttime_flag(void)
|
||||
return st;
|
||||
}
|
||||
|
||||
+static int test_coprime(void)
|
||||
+{
|
||||
+ BIGNUM *a = NULL, *b = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ ret = TEST_ptr(a = BN_new())
|
||||
+ && TEST_ptr(b = BN_new())
|
||||
+ && TEST_true(BN_set_word(a, 66))
|
||||
+ && TEST_true(BN_set_word(b, 99))
|
||||
+ && TEST_int_eq(BN_are_coprime(a, b, ctx), 0)
|
||||
+ && TEST_int_eq(BN_are_coprime(b, a, ctx), 0)
|
||||
+ && TEST_true(BN_set_word(a, 67))
|
||||
+ && TEST_int_eq(BN_are_coprime(a, b, ctx), 1)
|
||||
+ && TEST_int_eq(BN_are_coprime(b, a, ctx), 1);
|
||||
+ BN_free(a);
|
||||
+ BN_free(b);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int test_gcd_prime(void)
|
||||
{
|
||||
BIGNUM *a = NULL, *b = NULL, *gcd = NULL;
|
||||
@@ -2734,11 +2754,12 @@ static int test_gcd_prime(void)
|
||||
|
||||
if (!TEST_true(BN_generate_prime_ex(a, 1024, 0, NULL, NULL, NULL)))
|
||||
goto err;
|
||||
- for (i = 0; i < NUM0; i++) {
|
||||
+ for (i = 0; i < NUM_PRIME_TESTS; i++) {
|
||||
if (!TEST_true(BN_generate_prime_ex(b, 1024, 0,
|
||||
NULL, NULL, NULL))
|
||||
|| !TEST_true(BN_gcd(gcd, a, b, ctx))
|
||||
- || !TEST_true(BN_is_one(gcd)))
|
||||
+ || !TEST_true(BN_is_one(gcd))
|
||||
+ || !TEST_true(BN_are_coprime(a, b, ctx)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -3216,6 +3237,7 @@ int setup_tests(void)
|
||||
ADD_ALL_TESTS(test_is_prime, (int)OSSL_NELEM(primes));
|
||||
ADD_ALL_TESTS(test_not_prime, (int)OSSL_NELEM(not_primes));
|
||||
ADD_TEST(test_gcd_prime);
|
||||
+ ADD_TEST(test_coprime);
|
||||
ADD_ALL_TESTS(test_mod_exp, (int)OSSL_NELEM(ModExpTests));
|
||||
ADD_ALL_TESTS(test_mod_exp_consttime, (int)OSSL_NELEM(ModExpTests));
|
||||
ADD_TEST(test_mod_exp2_mont);
|
||||
diff --git a/util/libcrypto.num b/util/libcrypto.num
|
||||
index 0f6f30b..4a20709 100644
|
||||
--- a/util/libcrypto.num
|
||||
+++ b/util/libcrypto.num
|
||||
@@ -5429,3 +5429,4 @@ OPENSSL_strcasecmp 5556 3_0_3 EXIST::FUNCTION:
|
||||
OPENSSL_strncasecmp 5557 3_0_3 EXIST::FUNCTION:
|
||||
OSSL_CMP_CTX_reset_geninfo_ITAVs 5558 3_0_8 EXIST::FUNCTION:CMP
|
||||
OSSL_CMP_MSG_update_recipNonce 5559 3_0_9 EXIST::FUNCTION:CMP
|
||||
+BN_are_coprime 5560 3_0_12 EXIST::FUNCTION:
|
||||
--
|
||||
2.33.0
|
||||
|
||||
179
backport-02-Improve-FIPS-RSA-keygen-performance.patch
Normal file
179
backport-02-Improve-FIPS-RSA-keygen-performance.patch
Normal file
@ -0,0 +1,179 @@
|
||||
From d2f6e66d2837bff1f5f7636bb2118e3a45c9df61 Mon Sep 17 00:00:00 2001
|
||||
From: slontis <shane.lontis@oracle.com>
|
||||
Date: Wed, 2 Nov 2022 13:20:55 +1000
|
||||
Subject: [PATCH] Improve FIPS RSA keygen performance.
|
||||
|
||||
Reduce the Miller Rabin counts to the values specified by FIPS 186-5.
|
||||
The old code was using a fixed value of 64.
|
||||
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/19579)
|
||||
---
|
||||
crypto/bn/bn_prime.c | 11 ++++++++
|
||||
crypto/bn/bn_rsa_fips186_4.c | 49 ++++++++++++++++++++++++++++++------
|
||||
include/crypto/bn.h | 2 ++
|
||||
3 files changed, 54 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
|
||||
index 560855542f..96eb1b3c34 100644
|
||||
--- a/crypto/bn/bn_prime.c
|
||||
+++ b/crypto/bn/bn_prime.c
|
||||
@@ -250,6 +250,17 @@ int ossl_bn_check_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
|
||||
return bn_is_prime_int(w, checks, ctx, do_trial_division, cb);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Use this only for key generation.
|
||||
+ * It always uses trial division. The number of checks
|
||||
+ * (MR rounds) passed in is used without being clamped to a minimum value.
|
||||
+ */
|
||||
+int ossl_bn_check_generated_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
|
||||
+ BN_GENCB *cb)
|
||||
+{
|
||||
+ return bn_is_prime_int(w, checks, ctx, 1, cb);
|
||||
+}
|
||||
+
|
||||
int BN_check_prime(const BIGNUM *p, BN_CTX *ctx, BN_GENCB *cb)
|
||||
{
|
||||
return ossl_bn_check_prime(p, 0, ctx, 1, cb);
|
||||
diff --git a/crypto/bn/bn_rsa_fips186_4.c b/crypto/bn/bn_rsa_fips186_4.c
|
||||
index e3a2ad76af..765ee250e7 100644
|
||||
--- a/crypto/bn/bn_rsa_fips186_4.c
|
||||
+++ b/crypto/bn/bn_rsa_fips186_4.c
|
||||
@@ -48,6 +48,34 @@ const BIGNUM ossl_bn_inv_sqrt_2 = {
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Refer to FIPS 186-5 Table B.1 for minimum rounds of Miller Rabin
|
||||
+ * required for generation of RSA aux primes (p1, p2, q1 and q2).
|
||||
+ */
|
||||
+static int bn_rsa_fips186_5_aux_prime_MR_rounds(int nbits)
|
||||
+{
|
||||
+ if (nbits >= 4096)
|
||||
+ return 44;
|
||||
+ if (nbits >= 3072)
|
||||
+ return 41;
|
||||
+ if (nbits >= 2048)
|
||||
+ return 38;
|
||||
+ return 0; /* Error */
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Refer to FIPS 186-5 Table B.1 for minimum rounds of Miller Rabin
|
||||
+ * required for generation of RSA primes (p and q)
|
||||
+ */
|
||||
+static int bn_rsa_fips186_5_prime_MR_rounds(int nbits)
|
||||
+{
|
||||
+ if (nbits >= 3072)
|
||||
+ return 4;
|
||||
+ if (nbits >= 2048)
|
||||
+ return 5;
|
||||
+ return 0; /* Error */
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* FIPS 186-5 Table A.1. "Min length of auxiliary primes p1, p2, q1, q2".
|
||||
* (FIPS 186-5 has an entry for >= 4096 bits).
|
||||
@@ -97,11 +125,13 @@ static int bn_rsa_fips186_5_aux_prime_max_sum_size_for_prob_primes(int nbits)
|
||||
* Xp1 The passed in starting point to find a probably prime.
|
||||
* p1 The returned probable prime (first odd integer >= Xp1)
|
||||
* ctx A BN_CTX object.
|
||||
+ * rounds The number of Miller Rabin rounds
|
||||
* cb An optional BIGNUM callback.
|
||||
* Returns: 1 on success otherwise it returns 0.
|
||||
*/
|
||||
static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1,
|
||||
BIGNUM *p1, BN_CTX *ctx,
|
||||
+ int rounds,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -117,7 +147,7 @@ static int bn_rsa_fips186_4_find_aux_prob_prime(const BIGNUM *Xp1,
|
||||
i++;
|
||||
BN_GENCB_call(cb, 0, i);
|
||||
/* MR test with trial division */
|
||||
- tmp = BN_check_prime(p1, ctx, cb);
|
||||
+ tmp = ossl_bn_check_generated_prime(p1, rounds, ctx, cb);
|
||||
if (tmp > 0)
|
||||
break;
|
||||
if (tmp < 0)
|
||||
@@ -160,7 +190,7 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *p1i = NULL, *p2i = NULL, *Xp1i = NULL, *Xp2i = NULL;
|
||||
- int bitlen;
|
||||
+ int bitlen, rounds;
|
||||
|
||||
if (p == NULL || Xpout == NULL)
|
||||
return 0;
|
||||
@@ -177,6 +207,7 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
|
||||
bitlen = bn_rsa_fips186_5_aux_prime_min_size(nlen);
|
||||
if (bitlen == 0)
|
||||
goto err;
|
||||
+ rounds = bn_rsa_fips186_5_aux_prime_MR_rounds(nlen);
|
||||
|
||||
/* (Steps 4.1/5.1): Randomly generate Xp1 if it is not passed in */
|
||||
if (Xp1 == NULL) {
|
||||
@@ -194,8 +225,8 @@ int ossl_bn_rsa_fips186_4_gen_prob_primes(BIGNUM *p, BIGNUM *Xpout,
|
||||
}
|
||||
|
||||
/* (Steps 4.2/5.2) - find first auxiliary probable primes */
|
||||
- if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, cb)
|
||||
- || !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, cb))
|
||||
+ if (!bn_rsa_fips186_4_find_aux_prob_prime(Xp1i, p1i, ctx, rounds, cb)
|
||||
+ || !bn_rsa_fips186_4_find_aux_prob_prime(Xp2i, p2i, ctx, rounds, cb))
|
||||
goto err;
|
||||
/* (Table B.1) auxiliary prime Max length check */
|
||||
if ((BN_num_bits(p1i) + BN_num_bits(p2i)) >=
|
||||
@@ -243,11 +274,11 @@ err:
|
||||
*/
|
||||
int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
const BIGNUM *r1, const BIGNUM *r2,
|
||||
- int nlen, const BIGNUM *e, BN_CTX *ctx,
|
||||
- BN_GENCB *cb)
|
||||
+ int nlen, const BIGNUM *e,
|
||||
+ BN_CTX *ctx, BN_GENCB *cb)
|
||||
{
|
||||
int ret = 0;
|
||||
- int i, imax;
|
||||
+ int i, imax, rounds;
|
||||
int bits = nlen >> 1;
|
||||
BIGNUM *tmp, *R, *r1r2x2, *y1, *r1x2;
|
||||
BIGNUM *base, *range;
|
||||
@@ -317,6 +348,7 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
* The number has been updated to 20 * nlen/2 as used in
|
||||
* FIPS186-5 Appendix B.9 Step 9.
|
||||
*/
|
||||
+ rounds = bn_rsa_fips186_5_prime_MR_rounds(nlen);
|
||||
imax = 20 * bits; /* max = 20/2 * nbits */
|
||||
for (;;) {
|
||||
if (Xin == NULL) {
|
||||
@@ -346,8 +378,9 @@ int ossl_bn_rsa_fips186_4_derive_prime(BIGNUM *Y, BIGNUM *X, const BIGNUM *Xin,
|
||||
if (BN_copy(y1, Y) == NULL
|
||||
|| !BN_sub_word(y1, 1))
|
||||
goto err;
|
||||
+
|
||||
if (BN_are_coprime(y1, e, ctx)) {
|
||||
- int rv = BN_check_prime(Y, ctx, cb);
|
||||
+ int rv = ossl_bn_check_generated_prime(Y, rounds, ctx, cb);
|
||||
|
||||
if (rv > 0)
|
||||
goto end;
|
||||
diff --git a/include/crypto/bn.h b/include/crypto/bn.h
|
||||
index cf69bea848..4d11e0e4b1 100644
|
||||
--- a/include/crypto/bn.h
|
||||
+++ b/include/crypto/bn.h
|
||||
@@ -95,6 +95,8 @@ int bn_div_fixed_top(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
|
||||
|
||||
int ossl_bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx,
|
||||
BN_GENCB *cb, int enhanced, int *status);
|
||||
+int ossl_bn_check_generated_prime(const BIGNUM *w, int checks, BN_CTX *ctx,
|
||||
+ BN_GENCB *cb);
|
||||
|
||||
const BIGNUM *ossl_bn_get0_small_factors(void);
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,306 @@
|
||||
From 4c41aa4b338ca181a394483c8bb6aeb6366c6f96 Mon Sep 17 00:00:00 2001
|
||||
From: wangcheng <bangwangnj@163.com>
|
||||
Date: Sat, 26 Oct 2024 17:10:38 +0800
|
||||
Subject: [PATCH] Add CTX copy function for EVP_MD to optimize the performance
|
||||
of EVP_MD_CTX_copy_ex.
|
||||
|
||||
1. Add OSSL_FUNC_digest_copyctx_fn function for EVP_MD, which is used to copy algctx from the old EVP_MD_CTX to the new one.
|
||||
|
||||
2. Add implementation of OSSL_FUNC_digest_copyctx_fn function for default providers.
|
||||
|
||||
3. Modify EVP_MD_CTX_copy_ex: When the fetched digest is the same in in and out contexts, use the copy function to copy the members in EVP_MD_CTX if the OSSL_FUNC_digest_copyctx_fn function exists. Otherwise, use the previous method to copy.
|
||||
|
||||
4. Add documentation for OSSL_FUNC_digest_copyctx function in doc/man7/provider-digest.pod.
|
||||
|
||||
5. Add testcase.
|
||||
|
||||
Fixes #25703
|
||||
|
||||
Signed-off-by: wangcheng <bangwangnj@163.com>
|
||||
|
||||
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/25726)
|
||||
---
|
||||
crypto/evp/digest.c | 47 +++++++++++++------
|
||||
doc/man7/provider-digest.pod | 11 +++++
|
||||
include/crypto/evp.h | 1 +
|
||||
include/openssl/core_dispatch.h | 2 +
|
||||
providers/implementations/digests/sha3_prov.c | 10 ++++
|
||||
.../include/prov/digestcommon.h | 7 +++
|
||||
test/evp_extra_test2.c | 43 +++++++++++++++++
|
||||
7 files changed, 106 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
|
||||
index eefed52..f5c44b1 100644
|
||||
--- a/crypto/evp/digest.c
|
||||
+++ b/crypto/evp/digest.c
|
||||
@@ -548,23 +548,35 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- evp_md_ctx_reset_ex(out, 1);
|
||||
- digest_change = (out->fetched_digest != in->fetched_digest);
|
||||
- if (digest_change && out->fetched_digest != NULL)
|
||||
- EVP_MD_free(out->fetched_digest);
|
||||
- *out = *in;
|
||||
- /* NULL out pointers in case of error */
|
||||
- out->pctx = NULL;
|
||||
- out->algctx = NULL;
|
||||
+ if (out->digest == in->digest && in->digest->copyctx != NULL) {
|
||||
|
||||
- if (digest_change && in->fetched_digest != NULL)
|
||||
- EVP_MD_up_ref(in->fetched_digest);
|
||||
+ in->digest->copyctx(out->algctx, in->algctx);
|
||||
|
||||
- if (in->algctx != NULL) {
|
||||
- out->algctx = in->digest->dupctx(in->algctx);
|
||||
- if (out->algctx == NULL) {
|
||||
- ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
- return 0;
|
||||
+ EVP_PKEY_CTX_free(out->pctx);
|
||||
+ out->pctx = NULL;
|
||||
+ cleanup_old_md_data(out, 0);
|
||||
+
|
||||
+ out->flags = in->flags;
|
||||
+ out->update = in->update;
|
||||
+ } else {
|
||||
+ evp_md_ctx_reset_ex(out, 1);
|
||||
+ digest_change = (out->fetched_digest != in->fetched_digest);
|
||||
+ if (digest_change && out->fetched_digest != NULL)
|
||||
+ EVP_MD_free(out->fetched_digest);
|
||||
+ *out = *in;
|
||||
+ /* NULL out pointers in case of error */
|
||||
+ out->pctx = NULL;
|
||||
+ out->algctx = NULL;
|
||||
+
|
||||
+ if (digest_change && in->fetched_digest != NULL)
|
||||
+ EVP_MD_up_ref(in->fetched_digest);
|
||||
+
|
||||
+ if (in->algctx != NULL) {
|
||||
+ out->algctx = in->digest->dupctx(in->algctx);
|
||||
+ if (out->algctx == NULL) {
|
||||
+ ERR_raise(ERR_LIB_EVP, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1029,6 +1041,11 @@ static void *evp_md_from_algorithm(int name_id,
|
||||
md->gettable_ctx_params =
|
||||
OSSL_FUNC_digest_gettable_ctx_params(fns);
|
||||
break;
|
||||
+ case OSSL_FUNC_DIGEST_COPYCTX:
|
||||
+ if (md->copyctx == NULL)
|
||||
+ md->copyctx =
|
||||
+ OSSL_FUNC_digest_copyctx(fns);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
if ((fncnt != 0 && fncnt != 5)
|
||||
diff --git a/doc/man7/provider-digest.pod b/doc/man7/provider-digest.pod
|
||||
index cac53ac..0ed0d3b 100644
|
||||
--- a/doc/man7/provider-digest.pod
|
||||
+++ b/doc/man7/provider-digest.pod
|
||||
@@ -20,6 +20,7 @@ provider-digest - The digest library E<lt>-E<gt> provider functions
|
||||
void *OSSL_FUNC_digest_newctx(void *provctx);
|
||||
void OSSL_FUNC_digest_freectx(void *dctx);
|
||||
void *OSSL_FUNC_digest_dupctx(void *dctx);
|
||||
+ void OSSL_FUNC_digest_copyctx(void *voutctx, void *vinctx);
|
||||
|
||||
/* Digest generation */
|
||||
int OSSL_FUNC_digest_init(void *dctx, const OSSL_PARAM params[]);
|
||||
@@ -76,6 +77,7 @@ macros in L<openssl-core_dispatch.h(7)>, as follows:
|
||||
OSSL_FUNC_digest_newctx OSSL_FUNC_DIGEST_NEWCTX
|
||||
OSSL_FUNC_digest_freectx OSSL_FUNC_DIGEST_FREECTX
|
||||
OSSL_FUNC_digest_dupctx OSSL_FUNC_DIGEST_DUPCTX
|
||||
+ OSSL_FUNC_digest_copyctx OSSL_FUNC_DIGEST_COPYCTX
|
||||
|
||||
OSSL_FUNC_digest_init OSSL_FUNC_DIGEST_INIT
|
||||
OSSL_FUNC_digest_update OSSL_FUNC_DIGEST_UPDATE
|
||||
@@ -111,6 +113,14 @@ This function should free any resources associated with that context.
|
||||
OSSL_FUNC_digest_dupctx() should duplicate the provider side digest context in the
|
||||
I<dctx> parameter and return the duplicate copy.
|
||||
|
||||
+OSSL_FUNC_digest_copyctx() should copy the provider side digest context in the
|
||||
+I<vinctx> parameter to the I<voutctx> parameter which is the another provider side
|
||||
+context.
|
||||
+The OSSL_FUNC_digest_copyctx function is used in the EVP_MD_CTX_copy_ex function to
|
||||
+speed up HMAC operations in the PBKDF2.
|
||||
+This function is optional, and dupctx will be used if there is no EVP_MD_CTX_copy_ex
|
||||
+function.
|
||||
+
|
||||
=head2 Digest Generation Functions
|
||||
|
||||
OSSL_FUNC_digest_init() initialises a digest operation given a newly created
|
||||
@@ -274,6 +284,7 @@ L<life_cycle-digest(7)>, L<EVP_DigestInit(3)>
|
||||
=head1 HISTORY
|
||||
|
||||
The provider DIGEST interface was introduced in OpenSSL 3.0.
|
||||
+OSSL_FUNC_digest_copyctx() was added in 3.5 version.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
|
||||
index e70d8e9..f17b569 100644
|
||||
--- a/include/crypto/evp.h
|
||||
+++ b/include/crypto/evp.h
|
||||
@@ -277,6 +277,7 @@ struct evp_md_st {
|
||||
OSSL_FUNC_digest_final_fn *dfinal;
|
||||
OSSL_FUNC_digest_digest_fn *digest;
|
||||
OSSL_FUNC_digest_freectx_fn *freectx;
|
||||
+ OSSL_FUNC_digest_copyctx_fn *copyctx;
|
||||
OSSL_FUNC_digest_dupctx_fn *dupctx;
|
||||
OSSL_FUNC_digest_get_params_fn *get_params;
|
||||
OSSL_FUNC_digest_set_ctx_params_fn *set_ctx_params;
|
||||
diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h
|
||||
index 99fcda0..e6fa38d 100644
|
||||
--- a/include/openssl/core_dispatch.h
|
||||
+++ b/include/openssl/core_dispatch.h
|
||||
@@ -283,6 +283,7 @@ OSSL_CORE_MAKE_FUNC(int, provider_self_test, (void *provctx))
|
||||
# define OSSL_FUNC_DIGEST_GETTABLE_PARAMS 11
|
||||
# define OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS 12
|
||||
# define OSSL_FUNC_DIGEST_GETTABLE_CTX_PARAMS 13
|
||||
+# define OSSL_FUNC_DIGEST_COPYCTX 14
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void *, digest_newctx, (void *provctx))
|
||||
OSSL_CORE_MAKE_FUNC(int, digest_init, (void *dctx, const OSSL_PARAM params[]))
|
||||
@@ -297,6 +298,7 @@ OSSL_CORE_MAKE_FUNC(int, digest_digest,
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(void, digest_freectx, (void *dctx))
|
||||
OSSL_CORE_MAKE_FUNC(void *, digest_dupctx, (void *dctx))
|
||||
+OSSL_CORE_MAKE_FUNC(void, digest_copyctx, (void *outctx, void *inctx))
|
||||
|
||||
OSSL_CORE_MAKE_FUNC(int, digest_get_params, (OSSL_PARAM params[]))
|
||||
OSSL_CORE_MAKE_FUNC(int, digest_set_ctx_params,
|
||||
diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c
|
||||
index 168825d..3929f97 100644
|
||||
--- a/providers/implementations/digests/sha3_prov.c
|
||||
+++ b/providers/implementations/digests/sha3_prov.c
|
||||
@@ -32,6 +32,7 @@ static OSSL_FUNC_digest_init_fn keccak_init_params;
|
||||
static OSSL_FUNC_digest_update_fn keccak_update;
|
||||
static OSSL_FUNC_digest_final_fn keccak_final;
|
||||
static OSSL_FUNC_digest_freectx_fn keccak_freectx;
|
||||
+static OSSL_FUNC_digest_copyctx_fn keccak_copyctx;
|
||||
static OSSL_FUNC_digest_dupctx_fn keccak_dupctx;
|
||||
static OSSL_FUNC_digest_set_ctx_params_fn shake_set_ctx_params;
|
||||
static OSSL_FUNC_digest_settable_ctx_params_fn shake_settable_ctx_params;
|
||||
@@ -236,6 +237,7 @@ const OSSL_DISPATCH ossl_##name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
|
||||
+ { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))keccak_copyctx }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
|
||||
|
||||
#define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags) \
|
||||
@@ -258,6 +260,14 @@ static void keccak_freectx(void *vctx)
|
||||
OPENSSL_clear_free(ctx, sizeof(*ctx));
|
||||
}
|
||||
|
||||
+static void keccak_copyctx(void *voutctx, void *vinctx)
|
||||
+{
|
||||
+ KECCAK1600_CTX *outctx = (KECCAK1600_CTX *)voutctx;
|
||||
+ KECCAK1600_CTX *inctx = (KECCAK1600_CTX *)vinctx;
|
||||
+
|
||||
+ *outctx = *inctx;
|
||||
+}
|
||||
+
|
||||
static void *keccak_dupctx(void *ctx)
|
||||
{
|
||||
KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx;
|
||||
diff --git a/providers/implementations/include/prov/digestcommon.h b/providers/implementations/include/prov/digestcommon.h
|
||||
index abdb8bb..332d473 100644
|
||||
--- a/providers/implementations/include/prov/digestcommon.h
|
||||
+++ b/providers/implementations/include/prov/digestcommon.h
|
||||
@@ -70,6 +70,12 @@ static void *name##_dupctx(void *ctx) \
|
||||
*ret = *in; \
|
||||
return ret; \
|
||||
} \
|
||||
+static void name##_copyctx(void *voutctx, void *vinctx) \
|
||||
+{ \
|
||||
+ CTX *outctx = (CTX *)voutctx; \
|
||||
+ CTX *inctx = (CTX *)vinctx; \
|
||||
+ *outctx = *inctx; \
|
||||
+} \
|
||||
PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \
|
||||
PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
|
||||
const OSSL_DISPATCH ossl_##name##_functions[] = { \
|
||||
@@ -78,6 +84,7 @@ const OSSL_DISPATCH ossl_##name##_functions[] = { \
|
||||
{ OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_internal_final }, \
|
||||
{ OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \
|
||||
{ OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \
|
||||
+ { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))name##_copyctx }, \
|
||||
PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
|
||||
|
||||
# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END \
|
||||
diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c
|
||||
index 68329b0..be7db00 100644
|
||||
--- a/test/evp_extra_test2.c
|
||||
+++ b/test/evp_extra_test2.c
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include "testutil.h"
|
||||
#include "internal/nelem.h"
|
||||
+#include "crypto/evp.h"
|
||||
+#include "../crypto/evp/evp_local.h"
|
||||
|
||||
static OSSL_LIB_CTX *mainctx = NULL;
|
||||
static OSSL_PROVIDER *nullprov = NULL;
|
||||
@@ -1193,6 +1195,46 @@ static int test_evp_md_ctx_copy(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int test_evp_md_ctx_copy2(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ EVP_MD *md = NULL;
|
||||
+ OSSL_LIB_CTX *ctx = NULL;
|
||||
+ EVP_MD_CTX *inctx = NULL, *outctx = NULL;
|
||||
+ void *origin_algctx = NULL;
|
||||
+
|
||||
+ if (!TEST_ptr(ctx = OSSL_LIB_CTX_new())
|
||||
+ || !TEST_ptr(md = EVP_MD_fetch(ctx, "sha256", NULL)))
|
||||
+ goto end;
|
||||
+
|
||||
+ inctx = EVP_MD_CTX_new();
|
||||
+ outctx = EVP_MD_CTX_new();
|
||||
+
|
||||
+ if (!TEST_ptr(inctx) || !TEST_ptr(outctx))
|
||||
+ goto end;
|
||||
+
|
||||
+ /* init inctx and outctx, now the contexts are from same providers */
|
||||
+ if (!TEST_true(EVP_DigestInit_ex2(inctx, md, NULL)))
|
||||
+ goto end;
|
||||
+ if (!TEST_true(EVP_DigestInit_ex2(outctx, md, NULL)))
|
||||
+ goto end;
|
||||
+
|
||||
+ /*
|
||||
+ * Test the EVP_MD_CTX_copy_ex function. After copying,
|
||||
+ * outctx->algctx should be the same as the original.
|
||||
+ */
|
||||
+ origin_algctx = outctx->algctx;
|
||||
+ ret = TEST_true(EVP_MD_CTX_copy_ex(outctx, inctx))
|
||||
+ && TEST_true(outctx->algctx == origin_algctx);
|
||||
+
|
||||
+end:
|
||||
+ EVP_MD_free(md);
|
||||
+ EVP_MD_CTX_free(inctx);
|
||||
+ EVP_MD_CTX_free(outctx);
|
||||
+ OSSL_LIB_CTX_free(ctx);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
#if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_MD5
|
||||
static int test_evp_pbe_alg_add(void)
|
||||
{
|
||||
@@ -1262,6 +1304,7 @@ int setup_tests(void)
|
||||
ADD_ALL_TESTS(test_PEM_read_bio_negative_wrong_password, 2);
|
||||
ADD_TEST(test_rsa_pss_sign);
|
||||
ADD_TEST(test_evp_md_ctx_copy);
|
||||
+ ADD_TEST(test_evp_md_ctx_copy2);
|
||||
ADD_ALL_TESTS(test_provider_unload_effective, 2);
|
||||
#if !defined OPENSSL_NO_DES && !defined OPENSSL_NO_MD5
|
||||
ADD_TEST(test_evp_pbe_alg_add);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From 00bea959ab580c78e00eb56780fec8d53dab054d Mon Sep 17 00:00:00 2001
|
||||
From: Matt Caswell <matt@openssl.org>
|
||||
Date: Fri, 12 May 2023 15:52:07 +0100
|
||||
Subject: [PATCH] Avoid an unneccessary lock if we didn't add anything to the
|
||||
store
|
||||
|
||||
Partially fixes #20286
|
||||
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20952)
|
||||
|
||||
(cherry picked from commit 50001e0e15d4a96213c2eea7c56f80087afa89fd)
|
||||
---
|
||||
crypto/x509/by_dir.c | 14 +++++++++-----
|
||||
1 file changed, 9 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
|
||||
index 1bc397a847..97e6ea0ee1 100644
|
||||
--- a/crypto/x509/by_dir.c
|
||||
+++ b/crypto/x509/by_dir.c
|
||||
@@ -348,12 +348,16 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
|
||||
/*
|
||||
* we have added it to the cache so now pull it out again
|
||||
*/
|
||||
- if (!X509_STORE_lock(xl->store_ctx))
|
||||
- goto finish;
|
||||
- j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
|
||||
- tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
|
||||
- X509_STORE_unlock(xl->store_ctx);
|
||||
-
|
||||
+ if (k > 0) {
|
||||
+ if (!X509_STORE_lock(xl->store_ctx))
|
||||
+ goto finish;
|
||||
+ j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp);
|
||||
+ tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j);
|
||||
+ X509_STORE_unlock(xl->store_ctx);
|
||||
+ } else {
|
||||
+ j = -1;
|
||||
+ tmp = NULL;
|
||||
+ }
|
||||
/*
|
||||
* If a CRL, update the last file suffix added for this.
|
||||
* We don't need to add an entry if k is 0 as this is the initial value.
|
||||
--
|
||||
2.33.0
|
||||
|
||||
566
backport-Decoder-resolution-performance-optimizations.patch
Normal file
566
backport-Decoder-resolution-performance-optimizations.patch
Normal file
@ -0,0 +1,566 @@
|
||||
From 4a1108eb5906cd3cf47a3f70bd58722dbe2023a4 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Landau <hlandau@openssl.org>
|
||||
Date: Thu, 17 Mar 2022 17:29:22 +0000
|
||||
Subject: [PATCH] Decoder resolution performance optimizations
|
||||
|
||||
This refactors decoder functionality to reduce calls to
|
||||
OSSL_DECODER_is_a / EVP_KEYMGMT_is_a, which are substantial bottlenecks
|
||||
in the performance of repeated decode operations (see #15199).
|
||||
|
||||
Reviewed-by: Matt Caswell <matt@openssl.org>
|
||||
Reviewed-by: Richard Levitte <levitte@openssl.org>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/17921)
|
||||
|
||||
(cherry picked from commit 247554458435eaab175cdc9d36878158b9eb6f6e)
|
||||
---
|
||||
crypto/encode_decode/decoder_lib.c | 20 +-
|
||||
crypto/encode_decode/decoder_meth.c | 18 ++
|
||||
crypto/encode_decode/decoder_pkey.c | 323 +++++++++++++++------------
|
||||
crypto/encode_decode/encoder_local.h | 4 +
|
||||
4 files changed, 222 insertions(+), 143 deletions(-)
|
||||
|
||||
diff --git a/crypto/encode_decode/decoder_lib.c b/crypto/encode_decode/decoder_lib.c
|
||||
index 817f335453..8863c316d6 100644
|
||||
--- a/crypto/encode_decode/decoder_lib.c
|
||||
+++ b/crypto/encode_decode/decoder_lib.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <openssl/trace.h>
|
||||
#include "internal/bio.h"
|
||||
#include "internal/provider.h"
|
||||
+#include "internal/namemap.h"
|
||||
#include "crypto/decoder.h"
|
||||
#include "encoder_local.h"
|
||||
#include "e_os.h"
|
||||
@@ -241,6 +242,7 @@ OSSL_DECODER_INSTANCE *ossl_decoder_instance_new(OSSL_DECODER *decoder,
|
||||
/* The "input" property is mandatory */
|
||||
prop = ossl_property_find_property(props, libctx, "input");
|
||||
decoder_inst->input_type = ossl_property_get_string_value(libctx, prop);
|
||||
+ decoder_inst->input_type_id = 0;
|
||||
if (decoder_inst->input_type == NULL) {
|
||||
ERR_raise_data(ERR_LIB_OSSL_DECODER, ERR_R_INVALID_PROPERTY_DEFINITION,
|
||||
"the mandatory 'input' property is missing "
|
||||
@@ -343,6 +345,8 @@ int OSSL_DECODER_CTX_add_decoder(OSSL_DECODER_CTX *ctx, OSSL_DECODER *decoder)
|
||||
struct collect_extra_decoder_data_st {
|
||||
OSSL_DECODER_CTX *ctx;
|
||||
const char *output_type;
|
||||
+ int output_type_id;
|
||||
+
|
||||
/*
|
||||
* 0 to check that the decoder's input type is the same as the decoder name
|
||||
* 1 to check that the decoder's input type differs from the decoder name
|
||||
@@ -370,7 +374,7 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg)
|
||||
const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder);
|
||||
void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
|
||||
|
||||
- if (OSSL_DECODER_is_a(decoder, data->output_type)) {
|
||||
+ if (ossl_decoder_fast_is_a(decoder, data->output_type, &data->output_type_id)) {
|
||||
void *decoderctx = NULL;
|
||||
OSSL_DECODER_INSTANCE *di = NULL;
|
||||
|
||||
@@ -413,8 +417,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg)
|
||||
switch (data->type_check) {
|
||||
case IS_SAME:
|
||||
/* If it differs, this is not a decoder to add for now. */
|
||||
- if (!OSSL_DECODER_is_a(decoder,
|
||||
- OSSL_DECODER_INSTANCE_get_input_type(di))) {
|
||||
+ if (!ossl_decoder_fast_is_a(decoder,
|
||||
+ OSSL_DECODER_INSTANCE_get_input_type(di),
|
||||
+ &di->input_type_id)) {
|
||||
ossl_decoder_instance_free(di);
|
||||
OSSL_TRACE_BEGIN(DECODER) {
|
||||
BIO_printf(trc_out,
|
||||
@@ -425,8 +430,9 @@ static void collect_extra_decoder(OSSL_DECODER *decoder, void *arg)
|
||||
break;
|
||||
case IS_DIFFERENT:
|
||||
/* If it's the same, this is not a decoder to add for now. */
|
||||
- if (OSSL_DECODER_is_a(decoder,
|
||||
- OSSL_DECODER_INSTANCE_get_input_type(di))) {
|
||||
+ if (ossl_decoder_fast_is_a(decoder,
|
||||
+ OSSL_DECODER_INSTANCE_get_input_type(di),
|
||||
+ &di->input_type_id)) {
|
||||
ossl_decoder_instance_free(di);
|
||||
OSSL_TRACE_BEGIN(DECODER) {
|
||||
BIO_printf(trc_out,
|
||||
@@ -534,6 +540,7 @@ int OSSL_DECODER_CTX_add_extra(OSSL_DECODER_CTX *ctx,
|
||||
data.output_type
|
||||
= OSSL_DECODER_INSTANCE_get_input_type(decoder_inst);
|
||||
|
||||
+ data.output_type_id = 0;
|
||||
|
||||
for (j = 0; j < numdecoders; j++)
|
||||
collect_extra_decoder(sk_OSSL_DECODER_value(skdecoders, j),
|
||||
@@ -867,7 +874,8 @@ static int decoder_process(const OSSL_PARAM params[], void *arg)
|
||||
* |new_input_type| holds the value of the "input-type" parameter
|
||||
* for the decoder we're currently considering.
|
||||
*/
|
||||
- if (decoder != NULL && !OSSL_DECODER_is_a(decoder, new_input_type)) {
|
||||
+ if (decoder != NULL && !ossl_decoder_fast_is_a(decoder, new_input_type,
|
||||
+ &new_decoder_inst->input_type_id)) {
|
||||
OSSL_TRACE_BEGIN(DECODER) {
|
||||
BIO_printf(trc_out,
|
||||
"(ctx %p) %s [%u] the input type doesn't match the name of the previous decoder (%p), skipping...\n",
|
||||
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
|
||||
index 56899a9269..496fbe3320 100644
|
||||
--- a/crypto/encode_decode/decoder_meth.c
|
||||
+++ b/crypto/encode_decode/decoder_meth.c
|
||||
@@ -558,6 +558,24 @@ int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int resolve_name(OSSL_DECODER *decoder, const char *name)
|
||||
+{
|
||||
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(decoder->base.prov);
|
||||
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
|
||||
+
|
||||
+ return ossl_namemap_name2num(namemap, name);
|
||||
+}
|
||||
+
|
||||
+int ossl_decoder_fast_is_a(OSSL_DECODER *decoder, const char *name, int *id_cache)
|
||||
+{
|
||||
+ int id = *id_cache;
|
||||
+
|
||||
+ if (id <= 0)
|
||||
+ *id_cache = id = resolve_name(decoder, name);
|
||||
+
|
||||
+ return id > 0 && ossl_decoder_get_number(decoder) == id;
|
||||
+}
|
||||
+
|
||||
struct do_one_data_st {
|
||||
void (*user_fn)(OSSL_DECODER *decoder, void *arg);
|
||||
void *user_arg;
|
||||
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
|
||||
index ed10bb1cee..00d3d48420 100644
|
||||
--- a/crypto/encode_decode/decoder_pkey.c
|
||||
+++ b/crypto/encode_decode/decoder_pkey.c
|
||||
@@ -17,7 +17,9 @@
|
||||
#include <openssl/trace.h>
|
||||
#include "crypto/evp.h"
|
||||
#include "crypto/decoder.h"
|
||||
+#include "crypto/evp/evp_local.h"
|
||||
#include "encoder_local.h"
|
||||
+#include "internal/namemap.h"
|
||||
|
||||
int OSSL_DECODER_CTX_set_passphrase(OSSL_DECODER_CTX *ctx,
|
||||
const unsigned char *kstr,
|
||||
@@ -195,53 +197,83 @@ static void decoder_clean_pkey_construct_arg(void *construct_data)
|
||||
}
|
||||
}
|
||||
|
||||
-static void collect_name(const char *name, void *arg)
|
||||
-{
|
||||
- STACK_OF(OPENSSL_CSTRING) *names = arg;
|
||||
+struct collect_data_st {
|
||||
+ OSSL_LIB_CTX *libctx;
|
||||
+ OSSL_DECODER_CTX *ctx;
|
||||
|
||||
- sk_OPENSSL_CSTRING_push(names, name);
|
||||
-}
|
||||
+ const char *keytype; /* the keytype requested, if any */
|
||||
+ int keytype_id; /* if keytype_resolved is set, keymgmt name_id; else 0 */
|
||||
+ int sm2_id; /* if keytype_resolved is set and EC, SM2 name_id; else 0 */
|
||||
+ int total; /* number of matching results */
|
||||
+ char error_occurred;
|
||||
+ char keytype_resolved;
|
||||
|
||||
-static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg)
|
||||
+ STACK_OF(EVP_KEYMGMT) *keymgmts;
|
||||
+};
|
||||
+
|
||||
+static void collect_decoder_keymgmt(EVP_KEYMGMT *keymgmt, OSSL_DECODER *decoder,
|
||||
+ void *provctx, struct collect_data_st *data)
|
||||
{
|
||||
- STACK_OF(EVP_KEYMGMT) *keymgmts = arg;
|
||||
+ void *decoderctx = NULL;
|
||||
+ OSSL_DECODER_INSTANCE *di = NULL;
|
||||
+
|
||||
+ /*
|
||||
+ * We already checked the EVP_KEYMGMT is applicable in check_keymgmt so we
|
||||
+ * don't check it again here.
|
||||
+ */
|
||||
|
||||
- if (!EVP_KEYMGMT_up_ref(keymgmt) /* ref++ */)
|
||||
+ if (keymgmt->name_id != decoder->base.id)
|
||||
+ /* Mismatch is not an error, continue. */
|
||||
return;
|
||||
- if (sk_EVP_KEYMGMT_push(keymgmts, keymgmt) <= 0) {
|
||||
- EVP_KEYMGMT_free(keymgmt); /* ref-- */
|
||||
+
|
||||
+ if ((decoderctx = decoder->newctx(provctx)) == NULL) {
|
||||
+ data->error_occurred = 1;
|
||||
return;
|
||||
}
|
||||
-}
|
||||
|
||||
-struct collect_decoder_data_st {
|
||||
- STACK_OF(OPENSSL_CSTRING) *names;
|
||||
- OSSL_DECODER_CTX *ctx;
|
||||
+ if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
|
||||
+ decoder->freectx(decoderctx);
|
||||
+ data->error_occurred = 1;
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- int total;
|
||||
- unsigned int error_occurred:1;
|
||||
-};
|
||||
+ OSSL_TRACE_BEGIN(DECODER) {
|
||||
+ BIO_printf(trc_out,
|
||||
+ "(ctx %p) Checking out decoder %p:\n"
|
||||
+ " %s with %s\n",
|
||||
+ (void *)data->ctx, (void *)decoder,
|
||||
+ OSSL_DECODER_get0_name(decoder),
|
||||
+ OSSL_DECODER_get0_properties(decoder));
|
||||
+ } OSSL_TRACE_END(DECODER);
|
||||
+
|
||||
+ if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
|
||||
+ ossl_decoder_instance_free(di);
|
||||
+ data->error_occurred = 1;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ++data->total;
|
||||
+}
|
||||
|
||||
static void collect_decoder(OSSL_DECODER *decoder, void *arg)
|
||||
{
|
||||
- struct collect_decoder_data_st *data = arg;
|
||||
+ struct collect_data_st *data = arg;
|
||||
+ STACK_OF(EVP_KEYMGMT) *keymgmts = data->keymgmts;
|
||||
size_t i, end_i;
|
||||
- const OSSL_PROVIDER *prov = OSSL_DECODER_get0_provider(decoder);
|
||||
- void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
|
||||
+ EVP_KEYMGMT *keymgmt;
|
||||
+ const OSSL_PROVIDER *prov;
|
||||
+ void *provctx;
|
||||
|
||||
if (data->error_occurred)
|
||||
return;
|
||||
|
||||
- if (data->names == NULL) {
|
||||
- data->error_occurred = 1;
|
||||
- return;
|
||||
- }
|
||||
+ prov = OSSL_DECODER_get0_provider(decoder);
|
||||
+ provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
|
||||
|
||||
/*
|
||||
- * Either the caller didn't give a selection, or if they did,
|
||||
- * the decoder must tell us if it supports that selection to
|
||||
- * be accepted. If the decoder doesn't have |does_selection|,
|
||||
- * it's seen as taking anything.
|
||||
+ * Either the caller didn't give us a selection, or if they did, the decoder
|
||||
+ * must tell us if it supports that selection to be accepted. If the decoder
|
||||
+ * doesn't have |does_selection|, it's seen as taking anything.
|
||||
*/
|
||||
if (decoder->does_selection != NULL
|
||||
&& !decoder->does_selection(provctx, data->ctx->selection))
|
||||
@@ -256,68 +288,101 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
|
||||
OSSL_DECODER_get0_properties(decoder));
|
||||
} OSSL_TRACE_END(DECODER);
|
||||
|
||||
- end_i = sk_OPENSSL_CSTRING_num(data->names);
|
||||
- for (i = 0; i < end_i; i++) {
|
||||
- const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
|
||||
-
|
||||
- if (OSSL_DECODER_is_a(decoder, name)) {
|
||||
- void *decoderctx = NULL;
|
||||
- OSSL_DECODER_INSTANCE *di = NULL;
|
||||
-
|
||||
- if ((decoderctx = decoder->newctx(provctx)) == NULL) {
|
||||
- data->error_occurred = 1;
|
||||
- return;
|
||||
- }
|
||||
- if ((di = ossl_decoder_instance_new(decoder, decoderctx)) == NULL) {
|
||||
- decoder->freectx(decoderctx);
|
||||
- data->error_occurred = 1;
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- OSSL_TRACE_BEGIN(DECODER) {
|
||||
- BIO_printf(trc_out,
|
||||
- "(ctx %p) Checking out decoder %p:\n"
|
||||
- " %s with %s\n",
|
||||
- (void *)data->ctx, (void *)decoder,
|
||||
- OSSL_DECODER_get0_name(decoder),
|
||||
- OSSL_DECODER_get0_properties(decoder));
|
||||
- } OSSL_TRACE_END(DECODER);
|
||||
-
|
||||
- if (!ossl_decoder_ctx_add_decoder_inst(data->ctx, di)) {
|
||||
- ossl_decoder_instance_free(di);
|
||||
- data->error_occurred = 1;
|
||||
- return;
|
||||
- }
|
||||
- data->total++;
|
||||
-
|
||||
- /* Success */
|
||||
+ end_i = sk_EVP_KEYMGMT_num(keymgmts);
|
||||
+ for (i = 0; i < end_i; ++i) {
|
||||
+ keymgmt = sk_EVP_KEYMGMT_value(keymgmts, i);
|
||||
+
|
||||
+ collect_decoder_keymgmt(keymgmt, decoder, provctx, data);
|
||||
+ if (data->error_occurred)
|
||||
return;
|
||||
- }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Is this EVP_KEYMGMT applicable given the key type given in the call to
|
||||
+ * ossl_decoder_ctx_setup_for_pkey (if any)?
|
||||
+ */
|
||||
+static int check_keymgmt(EVP_KEYMGMT *keymgmt, struct collect_data_st *data)
|
||||
+{
|
||||
+ /* If no keytype was specified, everything matches. */
|
||||
+ if (data->keytype == NULL)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (!data->keytype_resolved) {
|
||||
+ /* We haven't cached the IDs from the keytype string yet. */
|
||||
+ OSSL_NAMEMAP *namemap = ossl_namemap_stored(data->libctx);
|
||||
+ data->keytype_id = ossl_namemap_name2num(namemap, data->keytype);
|
||||
+
|
||||
+ /*
|
||||
+ * If keytype is a value ambiguously used for both EC and SM2,
|
||||
+ * collect the ID for SM2 as well.
|
||||
+ */
|
||||
+ if (data->keytype_id != 0
|
||||
+ && (strcmp(data->keytype, "id-ecPublicKey") == 0
|
||||
+ || strcmp(data->keytype, "1.2.840.10045.2.1") == 0))
|
||||
+ data->sm2_id = ossl_namemap_name2num(namemap, "SM2");
|
||||
+
|
||||
+ /*
|
||||
+ * If keytype_id is zero the name was not found, but we still
|
||||
+ * set keytype_resolved to avoid trying all this again.
|
||||
+ */
|
||||
+ data->keytype_resolved = 1;
|
||||
}
|
||||
|
||||
- /* Decoder not suitable - but not a fatal error */
|
||||
- data->error_occurred = 0;
|
||||
+ /* Specified keytype could not be resolved, so nothing matches. */
|
||||
+ if (data->keytype_id == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Does not match the keytype specified, so skip. */
|
||||
+ if (keymgmt->name_id != data->keytype_id
|
||||
+ && keymgmt->name_id != data->sm2_id)
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
+static void collect_keymgmt(EVP_KEYMGMT *keymgmt, void *arg)
|
||||
+{
|
||||
+ struct collect_data_st *data = arg;
|
||||
+
|
||||
+ if (!check_keymgmt(keymgmt, data))
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * We have to ref EVP_KEYMGMT here because in the success case,
|
||||
+ * data->keymgmts is referenced by the constructor we register in the
|
||||
+ * OSSL_DECODER_CTX. The registered cleanup function
|
||||
+ * (decoder_clean_pkey_construct_arg) unrefs every element of the stack and
|
||||
+ * frees it.
|
||||
+ */
|
||||
+ if (!EVP_KEYMGMT_up_ref(keymgmt))
|
||||
+ return;
|
||||
+
|
||||
+ if (sk_EVP_KEYMGMT_push(data->keymgmts, keymgmt) <= 0) {
|
||||
+ EVP_KEYMGMT_free(keymgmt);
|
||||
+ data->error_occurred = 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * This function does the actual binding of decoders to the OSSL_DECODER_CTX. It
|
||||
+ * searches for decoders matching 'keytype', which is a string like "RSA", "DH",
|
||||
+ * etc. If 'keytype' is NULL, decoders for all keytypes are bound.
|
||||
+ */
|
||||
int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
|
||||
EVP_PKEY **pkey, const char *keytype,
|
||||
OSSL_LIB_CTX *libctx,
|
||||
const char *propquery)
|
||||
{
|
||||
- struct decoder_pkey_data_st *process_data = NULL;
|
||||
- STACK_OF(OPENSSL_CSTRING) *names = NULL;
|
||||
- const char *input_type = ctx->start_input_type;
|
||||
- const char *input_structure = ctx->input_structure;
|
||||
int ok = 0;
|
||||
- int isecoid = 0;
|
||||
- int i, end;
|
||||
-
|
||||
- if (keytype != NULL
|
||||
- && (strcmp(keytype, "id-ecPublicKey") == 0
|
||||
- || strcmp(keytype, "1.2.840.10045.2.1") == 0))
|
||||
- isecoid = 1;
|
||||
+ struct decoder_pkey_data_st *process_data = NULL;
|
||||
+ struct collect_data_st collect_data = { NULL };
|
||||
+ STACK_OF(EVP_KEYMGMT) *keymgmts = NULL;
|
||||
|
||||
OSSL_TRACE_BEGIN(DECODER) {
|
||||
+ const char *input_type = ctx->start_input_type;
|
||||
+ const char *input_structure = ctx->input_structure;
|
||||
+
|
||||
BIO_printf(trc_out,
|
||||
"(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n",
|
||||
(void *)ctx,
|
||||
@@ -329,81 +394,67 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
|
||||
input_structure != NULL ? input_structure : "");
|
||||
} OSSL_TRACE_END(DECODER);
|
||||
|
||||
+ /* Allocate data. */
|
||||
if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL
|
||||
|| (propquery != NULL
|
||||
- && (process_data->propq = OPENSSL_strdup(propquery)) == NULL)
|
||||
- || (process_data->keymgmts = sk_EVP_KEYMGMT_new_null()) == NULL
|
||||
- || (names = sk_OPENSSL_CSTRING_new_null()) == NULL) {
|
||||
+ && (process_data->propq = OPENSSL_strdup(propquery)) == NULL)) {
|
||||
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
- process_data->object = (void **)pkey;
|
||||
- process_data->libctx = libctx;
|
||||
+ /* Allocate our list of EVP_KEYMGMTs. */
|
||||
+ keymgmts = sk_EVP_KEYMGMT_new_null();
|
||||
+ if (keymgmts == NULL) {
|
||||
+ ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_MALLOC_FAILURE);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ process_data->object = (void **)pkey;
|
||||
+ process_data->libctx = libctx;
|
||||
process_data->selection = ctx->selection;
|
||||
+ process_data->keymgmts = keymgmts;
|
||||
|
||||
- /* First, find all keymgmts to form goals */
|
||||
- EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt,
|
||||
- process_data->keymgmts);
|
||||
+ /*
|
||||
+ * Enumerate all keymgmts into a stack.
|
||||
+ *
|
||||
+ * We could nest EVP_KEYMGMT_do_all_provided inside
|
||||
+ * OSSL_DECODER_do_all_provided or vice versa but these functions become
|
||||
+ * bottlenecks if called repeatedly, which is why we collect the
|
||||
+ * EVP_KEYMGMTs into a stack here and call both functions only once.
|
||||
+ *
|
||||
+ * We resolve the keytype string to a name ID so we don't have to resolve it
|
||||
+ * multiple times, avoiding repeated calls to EVP_KEYMGMT_is_a, which is a
|
||||
+ * performance bottleneck. However, we do this lazily on the first call to
|
||||
+ * collect_keymgmt made by EVP_KEYMGMT_do_all_provided, rather than do it
|
||||
+ * upfront, as this ensures that the names for all loaded providers have
|
||||
+ * been registered by the time we try to resolve the keytype string.
|
||||
+ */
|
||||
+ collect_data.ctx = ctx;
|
||||
+ collect_data.libctx = libctx;
|
||||
+ collect_data.keymgmts = keymgmts;
|
||||
+ collect_data.keytype = keytype;
|
||||
+ EVP_KEYMGMT_do_all_provided(libctx, collect_keymgmt, &collect_data);
|
||||
|
||||
- /* Then, we collect all the keymgmt names */
|
||||
- end = sk_EVP_KEYMGMT_num(process_data->keymgmts);
|
||||
- for (i = 0; i < end; i++) {
|
||||
- EVP_KEYMGMT *keymgmt = sk_EVP_KEYMGMT_value(process_data->keymgmts, i);
|
||||
+ if (collect_data.error_occurred)
|
||||
+ goto err;
|
||||
|
||||
- /*
|
||||
- * If the key type is given by the caller, we only use the matching
|
||||
- * KEYMGMTs, otherwise we use them all.
|
||||
- * We have to special case SM2 here because of its abuse of the EC OID.
|
||||
- * The EC OID can be used to identify an EC key or an SM2 key - so if
|
||||
- * we have seen that OID we try both key types
|
||||
- */
|
||||
- if (keytype == NULL
|
||||
- || EVP_KEYMGMT_is_a(keymgmt, keytype)
|
||||
- || (isecoid && EVP_KEYMGMT_is_a(keymgmt, "SM2"))) {
|
||||
- if (!EVP_KEYMGMT_names_do_all(keymgmt, collect_name, names)) {
|
||||
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
|
||||
- goto err;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ /* Enumerate all matching decoders. */
|
||||
+ OSSL_DECODER_do_all_provided(libctx, collect_decoder, &collect_data);
|
||||
+
|
||||
+ if (collect_data.error_occurred)
|
||||
+ goto err;
|
||||
|
||||
OSSL_TRACE_BEGIN(DECODER) {
|
||||
- end = sk_OPENSSL_CSTRING_num(names);
|
||||
BIO_printf(trc_out,
|
||||
- " Found %d keytypes (possibly with duplicates)",
|
||||
- end);
|
||||
- for (i = 0; i < end; i++)
|
||||
- BIO_printf(trc_out, "%s%s",
|
||||
- i == 0 ? ": " : ", ",
|
||||
- sk_OPENSSL_CSTRING_value(names, i));
|
||||
- BIO_printf(trc_out, "\n");
|
||||
+ "(ctx %p) Got %d decoders producing keys\n",
|
||||
+ (void *)ctx, collect_data.total);
|
||||
} OSSL_TRACE_END(DECODER);
|
||||
|
||||
/*
|
||||
- * Finally, find all decoders that have any keymgmt of the collected
|
||||
- * keymgmt names
|
||||
+ * Finish initializing the decoder context. If one or more decoders matched
|
||||
+ * above then the number of decoders attached to the OSSL_DECODER_CTX will
|
||||
+ * be nonzero. Else nothing was found and we do nothing.
|
||||
*/
|
||||
- {
|
||||
- struct collect_decoder_data_st collect_decoder_data = { NULL, };
|
||||
-
|
||||
- collect_decoder_data.names = names;
|
||||
- collect_decoder_data.ctx = ctx;
|
||||
- OSSL_DECODER_do_all_provided(libctx,
|
||||
- collect_decoder, &collect_decoder_data);
|
||||
- sk_OPENSSL_CSTRING_free(names);
|
||||
- names = NULL;
|
||||
-
|
||||
- if (collect_decoder_data.error_occurred)
|
||||
- goto err;
|
||||
-
|
||||
- OSSL_TRACE_BEGIN(DECODER) {
|
||||
- BIO_printf(trc_out,
|
||||
- "(ctx %p) Got %d decoders producing keys\n",
|
||||
- (void *)ctx, collect_decoder_data.total);
|
||||
- } OSSL_TRACE_END(DECODER);
|
||||
- }
|
||||
-
|
||||
if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) {
|
||||
if (!OSSL_DECODER_CTX_set_construct(ctx, decoder_construct_pkey)
|
||||
|| !OSSL_DECODER_CTX_set_construct_data(ctx, process_data)
|
||||
@@ -417,8 +468,6 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
|
||||
ok = 1;
|
||||
err:
|
||||
decoder_clean_pkey_construct_arg(process_data);
|
||||
- sk_OPENSSL_CSTRING_free(names);
|
||||
-
|
||||
return ok;
|
||||
}
|
||||
|
||||
diff --git a/crypto/encode_decode/encoder_local.h b/crypto/encode_decode/encoder_local.h
|
||||
index c1885ffc77..939e831727 100644
|
||||
--- a/crypto/encode_decode/encoder_local.h
|
||||
+++ b/crypto/encode_decode/encoder_local.h
|
||||
@@ -108,6 +108,7 @@ struct ossl_decoder_instance_st {
|
||||
void *decoderctx; /* Never NULL */
|
||||
const char *input_type; /* Never NULL */
|
||||
const char *input_structure; /* May be NULL */
|
||||
+ int input_type_id;
|
||||
|
||||
unsigned int flag_input_structure_was_set : 1;
|
||||
};
|
||||
@@ -162,3 +163,6 @@ const OSSL_PROPERTY_LIST *
|
||||
ossl_decoder_parsed_properties(const OSSL_DECODER *decoder);
|
||||
const OSSL_PROPERTY_LIST *
|
||||
ossl_encoder_parsed_properties(const OSSL_ENCODER *encoder);
|
||||
+
|
||||
+int ossl_decoder_fast_is_a(OSSL_DECODER *decoder,
|
||||
+ const char *name, int *id_cache);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,275 @@
|
||||
From fca5d6a2b76d0c1f20e63cec5ac1b927eeba7b43 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tomas@openssl.org>
|
||||
Date: Thu, 19 May 2022 11:38:23 +0200
|
||||
Subject: [PATCH] Drop ossl_namemap_add_name_n() and simplify
|
||||
ossl_namemap_add_names()
|
||||
|
||||
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/18341)
|
||||
|
||||
(cherry picked from commit b00cf0e790661636e1df1026554f712cc513592d)
|
||||
---
|
||||
crypto/core_namemap.c | 96 +++++++++++---------------
|
||||
doc/internal/man3/ossl_namemap_new.pod | 15 ++--
|
||||
include/internal/namemap.h | 2 -
|
||||
3 files changed, 48 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
|
||||
index 4c1ca05308..380f4da9c2 100644
|
||||
--- a/crypto/core_namemap.c
|
||||
+++ b/crypto/core_namemap.c
|
||||
@@ -166,6 +166,7 @@ int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/* This function is not thread safe, the namemap must be locked */
|
||||
static int namemap_name2num(const OSSL_NAMEMAP *namemap,
|
||||
const char *name)
|
||||
{
|
||||
@@ -239,25 +240,22 @@ const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
|
||||
return data.name;
|
||||
}
|
||||
|
||||
-static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
- const char *name, size_t name_len)
|
||||
+/* This function is not thread safe, the namemap must be locked */
|
||||
+static int namemap_add_name(OSSL_NAMEMAP *namemap, int number,
|
||||
+ const char *name)
|
||||
{
|
||||
NAMENUM_ENTRY *namenum = NULL;
|
||||
int tmp_number;
|
||||
- char *tmp = OPENSSL_strndup(name, name_len);
|
||||
-
|
||||
- if (tmp == NULL)
|
||||
- return 0;
|
||||
|
||||
/* If it already exists, we don't add it */
|
||||
- if ((tmp_number = namemap_name2num(namemap, tmp)) != 0) {
|
||||
- OPENSSL_free(tmp);
|
||||
+ if ((tmp_number = namemap_name2num(namemap, name)) != 0)
|
||||
return tmp_number;
|
||||
- }
|
||||
|
||||
if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((namenum->name = OPENSSL_strdup(name)) == NULL)
|
||||
goto err;
|
||||
- namenum->name = tmp;
|
||||
|
||||
/* The tsan_counter use here is safe since we're under lock */
|
||||
namenum->number =
|
||||
@@ -269,13 +267,12 @@ static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
return namenum->number;
|
||||
|
||||
err:
|
||||
- OPENSSL_free(tmp);
|
||||
- OPENSSL_free(namenum);
|
||||
+ namenum_free(namenum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
- const char *name, size_t name_len)
|
||||
+int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number,
|
||||
+ const char *name)
|
||||
{
|
||||
int tmp_number;
|
||||
|
||||
@@ -284,29 +281,20 @@ int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
namemap = ossl_namemap_stored(NULL);
|
||||
#endif
|
||||
|
||||
- if (name == NULL || name_len == 0 || namemap == NULL)
|
||||
+ if (name == NULL || *name == 0 || namemap == NULL)
|
||||
return 0;
|
||||
|
||||
if (!CRYPTO_THREAD_write_lock(namemap->lock))
|
||||
return 0;
|
||||
- tmp_number = namemap_add_name_n(namemap, number, name, name_len);
|
||||
+ tmp_number = namemap_add_name(namemap, number, name);
|
||||
CRYPTO_THREAD_unlock(namemap->lock);
|
||||
return tmp_number;
|
||||
}
|
||||
|
||||
-int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name)
|
||||
-{
|
||||
- if (name == NULL)
|
||||
- return 0;
|
||||
-
|
||||
- return ossl_namemap_add_name_n(namemap, number, name, strlen(name));
|
||||
-}
|
||||
-
|
||||
int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
|
||||
const char *names, const char separator)
|
||||
{
|
||||
- const char *p, *q;
|
||||
- size_t l;
|
||||
+ char *tmp, *p, *q, *endp;
|
||||
|
||||
/* Check that we have a namemap */
|
||||
if (!ossl_assert(namemap != NULL)) {
|
||||
@@ -314,71 +302,71 @@ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (!CRYPTO_THREAD_write_lock(namemap->lock))
|
||||
+ if ((tmp = OPENSSL_strdup(names)) == NULL)
|
||||
return 0;
|
||||
+
|
||||
+ if (!CRYPTO_THREAD_write_lock(namemap->lock)) {
|
||||
+ OPENSSL_free(tmp);
|
||||
+ return 0;
|
||||
+ }
|
||||
/*
|
||||
* Check that no name is an empty string, and that all names have at
|
||||
* most one numeric identity together.
|
||||
*/
|
||||
- for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
|
||||
+ for (p = tmp; *p != '\0'; p = q) {
|
||||
int this_number;
|
||||
- char *allocated;
|
||||
- const char *tmp;
|
||||
+ size_t l;
|
||||
|
||||
if ((q = strchr(p, separator)) == NULL) {
|
||||
l = strlen(p); /* offset to \0 */
|
||||
- tmp = p;
|
||||
- allocated = NULL;
|
||||
+ q = p + l;
|
||||
} else {
|
||||
l = q - p; /* offset to the next separator */
|
||||
- tmp = allocated = OPENSSL_strndup(p, l);
|
||||
- if (tmp == NULL)
|
||||
- goto err;
|
||||
+ *q++ = '\0';
|
||||
}
|
||||
|
||||
- this_number = namemap_name2num(namemap, tmp);
|
||||
- OPENSSL_free(allocated);
|
||||
-
|
||||
- if (*p == '\0' || *p == separator) {
|
||||
+ if (*p == '\0') {
|
||||
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
|
||||
- goto err;
|
||||
+ number = 0;
|
||||
+ goto end;
|
||||
}
|
||||
+
|
||||
+ this_number = namemap_name2num(namemap, p);
|
||||
+
|
||||
if (number == 0) {
|
||||
number = this_number;
|
||||
} else if (this_number != 0 && this_number != number) {
|
||||
ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES,
|
||||
- "\"%.*s\" has an existing different identity %d (from \"%s\")",
|
||||
- l, p, this_number, names);
|
||||
- goto err;
|
||||
+ "\"%s\" has an existing different identity %d (from \"%s\")",
|
||||
+ p, this_number, names);
|
||||
+ number = 0;
|
||||
+ goto end;
|
||||
}
|
||||
}
|
||||
+ endp = p;
|
||||
|
||||
/* Now that we have checked, register all names */
|
||||
- for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
|
||||
+ for (p = tmp; p < endp; p = q) {
|
||||
int this_number;
|
||||
|
||||
- if ((q = strchr(p, separator)) == NULL)
|
||||
- l = strlen(p); /* offset to \0 */
|
||||
- else
|
||||
- l = q - p; /* offset to the next separator */
|
||||
+ q = p + strlen(p) + 1;
|
||||
|
||||
- this_number = namemap_add_name_n(namemap, number, p, l);
|
||||
+ this_number = namemap_add_name(namemap, number, p);
|
||||
if (number == 0) {
|
||||
number = this_number;
|
||||
} else if (this_number != number) {
|
||||
ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
|
||||
"Got number %d when expecting %d",
|
||||
this_number, number);
|
||||
- goto err;
|
||||
+ number = 0;
|
||||
+ goto end;
|
||||
}
|
||||
}
|
||||
|
||||
+ end:
|
||||
CRYPTO_THREAD_unlock(namemap->lock);
|
||||
+ OPENSSL_free(tmp);
|
||||
return number;
|
||||
-
|
||||
- err:
|
||||
- CRYPTO_THREAD_unlock(namemap->lock);
|
||||
- return 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
diff --git a/doc/internal/man3/ossl_namemap_new.pod b/doc/internal/man3/ossl_namemap_new.pod
|
||||
index ff247e87b0..7f4940fc93 100644
|
||||
--- a/doc/internal/man3/ossl_namemap_new.pod
|
||||
+++ b/doc/internal/man3/ossl_namemap_new.pod
|
||||
@@ -3,7 +3,7 @@
|
||||
=head1 NAME
|
||||
|
||||
ossl_namemap_new, ossl_namemap_free, ossl_namemap_stored, ossl_namemap_empty,
|
||||
-ossl_namemap_add_name, ossl_namemap_add_name_n, ossl_namemap_add_names,
|
||||
+ossl_namemap_add_name, ossl_namemap_add_names,
|
||||
ossl_namemap_name2num, ossl_namemap_name2num_n,
|
||||
ossl_namemap_doall_names
|
||||
- internal number E<lt>-E<gt> name map
|
||||
@@ -19,8 +19,6 @@ ossl_namemap_doall_names
|
||||
int ossl_namemap_empty(OSSL_NAMEMAP *namemap);
|
||||
|
||||
int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name);
|
||||
- int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
- const char *name, size_t name_len);
|
||||
|
||||
int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name);
|
||||
int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
|
||||
@@ -62,10 +60,9 @@ names already associated with that number.
|
||||
ossl_namemap_name2num() finds the number corresponding to the given
|
||||
I<name>.
|
||||
|
||||
-ossl_namemap_add_name_n() and ossl_namemap_name2num_n() do the same thing
|
||||
-as ossl_namemap_add_name() and ossl_namemap_name2num(), but take a string
|
||||
-length I<name_len> as well, allowing the caller to use a fragment of
|
||||
-a string as a name.
|
||||
+ossl_namemap_name2num_n() does the same thing as
|
||||
+ossl_namemap_name2num(), but takes a string length I<name_len> as well,
|
||||
+allowing the caller to use a fragment of a string as a name.
|
||||
|
||||
ossl_namemap_doall_names() walks through all names associated with
|
||||
I<number> in the given I<namemap> and calls the function I<fn> for
|
||||
@@ -88,8 +85,8 @@ ossl_namemap_empty() returns 1 if the B<OSSL_NAMEMAP> is NULL or
|
||||
empty, 0 if it's not empty, or -1 on internal error (such as inability
|
||||
to lock).
|
||||
|
||||
-ossl_namemap_add_name() and ossl_namemap_add_name_n() return the number
|
||||
-associated with the added string, or zero on error.
|
||||
+ossl_namemap_add_name() returns the number associated with the added
|
||||
+string, or zero on error.
|
||||
|
||||
ossl_namemap_num2names() returns a pointer to a NULL-terminated list of
|
||||
pointers to the names corresponding to the given number, or NULL if
|
||||
diff --git a/include/internal/namemap.h b/include/internal/namemap.h
|
||||
index a4c60ae695..6c42a9cd7c 100644
|
||||
--- a/include/internal/namemap.h
|
||||
+++ b/include/internal/namemap.h
|
||||
@@ -18,8 +18,6 @@ void ossl_namemap_free(OSSL_NAMEMAP *namemap);
|
||||
int ossl_namemap_empty(OSSL_NAMEMAP *namemap);
|
||||
|
||||
int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name);
|
||||
-int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
- const char *name, size_t name_len);
|
||||
|
||||
/*
|
||||
* The number<->name relationship is 1<->many
|
||||
--
|
||||
2.33.0
|
||||
|
||||
153
backport-Improve-performance-of-the-encoder-collection.patch
Normal file
153
backport-Improve-performance-of-the-encoder-collection.patch
Normal file
@ -0,0 +1,153 @@
|
||||
From 762473f53a0cf319e511895556a6df0e3fbb3f9e Mon Sep 17 00:00:00 2001
|
||||
From: slontis <shane.lontis@oracle.com>
|
||||
Date: Wed, 5 Oct 2022 09:57:51 +1000
|
||||
Subject: [PATCH] Improve performance of the encoder collection
|
||||
|
||||
Reviewed-by: Richard Levitte <levitte@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
Reviewed-by: Hugo Landau <hlandau@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/19344)
|
||||
|
||||
(cherry picked from commit c3b46409559c18f103ebb2221c6f8af3cd7db00d)
|
||||
---
|
||||
crypto/encode_decode/encoder_pkey.c | 80 ++++++++++++++++++-----------
|
||||
1 file changed, 51 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/crypto/encode_decode/encoder_pkey.c b/crypto/encode_decode/encoder_pkey.c
|
||||
index 3a24317cf4..f8a5a45acc 100644
|
||||
--- a/crypto/encode_decode/encoder_pkey.c
|
||||
+++ b/crypto/encode_decode/encoder_pkey.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <openssl/trace.h>
|
||||
#include "internal/provider.h"
|
||||
#include "internal/property.h"
|
||||
+#include "internal/namemap.h"
|
||||
#include "crypto/evp.h"
|
||||
#include "encoder_local.h"
|
||||
|
||||
@@ -72,6 +73,7 @@ int OSSL_ENCODER_CTX_set_passphrase_cb(OSSL_ENCODER_CTX *ctx,
|
||||
|
||||
struct collected_encoder_st {
|
||||
STACK_OF(OPENSSL_CSTRING) *names;
|
||||
+ int *id_names;
|
||||
const char *output_structure;
|
||||
const char *output_type;
|
||||
|
||||
@@ -85,41 +87,41 @@ struct collected_encoder_st {
|
||||
static void collect_encoder(OSSL_ENCODER *encoder, void *arg)
|
||||
{
|
||||
struct collected_encoder_st *data = arg;
|
||||
- size_t i, end_i;
|
||||
+ const OSSL_PROVIDER *prov;
|
||||
|
||||
if (data->error_occurred)
|
||||
return;
|
||||
|
||||
data->error_occurred = 1; /* Assume the worst */
|
||||
|
||||
- if (data->names == NULL)
|
||||
- return;
|
||||
-
|
||||
- end_i = sk_OPENSSL_CSTRING_num(data->names);
|
||||
- for (i = 0; i < end_i; i++) {
|
||||
- const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
|
||||
- const OSSL_PROVIDER *prov = OSSL_ENCODER_get0_provider(encoder);
|
||||
+ prov = OSSL_ENCODER_get0_provider(encoder);
|
||||
+ /*
|
||||
+ * collect_encoder() is called in two passes, one where the encoders
|
||||
+ * from the same provider as the keymgmt are looked up, and one where
|
||||
+ * the other encoders are looked up. |data->flag_find_same_provider|
|
||||
+ * tells us which pass we're in.
|
||||
+ */
|
||||
+ if ((data->keymgmt_prov == prov) == data->flag_find_same_provider) {
|
||||
void *provctx = OSSL_PROVIDER_get0_provider_ctx(prov);
|
||||
-
|
||||
- /*
|
||||
- * collect_encoder() is called in two passes, one where the encoders
|
||||
- * from the same provider as the keymgmt are looked up, and one where
|
||||
- * the other encoders are looked up. |data->flag_find_same_provider|
|
||||
- * tells us which pass we're in.
|
||||
- */
|
||||
- if ((data->keymgmt_prov == prov) != data->flag_find_same_provider)
|
||||
- continue;
|
||||
-
|
||||
- if (!OSSL_ENCODER_is_a(encoder, name)
|
||||
- || (encoder->does_selection != NULL
|
||||
- && !encoder->does_selection(provctx, data->ctx->selection))
|
||||
- || (data->keymgmt_prov != prov
|
||||
- && encoder->import_object == NULL))
|
||||
- continue;
|
||||
-
|
||||
- /* Only add each encoder implementation once */
|
||||
- if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder))
|
||||
- break;
|
||||
+ size_t i, end_i = sk_OPENSSL_CSTRING_num(data->names);
|
||||
+ int match;
|
||||
+
|
||||
+ for (i = 0; i < end_i; i++) {
|
||||
+ if (data->flag_find_same_provider)
|
||||
+ match = (data->id_names[i] == encoder->base.id);
|
||||
+ else
|
||||
+ match = OSSL_ENCODER_is_a(encoder, sk_OPENSSL_CSTRING_value(data->names, i));
|
||||
+ if (!match
|
||||
+ || (encoder->does_selection != NULL
|
||||
+ && !encoder->does_selection(provctx, data->ctx->selection))
|
||||
+ || (data->keymgmt_prov != prov
|
||||
+ && encoder->import_object == NULL))
|
||||
+ continue;
|
||||
+
|
||||
+ /* Only add each encoder implementation once */
|
||||
+ if (OSSL_ENCODER_CTX_add_encoder(data->ctx, encoder))
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
data->error_occurred = 0; /* All is good now */
|
||||
@@ -227,7 +229,8 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx,
|
||||
struct construct_data_st *data = NULL;
|
||||
const OSSL_PROVIDER *prov = NULL;
|
||||
OSSL_LIB_CTX *libctx = NULL;
|
||||
- int ok = 0;
|
||||
+ int ok = 0, i, end;
|
||||
+ OSSL_NAMEMAP *namemap;
|
||||
|
||||
if (!ossl_assert(ctx != NULL) || !ossl_assert(pkey != NULL)) {
|
||||
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_NULL_PARAMETER);
|
||||
@@ -271,7 +274,25 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx,
|
||||
encoder_data.error_occurred = 0;
|
||||
encoder_data.keymgmt_prov = prov;
|
||||
encoder_data.ctx = ctx;
|
||||
+ encoder_data.id_names = NULL;
|
||||
|
||||
+ /*
|
||||
+ * collect_encoder() is called many times, and for every call it converts all encoder_data.names
|
||||
+ * into namemap ids if it calls OSSL_ENCODER_is_a(). We cache the ids here instead,
|
||||
+ * and can use them for encoders with the same provider as the keymgmt.
|
||||
+ */
|
||||
+ namemap = ossl_namemap_stored(libctx);
|
||||
+ end = sk_OPENSSL_CSTRING_num(encoder_data.names);
|
||||
+ if (end > 0) {
|
||||
+ encoder_data.id_names = OPENSSL_malloc(end * sizeof(int));
|
||||
+ if (encoder_data.id_names == NULL)
|
||||
+ goto err;
|
||||
+ for (i = 0; i < end; ++i) {
|
||||
+ const char *name = sk_OPENSSL_CSTRING_value(keymgmt_data.names, i);
|
||||
+
|
||||
+ encoder_data.id_names[i] = ossl_namemap_name2num(namemap, name);
|
||||
+ }
|
||||
+ }
|
||||
/*
|
||||
* Place the encoders with the a different provider as the keymgmt
|
||||
* last (the chain is processed in reverse order)
|
||||
@@ -286,6 +307,7 @@ static int ossl_encoder_ctx_setup_for_pkey(OSSL_ENCODER_CTX *ctx,
|
||||
encoder_data.flag_find_same_provider = 1;
|
||||
OSSL_ENCODER_do_all_provided(libctx, collect_encoder, &encoder_data);
|
||||
|
||||
+ OPENSSL_free(encoder_data.id_names);
|
||||
sk_OPENSSL_CSTRING_free(keymgmt_data.names);
|
||||
if (encoder_data.error_occurred) {
|
||||
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_MALLOC_FAILURE);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
62
backport-Make-IV-buf-in-prov_cipher_ctx_st-aligned.patch
Normal file
62
backport-Make-IV-buf-in-prov_cipher_ctx_st-aligned.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From a91c268853c4bda825a505629a873e21685490bf Mon Sep 17 00:00:00 2001
|
||||
From: "Hongren (Zenithal) Zheng" <i@zenithal.me>
|
||||
Date: Mon, 9 May 2022 19:42:39 +0800
|
||||
Subject: [PATCH] Make IV/buf in prov_cipher_ctx_st aligned
|
||||
|
||||
Make IV/buf aligned will drastically improve performance
|
||||
as some architecture performs badly on misaligned memory
|
||||
access.
|
||||
|
||||
Ref to
|
||||
https://gist.github.com/ZenithalHourlyRate/7b5175734f87acb73d0bbc53391d7140#file-2-openssl-long-md
|
||||
Ref to
|
||||
openssl#18197
|
||||
|
||||
Signed-off-by: Hongren (Zenithal) Zheng <i@zenithal.me>
|
||||
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
|
||||
(cherry picked from commit 2787a709c984d3884e1726383c2f2afca428d795)
|
||||
|
||||
Reviewed-by: Neil Horman <nhorman@openssl.org>
|
||||
Reviewed-by: Matt Caswell <matt@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/23463)
|
||||
---
|
||||
.../implementations/include/prov/ciphercommon.h | 13 +++++++------
|
||||
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h
|
||||
index 383b759304..7f9a4a3bf2 100644
|
||||
--- a/providers/implementations/include/prov/ciphercommon.h
|
||||
+++ b/providers/implementations/include/prov/ciphercommon.h
|
||||
@@ -42,6 +42,13 @@ typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out,
|
||||
#define PROV_CIPHER_FLAG_INVERSE_CIPHER 0x0200
|
||||
|
||||
struct prov_cipher_ctx_st {
|
||||
+ /* place buffer at the beginning for memory alignment */
|
||||
+ /* The original value of the iv */
|
||||
+ unsigned char oiv[GENERIC_BLOCK_SIZE];
|
||||
+ /* Buffer of partial blocks processed via update calls */
|
||||
+ unsigned char buf[GENERIC_BLOCK_SIZE];
|
||||
+ unsigned char iv[GENERIC_BLOCK_SIZE];
|
||||
+
|
||||
block128_f block;
|
||||
union {
|
||||
cbc128_f cbc;
|
||||
@@ -83,12 +90,6 @@ struct prov_cipher_ctx_st {
|
||||
* manage partial blocks themselves.
|
||||
*/
|
||||
unsigned int num;
|
||||
-
|
||||
- /* The original value of the iv */
|
||||
- unsigned char oiv[GENERIC_BLOCK_SIZE];
|
||||
- /* Buffer of partial blocks processed via update calls */
|
||||
- unsigned char buf[GENERIC_BLOCK_SIZE];
|
||||
- unsigned char iv[GENERIC_BLOCK_SIZE];
|
||||
const PROV_CIPHER_HW *hw; /* hardware specific functions */
|
||||
const void *ks; /* Pointer to algorithm specific key data */
|
||||
OSSL_LIB_CTX *libctx;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
509
backport-Remove-the-_fetch_by_number-functions.patch
Normal file
509
backport-Remove-the-_fetch_by_number-functions.patch
Normal file
@ -0,0 +1,509 @@
|
||||
From 4a929c7c5cb06dcf1952691ee8732007cc1a41d4 Mon Sep 17 00:00:00 2001
|
||||
From: Pauli <pauli@openssl.org>
|
||||
Date: Wed, 4 May 2022 14:54:13 +1000
|
||||
Subject: [PATCH] Remove the _fetch_by_number functions
|
||||
|
||||
These functions are unused and untested. They are also implemented rather
|
||||
inefficiently. If we ever needed them in the future, they'd almost surely
|
||||
need to be rewritten more efficiently.
|
||||
|
||||
Fixes #18227
|
||||
|
||||
Reviewed-by: Matt Caswell <matt@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/18237)
|
||||
|
||||
(cherry picked from commit 16ff70a58cfb5c40197e6a940cf4666226f31b79)
|
||||
---
|
||||
crypto/encode_decode/decoder_meth.c | 36 +++-------------
|
||||
crypto/encode_decode/encoder_meth.c | 36 +++-------------
|
||||
crypto/evp/evp_fetch.c | 55 ++++---------------------
|
||||
crypto/evp/evp_local.h | 7 ----
|
||||
crypto/evp/keymgmt_meth.c | 10 -----
|
||||
crypto/store/store_local.h | 3 --
|
||||
crypto/store/store_meth.c | 37 +++--------------
|
||||
doc/internal/man3/evp_generic_fetch.pod | 19 +--------
|
||||
include/crypto/decoder.h | 4 --
|
||||
include/crypto/encoder.h | 2 -
|
||||
10 files changed, 27 insertions(+), 182 deletions(-)
|
||||
|
||||
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
|
||||
index 62e30ccb1a..74c86a8fe8 100644
|
||||
--- a/crypto/encode_decode/decoder_meth.c
|
||||
+++ b/crypto/encode_decode/decoder_meth.c
|
||||
@@ -340,38 +340,27 @@ static void free_decoder(void *method)
|
||||
|
||||
/* Fetching support. Can fetch by numeric identity or by name */
|
||||
static OSSL_DECODER *
|
||||
-inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
|
||||
+inner_ossl_decoder_fetch(struct decoder_data_st *methdata,
|
||||
const char *name, const char *properties)
|
||||
{
|
||||
OSSL_METHOD_STORE *store = get_decoder_store(methdata->libctx);
|
||||
OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
|
||||
const char *const propq = properties != NULL ? properties : "";
|
||||
void *method = NULL;
|
||||
- int unsupported = 0;
|
||||
+ int unsupported, id;
|
||||
|
||||
if (store == NULL || namemap == NULL) {
|
||||
ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If we have been passed both an id and a name, we have an
|
||||
- * internal programming error.
|
||||
- */
|
||||
- if (!ossl_assert(id == 0 || name == NULL)) {
|
||||
- ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (id == 0 && name != NULL)
|
||||
- id = ossl_namemap_name2num(namemap, name);
|
||||
+ id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0;
|
||||
|
||||
/*
|
||||
* If we haven't found the name yet, chances are that the algorithm to
|
||||
* be fetched is unsupported.
|
||||
*/
|
||||
- if (id == 0)
|
||||
- unsupported = 1;
|
||||
+ unsupported = id == 0;
|
||||
|
||||
if (id == 0
|
||||
|| !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
|
||||
@@ -436,20 +425,7 @@ OSSL_DECODER *OSSL_DECODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- method = inner_ossl_decoder_fetch(&methdata, 0, name, properties);
|
||||
- dealloc_tmp_decoder_store(methdata.tmp_store);
|
||||
- return method;
|
||||
-}
|
||||
-
|
||||
-OSSL_DECODER *ossl_decoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
|
||||
- const char *properties)
|
||||
-{
|
||||
- struct decoder_data_st methdata;
|
||||
- void *method;
|
||||
-
|
||||
- methdata.libctx = libctx;
|
||||
- methdata.tmp_store = NULL;
|
||||
- method = inner_ossl_decoder_fetch(&methdata, id, NULL, properties);
|
||||
+ method = inner_ossl_decoder_fetch(&methdata, name, properties);
|
||||
dealloc_tmp_decoder_store(methdata.tmp_store);
|
||||
return method;
|
||||
}
|
||||
@@ -579,7 +555,7 @@ void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- (void)inner_ossl_decoder_fetch(&methdata, 0, NULL, NULL /* properties */);
|
||||
+ (void)inner_ossl_decoder_fetch(&methdata, NULL, NULL /* properties */);
|
||||
|
||||
data.user_fn = user_fn;
|
||||
data.user_arg = user_arg;
|
||||
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
|
||||
index f91d349587..7092ba7ef8 100644
|
||||
--- a/crypto/encode_decode/encoder_meth.c
|
||||
+++ b/crypto/encode_decode/encoder_meth.c
|
||||
@@ -350,38 +350,27 @@ static void free_encoder(void *method)
|
||||
|
||||
/* Fetching support. Can fetch by numeric identity or by name */
|
||||
static OSSL_ENCODER *
|
||||
-inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
|
||||
+inner_ossl_encoder_fetch(struct encoder_data_st *methdata,
|
||||
const char *name, const char *properties)
|
||||
{
|
||||
OSSL_METHOD_STORE *store = get_encoder_store(methdata->libctx);
|
||||
OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
|
||||
const char *const propq = properties != NULL ? properties : "";
|
||||
void *method = NULL;
|
||||
- int unsupported = 0;
|
||||
+ int unsupported, id;
|
||||
|
||||
if (store == NULL || namemap == NULL) {
|
||||
ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If we have been passed both an id and a name, we have an
|
||||
- * internal programming error.
|
||||
- */
|
||||
- if (!ossl_assert(id == 0 || name == NULL)) {
|
||||
- ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- if (id == 0)
|
||||
- id = ossl_namemap_name2num(namemap, name);
|
||||
+ id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0;
|
||||
|
||||
/*
|
||||
* If we haven't found the name yet, chances are that the algorithm to
|
||||
* be fetched is unsupported.
|
||||
*/
|
||||
- if (id == 0)
|
||||
- unsupported = 1;
|
||||
+ unsupported = id == 0;
|
||||
|
||||
if (id == 0
|
||||
|| !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
|
||||
@@ -445,20 +434,7 @@ OSSL_ENCODER *OSSL_ENCODER_fetch(OSSL_LIB_CTX *libctx, const char *name,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- method = inner_ossl_encoder_fetch(&methdata, 0, name, properties);
|
||||
- dealloc_tmp_encoder_store(methdata.tmp_store);
|
||||
- return method;
|
||||
-}
|
||||
-
|
||||
-OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
|
||||
- const char *properties)
|
||||
-{
|
||||
- struct encoder_data_st methdata;
|
||||
- void *method;
|
||||
-
|
||||
- methdata.libctx = libctx;
|
||||
- methdata.tmp_store = NULL;
|
||||
- method = inner_ossl_encoder_fetch(&methdata, id, NULL, properties);
|
||||
+ method = inner_ossl_encoder_fetch(&methdata, name, properties);
|
||||
dealloc_tmp_encoder_store(methdata.tmp_store);
|
||||
return method;
|
||||
}
|
||||
@@ -570,7 +546,7 @@ void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- (void)inner_ossl_encoder_fetch(&methdata, 0, NULL, NULL /* properties */);
|
||||
+ (void)inner_ossl_encoder_fetch(&methdata, NULL, NULL /* properties */);
|
||||
|
||||
data.user_fn = user_fn;
|
||||
data.user_arg = user_arg;
|
||||
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
|
||||
index 26ed5edcaf..4908f6cfee 100644
|
||||
--- a/crypto/evp/evp_fetch.c
|
||||
+++ b/crypto/evp/evp_fetch.c
|
||||
@@ -122,7 +122,7 @@ static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov,
|
||||
{
|
||||
struct evp_method_data_st *methdata = data;
|
||||
void *method = NULL;
|
||||
- int name_id = 0;
|
||||
+ int name_id;
|
||||
uint32_t meth_id;
|
||||
|
||||
/*
|
||||
@@ -239,8 +239,7 @@ static void destruct_evp_method(void *method, void *data)
|
||||
static void *
|
||||
inner_evp_generic_fetch(struct evp_method_data_st *methdata,
|
||||
OSSL_PROVIDER *prov, int operation_id,
|
||||
- int name_id, const char *name,
|
||||
- const char *properties,
|
||||
+ const char *name, const char *properties,
|
||||
void *(*new_method)(int name_id,
|
||||
const OSSL_ALGORITHM *algodef,
|
||||
OSSL_PROVIDER *prov),
|
||||
@@ -252,7 +251,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
|
||||
const char *const propq = properties != NULL ? properties : "";
|
||||
uint32_t meth_id = 0;
|
||||
void *method = NULL;
|
||||
- int unsupported = 0;
|
||||
+ int unsupported, name_id;
|
||||
|
||||
if (store == NULL || namemap == NULL) {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
@@ -268,18 +267,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If we have been passed both a name_id and a name, we have an
|
||||
- * internal programming error.
|
||||
- */
|
||||
- if (!ossl_assert(name_id == 0 || name == NULL)) {
|
||||
- ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
/* If we haven't received a name id yet, try to get one for the name */
|
||||
- if (name_id == 0 && name != NULL)
|
||||
- name_id = ossl_namemap_name2num(namemap, name);
|
||||
+ name_id = name != NULL ? ossl_namemap_name2num(namemap, name) : 0;
|
||||
|
||||
/*
|
||||
* If we have a name id, calculate a method id with evp_method_id().
|
||||
@@ -298,8 +287,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
|
||||
* If we haven't found the name yet, chances are that the algorithm to
|
||||
* be fetched is unsupported.
|
||||
*/
|
||||
- if (name_id == 0)
|
||||
- unsupported = 1;
|
||||
+ unsupported = name_id == 0;
|
||||
|
||||
if (meth_id == 0
|
||||
|| !ossl_method_store_cache_get(store, prov, meth_id, propq, &method)) {
|
||||
@@ -374,34 +362,7 @@ void *evp_generic_fetch(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
|
||||
- 0, name, properties,
|
||||
- new_method, up_ref_method, free_method);
|
||||
- dealloc_tmp_evp_method_store(methdata.tmp_store);
|
||||
- return method;
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * evp_generic_fetch_by_number() is special, and only returns methods for
|
||||
- * already known names, i.e. it refuses to work if no name_id can be found
|
||||
- * (it's considered an internal programming error).
|
||||
- * This is meant to be used when one method needs to fetch an associated
|
||||
- * method.
|
||||
- */
|
||||
-void *evp_generic_fetch_by_number(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
- int name_id, const char *properties,
|
||||
- void *(*new_method)(int name_id,
|
||||
- const OSSL_ALGORITHM *algodef,
|
||||
- OSSL_PROVIDER *prov),
|
||||
- int (*up_ref_method)(void *),
|
||||
- void (*free_method)(void *))
|
||||
-{
|
||||
- struct evp_method_data_st methdata;
|
||||
- void *method;
|
||||
-
|
||||
- methdata.libctx = libctx;
|
||||
- methdata.tmp_store = NULL;
|
||||
- method = inner_evp_generic_fetch(&methdata, NULL, operation_id,
|
||||
- name_id, NULL, properties,
|
||||
+ name, properties,
|
||||
new_method, up_ref_method, free_method);
|
||||
dealloc_tmp_evp_method_store(methdata.tmp_store);
|
||||
return method;
|
||||
@@ -427,7 +388,7 @@ void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
|
||||
methdata.libctx = ossl_provider_libctx(prov);
|
||||
methdata.tmp_store = NULL;
|
||||
method = inner_evp_generic_fetch(&methdata, prov, operation_id,
|
||||
- 0, name, properties,
|
||||
+ name, properties,
|
||||
new_method, up_ref_method, free_method);
|
||||
dealloc_tmp_evp_method_store(methdata.tmp_store);
|
||||
return method;
|
||||
@@ -631,7 +592,7 @@ void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, 0, NULL, NULL,
|
||||
+ (void)inner_evp_generic_fetch(&methdata, NULL, operation_id, NULL, NULL,
|
||||
new_method, up_ref_method, free_method);
|
||||
|
||||
data.operation_id = operation_id;
|
||||
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
|
||||
index 3ccfaeb37c..a853174452 100644
|
||||
--- a/crypto/evp/evp_local.h
|
||||
+++ b/crypto/evp/evp_local.h
|
||||
@@ -270,13 +270,6 @@ void *evp_generic_fetch(OSSL_LIB_CTX *ctx, int operation_id,
|
||||
OSSL_PROVIDER *prov),
|
||||
int (*up_ref_method)(void *),
|
||||
void (*free_method)(void *));
|
||||
-void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id,
|
||||
- int name_id, const char *properties,
|
||||
- void *(*new_method)(int name_id,
|
||||
- const OSSL_ALGORITHM *algodef,
|
||||
- OSSL_PROVIDER *prov),
|
||||
- int (*up_ref_method)(void *),
|
||||
- void (*free_method)(void *));
|
||||
void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
|
||||
const char *name, const char *properties,
|
||||
void *(*new_method)(int name_id,
|
||||
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
|
||||
index 90fd8068dc..5fab4a7639 100644
|
||||
--- a/crypto/evp/keymgmt_meth.c
|
||||
+++ b/crypto/evp/keymgmt_meth.c
|
||||
@@ -203,16 +203,6 @@ static void *keymgmt_from_algorithm(int name_id,
|
||||
return keymgmt;
|
||||
}
|
||||
|
||||
-EVP_KEYMGMT *evp_keymgmt_fetch_by_number(OSSL_LIB_CTX *ctx, int name_id,
|
||||
- const char *properties)
|
||||
-{
|
||||
- return evp_generic_fetch_by_number(ctx,
|
||||
- OSSL_OP_KEYMGMT, name_id, properties,
|
||||
- keymgmt_from_algorithm,
|
||||
- (int (*)(void *))EVP_KEYMGMT_up_ref,
|
||||
- (void (*)(void *))EVP_KEYMGMT_free);
|
||||
-}
|
||||
-
|
||||
EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
|
||||
const char *name,
|
||||
const char *properties)
|
||||
diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h
|
||||
index 8f817fd514..f73bce32b9 100644
|
||||
--- a/crypto/store/store_local.h
|
||||
+++ b/crypto/store/store_local.h
|
||||
@@ -168,9 +168,6 @@ int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx);
|
||||
OSSL_STORE_LOADER *ossl_store_loader_fetch(OSSL_LIB_CTX *libctx,
|
||||
const char *scheme,
|
||||
const char *properties);
|
||||
-OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx,
|
||||
- int scheme_id,
|
||||
- const char *properties);
|
||||
|
||||
/* Standard function to handle the result from OSSL_FUNC_store_load() */
|
||||
struct ossl_load_result_data_st {
|
||||
diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c
|
||||
index 42848b799a..ab1016853e 100644
|
||||
--- a/crypto/store/store_meth.c
|
||||
+++ b/crypto/store/store_meth.c
|
||||
@@ -278,39 +278,28 @@ static void destruct_loader(void *method, void *data)
|
||||
|
||||
/* Fetching support. Can fetch by numeric identity or by scheme */
|
||||
static OSSL_STORE_LOADER *
|
||||
-inner_loader_fetch(struct loader_data_st *methdata, int id,
|
||||
+inner_loader_fetch(struct loader_data_st *methdata,
|
||||
const char *scheme, const char *properties)
|
||||
{
|
||||
OSSL_METHOD_STORE *store = get_loader_store(methdata->libctx);
|
||||
OSSL_NAMEMAP *namemap = ossl_namemap_stored(methdata->libctx);
|
||||
const char *const propq = properties != NULL ? properties : "";
|
||||
void *method = NULL;
|
||||
- int unsupported = 0;
|
||||
+ int unsupported, id;
|
||||
|
||||
if (store == NULL || namemap == NULL) {
|
||||
ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_INVALID_ARGUMENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If we have been passed both an id and a scheme, we have an
|
||||
- * internal programming error.
|
||||
- */
|
||||
- if (!ossl_assert(id == 0 || scheme == NULL)) {
|
||||
- ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
/* If we haven't received a name id yet, try to get one for the name */
|
||||
- if (id == 0 && scheme != NULL)
|
||||
- id = ossl_namemap_name2num(namemap, scheme);
|
||||
+ id = scheme != NULL ? ossl_namemap_name2num(namemap, scheme) : 0;
|
||||
|
||||
/*
|
||||
* If we haven't found the name yet, chances are that the algorithm to
|
||||
* be fetched is unsupported.
|
||||
*/
|
||||
- if (id == 0)
|
||||
- unsupported = 1;
|
||||
+ unsupported = id == 0;
|
||||
|
||||
if (id == 0
|
||||
|| !ossl_method_store_cache_get(store, NULL, id, propq, &method)) {
|
||||
@@ -381,21 +370,7 @@ OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(OSSL_LIB_CTX *libctx,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- method = inner_loader_fetch(&methdata, 0, scheme, properties);
|
||||
- dealloc_tmp_loader_store(methdata.tmp_store);
|
||||
- return method;
|
||||
-}
|
||||
-
|
||||
-OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OSSL_LIB_CTX *libctx,
|
||||
- int scheme_id,
|
||||
- const char *properties)
|
||||
-{
|
||||
- struct loader_data_st methdata;
|
||||
- void *method;
|
||||
-
|
||||
- methdata.libctx = libctx;
|
||||
- methdata.tmp_store = NULL;
|
||||
- method = inner_loader_fetch(&methdata, scheme_id, NULL, properties);
|
||||
+ method = inner_loader_fetch(&methdata, scheme, properties);
|
||||
dealloc_tmp_loader_store(methdata.tmp_store);
|
||||
return method;
|
||||
}
|
||||
@@ -491,7 +466,7 @@ void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
|
||||
|
||||
methdata.libctx = libctx;
|
||||
methdata.tmp_store = NULL;
|
||||
- (void)inner_loader_fetch(&methdata, 0, NULL, NULL /* properties */);
|
||||
+ (void)inner_loader_fetch(&methdata, NULL, NULL /* properties */);
|
||||
|
||||
data.user_fn = user_fn;
|
||||
data.user_arg = user_arg;
|
||||
diff --git a/doc/internal/man3/evp_generic_fetch.pod b/doc/internal/man3/evp_generic_fetch.pod
|
||||
index b23d2ec0ea..ce75ffbfc8 100644
|
||||
--- a/doc/internal/man3/evp_generic_fetch.pod
|
||||
+++ b/doc/internal/man3/evp_generic_fetch.pod
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
=head1 NAME
|
||||
|
||||
-evp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov
|
||||
+evp_generic_fetch, evp_generic_fetch_from_prov
|
||||
- generic algorithm fetchers and method creators for EVP
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@@ -20,15 +20,6 @@ evp_generic_fetch, evp_generic_fetch_by_number, evp_generic_fetch_from_prov
|
||||
int (*up_ref_method)(void *),
|
||||
void (*free_method)(void *));
|
||||
|
||||
- void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id,
|
||||
- int name_id, const char *properties,
|
||||
- void *(*new_method)(int name_id,
|
||||
- const OSSL_DISPATCH *fns,
|
||||
- OSSL_PROVIDER *prov,
|
||||
- void *method_data),
|
||||
- void *method_data,
|
||||
- int (*up_ref_method)(void *),
|
||||
- void (*free_method)(void *));
|
||||
void *evp_generic_fetch_from_prov(OSSL_PROVIDER *prov, int operation_id,
|
||||
int name_id, const char *properties,
|
||||
void *(*new_method)(int name_id,
|
||||
@@ -46,14 +37,6 @@ I<libctx>, I<operation_id>, I<name>, and I<properties> and uses
|
||||
it to create an EVP method with the help of the functions
|
||||
I<new_method>, I<up_ref_method>, and I<free_method>.
|
||||
|
||||
-evp_generic_fetch_by_number() does the same thing as evp_generic_fetch(),
|
||||
-but takes a numeric I<name_id> instead of a name.
|
||||
-I<name_id> must always be nonzero; as a matter of fact, it being zero
|
||||
-is considered a programming error.
|
||||
-This is meant to be used when one method needs to fetch an associated
|
||||
-method, and is typically called from inside the given function
|
||||
-I<new_method>.
|
||||
-
|
||||
evp_generic_fetch_from_prov() does the same thing as evp_generic_fetch(),
|
||||
but limits the search of methods to the provider given with I<prov>.
|
||||
This is meant to be used when one method needs to fetch an associated
|
||||
diff --git a/include/crypto/decoder.h b/include/crypto/decoder.h
|
||||
index 107a7b502a..6b5ee56ac6 100644
|
||||
--- a/include/crypto/decoder.h
|
||||
+++ b/include/crypto/decoder.h
|
||||
@@ -13,10 +13,6 @@
|
||||
|
||||
# include <openssl/decoder.h>
|
||||
|
||||
-OSSL_DECODER *ossl_decoder_fetch_by_number(OSSL_LIB_CTX *libctx,
|
||||
- int id,
|
||||
- const char *properties);
|
||||
-
|
||||
/*
|
||||
* These are specially made for the 'file:' provider-native loader, which
|
||||
* uses this to install a DER to anything decoder, which doesn't do much
|
||||
diff --git a/include/crypto/encoder.h b/include/crypto/encoder.h
|
||||
index 562081ad41..5c53bbea39 100644
|
||||
--- a/include/crypto/encoder.h
|
||||
+++ b/include/crypto/encoder.h
|
||||
@@ -13,8 +13,6 @@
|
||||
|
||||
# include <openssl/types.h>
|
||||
|
||||
-OSSL_ENCODER *ossl_encoder_fetch_by_number(OSSL_LIB_CTX *libctx, int id,
|
||||
- const char *properties);
|
||||
int ossl_encoder_get_number(const OSSL_ENCODER *encoder);
|
||||
int ossl_encoder_store_cache_flush(OSSL_LIB_CTX *libctx);
|
||||
int ossl_encoder_store_remove_all_provided(const OSSL_PROVIDER *prov);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,115 @@
|
||||
From f56744fe1e47ca153f487eb383e62aac0e8b0545 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Caswell <matt@openssl.org>
|
||||
Date: Thu, 11 May 2023 11:25:07 +0100
|
||||
Subject: [PATCH] When we're just reading EX_CALLBACK data just get a read lock
|
||||
|
||||
The crypto_ex_data code was always obtaining a write lock in all functions
|
||||
regardless of whether we were only reading EX_CALLBACK data or actually
|
||||
changing it. Changes to the EX_CALLBACK data are rare, with many reads so
|
||||
we should change to a read lock where we can.
|
||||
|
||||
We hit this every time we create or free any object that can have ex_data
|
||||
associated with it (e.g. BIOs, SSL, etc)
|
||||
|
||||
Partially fixes #20286
|
||||
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Hugo Landau <hlandau@openssl.org>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20943)
|
||||
|
||||
(cherry picked from commit 6d15357aeb893c6e8b4c7a8188c18f4db54c0612)
|
||||
---
|
||||
crypto/ex_data.c | 26 +++++++++++++++++---------
|
||||
1 file changed, 17 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
|
||||
index 40223f06e4..33c35da7d0 100644
|
||||
--- a/crypto/ex_data.c
|
||||
+++ b/crypto/ex_data.c
|
||||
@@ -26,8 +26,10 @@ int ossl_do_ex_data_init(OSSL_LIB_CTX *ctx)
|
||||
* Return the EX_CALLBACKS from the |ex_data| array that corresponds to
|
||||
* a given class. On success, *holds the lock.*
|
||||
* The |global| parameter is assumed to be non null (checked by the caller).
|
||||
+ * If |read| is 1 then a read lock is obtained. Otherwise it is a write lock.
|
||||
*/
|
||||
-static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index)
|
||||
+static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index,
|
||||
+ int read)
|
||||
{
|
||||
EX_CALLBACKS *ip;
|
||||
|
||||
@@ -44,8 +46,14 @@ static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- if (!CRYPTO_THREAD_write_lock(global->ex_data_lock))
|
||||
- return NULL;
|
||||
+ if (read) {
|
||||
+ if (!CRYPTO_THREAD_read_lock(global->ex_data_lock))
|
||||
+ return NULL;
|
||||
+ } else {
|
||||
+ if (!CRYPTO_THREAD_write_lock(global->ex_data_lock))
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
ip = &global->ex_data[class_index];
|
||||
return ip;
|
||||
}
|
||||
@@ -112,7 +120,7 @@ int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx)
|
||||
if (global == NULL)
|
||||
return 0;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 0);
|
||||
if (ip == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -153,7 +161,7 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index,
|
||||
if (global == NULL)
|
||||
return -1;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 0);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -221,7 +229,7 @@ int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,
|
||||
if (global == NULL)
|
||||
return 0;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 1);
|
||||
if (ip == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -284,7 +292,7 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
|
||||
if (global == NULL)
|
||||
return 0;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 1);
|
||||
if (ip == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -373,7 +381,7 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
|
||||
if (global == NULL)
|
||||
goto err;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 1);
|
||||
if (ip == NULL)
|
||||
goto err;
|
||||
|
||||
@@ -440,7 +448,7 @@ int ossl_crypto_alloc_ex_data_intern(int class_index, void *obj,
|
||||
if (global == NULL)
|
||||
return 0;
|
||||
|
||||
- ip = get_and_lock(global, class_index);
|
||||
+ ip = get_and_lock(global, class_index, 1);
|
||||
if (ip == NULL)
|
||||
return 0;
|
||||
f = sk_EX_CALLBACK_value(ip->meth, idx);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,134 @@
|
||||
From 708bf3dde8f53446cccded5dadafb853e7e9d38b Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tomas@openssl.org>
|
||||
Date: Wed, 13 Apr 2022 16:26:18 +0200
|
||||
Subject: [PATCH] evp_md_init_internal: Avoid reallocating algctx if digest
|
||||
unchanged
|
||||
|
||||
Fixes #16947
|
||||
|
||||
Also refactor out algctx freeing into a separate function.
|
||||
|
||||
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/18105)
|
||||
|
||||
(cherry picked from commit fe5c5cb85197aec7d68ab095b866ed22076850d0)
|
||||
---
|
||||
crypto/evp/digest.c | 35 ++++++++++++++++++++---------------
|
||||
crypto/evp/m_sigver.c | 11 ++---------
|
||||
include/crypto/evp.h | 2 ++
|
||||
3 files changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
|
||||
index b93e079b15..7a8e15241f 100644
|
||||
--- a/crypto/evp/digest.c
|
||||
+++ b/crypto/evp/digest.c
|
||||
@@ -141,6 +141,20 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
+int evp_md_ctx_free_algctx(EVP_MD_CTX *ctx)
|
||||
+{
|
||||
+ if (ctx->algctx != NULL) {
|
||||
+ if (!ossl_assert(ctx->digest != NULL)) {
|
||||
+ ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (ctx->digest->freectx != NULL)
|
||||
+ ctx->digest->freectx(ctx->algctx);
|
||||
+ ctx->algctx = NULL;
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
|
||||
const OSSL_PARAM params[], ENGINE *impl)
|
||||
{
|
||||
@@ -169,16 +183,6 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
|
||||
|
||||
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
|
||||
|
||||
- if (ctx->algctx != NULL) {
|
||||
- if (!ossl_assert(ctx->digest != NULL)) {
|
||||
- ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
||||
- return 0;
|
||||
- }
|
||||
- if (ctx->digest->freectx != NULL)
|
||||
- ctx->digest->freectx(ctx->algctx);
|
||||
- ctx->algctx = NULL;
|
||||
- }
|
||||
-
|
||||
if (type != NULL) {
|
||||
ctx->reqdigest = type;
|
||||
} else {
|
||||
@@ -229,6 +233,10 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
|
||||
|| (type != NULL && type->origin == EVP_ORIG_METH)
|
||||
|| (type == NULL && ctx->digest != NULL
|
||||
&& ctx->digest->origin == EVP_ORIG_METH)) {
|
||||
+ /* If we were using provided hash before, cleanup algctx */
|
||||
+ if (!evp_md_ctx_free_algctx(ctx))
|
||||
+ return 0;
|
||||
+
|
||||
if (ctx->digest == ctx->fetched_digest)
|
||||
ctx->digest = NULL;
|
||||
EVP_MD_free(ctx->fetched_digest);
|
||||
@@ -239,6 +247,8 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
|
||||
cleanup_old_md_data(ctx, 1);
|
||||
|
||||
/* Start of non-legacy code below */
|
||||
+ if (ctx->digest != type && !evp_md_ctx_free_algctx(ctx))
|
||||
+ return 0;
|
||||
|
||||
if (type->prov == NULL) {
|
||||
#ifdef FIPS_MODULE
|
||||
@@ -261,11 +271,6 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type,
|
||||
#endif
|
||||
}
|
||||
|
||||
- if (ctx->algctx != NULL && ctx->digest != NULL && ctx->digest != type) {
|
||||
- if (ctx->digest->freectx != NULL)
|
||||
- ctx->digest->freectx(ctx->algctx);
|
||||
- ctx->algctx = NULL;
|
||||
- }
|
||||
if (type->prov != NULL && ctx->fetched_digest != type) {
|
||||
if (!EVP_MD_up_ref((EVP_MD *)type)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
||||
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
|
||||
index fc087d2cb6..630d339c35 100644
|
||||
--- a/crypto/evp/m_sigver.c
|
||||
+++ b/crypto/evp/m_sigver.c
|
||||
@@ -51,15 +51,8 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
|
||||
void *provkey = NULL;
|
||||
int ret, iter, reinit = 1;
|
||||
|
||||
- if (ctx->algctx != NULL) {
|
||||
- if (!ossl_assert(ctx->digest != NULL)) {
|
||||
- ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
||||
- return 0;
|
||||
- }
|
||||
- if (ctx->digest->freectx != NULL)
|
||||
- ctx->digest->freectx(ctx->algctx);
|
||||
- ctx->algctx = NULL;
|
||||
- }
|
||||
+ if (!evp_md_ctx_free_algctx(ctx))
|
||||
+ return 0;
|
||||
|
||||
if (ctx->pctx == NULL) {
|
||||
reinit = 0;
|
||||
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
|
||||
index e70d8e9e84..dbbdcccbda 100644
|
||||
--- a/include/crypto/evp.h
|
||||
+++ b/include/crypto/evp.h
|
||||
@@ -909,6 +909,8 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
|
||||
char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig);
|
||||
|
||||
void evp_md_ctx_clear_digest(EVP_MD_CTX *ctx, int force, int keep_digest);
|
||||
+/* just free the algctx if set, returns 0 on inconsistent state of ctx */
|
||||
+int evp_md_ctx_free_algctx(EVP_MD_CTX *ctx);
|
||||
|
||||
/* Three possible states: */
|
||||
# define EVP_PKEY_STATE_UNKNOWN 0
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,137 @@
|
||||
From 8af5c6c4d340961dcb853a6126831ebc5a86b311 Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tomas@openssl.org>
|
||||
Date: Wed, 18 May 2022 16:45:20 +0200
|
||||
Subject: [PATCH] ossl_namemap_name2_num: Avoid unnecessary OPENSSL_strndup().
|
||||
|
||||
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/18341)
|
||||
|
||||
(cherry picked from commit dab5098eacb9e264c32a33332ba047f234a3de68)
|
||||
---
|
||||
crypto/core_namemap.c | 55 +++++++++++++++++++++++++++++--------------
|
||||
1 file changed, 37 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
|
||||
index 554524a5c4..4c1ca05308 100644
|
||||
--- a/crypto/core_namemap.c
|
||||
+++ b/crypto/core_namemap.c
|
||||
@@ -166,22 +166,19 @@ int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int namemap_name2num_n(const OSSL_NAMEMAP *namemap,
|
||||
- const char *name, size_t name_len)
|
||||
+static int namemap_name2num(const OSSL_NAMEMAP *namemap,
|
||||
+ const char *name)
|
||||
{
|
||||
NAMENUM_ENTRY *namenum_entry, namenum_tmpl;
|
||||
|
||||
- if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL)
|
||||
- return 0;
|
||||
+ namenum_tmpl.name = (char *)name;
|
||||
namenum_tmpl.number = 0;
|
||||
namenum_entry =
|
||||
lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl);
|
||||
- OPENSSL_free(namenum_tmpl.name);
|
||||
return namenum_entry != NULL ? namenum_entry->number : 0;
|
||||
}
|
||||
|
||||
-int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
|
||||
- const char *name, size_t name_len)
|
||||
+int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
|
||||
{
|
||||
int number;
|
||||
|
||||
@@ -195,18 +192,24 @@ int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
|
||||
|
||||
if (!CRYPTO_THREAD_read_lock(namemap->lock))
|
||||
return 0;
|
||||
- number = namemap_name2num_n(namemap, name, name_len);
|
||||
+ number = namemap_name2num(namemap, name);
|
||||
CRYPTO_THREAD_unlock(namemap->lock);
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
-int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
|
||||
+int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
|
||||
+ const char *name, size_t name_len)
|
||||
{
|
||||
- if (name == NULL)
|
||||
+ char *tmp;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (name == NULL || (tmp = OPENSSL_strndup(name, name_len)) == NULL)
|
||||
return 0;
|
||||
|
||||
- return ossl_namemap_name2num_n(namemap, name, strlen(name));
|
||||
+ ret = ossl_namemap_name2num(namemap, tmp);
|
||||
+ OPENSSL_free(tmp);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
struct num2name_data_st {
|
||||
@@ -241,14 +244,20 @@ static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
{
|
||||
NAMENUM_ENTRY *namenum = NULL;
|
||||
int tmp_number;
|
||||
+ char *tmp = OPENSSL_strndup(name, name_len);
|
||||
+
|
||||
+ if (tmp == NULL)
|
||||
+ return 0;
|
||||
|
||||
/* If it already exists, we don't add it */
|
||||
- if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0)
|
||||
+ if ((tmp_number = namemap_name2num(namemap, tmp)) != 0) {
|
||||
+ OPENSSL_free(tmp);
|
||||
return tmp_number;
|
||||
+ }
|
||||
|
||||
- if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL
|
||||
- || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL)
|
||||
+ if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL)
|
||||
goto err;
|
||||
+ namenum->name = tmp;
|
||||
|
||||
/* The tsan_counter use here is safe since we're under lock */
|
||||
namenum->number =
|
||||
@@ -260,7 +269,8 @@ static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
|
||||
return namenum->number;
|
||||
|
||||
err:
|
||||
- namenum_free(namenum);
|
||||
+ OPENSSL_free(tmp);
|
||||
+ OPENSSL_free(namenum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -312,13 +322,22 @@ int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
|
||||
*/
|
||||
for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
|
||||
int this_number;
|
||||
+ char *allocated;
|
||||
+ const char *tmp;
|
||||
|
||||
- if ((q = strchr(p, separator)) == NULL)
|
||||
+ if ((q = strchr(p, separator)) == NULL) {
|
||||
l = strlen(p); /* offset to \0 */
|
||||
- else
|
||||
+ tmp = p;
|
||||
+ allocated = NULL;
|
||||
+ } else {
|
||||
l = q - p; /* offset to the next separator */
|
||||
+ tmp = allocated = OPENSSL_strndup(p, l);
|
||||
+ if (tmp == NULL)
|
||||
+ goto err;
|
||||
+ }
|
||||
|
||||
- this_number = namemap_name2num_n(namemap, p, l);
|
||||
+ this_number = namemap_name2num(namemap, tmp);
|
||||
+ OPENSSL_free(allocated);
|
||||
|
||||
if (*p == '\0' || *p == separator) {
|
||||
ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
66
backport-performance-improve-ossl_lh_strcasehash.patch
Normal file
66
backport-performance-improve-ossl_lh_strcasehash.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From d295e4b1da6d223242eb43bfae10479616c5236d Mon Sep 17 00:00:00 2001
|
||||
From: Pauli <pauli@openssl.org>
|
||||
Date: Fri, 20 May 2022 10:15:55 +1000
|
||||
Subject: [PATCH] performance: improve ossl_lh_strcasehash
|
||||
|
||||
This improvement seems to roughly halve the time it takes to run the
|
||||
ossl_lh_strcasehash function.
|
||||
|
||||
It should have no impact on the strings we hash and search for often (algorithm
|
||||
names, property strings).
|
||||
|
||||
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/18354)
|
||||
|
||||
(cherry picked from commit a4e21d18d5b7cb4fef66c10f13b1b3b55945439f)
|
||||
---
|
||||
crypto/lhash/lhash.c | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
|
||||
index 1cd988f01f..c319a44c7b 100644
|
||||
--- a/crypto/lhash/lhash.c
|
||||
+++ b/crypto/lhash/lhash.c
|
||||
@@ -344,18 +344,37 @@ unsigned long OPENSSL_LH_strhash(const char *c)
|
||||
return (ret >> 16) ^ ret;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Case insensitive string hashing.
|
||||
+ *
|
||||
+ * The lower/upper case bit is masked out (forcing all letters to be capitals).
|
||||
+ * The major side effect on non-alpha characters is mapping the symbols and
|
||||
+ * digits into the control character range (which should be harmless).
|
||||
+ * The duplication (with respect to the hash value) of printable characters
|
||||
+ * are that '`', '{', '|', '}' and '~' map to '@', '[', '\', ']' and '^'
|
||||
+ * respectively (which seems tolerable).
|
||||
+ *
|
||||
+ * For EBCDIC, the alpha mapping is to lower case, most symbols go to control
|
||||
+ * characters. The only duplication is '0' mapping to '^', which is better
|
||||
+ * than for ASCII.
|
||||
+ */
|
||||
unsigned long ossl_lh_strcasehash(const char *c)
|
||||
{
|
||||
unsigned long ret = 0;
|
||||
long n;
|
||||
unsigned long v;
|
||||
int r;
|
||||
+#if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST)
|
||||
+ const long int case_adjust = ~0x40;
|
||||
+#else
|
||||
+ const long int case_adjust = ~0x20;
|
||||
+#endif
|
||||
|
||||
if (c == NULL || *c == '\0')
|
||||
return ret;
|
||||
|
||||
for (n = 0x100; *c != '\0'; n += 0x100) {
|
||||
- v = n | ossl_tolower(*c);
|
||||
+ v = n | (case_adjust & *c);
|
||||
r = (int)((v >> 2) ^ v) & 0x0f;
|
||||
/* cast to uint64_t to avoid 32 bit shift of 32 bit value */
|
||||
ret = (ret << r) | (unsigned long)((uint64_t)ret >> (32 - r));
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -0,0 +1,128 @@
|
||||
From ed6dfd1e3694b3438249f3d0117bc314afa6b240 Mon Sep 17 00:00:00 2001
|
||||
From: Liu-ErMeng <liuermeng2@huawei.com>
|
||||
Date: Tue, 11 Jul 2023 16:22:53 +0800
|
||||
Subject: [PATCH] use '__builtin_expect' to improve EVP_EncryptUpdate
|
||||
performance for gcc/clang.
|
||||
|
||||
Signed-off-by: Liu-ErMeng <liuermeng2@huawei.com>
|
||||
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/21425)
|
||||
---
|
||||
crypto/evp/evp_enc.c | 24 ++++++++++++------------
|
||||
include/internal/common.h | 8 ++++++++
|
||||
2 files changed, 20 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
|
||||
index 6b6d65163f..8dddcc0bb5 100644
|
||||
--- a/crypto/evp/evp_enc.c
|
||||
+++ b/crypto/evp/evp_enc.c
|
||||
@@ -27,6 +27,14 @@
|
||||
#include "crypto/evp.h"
|
||||
#include "evp_local.h"
|
||||
|
||||
+#if defined(__GNUC__) || defined(__clang__)
|
||||
+ #define likely(x) __builtin_expect(!!(x), 1)
|
||||
+ #define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
+#else
|
||||
+ #define likely(x) x
|
||||
+ #define unlikely(x) x
|
||||
+#endif
|
||||
+
|
||||
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
@@ -621,7 +621,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
size_t soutl, inl_ = (size_t)inl;
|
||||
int blocksize;
|
||||
|
||||
- if (outl != NULL) {
|
||||
+ if (likely(outl != NULL)) {
|
||||
*outl = 0;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
||||
@@ -629,22 +629,22 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
}
|
||||
|
||||
/* Prevent accidental use of decryption context when encrypting */
|
||||
- if (!ctx->encrypt) {
|
||||
+ if (unlikely(!ctx->encrypt)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (ctx->cipher == NULL) {
|
||||
+ if (unlikely(ctx->cipher == NULL)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (ctx->cipher->prov == NULL)
|
||||
+ if (unlikely(ctx->cipher->prov == NULL))
|
||||
goto legacy;
|
||||
|
||||
blocksize = ctx->cipher->block_size;
|
||||
|
||||
- if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
||||
+ if (unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
@@ -653,7 +653,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
|
||||
in, inl_);
|
||||
|
||||
- if (ret) {
|
||||
+ if (likely(ret)) {
|
||||
if (soutl > INT_MAX) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
@@ -770,7 +770,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
size_t soutl, inl_ = (size_t)inl;
|
||||
int blocksize;
|
||||
|
||||
- if (outl != NULL) {
|
||||
+ if (likely(outl != NULL)) {
|
||||
*outl = 0;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
||||
@@ -778,21 +778,21 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
}
|
||||
|
||||
/* Prevent accidental use of encryption context when decrypting */
|
||||
- if (ctx->encrypt) {
|
||||
+ if (unlikely(ctx->encrypt)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (ctx->cipher == NULL) {
|
||||
+ if (unlikely(ctx->cipher == NULL)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
|
||||
return 0;
|
||||
}
|
||||
- if (ctx->cipher->prov == NULL)
|
||||
+ if (unlikely(ctx->cipher->prov == NULL))
|
||||
goto legacy;
|
||||
|
||||
blocksize = EVP_CIPHER_CTX_get_block_size(ctx);
|
||||
|
||||
- if (ctx->cipher->cupdate == NULL || blocksize < 1) {
|
||||
+ if (unlikely(ctx->cipher->cupdate == NULL || blocksize < 1)) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
@@ -800,7 +800,7 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
|
||||
inl_ + (size_t)(blocksize == 1 ? 0 : blocksize),
|
||||
in, inl_);
|
||||
|
||||
- if (ret) {
|
||||
+ if (likely(ret)) {
|
||||
if (soutl > INT_MAX) {
|
||||
ERR_raise(ERR_LIB_EVP, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
30
openssl.spec
30
openssl.spec
@ -2,7 +2,7 @@
|
||||
Name: openssl
|
||||
Epoch: 1
|
||||
Version: 3.0.12
|
||||
Release: 13
|
||||
Release: 14
|
||||
Summary: Cryptography and SSL/TLS Toolkit
|
||||
License: OpenSSL and SSLeay
|
||||
URL: https://www.openssl.org/
|
||||
@ -46,14 +46,29 @@ Patch34: Backport-CVE-2024-4741-Extend-the-SSL_free_buffers-testing.patch
|
||||
Patch35: Backport-CVE-2024-4741-Move-the-ability-to-load-the-dasync-engine-into-sslt.patch
|
||||
Patch36: Backport-CVE-2024-4741-Further-extend-the-SSL_free_buffers-testing.patch
|
||||
Patch37: Backport-bn-Properly-error-out-if-aliasing-return-value-with-.patch
|
||||
Patch38: Fix-build-error-for-ppc64le.patch
|
||||
Patch39: Backport-CVE-2024-5535-Fix-SSL_select_next_proto.patch
|
||||
Patch40: Backport-CVE-2024-5535-Add-a-test-for-ALPN-and-NPN.patch
|
||||
Patch41: backport-Add-FIPS_mode-compatibility-macro.patch
|
||||
Patch42: Backport-CVE-2024-6119-Avoid-type-errors-in-EAI-related-name-check-logic.patch
|
||||
Patch38: Backport-CVE-2024-5535-Fix-SSL_select_next_proto.patch
|
||||
Patch39: Backport-CVE-2024-5535-Add-a-test-for-ALPN-and-NPN.patch
|
||||
Patch40: backport-Add-FIPS_mode-compatibility-macro.patch
|
||||
Patch41: Backport-CVE-2024-6119-Avoid-type-errors-in-EAI-related-name-check-logic.patch
|
||||
|
||||
Patch42: backport-Add-CTX-copy-function-for-EVP_MD-to-optimize-the-per.patch
|
||||
Patch43: backport-Decoder-resolution-performance-optimizations.patch
|
||||
Patch44: backport-Improve-performance-of-the-encoder-collection.patch
|
||||
Patch45: backport-evp_md_init_internal-Avoid-reallocating-algctx-if-di.patch
|
||||
Patch46: backport-Remove-the-_fetch_by_number-functions.patch
|
||||
Patch47: backport-Make-IV-buf-in-prov_cipher_ctx_st-aligned.patch
|
||||
Patch48: backport-ossl_namemap_name2_num-Avoid-unnecessary-OPENSSL_str.patch
|
||||
Patch49: backport-performance-improve-ossl_lh_strcasehash.patch
|
||||
Patch50: backport-01-Improve-FIPS-RSA-keygen-performance.patch
|
||||
Patch51: backport-02-Improve-FIPS-RSA-keygen-performance.patch
|
||||
Patch52: backport-When-we-re-just-reading-EX_CALLBACK-data-just-get-a-.patch
|
||||
Patch53: backport-Avoid-an-unneccessary-lock-if-we-didn-t-add-anything.patch
|
||||
Patch54: backport-use-__builtin_expect-to-improve-EVP_EncryptUpdate-pe.patch
|
||||
Patch55: backport-Drop-ossl_namemap_add_name_n-and-simplify-ossl_namem.patch
|
||||
|
||||
Patch9000: add-FIPS_mode_set-support.patch
|
||||
Patch9001: backport-CVE-2024-9143-Harden-BN_GF2m_poly2arr-against-misuse.patch
|
||||
Patch9002: Fix-build-error-for-ppc64le.patch
|
||||
|
||||
BuildRequires: gcc gcc-c++ perl make lksctp-tools-devel coreutils util-linux zlib-devel
|
||||
Requires: coreutils %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release}
|
||||
@ -254,6 +269,9 @@ make test || :
|
||||
%ldconfig_scriptlets libs
|
||||
|
||||
%changelog
|
||||
* Wed Nov 27 2024 zhujianwei <zhujianwei7@huawei.com> - 1:3.0.12-14
|
||||
- backport patch for performance improvements
|
||||
|
||||
* Wed Nov 27 2024 wangjinchao <wangjinchao@xfusion.com> - 1:3.0.12-13
|
||||
- fix broken link
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user