diff options
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 |