!417 [sync] PR-406: backport patch for performance improvements

From: @fly_fzc 
Reviewed-by: @zcfsite 
Signed-off-by: @zcfsite
This commit is contained in:
openeuler-ci-bot 2024-11-27 11:42:53 +00:00 committed by Gitee
commit 6678c1ccb6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
15 changed files with 2966 additions and 6 deletions

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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