/*
 * Copyright (C) 2014 Igalia S.L. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "CryptoKeyRSA.h"

#if ENABLE(WEB_CRYPTO)

#include "CryptoAlgorithmRegistry.h"
#include "CryptoKeyPair.h"
#include "CryptoKeyRSAComponents.h"
#include "GCryptUtilities.h"
#include "ScriptExecutionContext.h"
#include <JavaScriptCore/GenericTypedArrayViewInlines.h>
#include <JavaScriptCore/HeapInlines.h>
#include <JavaScriptCore/JSGenericTypedArrayViewInlines.h>
#include <pal/crypto/gcrypt/Utilities.h>
#include <pal/crypto/tasn1/Utilities.h>

namespace WebCore {

static size_t getRSAModulusLength(gcry_sexp_t keySexp)
{
    // Retrieve the s-expression token for the public modulus N of the given RSA key.
    PAL::GCrypt::Handle<gcry_sexp_t> nSexp(gcry_sexp_find_token(keySexp, "n", 0));
    if (!nSexp)
        return 0;

    // Retrieve the MPI length for the corresponding s-expression token, in bits.
    auto length = mpiLength(nSexp);
    if (!length)
        return 0;

    return *length * 8;
}

static Vector<uint8_t> getRSAKeyParameter(gcry_sexp_t keySexp, const char* name)
{
    // Retrieve the s-expression token for the specified parameter of the given RSA key.
    PAL::GCrypt::Handle<gcry_sexp_t> paramSexp(gcry_sexp_find_token(keySexp, name, 0));
    if (!paramSexp)
        return { };

    // Retrieve the MPI data for the corresponding s-expression token.
    auto data = mpiData(paramSexp);
    if (!data)
        return { };

    return WTFMove(data.value());
}

RefPtr<CryptoKeyRSA> CryptoKeyRSA::create(CryptoAlgorithmIdentifier identifier, CryptoAlgorithmIdentifier hash, bool hasHash, const CryptoKeyRSAComponents& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    // When creating a private key, we require the p and q prime information.
    if (keyData.type() == CryptoKeyRSAComponents::Type::Private && !keyData.hasAdditionalPrivateKeyParameters())
        return nullptr;

    // But we don't currently support creating keys with any additional prime information.
    if (!keyData.otherPrimeInfos().isEmpty())
        return nullptr;

    // Validate the key data.
    {
        bool valid = true;

        // For both public and private keys, we need the public modulus and exponent.
        valid &= !keyData.modulus().isEmpty() && !keyData.exponent().isEmpty();

        // For private keys, we require the private exponent, as well as p and q prime information.
        if (keyData.type() == CryptoKeyRSAComponents::Type::Private)
            valid &= !keyData.privateExponent().isEmpty() && !keyData.firstPrimeInfo().primeFactor.isEmpty() && !keyData.secondPrimeInfo().primeFactor.isEmpty();

        if (!valid)
            return nullptr;
    }

    CryptoKeyType keyType;
    switch (keyData.type()) {
    case CryptoKeyRSAComponents::Type::Public:
        keyType = CryptoKeyType::Public;
        break;
    case CryptoKeyRSAComponents::Type::Private:
        keyType = CryptoKeyType::Private;
        break;
    }

    // Construct the key s-expression, using the data that's available.
    PAL::GCrypt::Handle<gcry_sexp_t> keySexp;
    {
        gcry_error_t error = GPG_ERR_NO_ERROR;

        switch (keyType) {
        case CryptoKeyType::Public:
            error = gcry_sexp_build(&keySexp, nullptr, "(public-key(rsa(n %b)(e %b)))",
                keyData.modulus().size(), keyData.modulus().data(),
                keyData.exponent().size(), keyData.exponent().data());
            break;
        case CryptoKeyType::Private:
            if (keyData.hasAdditionalPrivateKeyParameters()) {
                error = gcry_sexp_build(&keySexp, nullptr, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)))",
                    keyData.modulus().size(), keyData.modulus().data(),
                    keyData.exponent().size(), keyData.exponent().data(),
                    keyData.privateExponent().size(), keyData.privateExponent().data(),
                    keyData.secondPrimeInfo().primeFactor.size(), keyData.secondPrimeInfo().primeFactor.data(),
                    keyData.firstPrimeInfo().primeFactor.size(), keyData.firstPrimeInfo().primeFactor.data());
                break;
            }

            error = gcry_sexp_build(&keySexp, nullptr, "(private-key(rsa(n %b)(e %b)(d %b)))",
                keyData.modulus().size(), keyData.modulus().data(),
                keyData.exponent().size(), keyData.exponent().data(),
                keyData.privateExponent().size(), keyData.privateExponent().data());
            break;
        case CryptoKeyType::Secret:
            ASSERT_NOT_REACHED();
            return nullptr;
        }

        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }
    }

    return adoptRef(new CryptoKeyRSA(identifier, hash, hasHash, keyType, PlatformRSAKeyContainer(keySexp.release()), extractable, usages));
}

CryptoKeyRSA::CryptoKeyRSA(CryptoAlgorithmIdentifier identifier, CryptoAlgorithmIdentifier hash, bool hasHash, CryptoKeyType type, PlatformRSAKeyContainer&& platformKey, bool extractable, CryptoKeyUsageBitmap usage)
    : CryptoKey(identifier, type, extractable, usage)
    , m_platformKey(WTFMove(platformKey))
    , m_restrictedToSpecificHash(hasHash)
    , m_hash(hash)
{
}

bool CryptoKeyRSA::isRestrictedToHash(CryptoAlgorithmIdentifier& identifier) const
{
    if (!m_restrictedToSpecificHash)
        return false;

    identifier = m_hash;
    return true;
}

size_t CryptoKeyRSA::keySizeInBits() const
{
    return getRSAModulusLength(m_platformKey.get());
}

// Convert the exponent vector to a 32-bit value, if possible.
static std::optional<uint32_t> exponentVectorToUInt32(const Vector<uint8_t>& exponent)
{
    if (exponent.size() > 4) {
        if (std::any_of(exponent.begin(), exponent.end() - 4, [](uint8_t element) { return !!element; }))
            return std::nullopt;
    }

    uint32_t result = 0;
    for (size_t size = exponent.size(), i = std::min<size_t>(4, size); i > 0; --i) {
        result <<= 8;
        result += exponent[size - i];
    }

    return result;
}

void CryptoKeyRSA::generatePair(CryptoAlgorithmIdentifier algorithm, CryptoAlgorithmIdentifier hash, bool hasHash, unsigned modulusLength, const Vector<uint8_t>& publicExponent, bool extractable, CryptoKeyUsageBitmap usage, KeyPairCallback&& callback, VoidCallback&& failureCallback, ScriptExecutionContext* context)
{
    // libgcrypt doesn't report an error if the exponent is smaller than three or even.
    auto e = exponentVectorToUInt32(publicExponent);
    if (!e || *e < 3 || !(*e & 0x1)) {
        failureCallback();
        return;
    }

    // libgcrypt doesn't support generating primes of less than 16 bits.
    if (modulusLength < 16) {
        failureCallback();
        return;
    }

    PAL::GCrypt::Handle<gcry_sexp_t> genkeySexp;
    gcry_error_t error = gcry_sexp_build(&genkeySexp, nullptr, "(genkey(rsa(nbits %d)(rsa-use-e %d)))", modulusLength, *e);
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        failureCallback();
        return;
    }

    PAL::GCrypt::Handle<gcry_sexp_t> keyPairSexp;
    error = gcry_pk_genkey(&keyPairSexp, genkeySexp);
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        failureCallback();
        return;
    }

    PAL::GCrypt::Handle<gcry_sexp_t> publicKeySexp(gcry_sexp_find_token(keyPairSexp, "public-key", 0));
    PAL::GCrypt::Handle<gcry_sexp_t> privateKeySexp(gcry_sexp_find_token(keyPairSexp, "private-key", 0));
    if (!publicKeySexp || !privateKeySexp) {
        failureCallback();
        return;
    }

    context->postTask(
        [algorithm, hash, hasHash, extractable, usage, publicKeySexp = PlatformRSAKeyContainer(publicKeySexp.release()), privateKeySexp = PlatformRSAKeyContainer(privateKeySexp.release()), callback = WTFMove(callback)](auto&) mutable {
            auto publicKey = CryptoKeyRSA::create(algorithm, hash, hasHash, CryptoKeyType::Public, WTFMove(publicKeySexp), true, usage);
            auto privateKey = CryptoKeyRSA::create(algorithm, hash, hasHash, CryptoKeyType::Private, WTFMove(privateKeySexp), extractable, usage);

            callback(CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) });
        });
}

static bool supportedAlgorithmIdentifier(const uint8_t* data, size_t size)
{
    // FIXME: This is far from sufficient. Per the spec, when importing for key algorithm
    // - RSASSA-PKCS1-v1_5:
    //     - rsaEncryption, sha{1,256,384,512}WithRSAEncryption OIDs must be supported
    //     - in case of sha{1,256,384,512}WithRSAEncryption OIDs the specified hash algorithm
    //       has to match the algorithm in the OID
    // - RSA-PSS:
    //     - rsaEncryption, id-RSASSA-PSS OIDs must be supported
    //     - in case of id-RSASSA-PSS OID the parameters field of AlgorithmIdentifier has
    //       to be decoded as RSASSA-PSS-params ASN.1 structure, and the hashAlgorithm field
    //       of that structure has to contain one of id-sha{1,256,384,512} OIDs that match
    //       the specified hash algorithm
    // - RSA-OAEP:
    //     - rsaEncryption, id-RSAES-OAEP OIDS must be supported
    //     - in case of id-RSAES-OAEP OID the parameters field of AlgorithmIdentifier has
    //       to be decoded as RSAES-OAEP-params ASN.1 structure, and the hashAlgorithm field
    //       of that structure has to contain one of id-sha{1,256,384,512} OIDs that match
    //       the specified hash algorithm

    if (CryptoConstants::matches(data, size, CryptoConstants::s_rsaEncryptionIdentifier))
        return true;
    if (CryptoConstants::matches(data, size, CryptoConstants::s_RSAES_OAEPIdentifier))
        return false; // Not yet supported.
    if (CryptoConstants::matches(data, size, CryptoConstants::s_RSASSA_PSSIdentifier))
        return false; // Not yet supported.
    return false;
}

RefPtr<CryptoKeyRSA> CryptoKeyRSA::importSpki(CryptoAlgorithmIdentifier identifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    // Decode the `SubjectPublicKeyInfo` structure using the provided key data.
    PAL::TASN1::Structure spki;
    if (!PAL::TASN1::decodeStructure(&spki, "WebCrypto.SubjectPublicKeyInfo", keyData))
        return nullptr;

    // Validate `algorithm.algorithm`.
    {
        auto algorithm = PAL::TASN1::elementData(spki, "algorithm.algorithm");
        if (!algorithm)
            return nullptr;

        if (!supportedAlgorithmIdentifier(algorithm->data(), algorithm->size()))
            return nullptr;
    }

    // Decode the `RSAPublicKey` structure using the `subjectPublicKey` data.
    PAL::TASN1::Structure rsaPublicKey;
    {
        auto subjectPublicKey = PAL::TASN1::elementData(spki, "subjectPublicKey");
        if (!subjectPublicKey)
            return nullptr;

        if (!PAL::TASN1::decodeStructure(&rsaPublicKey, "WebCrypto.RSAPublicKey", *subjectPublicKey))
            return nullptr;
    }

    // Retrieve the `modulus` and `publicExponent` data and embed it into the `public-key` s-expression.
    PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
    {
        auto modulus = PAL::TASN1::elementData(rsaPublicKey, "modulus");
        auto publicExponent = PAL::TASN1::elementData(rsaPublicKey, "publicExponent");
        if (!modulus || !publicExponent)
            return nullptr;

        gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(public-key(rsa(n %b)(e %b)))",
            modulus->size(), modulus->data(), publicExponent->size(), publicExponent->data());
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }
    }

    return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Public, PlatformRSAKeyContainer(platformKey.release()), extractable, usages));
}

RefPtr<CryptoKeyRSA> CryptoKeyRSA::importPkcs8(CryptoAlgorithmIdentifier identifier, std::optional<CryptoAlgorithmIdentifier> hash, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    // Decode the `PrivateKeyInfo` structure using the provided key data.
    PAL::TASN1::Structure pkcs8;
    if (!PAL::TASN1::decodeStructure(&pkcs8, "WebCrypto.PrivateKeyInfo", keyData))
        return nullptr;

    // Validate `version`.
    {
        auto version = PAL::TASN1::elementData(pkcs8, "version");
        if (!version)
            return nullptr;

        if (!CryptoConstants::matches(version->data(), version->size(), CryptoConstants::s_asn1Version0))
            return nullptr;
    }

    // Validate `privateKeyAlgorithm.algorithm`.
    {
        auto algorithm = PAL::TASN1::elementData(pkcs8, "privateKeyAlgorithm.algorithm");
        if (!algorithm)
            return nullptr;

        if (!supportedAlgorithmIdentifier(algorithm->data(), algorithm->size()))
            return nullptr;
    }

    // Decode the `RSAPrivateKey` structure using the `privateKey` data.
    PAL::TASN1::Structure rsaPrivateKey;
    {
        auto privateKey = PAL::TASN1::elementData(pkcs8, "privateKey");
        if (!privateKey)
            return nullptr;

        if (!PAL::TASN1::decodeStructure(&rsaPrivateKey, "WebCrypto.RSAPrivateKey", *privateKey))
            return nullptr;
    }

    // Validate `privateKey.version`.
    {
        auto version = PAL::TASN1::elementData(rsaPrivateKey, "version");
        if (!version)
            return nullptr;

        if (!CryptoConstants::matches(version->data(), version->size(), CryptoConstants::s_asn1Version0))
            return nullptr;
    }

    // Retrieve the `modulus`, `publicExponent`, `privateExponent`, `prime1`, `prime2`,
    // `exponent1`, `exponent2` and `coefficient` data and embed it into the `public-key` s-expression.
    PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
    {
        auto modulus = PAL::TASN1::elementData(rsaPrivateKey, "modulus");
        auto publicExponent = PAL::TASN1::elementData(rsaPrivateKey, "publicExponent");
        auto privateExponent = PAL::TASN1::elementData(rsaPrivateKey, "privateExponent");
        auto prime1 = PAL::TASN1::elementData(rsaPrivateKey, "prime1");
        auto prime2 = PAL::TASN1::elementData(rsaPrivateKey, "prime2");
        auto exponent1 = PAL::TASN1::elementData(rsaPrivateKey, "exponent1");
        auto exponent2 = PAL::TASN1::elementData(rsaPrivateKey, "exponent2");
        auto coefficient = PAL::TASN1::elementData(rsaPrivateKey, "coefficient");

        if (!modulus || !publicExponent || !privateExponent
            || !prime1 || !prime2 || !exponent1 || !exponent2 || !coefficient)
            return nullptr;

        // libgcrypt inverts the use of p and q parameters, so we have to recalculate the `coefficient` value.
        PAL::GCrypt::Handle<gcry_mpi_t> uMPI(gcry_mpi_new(0));
        {
            PAL::GCrypt::Handle<gcry_mpi_t> pMPI;
            gcry_error_t error = gcry_mpi_scan(&pMPI, GCRYMPI_FMT_USG, prime1->data(), prime1->size(), nullptr);
            if (error != GPG_ERR_NO_ERROR)
                return nullptr;

            PAL::GCrypt::Handle<gcry_mpi_t> qMPI;
            error = gcry_mpi_scan(&qMPI, GCRYMPI_FMT_USG, prime2->data(), prime2->size(), nullptr);
            if (error != GPG_ERR_NO_ERROR)
                return nullptr;

            gcry_mpi_invm(uMPI, qMPI, pMPI);
        }

        gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %M)))",
            modulus->size(), modulus->data(),
            publicExponent->size(), publicExponent->data(),
            privateExponent->size(), privateExponent->data(),
            prime2->size(), prime2->data(), prime1->size(), prime1->data(), uMPI.handle());
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }
    }

    return adoptRef(new CryptoKeyRSA(identifier, hash.value_or(CryptoAlgorithmIdentifier::SHA_1), !!hash, CryptoKeyType::Private, PlatformRSAKeyContainer(platformKey.release()), extractable, usages));
}

ExceptionOr<Vector<uint8_t>> CryptoKeyRSA::exportSpki() const
{
    if (type() != CryptoKeyType::Public)
        return Exception { InvalidAccessError };

    PAL::TASN1::Structure rsaPublicKey;
    {
        // Create the `RSAPublicKey` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.RSAPublicKey", &rsaPublicKey))
            return Exception { OperationError };

        // Retrieve the modulus and public exponent s-expressions.
        PAL::GCrypt::Handle<gcry_sexp_t> modulusSexp(gcry_sexp_find_token(m_platformKey.get(), "n", 0));
        PAL::GCrypt::Handle<gcry_sexp_t> publicExponentSexp(gcry_sexp_find_token(m_platformKey.get(), "e", 0));
        if (!modulusSexp || !publicExponentSexp)
            return Exception { OperationError };

        // Retrieve MPI data for the modulus and public exponent components.
        auto modulus = mpiSignedData(modulusSexp);
        auto publicExponent = mpiSignedData(publicExponentSexp);
        if (!modulus || !publicExponent)
            return Exception { OperationError };

        // Write out the modulus data under `modulus`.
        if (!PAL::TASN1::writeElement(rsaPublicKey, "modulus", modulus->data(), modulus->size()))
            return Exception { OperationError };

        // Write out the public exponent data under `publicExponent`.
        if (!PAL::TASN1::writeElement(rsaPublicKey, "publicExponent", publicExponent->data(), publicExponent->size()))
            return Exception { OperationError };
    }

    PAL::TASN1::Structure spki;
    {
        // Create the `SubjectPublicKeyInfo` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.SubjectPublicKeyInfo", &spki))
            return Exception { OperationError };

        // Write out the id-rsaEncryption identifier under `algorithm.algorithm`.
        // FIXME: In case the key algorithm is:
        // - RSA-PSS:
        //     - this should write out id-RSASSA-PSS, along with setting `algorithm.parameters`
        //       to a RSASSA-PSS-params structure
        // - RSA-OAEP:
        //     - this should write out id-RSAES-OAEP, along with setting `algorithm.parameters`
        //       to a RSAES-OAEP-params structure
        if (!PAL::TASN1::writeElement(spki, "algorithm.algorithm", CryptoConstants::s_rsaEncryptionIdentifier.data(), 1))
            return Exception { OperationError };

        // Write out the null value under `algorithm.parameters`.
        if (!PAL::TASN1::writeElement(spki, "algorithm.parameters", CryptoConstants::s_asn1NullValue.data(), CryptoConstants::s_asn1NullValue.size()))
            return Exception { OperationError };

        // Write out the `RSAPublicKey` data under `subjectPublicKey`. Because this is a
        // bit string parameter, the data size has to be multiplied by 8.
        {
            auto data = PAL::TASN1::encodedData(rsaPublicKey, "");
            if (!data || !PAL::TASN1::writeElement(spki, "subjectPublicKey", data->data(), data->size() * 8))
                return Exception { OperationError };
        }
    }

    // Retrieve the encoded `SubjectPublicKeyInfo` data and return it.
    auto result = PAL::TASN1::encodedData(spki, "");
    if (!result)
        return Exception { OperationError };

    return WTFMove(result.value());
}

ExceptionOr<Vector<uint8_t>> CryptoKeyRSA::exportPkcs8() const
{
    if (type() != CryptoKeyType::Private)
        return Exception { InvalidAccessError };

    PAL::TASN1::Structure rsaPrivateKey;
    {
        // Create the `RSAPrivateKey` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.RSAPrivateKey", &rsaPrivateKey))
            return Exception { OperationError };

        // Write out '0' under `version`.
        if (!PAL::TASN1::writeElement(rsaPrivateKey, "version", "0", 0))
            return Exception { OperationError };

        // Retrieve the `n`, `e`, `d`, `q` and `p` s-expression tokens. libgcrypt swaps the usage of
        // the p and q primes internally, so we adjust the lookup accordingly.
        PAL::GCrypt::Handle<gcry_sexp_t> nSexp(gcry_sexp_find_token(m_platformKey.get(), "n", 0));
        PAL::GCrypt::Handle<gcry_sexp_t> eSexp(gcry_sexp_find_token(m_platformKey.get(), "e", 0));
        PAL::GCrypt::Handle<gcry_sexp_t> dSexp(gcry_sexp_find_token(m_platformKey.get(), "d", 0));
        PAL::GCrypt::Handle<gcry_sexp_t> pSexp(gcry_sexp_find_token(m_platformKey.get(), "q", 0));
        PAL::GCrypt::Handle<gcry_sexp_t> qSexp(gcry_sexp_find_token(m_platformKey.get(), "p", 0));
        if (!nSexp || !eSexp || !dSexp || !pSexp || !qSexp)
            return Exception { OperationError };

        // Write the MPI data of retrieved s-expression tokens under `modulus`, `publicExponent`,
        // `privateExponent`, `prime1` and `prime2`.
        {
            auto modulus = mpiSignedData(nSexp);
            auto publicExponent = mpiSignedData(eSexp);
            auto privateExponent = mpiSignedData(dSexp);
            auto prime1 = mpiSignedData(pSexp);
            auto prime2 = mpiSignedData(qSexp);
            if (!modulus || !publicExponent || !privateExponent || !prime1 || !prime2)
                return Exception { OperationError };

            if (!PAL::TASN1::writeElement(rsaPrivateKey, "modulus", modulus->data(), modulus->size())
                || !PAL::TASN1::writeElement(rsaPrivateKey, "publicExponent", publicExponent->data(), publicExponent->size())
                || !PAL::TASN1::writeElement(rsaPrivateKey, "privateExponent", privateExponent->data(), privateExponent->size())
                || !PAL::TASN1::writeElement(rsaPrivateKey, "prime1", prime1->data(), prime1->size())
                || !PAL::TASN1::writeElement(rsaPrivateKey, "prime2", prime2->data(), prime2->size()))
                return Exception { OperationError };
        }

        // Manually compute the MPI values for the `exponent1`, `exponent2` and `coefficient`
        // parameters. Again note the swapped usage of the `p` and `q` s-expression parameters.
        {
            PAL::GCrypt::Handle<gcry_mpi_t> dMPI(gcry_sexp_nth_mpi(dSexp, 1, GCRYMPI_FMT_USG));
            PAL::GCrypt::Handle<gcry_mpi_t> pMPI(gcry_sexp_nth_mpi(pSexp, 1, GCRYMPI_FMT_USG));
            PAL::GCrypt::Handle<gcry_mpi_t> qMPI(gcry_sexp_nth_mpi(qSexp, 1, GCRYMPI_FMT_USG));
            if (!dMPI || !pMPI || !qMPI)
                return Exception { OperationError };

            // `exponent1`
            {
                PAL::GCrypt::Handle<gcry_mpi_t> dpMPI(gcry_mpi_set_ui(nullptr, 0));
                PAL::GCrypt::Handle<gcry_mpi_t> pm1MPI(gcry_mpi_set(nullptr, pMPI));
                gcry_mpi_sub_ui(pm1MPI, pm1MPI, 1);
                gcry_mpi_mod(dpMPI, dMPI, pm1MPI);

                auto dp = mpiSignedData(dpMPI);
                if (!dp || !PAL::TASN1::writeElement(rsaPrivateKey, "exponent1", dp->data(), dp->size()))
                    return Exception { OperationError };
            }

            // `exponent2`
            {
                PAL::GCrypt::Handle<gcry_mpi_t> dqMPI(gcry_mpi_set_ui(nullptr, 0));
                PAL::GCrypt::Handle<gcry_mpi_t> qm1MPI(gcry_mpi_set(nullptr, qMPI));
                gcry_mpi_sub_ui(qm1MPI, qm1MPI, 1);
                gcry_mpi_mod(dqMPI, dMPI, qm1MPI);

                auto dq = mpiSignedData(dqMPI);
                if (!dq || !PAL::TASN1::writeElement(rsaPrivateKey, "exponent2", dq->data(), dq->size()))
                    return Exception { OperationError };
            }

            // `coefficient`
            {
                PAL::GCrypt::Handle<gcry_mpi_t> qiMPI(gcry_mpi_set_ui(nullptr, 0));
                gcry_mpi_invm(qiMPI, qMPI, pMPI);

                auto qi = mpiSignedData(qiMPI);
                if (!qi || !PAL::TASN1::writeElement(rsaPrivateKey, "coefficient", qi->data(), qi->size()))
                    return Exception { OperationError };
            }
        }

        // Eliminate the optional `otherPrimeInfos` element.
        // FIXME: this should be supported in the future, if there is such information available.
        if (!PAL::TASN1::writeElement(rsaPrivateKey, "otherPrimeInfos", nullptr, 0))
            return Exception { OperationError };
    }

    PAL::TASN1::Structure pkcs8;
    {
        // Create the `PrivateKeyInfo` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.PrivateKeyInfo", &pkcs8))
            return Exception { OperationError };

        // Write out '0' under `version`.
        if (!PAL::TASN1::writeElement(pkcs8, "version", "0", 0))
            return Exception { OperationError };

        // Write out the id-rsaEncryption identifier under `algorithm.algorithm`.
        // FIXME: In case the key algorithm is:
        // - RSA-PSS:
        //     - this should write out id-RSASSA-PSS, along with setting `algorithm.parameters`
        //       to a RSASSA-PSS-params structure
        // - RSA-OAEP:
        //     - this should write out id-RSAES-OAEP, along with setting `algorithm.parameters`
        //       to a RSAES-OAEP-params structure
        if (!PAL::TASN1::writeElement(pkcs8, "privateKeyAlgorithm.algorithm", "1.2.840.113549.1.1.1", 1))
            return Exception { OperationError };

        // Write out a null value under `algorithm.parameters`.
        if (!PAL::TASN1::writeElement(pkcs8, "privateKeyAlgorithm.parameters", CryptoConstants::s_asn1NullValue.data(), CryptoConstants::s_asn1NullValue.size()))
            return Exception { OperationError };

        // Write out the `RSAPrivateKey` data under `privateKey`.
        {
            auto data = PAL::TASN1::encodedData(rsaPrivateKey, "");
            if (!data || !PAL::TASN1::writeElement(pkcs8, "privateKey", data->data(), data->size()))
                return Exception { OperationError };
        }

        // Eliminate the optional `attributes` element.
        if (!PAL::TASN1::writeElement(pkcs8, "attributes", nullptr, 0))
            return Exception { OperationError };
    }

    // Retrieve the encoded `PrivateKeyInfo` data and return it.
    auto result = PAL::TASN1::encodedData(pkcs8, "");
    if (!result)
        return Exception { OperationError };

    return WTFMove(result.value());
}

auto CryptoKeyRSA::algorithm() const -> KeyAlgorithm
{
    auto modulusLength = getRSAModulusLength(m_platformKey.get());
    auto publicExponent = getRSAKeyParameter(m_platformKey.get(), "e");

    if (m_restrictedToSpecificHash) {
        CryptoRsaHashedKeyAlgorithm result;
        result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier());
        result.modulusLength = modulusLength;
        result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size());
        result.hash.name = CryptoAlgorithmRegistry::singleton().name(m_hash);
        return result;
    }

    CryptoRsaKeyAlgorithm result;
    result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier());
    result.modulusLength = modulusLength;
    result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size());
    return result;
}

std::unique_ptr<CryptoKeyRSAComponents> CryptoKeyRSA::exportData() const
{
    switch (type()) {
    case CryptoKeyType::Public:
        return CryptoKeyRSAComponents::createPublic(getRSAKeyParameter(m_platformKey.get(), "n"), getRSAKeyParameter(m_platformKey.get(), "e"));
    case CryptoKeyType::Private: {
        auto parameterMPI =
            [](gcry_sexp_t sexp, const char* name) -> gcry_mpi_t {
                PAL::GCrypt::Handle<gcry_sexp_t> paramSexp(gcry_sexp_find_token(sexp, name, 0));
                if (!paramSexp)
                    return nullptr;
                return gcry_sexp_nth_mpi(paramSexp, 1, GCRYMPI_FMT_USG);
            };

        PAL::GCrypt::Handle<gcry_mpi_t> dMPI(parameterMPI(m_platformKey.get(), "d"));
        // libgcrypt internally uses p and q such that p < q, while usually it's q < p.
        // Switch the two primes here and continue with assuming the latter.
        PAL::GCrypt::Handle<gcry_mpi_t> pMPI(parameterMPI(m_platformKey.get(), "q"));
        PAL::GCrypt::Handle<gcry_mpi_t> qMPI(parameterMPI(m_platformKey.get(), "p"));
        if (!dMPI || !pMPI || !qMPI)
            return nullptr;

        CryptoKeyRSAComponents::PrimeInfo firstPrimeInfo;
        if (auto data = mpiData(pMPI))
            firstPrimeInfo.primeFactor = WTFMove(data.value());

        CryptoKeyRSAComponents::PrimeInfo secondPrimeInfo;
        if (auto data = mpiData(qMPI))
            secondPrimeInfo.primeFactor = WTFMove(data.value());

        // dp -- d mod (p - 1)
        {
            PAL::GCrypt::Handle<gcry_mpi_t> dpMPI(gcry_mpi_new(0));
            PAL::GCrypt::Handle<gcry_mpi_t> pm1MPI(gcry_mpi_new(0));
            gcry_mpi_sub_ui(pm1MPI, pMPI, 1);
            gcry_mpi_mod(dpMPI, dMPI, pm1MPI);

            if (auto data = mpiData(dpMPI))
                firstPrimeInfo.factorCRTExponent = WTFMove(data.value());
        }

        // dq -- d mod (q - 1)
        {
            PAL::GCrypt::Handle<gcry_mpi_t> dqMPI(gcry_mpi_new(0));
            PAL::GCrypt::Handle<gcry_mpi_t> qm1MPI(gcry_mpi_new(0));
            gcry_mpi_sub_ui(qm1MPI, qMPI, 1);
            gcry_mpi_mod(dqMPI, dMPI, qm1MPI);

            if (auto data = mpiData(dqMPI))
                secondPrimeInfo.factorCRTExponent = WTFMove(data.value());
        }

        // qi -- q^(-1) mod p
        {
            PAL::GCrypt::Handle<gcry_mpi_t> qiMPI(gcry_mpi_new(0));
            gcry_mpi_invm(qiMPI, qMPI, pMPI);

            if (auto data = mpiData(qiMPI))
                secondPrimeInfo.factorCRTCoefficient = WTFMove(data.value());
        }

        Vector<uint8_t> privateExponent;
        if (auto data = mpiData(dMPI))
            privateExponent = WTFMove(data.value());

        return CryptoKeyRSAComponents::createPrivateWithAdditionalData(
            getRSAKeyParameter(m_platformKey.get(), "n"), getRSAKeyParameter(m_platformKey.get(), "e"), WTFMove(privateExponent),
            WTFMove(firstPrimeInfo), WTFMove(secondPrimeInfo), Vector<CryptoKeyRSAComponents::PrimeInfo> { });
    }
    default:
        ASSERT_NOT_REACHED();
        return nullptr;
    }
}

} // namespace WebCore

#endif // ENABLE(WEB_CRYPTO)
