From fef1f62eccdc67d18a2d47322b2039b7182c690d Mon Sep 17 00:00:00 2001 From: devgianlu Date: Mon, 23 Dec 2024 18:19:46 +0100 Subject: [PATCH] LibCrypto: Use OpenSSL to generate RSA keys Replace our slow, possibly incorrect RSA key generation with OpenSSL. This should fix many WPT tests that are timing out because we were too slow at computing keys. --- Libraries/LibCrypto/OpenSSL.h | 4 +++ Libraries/LibCrypto/PK/RSA.cpp | 53 +++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Libraries/LibCrypto/OpenSSL.h b/Libraries/LibCrypto/OpenSSL.h index bcb49b1886ae..16047b00fe62 100644 --- a/Libraries/LibCrypto/OpenSSL.h +++ b/Libraries/LibCrypto/OpenSSL.h @@ -104,6 +104,10 @@ class OpenSSL_PKEY { } }; +class OpenSSL_PKEY_CTX { + OPENSSL_WRAPPER_CLASS(OpenSSL_PKEY_CTX, EVP_PKEY_CTX, EVP_PKEY_CTX); +}; + class OpenSSL_MD_CTX { OPENSSL_WRAPPER_CLASS(OpenSSL_MD_CTX, EVP_MD_CTX, EVP_MD_CTX); diff --git a/Libraries/LibCrypto/PK/RSA.cpp b/Libraries/LibCrypto/PK/RSA.cpp index af7c9d580a08..06988ca1a66f 100644 --- a/Libraries/LibCrypto/PK/RSA.cpp +++ b/Libraries/LibCrypto/PK/RSA.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, Ali Mohammad Pur + * Copyright (c) 2025, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,9 +12,15 @@ #include #include #include +#include #include #include +#include +#include +#include +#include + namespace Crypto::PK { ErrorOr RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, Vector current_scope) @@ -116,22 +123,46 @@ ErrorOr RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, ErrorOr RSA::generate_key_pair(size_t bits, IntegerType e) { - IntegerType p; - IntegerType q; - IntegerType lambda; + auto ctx = TRY(OpenSSL_PKEY_CTX::wrap(EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr))); + + OPENSSL_TRY(EVP_PKEY_keygen_init(ctx.ptr())); + + auto e_bn = TRY(unsigned_big_integer_to_openssl_bignum(e)); + + auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new()); + ScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); }; + + OPENSSL_TRY(OSSL_PARAM_BLD_push_size_t(params_bld, OSSL_PKEY_PARAM_RSA_BITS, bits)); + OPENSSL_TRY(OSSL_PARAM_BLD_push_BN(params_bld, OSSL_PKEY_PARAM_RSA_E, e_bn.ptr())); + + auto* params = OSSL_PARAM_BLD_to_param(params_bld); + ScopeGuard const free_params = [&] { OSSL_PARAM_free(params); }; + + OPENSSL_TRY(EVP_PKEY_CTX_set_params(ctx.ptr(), params)); + + auto key = TRY(OpenSSL_PKEY::create()); + auto* key_ptr = key.ptr(); + OPENSSL_TRY(EVP_PKEY_generate(ctx.ptr(), &key_ptr)); + +#define OPENSSL_GET_KEY_PARAM(param, openssl_name) \ + auto param##_bn = TRY(OpenSSL_BN::create()); \ + auto* param##_bn_ptr = param##_bn.ptr(); \ + OPENSSL_TRY(EVP_PKEY_get_bn_param(key.ptr(), openssl_name, ¶m##_bn_ptr)); \ + auto param = TRY(openssl_bignum_to_unsigned_big_integer(param##_bn)); - do { - p = NumberTheory::random_big_prime(bits / 2); - q = NumberTheory::random_big_prime(bits / 2); - lambda = NumberTheory::LCM(p.minus(1), q.minus(1)); - } while (!(NumberTheory::GCD(e, lambda) == 1)); + OPENSSL_GET_KEY_PARAM(n, OSSL_PKEY_PARAM_RSA_N); + OPENSSL_GET_KEY_PARAM(d, OSSL_PKEY_PARAM_RSA_D); + OPENSSL_GET_KEY_PARAM(p, OSSL_PKEY_PARAM_RSA_FACTOR1); + OPENSSL_GET_KEY_PARAM(q, OSSL_PKEY_PARAM_RSA_FACTOR2); + OPENSSL_GET_KEY_PARAM(dp, OSSL_PKEY_PARAM_RSA_EXPONENT1); + OPENSSL_GET_KEY_PARAM(dq, OSSL_PKEY_PARAM_RSA_EXPONENT2); + OPENSSL_GET_KEY_PARAM(qinv, OSSL_PKEY_PARAM_RSA_COEFFICIENT1); - auto n = p.multiplied_by(q); +#undef OPENSSL_GET_KEY_PARAM - auto d = NumberTheory::ModularInverse(e, lambda); RSAKeyPair keys { { n, e }, - { n, d, e, p, q } + { n, d, e, p, q, dp, dq, qinv } }; return keys; }