From b5aec2a201d55cfd02f2c77e9a7bd8fa372aee05 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/PK/RSA.cpp | 50 ++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/Libraries/LibCrypto/PK/RSA.cpp b/Libraries/LibCrypto/PK/RSA.cpp index 0491c5f7d598a..ebeab461d2a2d 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) 2024, Altomani Gianluca * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,8 +12,14 @@ #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) @@ -113,28 +120,49 @@ ErrorOr RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, } } +#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)); + 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)); - 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)); + auto* params_bld = OPENSSL_TRY_PTR(OSSL_PARAM_BLD_new()); + ArmedScopeGuard const free_params_bld = [&] { OSSL_PARAM_BLD_free(params_bld); }; - auto n = p.multiplied_by(q); + 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())); + + OPENSSL_TRY(EVP_PKEY_CTX_set_params(ctx.ptr(), OSSL_PARAM_BLD_to_param(params_bld))); + + auto key = TRY(OpenSSL_PKEY::create()); + auto* key_ptr = key.ptr(); + OPENSSL_TRY(EVP_PKEY_generate(ctx.ptr(), &key_ptr)); + + 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 d = NumberTheory::ModularInverse(e, lambda); RSAKeyPair keys { { n, e }, - { n, d, e, p, q } + { n, d, e, p, q, dp, dq, qinv } }; return keys; } +#undef OPENSSL_GET_KEY_PARAM + ErrorOr RSA::encrypt(ReadonlyBytes in, Bytes& out) { dbgln_if(CRYPTO_DEBUG, "in size: {}", in.size());