diff --git a/Libraries/LibCrypto/OpenSSL.h b/Libraries/LibCrypto/OpenSSL.h index bcb49b1886a..16047b00fe6 100644 --- a/Libraries/LibCrypto/OpenSSL.h +++ b/Libraries/LibCrypto/OpenSSL.h @@ -104,6 +104,10 @@ public: } }; +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 af7c9d580a0..06988ca1a66 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))); - 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_TRY(EVP_PKEY_keygen_init(ctx.ptr())); - auto n = p.multiplied_by(q); + 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)); + + 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); + +#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; }