summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.github/workflows/coveralls.yml2
-rw-r--r--apps/lib/cmp_mock_srv.c19
-rw-r--r--crypto/bn/bn_lib.c51
-rw-r--r--crypto/bn/bn_rand.c164
-rw-r--r--crypto/bn/bn_shift.c6
-rw-r--r--crypto/cmp/cmp_asn.c33
-rw-r--r--crypto/cmp/cmp_genm.c6
-rw-r--r--crypto/deterministic_nonce.c54
-rw-r--r--crypto/dsa/dsa_ossl.c9
-rw-r--r--crypto/ec/ecdsa_ossl.c8
-rw-r--r--crypto/ess/ess_lib.c2
-rw-r--r--crypto/x509/by_dir.c6
-rw-r--r--doc/man3/EVP_PKEY_CTX_ctrl.pod5
-rw-r--r--doc/man3/EVP_PKEY_decrypt.pod13
-rw-r--r--doc/man3/OSSL_CMP_ITAV_new_caCerts.pod5
-rw-r--r--doc/man3/RSA_public_encrypt.pod13
-rw-r--r--doc/man3/SSL_CIPHER_get_name.pod2
-rw-r--r--doc/man7/ossl-guide-migration.pod18
-rw-r--r--doc/man7/provider-asym_cipher.pod2
-rw-r--r--include/crypto/bn.h8
-rw-r--r--include/internal/constant_time.h23
m---------oqs-provider0
-rw-r--r--os-dep/Apple/PrivacyInfo.xcprivacy23
-rw-r--r--providers/fips/self_test_data.inc50
-rw-r--r--test/ct_test.c9
-rw-r--r--test/prov_config_test.c3
-rw-r--r--test/recipes/80-test_cmp_http_data/test_commands.csv2
-rwxr-xr-xtest/recipes/95-test_external_oqsprovider_data/oqsprovider.sh6
29 files changed, 416 insertions, 128 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d4d4352c11..889b6017e2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -469,7 +469,7 @@ jobs:
sudo apt-get update
sudo apt-get -yq install bison gettext keyutils ldap-utils libldap2-dev libkeyutils-dev python3 python3-paste python3-pyrad slapd tcsh python3-virtualenv virtualenv python3-kdcproxy
- name: install cpanm and Test2::V0 for gost_engine testing
- uses: perl-actions/install-with-cpanm@v1
+ uses: perl-actions/install-with-cpanm@stable
with:
install: Test2::V0
- name: setup hostname workaround
diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml
index 6df0543e5d..229b30a1d4 100644
--- a/.github/workflows/coveralls.yml
+++ b/.github/workflows/coveralls.yml
@@ -50,7 +50,7 @@ jobs:
sudo apt-get -yq install lcov
sudo apt-get -yq install bison gettext keyutils ldap-utils libldap2-dev libkeyutils-dev python3 python3-paste python3-pyrad slapd tcsh python3-virtualenv virtualenv python3-kdcproxy
- name: install Test2::V0 for gost_engine testing
- uses: perl-actions/install-with-cpanm@v1
+ uses: perl-actions/install-with-cpanm@stable
with:
install: Test2::V0
- name: setup hostname workaround
diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c
index a0450446c1..8e45a35fa7 100644
--- a/apps/lib/cmp_mock_srv.c
+++ b/apps/lib/cmp_mock_srv.c
@@ -321,9 +321,22 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
rsp = OSSL_CMP_ITAV_new_caCerts(ctx->caPubsOut);
break;
case NID_id_it_rootCaCert:
- rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx->newWithNew,
- ctx->newWithOld,
- ctx->oldWithNew);
+ {
+ X509 *rootcacert = NULL;
+
+ if (!OSSL_CMP_ITAV_get0_rootCaCert(req, &rootcacert))
+ return NULL;
+
+ if (rootcacert != NULL
+ && X509_NAME_cmp(X509_get_subject_name(rootcacert),
+ X509_get_subject_name(ctx->newWithNew)) != 0)
+ /* The subjects do not match */
+ rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(NULL, NULL, NULL);
+ else
+ rsp = OSSL_CMP_ITAV_new_rootCaKeyUpdate(ctx->newWithNew,
+ ctx->newWithOld,
+ ctx->oldWithNew);
+ }
break;
default:
rsp = OSSL_CMP_ITAV_dup(req);
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 9070647b35..cab87d9959 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -708,14 +708,29 @@ int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
int i;
BN_ULONG t1, t2, *ap, *bp;
+ ap = a->d;
+ bp = b->d;
+
+ if (BN_get_flags(a, BN_FLG_CONSTTIME)
+ && a->top == b->top) {
+ int res = 0;
+
+ for (i = 0; i < b->top; i++) {
+ res = constant_time_select_int(constant_time_lt_bn(ap[i], bp[i]),
+ -1, res);
+ res = constant_time_select_int(constant_time_lt_bn(bp[i], ap[i]),
+ 1, res);
+ }
+ return res;
+ }
+
bn_check_top(a);
bn_check_top(b);
i = a->top - b->top;
if (i != 0)
return i;
- ap = a->d;
- bp = b->d;
+
for (i = a->top - 1; i >= 0; i--) {
t1 = ap[i];
t2 = bp[i];
@@ -827,11 +842,10 @@ int BN_is_bit_set(const BIGNUM *a, int n)
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
}
-int BN_mask_bits(BIGNUM *a, int n)
+int ossl_bn_mask_bits_fixed_top(BIGNUM *a, int n)
{
int b, w;
- bn_check_top(a);
if (n < 0)
return 0;
@@ -845,10 +859,21 @@ int BN_mask_bits(BIGNUM *a, int n)
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
- bn_correct_top(a);
+ a->flags |= BN_FLG_FIXED_TOP;
return 1;
}
+int BN_mask_bits(BIGNUM *a, int n)
+{
+ int ret;
+
+ bn_check_top(a);
+ ret = ossl_bn_mask_bits_fixed_top(a, n);
+ if (ret)
+ bn_correct_top(a);
+ return ret;
+}
+
void BN_set_negative(BIGNUM *a, int b)
{
if (b && !BN_is_zero(a))
@@ -1022,6 +1047,22 @@ int BN_is_word(const BIGNUM *a, const BN_ULONG w)
return BN_abs_is_word(a, w) && (!w || !a->neg);
}
+int ossl_bn_is_word_fixed_top(const BIGNUM *a, const BN_ULONG w)
+{
+ int res, i;
+ const BN_ULONG *ap = a->d;
+
+ if (a->neg || a->top == 0)
+ return 0;
+
+ res = constant_time_select_int(constant_time_eq_bn(ap[0], w), 1, 0);
+
+ for (i = 1; i < a->top; i++)
+ res = constant_time_select_int(constant_time_is_zero_bn(ap[i]),
+ res, 0);
+ return res;
+}
+
int BN_is_odd(const BIGNUM *a)
{
return (a->top > 0) && (a->d[0] & 1);
diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c
index a94dfcecdf..650d057470 100644
--- a/crypto/bn/bn_rand.c
+++ b/crypto/bn/bn_rand.c
@@ -184,8 +184,8 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range,
} else {
do {
/* range = 11..._2 or range = 101..._2 */
- if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY, 0,
- ctx))
+ if (!bnrand(flag, r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY,
+ strength, ctx))
return 0;
if (!--count) {
@@ -238,17 +238,63 @@ int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
# endif
#endif
+int ossl_bn_priv_rand_range_fixed_top(BIGNUM *r, const BIGNUM *range,
+ unsigned int strength, BN_CTX *ctx)
+{
+ int n;
+ int count = 100;
+
+ if (r == NULL) {
+ ERR_raise(ERR_LIB_BN, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (range->neg || BN_is_zero(range)) {
+ ERR_raise(ERR_LIB_BN, BN_R_INVALID_RANGE);
+ return 0;
+ }
+
+ n = BN_num_bits(range); /* n > 0 */
+
+ /* BN_is_bit_set(range, n - 1) always holds */
+
+ if (n == 1) {
+ BN_zero(r);
+ } else {
+ BN_set_flags(r, BN_FLG_CONSTTIME);
+ do {
+ if (!bnrand(PRIVATE, r, n + 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY,
+ strength, ctx))
+ return 0;
+
+ if (!--count) {
+ ERR_raise(ERR_LIB_BN, BN_R_TOO_MANY_ITERATIONS);
+ return 0;
+ }
+ ossl_bn_mask_bits_fixed_top(r, n);
+ }
+ while (BN_ucmp(r, range) >= 0);
+#ifdef BN_DEBUG
+ /* With BN_DEBUG on a fixed top number cannot be returned */
+ bn_correct_top(r);
+#endif
+ }
+
+ return 1;
+}
+
/*
- * BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
- * BN_rand_range, it also includes the contents of |priv| and |message| in
- * the generation so that an RNG failure isn't fatal as long as |priv|
+ * ossl_bn_gen_dsa_nonce_fixed_top generates a random number 0 <= out < range.
+ * Unlike BN_rand_range, it also includes the contents of |priv| and |message|
+ * in the generation so that an RNG failure isn't fatal as long as |priv|
* remains secret. This is intended for use in DSA and ECDSA where an RNG
* weakness leads directly to private key exposure unless this function is
* used.
*/
-int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
- const BIGNUM *priv, const unsigned char *message,
- size_t message_len, BN_CTX *ctx)
+int ossl_bn_gen_dsa_nonce_fixed_top(BIGNUM *out, const BIGNUM *range,
+ const BIGNUM *priv,
+ const unsigned char *message,
+ size_t message_len, BN_CTX *ctx)
{
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
/*
@@ -258,20 +304,24 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
unsigned char random_bytes[64];
unsigned char digest[SHA512_DIGEST_LENGTH];
unsigned done, todo;
- /* We generate |range|+8 bytes of random output. */
- const unsigned num_k_bytes = BN_num_bytes(range) + 8;
+ /* We generate |range|+1 bytes of random output. */
+ const unsigned num_k_bytes = BN_num_bytes(range) + 1;
unsigned char private_bytes[96];
unsigned char *k_bytes = NULL;
+ const int max_n = 64; /* Pr(failure to generate) < 2^max_n */
+ int n;
int ret = 0;
EVP_MD *md = NULL;
OSSL_LIB_CTX *libctx = ossl_bn_get_libctx(ctx);
if (mdctx == NULL)
- goto err;
+ goto end;
k_bytes = OPENSSL_malloc(num_k_bytes);
if (k_bytes == NULL)
- goto err;
+ goto end;
+ /* Ensure top byte is set to avoid non-constant time in bin2bn */
+ k_bytes[0] = 0xff;
/* We copy |priv| into a local buffer to avoid exposing its length. */
if (BN_bn2binpad(priv, private_bytes, sizeof(private_bytes)) < 0) {
@@ -281,41 +331,60 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
* length of the private key.
*/
ERR_raise(ERR_LIB_BN, BN_R_PRIVATE_KEY_TOO_LARGE);
- goto err;
+ goto end;
}
md = EVP_MD_fetch(libctx, "SHA512", NULL);
if (md == NULL) {
ERR_raise(ERR_LIB_BN, BN_R_NO_SUITABLE_DIGEST);
- goto err;
- }
- for (done = 0; done < num_k_bytes;) {
- if (RAND_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes), 0) <= 0)
- goto err;
-
- if (!EVP_DigestInit_ex(mdctx, md, NULL)
- || !EVP_DigestUpdate(mdctx, &done, sizeof(done))
- || !EVP_DigestUpdate(mdctx, private_bytes,
- sizeof(private_bytes))
- || !EVP_DigestUpdate(mdctx, message, message_len)
- || !EVP_DigestUpdate(mdctx, random_bytes, sizeof(random_bytes))
- || !EVP_DigestFinal_ex(mdctx, digest, NULL))
- goto err;
-
- todo = num_k_bytes - done;
- if (todo > SHA512_DIGEST_LENGTH)
- todo = SHA512_DIGEST_LENGTH;
- memcpy(k_bytes + done, digest, todo);
- done += todo;
+ goto end;
}
+ for (n = 0; n < max_n; n++) {
+ unsigned char i = 0;
+
+ for (done = 1; done < num_k_bytes;) {
+ if (RAND_priv_bytes_ex(libctx, random_bytes, sizeof(random_bytes),
+ 0) <= 0)
+ goto end;
+
+ if (!EVP_DigestInit_ex(mdctx, md, NULL)
+ || !EVP_DigestUpdate(mdctx, &i, sizeof(i))
+ || !EVP_DigestUpdate(mdctx, private_bytes,
+ sizeof(private_bytes))
+ || !EVP_DigestUpdate(mdctx, message, message_len)
+ || !EVP_DigestUpdate(mdctx, random_bytes,
+ sizeof(random_bytes))
+ || !EVP_DigestFinal_ex(mdctx, digest, NULL))
+ goto end;
+
+ todo = num_k_bytes - done;
+ if (todo > SHA512_DIGEST_LENGTH)
+ todo = SHA512_DIGEST_LENGTH;
+ memcpy(k_bytes + done, digest, todo);
+ done += todo;
+ ++i;
+ }
- if (!BN_bin2bn(k_bytes, num_k_bytes, out))
- goto err;
- if (BN_mod(out, out, range, ctx) != 1)
- goto err;
- ret = 1;
+ if (!BN_bin2bn(k_bytes, num_k_bytes, out))
+ goto end;
- err:
+ /* Clear out the top bits and rejection filter into range */
+ BN_set_flags(out, BN_FLG_CONSTTIME);
+ ossl_bn_mask_bits_fixed_top(out, BN_num_bits(range));
+
+ if (BN_ucmp(out, range) < 0) {
+ ret = 1;
+#ifdef BN_DEBUG
+ /* With BN_DEBUG on a fixed top number cannot be returned */
+ bn_correct_top(out);
+#endif
+ goto end;
+ }
+ }
+ /* Failed to generate anything */
+ ERR_raise(ERR_LIB_BN, ERR_R_INTERNAL_ERROR);
+
+ end:
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md);
OPENSSL_clear_free(k_bytes, num_k_bytes);
@@ -324,3 +393,20 @@ int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
OPENSSL_cleanse(private_bytes, sizeof(private_bytes));
return ret;
}
+
+int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range,
+ const BIGNUM *priv, const unsigned char *message,
+ size_t message_len, BN_CTX *ctx)
+{
+ int ret;
+
+ ret = ossl_bn_gen_dsa_nonce_fixed_top(out, range, priv, message,
+ message_len, ctx);
+ /*
+ * This call makes the BN_generate_dsa_nonce non-const-time, thus we
+ * do not use it internally. But fixed_top BNs currently cannot be returned
+ * from public API calls.
+ */
+ bn_correct_top(out);
+ return ret;
+}
diff --git a/crypto/bn/bn_shift.c b/crypto/bn/bn_shift.c
index 8fcb04324e..a6976c7130 100644
--- a/crypto/bn/bn_shift.c
+++ b/crypto/bn/bn_shift.c
@@ -156,6 +156,9 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
return 0;
}
+ bn_check_top(r);
+ bn_check_top(a);
+
ret = bn_rshift_fixed_top(r, a, n);
bn_correct_top(r);
@@ -177,9 +180,6 @@ int bn_rshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n)
BN_ULONG *t, *f;
BN_ULONG l, m, mask;
- bn_check_top(r);
- bn_check_top(a);
-
assert(n >= 0);
nw = n / BN_BITS2;
diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c
index 0133dc5f80..9747782267 100644
--- a/crypto/cmp/cmp_asn.c
+++ b/crypto/cmp/cmp_asn.c
@@ -261,23 +261,30 @@ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew,
const X509 *oldWithNew)
{
OSSL_CMP_ITAV *itav;
- OSSL_CMP_ROOTCAKEYUPDATE *upd = OSSL_CMP_ROOTCAKEYUPDATE_new();
+ OSSL_CMP_ROOTCAKEYUPDATE *upd = NULL;
+
+ if (newWithNew != NULL) {
+ upd = OSSL_CMP_ROOTCAKEYUPDATE_new();
+ if (upd == NULL)
+ return NULL;
+
+ if ((upd->newWithNew = X509_dup(newWithNew)) == NULL)
+ goto err;
+ if (newWithOld != NULL
+ && (upd->newWithOld = X509_dup(newWithOld)) == NULL)
+ goto err;
+ if (oldWithNew != NULL
+ && (upd->oldWithNew = X509_dup(oldWithNew)) == NULL)
+ goto err;
+ }
- if (upd == NULL)
- return NULL;
- if (newWithNew != NULL && (upd->newWithNew = X509_dup(newWithNew)) == NULL)
- goto err;
- if (newWithOld != NULL && (upd->newWithOld = X509_dup(newWithOld)) == NULL)
- goto err;
- if (oldWithNew != NULL && (upd->oldWithNew = X509_dup(oldWithNew)) == NULL)
- goto err;
if ((itav = OSSL_CMP_ITAV_new()) == NULL)
goto err;
itav->infoType = OBJ_nid2obj(NID_id_it_rootCaKeyUpdate);
itav->infoValue.rootCaKeyUpdate = upd;
return itav;
- err:
+ err:
OSSL_CMP_ROOTCAKEYUPDATE_free(upd);
return NULL;
}
@@ -298,11 +305,11 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
return 0;
}
upd = itav->infoValue.rootCaKeyUpdate;
- *newWithNew = upd->newWithNew;
+ *newWithNew = upd != NULL ? upd->newWithNew : NULL;
if (newWithOld != NULL)
- *newWithOld = upd->newWithOld;
+ *newWithOld = upd != NULL ? upd->newWithOld : NULL;
if (oldWithNew != NULL)
- *oldWithNew = upd->oldWithNew;
+ *oldWithNew = upd != NULL ? upd->oldWithNew : NULL;
return 1;
}
diff --git a/crypto/cmp/cmp_genm.c b/crypto/cmp/cmp_genm.c
index dad6ef1189..7c38d3367c 100644
--- a/crypto/cmp/cmp_genm.c
+++ b/crypto/cmp/cmp_genm.c
@@ -307,9 +307,11 @@ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
if (!OSSL_CMP_ITAV_get0_rootCaKeyUpdate(itav, newWithNew,
&my_newWithOld, &my_oldWithNew))
goto end;
-
- if (*newWithNew == NULL) /* no root CA cert update available */
+ /* no root CA cert update available */
+ if (*newWithNew == NULL) {
+ res = 1;
goto end;
+ }
if ((oldWithOld_copy = X509_dup(oldWithOld)) == NULL && oldWithOld != NULL)
goto end;
if (!verify_ss_cert_trans(ctx, oldWithOld_copy, my_newWithOld,
diff --git a/crypto/deterministic_nonce.c b/crypto/deterministic_nonce.c
index 60af7f6ab6..67a5b98d2b 100644
--- a/crypto/deterministic_nonce.c
+++ b/crypto/deterministic_nonce.c
@@ -7,11 +7,13 @@
* https://www.openssl.org/source/license.html
*/
+#include <string.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
#include <openssl/kdf.h>
#include "internal/deterministic_nonce.h"
+#include "crypto/bn.h"
/*
* Convert a Bit String to an Integer (See RFC 6979 Section 2.3.2)
@@ -39,6 +41,36 @@ static int bits2int(BIGNUM *out, int qlen_bits,
}
/*
+ * Convert as above a Bit String in const time to an Integer w fixed top
+ *
+ * Params:
+ * out The returned Integer as a BIGNUM
+ * qlen_bits The maximum size of the returned integer in bits. The returned
+ * Integer is shifted right if inlen is larger than qlen_bits..
+ * in, inlen The input Bit String (in bytes). It has sizeof(BN_ULONG) bytes
+ * prefix with all bits set that needs to be cleared out after
+ * the conversion.
+ * Returns: 1 if successful, or 0 otherwise.
+ */
+static int bits2int_consttime(BIGNUM *out, int qlen_bits,
+ const unsigned char *in, size_t inlen)
+{
+ int blen_bits = (inlen - sizeof(BN_ULONG)) * 8;
+ int shift;
+
+ if (BN_bin2bn(in, (int)inlen, out) == NULL)
+ return 0;
+
+ BN_set_flags(out, BN_FLG_CONSTTIME);
+ ossl_bn_mask_bits_fixed_top(out, blen_bits);
+
+ shift = blen_bits - qlen_bits;
+ if (shift > 0)
+ return bn_rshift_fixed_top(out, out, shift);
+ return 1;
+}
+
+/*
* Convert an Integer to an Octet String (See RFC 6979 2.3.3).
* The value is zero padded if required.
*
@@ -155,8 +187,9 @@ int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
{
EVP_KDF_CTX *kdfctx = NULL;
int ret = 0, rlen = 0, qlen_bits = 0;
- unsigned char *entropyx = NULL, *nonceh = NULL, *T = NULL;
+ unsigned char *entropyx = NULL, *nonceh = NULL, *rbits = NULL, *T = NULL;
size_t allocsz = 0;
+ const size_t prefsz = sizeof(BN_ULONG);
if (out == NULL)
return 0;
@@ -167,15 +200,18 @@ int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
/* Note rlen used here is in bytes since the input values are byte arrays */
rlen = (qlen_bits + 7) / 8;
- allocsz = 3 * rlen;
+ allocsz = prefsz + 3 * rlen;
/* Use a single alloc for the buffers T, nonceh and entropyx */
T = (unsigned char *)OPENSSL_zalloc(allocsz);
if (T == NULL)
return 0;
- nonceh = T + rlen;
+ rbits = T + prefsz;
+ nonceh = rbits + rlen;
entropyx = nonceh + rlen;
+ memset(T, 0xff, prefsz);
+
if (!int2octets(entropyx, priv, rlen)
|| !bits2octets(nonceh, q, qlen_bits, rlen, hm, hmlen))
goto end;
@@ -185,10 +221,16 @@ int ossl_gen_deterministic_nonce_rfc6979(BIGNUM *out, const BIGNUM *q,
goto end;
do {
- if (!EVP_KDF_derive(kdfctx, T, rlen, NULL)
- || !bits2int(out, qlen_bits, T, rlen))
+ if (!EVP_KDF_derive(kdfctx, rbits, rlen, NULL)
+ || !bits2int_consttime(out, qlen_bits, T, rlen + prefsz))
goto end;
- } while (BN_is_zero(out) || BN_is_one(out) || BN_cmp(out, q) >= 0);
+ } while (ossl_bn_is_word_fixed_top(out, 0)
+ || ossl_bn_is_word_fixed_top(out, 1)
+ || BN_ucmp(out, q) >= 0);
+#ifdef BN_DEBUG
+ /* With BN_DEBUG on a fixed top number cannot be returned */
+ bn_correct_top(out);
+#endif
ret = 1;
end:
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 234362b6d7..409830092d 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -282,13 +282,14 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
- if (!BN_generate_dsa_nonce(k, dsa->params.q, dsa->priv_key, dgst,
- dlen, ctx))
+ if (!ossl_bn_gen_dsa_nonce_fixed_top(k, dsa->params.q,
+ dsa->priv_key, dgst,
+ dlen, ctx))
goto err;
}
- } else if (!BN_priv_rand_range_ex(k, dsa->params.q, 0, ctx))
+ } else if (!ossl_bn_priv_rand_range_fixed_top(k, dsa->params.q, 0, ctx))
goto err;
- } while (BN_is_zero(k));
+ } while (ossl_bn_is_word_fixed_top(k, 0));
BN_set_flags(k, BN_FLG_CONSTTIME);
BN_set_flags(l, BN_FLG_CONSTTIME);
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
index e60877aa05..1e611f7ffc 100644
--- a/crypto/ec/ecdsa_ossl.c
+++ b/crypto/ec/ecdsa_ossl.c
@@ -198,17 +198,17 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
libctx, propq);
#endif
} else {
- res = BN_generate_dsa_nonce(k, order, priv_key, dgst, dlen,
- ctx);
+ res = ossl_bn_gen_dsa_nonce_fixed_top(k, order, priv_key,
+ dgst, dlen, ctx);
}
} else {
- res = BN_priv_rand_range_ex(k, order, 0, ctx);
+ res = ossl_bn_priv_rand_range_fixed_top(k, order, 0, ctx);
}
if (!res) {
ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
- } while (BN_is_zero(k));
+ } while (ossl_bn_is_word_fixed_top(k, 0));
/* compute r the x-coordinate of generator * k */
if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) {
diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c
index 0612e68ee6..68c8d37001 100644
--- a/crypto/ess/ess_lib.c
+++ b/crypto/ess/ess_lib.c
@@ -346,7 +346,7 @@ int OSSL_ESS_check_signing_certs(const ESS_SIGNING_CERT *ss,
int i, ret;
if (require_signing_cert && ss == NULL && ssv2 == NULL) {
- ERR_raise(ERR_LIB_CMS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE);
+ ERR_raise(ERR_LIB_ESS, ESS_R_MISSING_SIGNING_CERTIFICATE_ATTRIBUTE);
return -1;
}
if (n_v1 == 0 || n_v2 == 0) {
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 1d401d0420..eb04be2e8c 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -420,11 +420,11 @@ static int get_cert_by_subject_ex(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
}
finish:
/* If we changed anything, resort the objects for faster lookup */
- if (!sk_X509_OBJECT_is_sorted(xl->store_ctx->objs)) {
- if (X509_STORE_lock(xl->store_ctx)) {
+ if (X509_STORE_lock(xl->store_ctx)) {
+ if (!sk_X509_OBJECT_is_sorted(xl->store_ctx->objs)) {
sk_X509_OBJECT_sort(xl->store_ctx->objs);
- X509_STORE_unlock(xl->store_ctx);
}
+ X509_STORE_unlock(xl->store_ctx);
}
BUF_MEM_free(b);
diff --git a/doc/man3/EVP_PKEY_CTX_ctrl.pod b/doc/man3/EVP_PKEY_CTX_ctrl.pod
index edbcb0dce8..21ae20adb0 100644
--- a/doc/man3/EVP_PKEY_CTX_ctrl.pod
+++ b/doc/man3/EVP_PKEY_CTX_ctrl.pod
@@ -396,11 +396,12 @@ negotiated protocol version. Otherwise it should be left unset.
Similarly to the B<RSA_PKCS1_WITH_TLS_PADDING> above, since OpenSSL version
3.2.0, the use of B<RSA_PKCS1_PADDING> will return a randomly generated message
instead of padding errors in case padding checks fail. Applications that
-want to remain secure while using earlier versions of OpenSSL, still need to
+want to remain secure while using earlier versions of OpenSSL, or a provider
+that doesn't implement the implicit rejection mechanism, still need to
handle both the error code from the RSA decryption operation and the
returned message in a side channel secure manner.
This protection against Bleichenbacher attacks can be disabled by setting
-the OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION (an unsigned integer) to 0.
+B<OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION> (an unsigned integer) to 0.
=head2 DSA parameters
diff --git a/doc/man3/EVP_PKEY_decrypt.pod b/doc/man3/EVP_PKEY_decrypt.pod
index 67e3f2da1e..903d933fb2 100644
--- a/doc/man3/EVP_PKEY_decrypt.pod
+++ b/doc/man3/EVP_PKEY_decrypt.pod
@@ -56,12 +56,21 @@ algorithm.
In OpenSSL versions before 3.2.0, when used in PKCS#1 v1.5 padding,
both the return value from the EVP_PKEY_decrypt() and the B<outlen> provided
information useful in mounting a Bleichenbacher attack against the
-used private key. They had to processed in a side-channel free way.
+used private key. They had to be processed in a side-channel free way.
Since version 3.2.0, the EVP_PKEY_decrypt() method when used with PKCS#1
-v1.5 padding doesn't return an error in case it detects an error in padding,
+v1.5 padding as implemented in the B<default> provider implements
+the implicit rejection mechanism (see
+B<OSSL_PKEY_PARAM_IMPLICIT_REJECTION> in L<provider-asym_cipher(7)>).
+That means it doesn't return an error when it detects an error in padding,
instead it returns a pseudo-randomly generated message, removing the need
of side-channel secure code from applications using OpenSSL.
+If OpenSSL is configured to use a provider that doesn't implement implicit
+rejection, the code still needs to handle the returned values
+using side-channel free code.
+Side-channel free handling of the error stack can be performed using
+either a pair of unconditional L<ERR_set_mark(3)> and L<ERR_pop_to_mark(3)>
+calls or by using the L<ERR_clear_error(3)> call.
=head1 EXAMPLES
diff --git a/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod b/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
index 66f0ac9030..133907d8ac 100644
--- a/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
+++ b/doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
@@ -49,6 +49,8 @@ the internal pointer to the certificate contained in the infoValue field.
OSSL_CMP_ITAV_new_rootCaKeyUpdate() creates a new B<OSSL_CMP_ITAV> structure
of type B<rootCaKeyUpdate> that includes an RootCaKeyUpdateContent structure
with the optional I<newWithNew>, I<newWithOld>, and I<oldWithNew> certificates.
+An RootCaKeyUpdateContent structure is included only if I<newWithNew>
+is not NULL.
OSSL_CMP_ITAV_get0_rootCaKeyUpdate() requires that I<itav> has infoType
B<rootCaKeyUpdate>.
@@ -59,7 +61,8 @@ If I<newWithOld> is not NULL, it assigns to I<*newWithOld> the internal pointer
to the certificate contained in the newWithOld infoValue sub-field of I<itav>.
If I<oldWithNew> is not NULL, it assigns to I<*oldWithNew> the internal pointer
to the certificate contained in the oldWithNew infoValue sub-field of I<itav>.
-Each of these pointers will be NULL if the respective sub-field is not set.
+Each of these pointers will be set to NULL if no root CA certificate update
+is present