/*
 * Copyright (C) 2017-2019 Apple Inc. 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 "CryptoKeyEC.h"

#if ENABLE(WEB_CRYPTO)

#include "CryptoKeyPair.h"
#include "GCryptUtilities.h"
#include "JsonWebKey.h"
#include <pal/crypto/gcrypt/Utilities.h>
#include <pal/crypto/tasn1/Utilities.h>
#include <wtf/text/Base64.h>

namespace WebCore {

static const char* curveName(CryptoKeyEC::NamedCurve curve)
{
    switch (curve) {
    case CryptoKeyEC::NamedCurve::P256:
        return "NIST P-256";
    case CryptoKeyEC::NamedCurve::P384:
        return "NIST P-384";
    case CryptoKeyEC::NamedCurve::P521:
        return "NIST P-521";
    }

    ASSERT_NOT_REACHED();
    return nullptr;
}

static const uint8_t* curveIdentifier(CryptoKeyEC::NamedCurve curve)
{
    switch (curve) {
    case CryptoKeyEC::NamedCurve::P256:
        return CryptoConstants::s_secp256r1Identifier.data();
    case CryptoKeyEC::NamedCurve::P384:
        return CryptoConstants::s_secp384r1Identifier.data();
    case CryptoKeyEC::NamedCurve::P521:
        return CryptoConstants::s_secp521r1Identifier.data();
    }

    ASSERT_NOT_REACHED();
    return nullptr;
}

static size_t curveSize(CryptoKeyEC::NamedCurve curve)
{
    switch (curve) {
    case CryptoKeyEC::NamedCurve::P256:
        return 256;
    case CryptoKeyEC::NamedCurve::P384:
        return 384;
    case CryptoKeyEC::NamedCurve::P521:
        return 521;
    }

    ASSERT_NOT_REACHED();
    return 0;
}

static unsigned curveUncompressedFieldElementSize(CryptoKeyEC::NamedCurve curve)
{
    switch (curve) {
    case CryptoKeyEC::NamedCurve::P256:
        return 32;
    case CryptoKeyEC::NamedCurve::P384:
        return 48;
    case CryptoKeyEC::NamedCurve::P521:
        return 66;
    }

    ASSERT_NOT_REACHED();
    return 0;
}

static unsigned curveUncompressedPointSize(CryptoKeyEC::NamedCurve curve)
{
    return 2 * curveUncompressedFieldElementSize(curve) + 1;
}

size_t CryptoKeyEC::keySizeInBits() const
{
    size_t size = curveSize(m_curve);
    ASSERT(size == gcry_pk_get_nbits(m_platformKey.get()));
    return size;
}

bool CryptoKeyEC::platformSupportedCurve(NamedCurve curve)
{
    return curve == NamedCurve::P256 || curve == NamedCurve::P384 || curve == NamedCurve::P521;
}

std::optional<CryptoKeyPair> CryptoKeyEC::platformGeneratePair(CryptoAlgorithmIdentifier identifier, NamedCurve curve, bool extractable, CryptoKeyUsageBitmap usages)
{
    PAL::GCrypt::Handle<gcry_sexp_t> genkeySexp;
    gcry_error_t error = gcry_sexp_build(&genkeySexp, nullptr, "(genkey(ecc(curve %s)))", curveName(curve));
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return std::nullopt;
    }

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

    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)
        return std::nullopt;

    auto publicKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Public, PlatformECKeyContainer(publicKeySexp.release()), true, usages);
    auto privateKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Private, PlatformECKeyContainer(privateKeySexp.release()), extractable, usages);
    return CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) };
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportRaw(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    if (keyData.size() != curveUncompressedPointSize(curve))
        return nullptr;

    PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
    gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(public-key(ecc(curve %s)(q %b)))",
        curveName(curve), keyData.size(), keyData.data());
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return nullptr;
    }

    return create(identifier, curve, CryptoKeyType::Public, PlatformECKeyContainer(platformKey.release()), extractable, usages);
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPublic(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, bool extractable, CryptoKeyUsageBitmap usages)
{
    unsigned uncompressedFieldElementSize = curveUncompressedFieldElementSize(curve);
    if (x.size() != uncompressedFieldElementSize || y.size() != uncompressedFieldElementSize)
        return nullptr;

    // Construct the Vector that represents the EC point in uncompressed format.
    Vector<uint8_t> q;
    q.reserveInitialCapacity(curveUncompressedPointSize(curve));
    q.append(CryptoConstants::s_ecUncompressedFormatLeadingByte.data(), CryptoConstants::s_ecUncompressedFormatLeadingByte.size());
    q.appendVector(x);
    q.appendVector(y);

    PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
    gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(public-key(ecc(curve %s)(q %b)))",
        curveName(curve), q.size(), q.data());
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return nullptr;
    }

    return create(identifier, curve, CryptoKeyType::Public, PlatformECKeyContainer(platformKey.release()), extractable, usages);
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPrivate(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, Vector<uint8_t>&& d, bool extractable, CryptoKeyUsageBitmap usages)
{
    unsigned uncompressedFieldElementSize = curveUncompressedFieldElementSize(curve);
    if (x.size() != uncompressedFieldElementSize || y.size() != uncompressedFieldElementSize || d.size() != uncompressedFieldElementSize)
        return nullptr;

    // Construct the Vector that represents the EC point in uncompressed format.
    Vector<uint8_t> q;
    q.reserveInitialCapacity(curveUncompressedPointSize(curve));
    q.append(CryptoConstants::s_ecUncompressedFormatLeadingByte.data(), CryptoConstants::s_ecUncompressedFormatLeadingByte.size());
    q.appendVector(x);
    q.appendVector(y);

    PAL::GCrypt::Handle<gcry_sexp_t> platformKey;
    gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(private-key(ecc(curve %s)(q %b)(d %b)))",
        curveName(curve), q.size(), q.data(), d.size(), d.data());
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return nullptr;
    }

    return create(identifier, curve, CryptoKeyType::Private, PlatformECKeyContainer(platformKey.release()), extractable, usages);
}

static bool supportedAlgorithmIdentifier(CryptoAlgorithmIdentifier keyIdentifier, const Vector<uint8_t>& identifier)
{
    auto* data = identifier.data();
    auto size = identifier.size();

    switch (keyIdentifier) {
    case CryptoAlgorithmIdentifier::ECDSA:
        // ECDSA only supports id-ecPublicKey algorithms for imported keys.
        if (CryptoConstants::matches(data, size, CryptoConstants::s_ecPublicKeyIdentifier))
            return true;
        return false;
    case CryptoAlgorithmIdentifier::ECDH:
        // ECDH supports both id-ecPublicKey and ic-ecDH algorithms for imported keys.
        if (CryptoConstants::matches(data, size, CryptoConstants::s_ecPublicKeyIdentifier))
            return true;
        if (CryptoConstants::matches(data, size, CryptoConstants::s_ecDHIdentifier))
            return true;
        return false;
    default:
        ASSERT_NOT_REACHED();
        break;
    }

    return false;
}

static std::optional<CryptoKeyEC::NamedCurve> curveForIdentifier(const Vector<uint8_t>& identifier)
{
    auto* data = identifier.data();
    auto size = identifier.size();

    if (CryptoConstants::matches(data, size, CryptoConstants::s_secp256r1Identifier))
        return CryptoKeyEC::NamedCurve::P256;
    if (CryptoConstants::matches(data, size, CryptoConstants::s_secp384r1Identifier))
        return CryptoKeyEC::NamedCurve::P384;
    if (CryptoConstants::matches(data, size, CryptoConstants::s_secp521r1Identifier))
        return CryptoKeyEC::NamedCurve::P521;

    return std::nullopt;
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier identifier, NamedCurve curve, 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(identifier, *algorithm))
            return nullptr;
    }

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

        // Decode the `ECParameters` structure using the `algorithm.parameters` data.
        PAL::TASN1::Structure ecParameters;
        if (!PAL::TASN1::decodeStructure(&ecParameters, "WebCrypto.ECParameters", *parameters))
            return nullptr;

        auto namedCurve = PAL::TASN1::elementData(ecParameters, "namedCurve");
        if (!namedCurve)
            return nullptr;

        auto parameterCurve = curveForIdentifier(*namedCurve);
        if (!parameterCurve || *parameterCurve != curve)
            return nullptr;
    }

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

        // Bail if the `subjectPublicKey` data size doesn't match the size of an uncompressed point
        // for this curve, or if the first byte in the `subjectPublicKey` data isn't 0x04, as required
        // for an uncompressed EC point encoded in an octet string.
        if (subjectPublicKey->size() != curveUncompressedPointSize(curve)
            || !CryptoConstants::matches(subjectPublicKey->data(), 1, CryptoConstants::s_ecUncompressedFormatLeadingByte))
            return nullptr;

        // Convert X and Y coordinate data into MPIs.
        unsigned coordinateSize = curveUncompressedFieldElementSize(curve);
        PAL::GCrypt::Handle<gcry_mpi_t> xMPI, yMPI;
        {
            gcry_error_t error = gcry_mpi_scan(&xMPI, GCRYMPI_FMT_USG, &subjectPublicKey->at(1), coordinateSize, nullptr);
            if (error != GPG_ERR_NO_ERROR) {
                PAL::GCrypt::logError(error);
                return nullptr;
            }

            error = gcry_mpi_scan(&yMPI, GCRYMPI_FMT_USG, &subjectPublicKey->at(1 + coordinateSize), coordinateSize, nullptr);
            if (error != GPG_ERR_NO_ERROR) {
                PAL::GCrypt::logError(error);
                return nullptr;
            }
        }

        // Construct an MPI point from the X and Y coordinates and using 1 as the Z coordinate.
        // This always allocates the gcry_mpi_point_t object.
        PAL::GCrypt::Handle<gcry_mpi_point_t> point(gcry_mpi_point_set(nullptr, xMPI, yMPI, GCRYMPI_CONST_ONE));

        // Create an EC context for the specified curve.
        PAL::GCrypt::Handle<gcry_ctx_t> context;
        gcry_error_t error = gcry_mpi_ec_new(&context, nullptr, curveName(curve));
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }

        // Bail if the constructed MPI point is not on the specified EC curve.
        if (!gcry_mpi_ec_curve_point(point, context))
            return nullptr;

        error = gcry_sexp_build(&platformKey, nullptr, "(public-key(ecc(curve %s)(q %b)))",
            curveName(curve), subjectPublicKey->size(), subjectPublicKey->data());
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }
    }

    // Finally create a new CryptoKeyEC object, transferring to it ownership of the `public-key` s-expression.
    return create(identifier, curve, CryptoKeyType::Public, PlatformECKeyContainer(platformKey.release()), extractable, usages);
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier identifier, NamedCurve curve, 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(identifier, *algorithm))
            return nullptr;
    }

    // Validate `privateKeyAlgorithm.parameters` and therein embedded `ECParameters`.
    {
        auto parameters = PAL::TASN1::elementData(pkcs8, "privateKeyAlgorithm.parameters");
        if (!parameters)
            return nullptr;

        PAL::TASN1::Structure ecParameters;
        if (!PAL::TASN1::decodeStructure(&ecParameters, "WebCrypto.ECParameters", *parameters))
            return nullptr;

        auto namedCurve = PAL::TASN1::elementData(ecParameters, "namedCurve");
        if (!namedCurve)
            return nullptr;

        auto parameterCurve = curveForIdentifier(*namedCurve);
        if (!parameterCurve || *parameterCurve != curve)
            return nullptr;
    }

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

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

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

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

    // Validate `privateKey.parameters.namedCurve`, if any.
    {
        auto namedCurve = PAL::TASN1::elementData(ecPrivateKey, "parameters.namedCurve");
        if (namedCurve) {
            auto parameterCurve = curveForIdentifier(*namedCurve);
            if (!parameterCurve || *parameterCurve != curve)
                return nullptr;
        }
    }

    // Validate `privateKey.publicKey`, if any, and scan the data into an MPI.
    PAL::GCrypt::Handle<gcry_mpi_t> publicKeyMPI;
    {
        auto publicKey = PAL::TASN1::elementData(ecPrivateKey, "publicKey");
        if (publicKey) {
            if (publicKey->size() != curveUncompressedPointSize(curve)
                || !CryptoConstants::matches(publicKey->data(), 1, CryptoConstants::s_ecUncompressedFormatLeadingByte))
                return nullptr;

            gcry_error_t error = gcry_mpi_scan(&publicKeyMPI, GCRYMPI_FMT_USG, publicKey->data(), publicKey->size(), nullptr);
            if (error != GPG_ERR_NO_ERROR) {
                PAL::GCrypt::logError(error);
                return nullptr;
            }
        }
    }

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

        // Validate the size of `privateKey`, making sure it fits the byte-size of the specified EC curve.
        if (privateKey->size() != (curveSize(curve) + 7) / 8)
            return nullptr;

        // Construct the `private-key` expression that will also be used for the EC context.
        gcry_error_t error = gcry_sexp_build(&platformKey, nullptr, "(private-key(ecc(curve %s)(d %b)))",
            curveName(curve), privateKey->size(), privateKey->data());
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }

        // Create an EC context for the specified curve.
        PAL::GCrypt::Handle<gcry_ctx_t> context;
        error = gcry_mpi_ec_new(&context, platformKey, nullptr);
        if (error != GPG_ERR_NO_ERROR) {
            PAL::GCrypt::logError(error);
            return nullptr;
        }

        // Set the 'q' value on the EC context if public key data was provided through the import.
        if (publicKeyMPI) {
            error = gcry_mpi_ec_set_mpi("q", publicKeyMPI, context);
            if (error != GPG_ERR_NO_ERROR) {
                PAL::GCrypt::logError(error);
                return nullptr;
            }
        }

        // Retrieve the `q` point. If the public key was provided through the PKCS#8 import, that
        // key value will be retrieved as an gcry_mpi_point_t. Otherwise, the `q` point value will
        // be computed on-the-fly by libgcrypt for the specified elliptic curve.
        PAL::GCrypt::Handle<gcry_mpi_point_t> point(gcry_mpi_ec_get_point("q", context, 1));
        if (!point)
            return nullptr;

        // Bail if the retrieved `q` MPI point is not on the specified EC curve.
        if (!gcry_mpi_ec_curve_point(point, context))
            return nullptr;
    }

    return create(identifier, curve, CryptoKeyType::Private, PlatformECKeyContainer(platformKey.release()), extractable, usages);
}

Vector<uint8_t> CryptoKeyEC::platformExportRaw() const
{
    PAL::GCrypt::Handle<gcry_ctx_t> context;
    gcry_error_t error = gcry_mpi_ec_new(&context, m_platformKey.get(), nullptr);
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return { };
    }

    PAL::GCrypt::Handle<gcry_mpi_t> qMPI(gcry_mpi_ec_get_mpi("q", context, 0));
    if (!qMPI)
        return { };

    auto q = mpiData(qMPI);
    if (!q || q->size() != curveUncompressedPointSize(m_curve))
        return { };

    return WTFMove(q.value());
}

bool CryptoKeyEC::platformAddFieldElements(JsonWebKey& jwk) const
{
    PAL::GCrypt::Handle<gcry_ctx_t> context;
    gcry_error_t error = gcry_mpi_ec_new(&context, m_platformKey.get(), nullptr);
    if (error != GPG_ERR_NO_ERROR) {
        PAL::GCrypt::logError(error);
        return false;
    }

    unsigned uncompressedFieldElementSize = curveUncompressedFieldElementSize(m_curve);

    PAL::GCrypt::Handle<gcry_mpi_t> qMPI(gcry_mpi_ec_get_mpi("q", context, 0));
    if (qMPI) {
        auto q = mpiData(qMPI);
        if (q && q->size() == curveUncompressedPointSize(m_curve)) {
            jwk.x = base64URLEncodeToString(Vector<uint8_t> { q->data() + 1, uncompressedFieldElementSize });
            jwk.y = base64URLEncodeToString(Vector<uint8_t> { q->data() + 1 + uncompressedFieldElementSize, uncompressedFieldElementSize });
        }
    }

    if (type() == Type::Private) {
        PAL::GCrypt::Handle<gcry_mpi_t> dMPI(gcry_mpi_ec_get_mpi("d", context, 0));
        if (dMPI) {
            auto d = mpiData(dMPI);
            if (d && d->size() <= uncompressedFieldElementSize) {
                // Zero-pad the private key data up to the field element size, if necessary.
                if (d->size() < uncompressedFieldElementSize) {
                    Vector<uint8_t> paddedData(uncompressedFieldElementSize - d->size(), 0);
                    paddedData.appendVector(*d);
                    *d = WTFMove(paddedData);
                }

                jwk.d = base64URLEncodeToString(*d);
            }
        }
    }

    return true;
}

Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
{
    PAL::TASN1::Structure ecParameters;
    {
        // Create the `ECParameters` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.ECParameters", &ecParameters))
            return { };

        // Select the `namedCurve` object identifier as the target `ECParameters` choice.
        if (!PAL::TASN1::writeElement(ecParameters, "", "namedCurve", 1))
            return { };

        // Write out the EC curve identifier under `namedCurve`.
        if (!PAL::TASN1::writeElement(ecParameters, "namedCurve", curveIdentifier(m_curve), 1))
            return { };
    }

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

        // Write out the id-ecPublicKey identifier under `algorithm.algorithm`.
        // FIXME: Per specification this should write out id-ecDH when the ECDH algorithm
        // is specified for this CryptoKeyEC object, but not even the W3C tests expect that.
        if (!PAL::TASN1::writeElement(spki, "algorithm.algorithm", CryptoConstants::s_ecPublicKeyIdentifier.data(), 1))
            return { };

        // Write out the `ECParameters` data under `algorithm.parameters`.
        {
            auto data = PAL::TASN1::encodedData(ecParameters, "");
            if (!data || !PAL::TASN1::writeElement(spki, "algorithm.parameters", data->data(), data->size()))
                return { };
        }

        // Retrieve the `q` s-expression, which should contain the public key data.
        PAL::GCrypt::Handle<gcry_sexp_t> qSexp(gcry_sexp_find_token(m_platformKey.get(), "q", 0));
        if (!qSexp)
            return { };

        // Retrieve the `q` data, which should be in the uncompressed point format.
        // Validate the data size and the first byte (which should be 0x04).
        auto qData = mpiData(qSexp);
        if (!qData || qData->size() != curveUncompressedPointSize(m_curve)
            || !CryptoConstants::matches(qData->data(), 1, CryptoConstants::s_ecUncompressedFormatLeadingByte))
            return { };

        // Write out the public key data under `subjectPublicKey`. Because this is a
        // bit string parameter, the data size has to be multiplied by 8.
        if (!PAL::TASN1::writeElement(spki, "subjectPublicKey", qData->data(), qData->size() * 8))
            return { };
    }

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

    return WTFMove(result.value());
}

Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
{
    PAL::TASN1::Structure ecParameters;
    {
        // Create the `ECParameters` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.ECParameters", &ecParameters))
            return { };

        // Select the `namedCurve` object identifier as the target `ECParameters` choice.
        if (!PAL::TASN1::writeElement(ecParameters, "", "namedCurve", 1))
            return { };

        // Write out the EC curve identifier under `namedCurve`.
        if (!PAL::TASN1::writeElement(ecParameters, "namedCurve", curveIdentifier(m_curve), 1))
            return { };
    }

    PAL::TASN1::Structure ecPrivateKey;
    {
        // Create the `ECPrivateKey` structure.
        if (!PAL::TASN1::createStructure("WebCrypto.ECPrivateKey", &ecPrivateKey))
            return { };

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

        // Construct the EC context that we'll use to retrieve private and public key data.
        PAL::GCrypt::Handle<gcry_ctx_t> context;
        gcry_error_t error = gcry_mpi_ec_new(&context, m_platformKey.get(), nullptr);
        if (error != GPG_ERR_NO_ERROR)
            return { };

        {
            // Retrieve the `d` MPI that holds the private key data.
            PAL::GCrypt::Handle<gcry_mpi_t> dMPI(gcry_mpi_ec_get_mpi("d", context, 0));
            if (!dMPI)
                return { };

            unsigned uncompressedFieldElementSize = curveUncompressedFieldElementSize(m_curve);

            // Retrieve the `d` MPI data.
            auto data = mpiData(dMPI);
            if (!data || data->size() > uncompressedFieldElementSize)
                return { };

            // Zero-pad the private key data up to the field element size, if necessary.
            if (data->size() < uncompressedFieldElementSize) {
                Vector<uint8_t> paddedData(uncompressedFieldElementSize - data->size(), 0);
                paddedData.appendVector(*data);
                *data = WTFMove(paddedData);
            }

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

        // Eliminate the optional `parameters` element.
        if (!PAL::TASN1::writeElement(ecPrivateKey, "parameters", nullptr, 0))
            return { };

        {
            // Retrieve the `q` MPI that holds the public key data.
            PAL::GCrypt::Handle<gcry_mpi_t> qMPI(gcry_mpi_ec_get_mpi("q", context, 0));
            if (!qMPI)
                return { };

            // Retrieve the MPI data and write it out under `publicKey`. Because this is a
            // bit string parameter, the data size has to be multiplied by 8.
            auto data = mpiData(qMPI);
            if (!data || !PAL::TASN1::writeElement(ecPrivateKey, "publicKey", data->data(), data->size() * 8))
                return { };
        }
    }

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

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

        // Write out the id-ecPublicKey identifier under `privateKeyAlgorithm.algorithm`.
        // FIXME: Per specification this should write out id-ecDH when the ECDH algorithm
        // is specified for this CryptoKeyEC object, but not even the W3C tests expect that.
        if (!PAL::TASN1::writeElement(pkcs8, "privateKeyAlgorithm.algorithm", CryptoConstants::s_ecPublicKeyIdentifier.data(), 1))
            return { };

        // Write out the `ECParameters` data under `privateKeyAlgorithm.parameters`.
        {
            auto data = PAL::TASN1::encodedData(ecParameters, "");
            if (!data || !PAL::TASN1::writeElement(pkcs8, "privateKeyAlgorithm.parameters", data->data(), data->size()))
                return { };
        }

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

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

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

    return WTFMove(result.value());
}

} // namespace WebCore

#endif // ENABLE(WEB_CRYPTO)
