diff options
Diffstat (limited to 'crypto/rsa/rsa_lib.c')
-rw-r--r-- | crypto/rsa/rsa_lib.c | 119 |
1 files changed, 99 insertions, 20 deletions
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index c9c661b1ede9..d9ceb8088005 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -76,15 +76,18 @@ static RSA *rsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx) { RSA *ret = OPENSSL_zalloc(sizeof(*ret)); - if (ret == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if (ret == NULL) return NULL; - } - ret->references = 1; ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_RSA, ERR_R_CRYPTO_LIB); + OPENSSL_free(ret); + return NULL; + } + + if (!CRYPTO_NEW_REF(&ret->references, 1)) { + CRYPTO_THREAD_lock_free(ret->lock); OPENSSL_free(ret); return NULL; } @@ -137,8 +140,8 @@ void RSA_free(RSA *r) if (r == NULL) return; - CRYPTO_DOWN_REF(&r->references, &i, r->lock); - REF_PRINT_COUNT("RSA", r); + CRYPTO_DOWN_REF(&r->references, &i); + REF_PRINT_COUNT("RSA", i, r); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -154,9 +157,15 @@ void RSA_free(RSA *r) #endif CRYPTO_THREAD_lock_free(r->lock); + CRYPTO_FREE_REF(&r->references); +#ifdef OPENSSL_PEDANTIC_ZEROIZATION + BN_clear_free(r->n); + BN_clear_free(r->e); +#else BN_free(r->n); BN_free(r->e); +#endif BN_clear_free(r->d); BN_clear_free(r->p); BN_clear_free(r->q); @@ -181,10 +190,10 @@ int RSA_up_ref(RSA *r) { int i; - if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) + if (CRYPTO_UP_REF(&r->references, &i) <= 0) return 0; - REF_PRINT_COUNT("RSA", r); + REF_PRINT_COUNT("RSA", i, r); REF_ASSERT_ISNT(i < 2); return i > 1 ? 1 : 0; } @@ -740,9 +749,13 @@ int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2) DEFINE_STACK_OF(BIGNUM) -int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, - const STACK_OF(BIGNUM) *exps, - const STACK_OF(BIGNUM) *coeffs) +/* + * Note: This function deletes values from the parameter + * stack values as they are consumed and set in the RSA key. + */ +int ossl_rsa_set0_all_params(RSA *r, STACK_OF(BIGNUM) *primes, + STACK_OF(BIGNUM) *exps, + STACK_OF(BIGNUM) *coeffs) { #ifndef FIPS_MODULE STACK_OF(RSA_PRIME_INFO) *prime_infos, *old_infos = NULL; @@ -753,6 +766,8 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, return 0; pnum = sk_BIGNUM_num(primes); + + /* we need at least 2 primes */ if (pnum < 2) return 0; @@ -760,6 +775,17 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, sk_BIGNUM_value(primes, 1))) return 0; + /* + * if we managed to set everything above, remove those elements from the + * stack + * Note, we do this after the above all to ensure that we have taken + * ownership of all the elements in the RSA key to avoid memory leaks + * we also use delete 0 here as we are grabbing items from the end of the + * stack rather than the start, otherwise we could use pop + */ + sk_BIGNUM_delete(primes, 0); + sk_BIGNUM_delete(primes, 0); + if (pnum == sk_BIGNUM_num(exps) && pnum == sk_BIGNUM_num(coeffs) + 1) { @@ -767,6 +793,11 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, sk_BIGNUM_value(exps, 1), sk_BIGNUM_value(coeffs, 0))) return 0; + + /* as above, once we consume the above params, delete them from the list */ + sk_BIGNUM_delete(exps, 0); + sk_BIGNUM_delete(exps, 0); + sk_BIGNUM_delete(coeffs, 0); } #ifndef FIPS_MODULE @@ -782,19 +813,17 @@ int ossl_rsa_set0_all_params(RSA *r, const STACK_OF(BIGNUM) *primes, return 0; for (i = 2; i < pnum; i++) { - BIGNUM *prime = sk_BIGNUM_value(primes, i); - BIGNUM *exp = sk_BIGNUM_value(exps, i); - BIGNUM *coeff = sk_BIGNUM_value(coeffs, i - 1); + BIGNUM *prime = sk_BIGNUM_pop(primes); + BIGNUM *exp = sk_BIGNUM_pop(exps); + BIGNUM *coeff = sk_BIGNUM_pop(coeffs); RSA_PRIME_INFO *pinfo = NULL; if (!ossl_assert(prime != NULL && exp != NULL && coeff != NULL)) goto err; /* Using ossl_rsa_multip_info_new() is wasteful, so allocate directly */ - if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) { - ERR_raise(ERR_LIB_RSA, ERR_R_MALLOC_FAILURE); + if ((pinfo = OPENSSL_zalloc(sizeof(*pinfo))) == NULL) goto err; - } pinfo->r = prime; pinfo->d = exp; @@ -877,6 +906,56 @@ int ossl_rsa_get0_all_params(RSA *r, STACK_OF(BIGNUM_const) *primes, return 1; } +#define safe_BN_num_bits(_k_) (((_k_) == NULL) ? 0 : BN_num_bits((_k_))) +int ossl_rsa_check_factors(RSA *r) +{ + int valid = 0; + int n, i, bits; + STACK_OF(BIGNUM_const) *factors = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *exps = sk_BIGNUM_const_new_null(); + STACK_OF(BIGNUM_const) *coeffs = sk_BIGNUM_const_new_null(); + + if (factors == NULL || exps == NULL || coeffs == NULL) + goto done; + + /* + * Simple sanity check for RSA key. All RSA key parameters + * must be less-than/equal-to RSA parameter n. + */ + ossl_rsa_get0_all_params(r, factors, exps, coeffs); + n = safe_BN_num_bits(RSA_get0_n(r)); + + if (safe_BN_num_bits(RSA_get0_d(r)) > n) + goto done; + + for (i = 0; i < sk_BIGNUM_const_num(exps); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(exps, i)); + if (bits > n) + goto done; + } + + for (i = 0; i < sk_BIGNUM_const_num(factors); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(factors, i)); + if (bits > n) + goto done; + } + + for (i = 0; i < sk_BIGNUM_const_num(coeffs); i++) { + bits = safe_BN_num_bits(sk_BIGNUM_const_value(coeffs, i)); + if (bits > n) + goto done; + } + + valid = 1; + +done: + sk_BIGNUM_const_free(factors); + sk_BIGNUM_const_free(exps); + sk_BIGNUM_const_free(coeffs); + + return valid; +} + #ifndef FIPS_MODULE /* Helpers to set or get diverse hash algorithm names */ static int int_set_rsa_md_name(EVP_PKEY_CTX *ctx, @@ -1127,7 +1206,7 @@ int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, void *label, int llen) if (ret <= 0) return ret; - /* Ownership is supposed to be transfered to the callee. */ + /* Ownership is supposed to be transferred to the callee. */ OPENSSL_free(label); return 1; } |