/*
 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
 *
 * 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 "JsonWebKey.h"
#include "OpenSSLUtilities.h"
#include <wtf/text/Base64.h>

namespace WebCore {

static int curveIdentifier(CryptoKeyEC::NamedCurve curve)
{
    switch (curve) {
    case CryptoKeyEC::NamedCurve::P256:
        return NID_X9_62_prime256v1;
    case CryptoKeyEC::NamedCurve::P384:
        return NID_secp384r1;
    case CryptoKeyEC::NamedCurve::P521:
        return NID_secp521r1;
    }

    ASSERT_NOT_REACHED();
    return NID_undef;
}

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 ECKeyPtr createECKey(CryptoKeyEC::NamedCurve curve)
{
    auto key = ECKeyPtr(EC_KEY_new_by_curve_name(curveIdentifier(curve)));
    if (key) {
        // OPENSSL_EC_NAMED_CURVE needs to be set to export the key with the curve name, not with the curve parameters.
        EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE);
    }
    return key;
}

// This function verifies that the group represents the named curve.
static bool verifyCurve(const EC_GROUP* group, CryptoKeyEC::NamedCurve curve)
{
    if (!group)
        return false;

    auto key = createECKey(curve);
    if (!key)
        return false;

    return !EC_GROUP_cmp(group, EC_KEY_get0_group(key.get()), nullptr);
}

size_t CryptoKeyEC::keySizeInBits() const
{
    // EVP_PKEY_size() returns the size of DER-encoded key and cannot be used for this function's purpose.
    // Instead we resolve the key size by CryptoKeyEC::NamedCurve.
    size_t size = curveSize(m_curve);
    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)
{
    // To generate a key pair, we generate a private key and extract the public key from the private key.
    auto privateECKey = createECKey(curve);
    if (!privateECKey)
        return std::nullopt;

    if (EC_KEY_generate_key(privateECKey.get()) <= 0)
        return std::nullopt;

    auto point = ECPointPtr(EC_POINT_dup(EC_KEY_get0_public_key(privateECKey.get()), EC_KEY_get0_group(privateECKey.get())));
    if (!point)
        return std::nullopt;

    auto publicECKey = createECKey(curve);
    if (!publicECKey)
        return std::nullopt;

    if (EC_KEY_set_public_key(publicECKey.get(), point.get()) <= 0)
        return std::nullopt;

    auto privatePKey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(privatePKey.get(), privateECKey.get()) <= 0)
        return std::nullopt;

    auto publicPKey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(publicPKey.get(), publicECKey.get()) <= 0)
        return std::nullopt;

    auto publicKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Public, WTFMove(publicPKey), true, usages);
    auto privateKey = CryptoKeyEC::create(identifier, curve, CryptoKeyType::Private, WTFMove(privatePKey), extractable, usages);
    return CryptoKeyPair { WTFMove(publicKey), WTFMove(privateKey) };
}

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

    auto group = EC_KEY_get0_group(key.get());
    auto point = ECPointPtr(EC_POINT_new(group));
    // Load an EC point from the keyData. This point is used as a public key.
    if (EC_POINT_oct2point(group, point.get(), keyData.data(), keyData.size(), nullptr) <= 0)
        return nullptr;

    if (EC_KEY_set_public_key(key.get(), point.get()) <= 0)
        return nullptr;

    if (EC_KEY_check_key(key.get()) <= 0)
        return nullptr;

    auto pkey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0)
        return nullptr;

    return create(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), extractable, usages);
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportJWKPublic(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& x, Vector<uint8_t>&& y, bool extractable, CryptoKeyUsageBitmap usages)
{
    auto key = createECKey(curve);
    if (!key)
        return nullptr;

    auto group = EC_KEY_get0_group(key.get());
    auto point = ECPointPtr(EC_POINT_new(group));

    // Currently we only support elliptic curves over GF(p).   
    if (EC_POINT_set_affine_coordinates_GFp(group, point.get(), BIGNUMPtr(convertToBigNumber(nullptr, x)).get(), BIGNUMPtr(convertToBigNumber(nullptr, y)).get(), nullptr) <= 0)
        return nullptr;

    if (EC_KEY_set_public_key(key.get(), point.get()) <= 0)
        return nullptr;

    if (EC_KEY_check_key(key.get()) <= 0)
        return nullptr;

    auto pkey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0)
        return nullptr;

    return create(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), 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)
{
    auto key = createECKey(curve);
    if (!key)
        return nullptr;

    auto group = EC_KEY_get0_group(key.get());
    auto point = ECPointPtr(EC_POINT_new(group));

    // Currently we only support elliptic curves over GF(p).   
    if (EC_POINT_set_affine_coordinates_GFp(group, point.get(), BIGNUMPtr(convertToBigNumber(nullptr, x)).get(), BIGNUMPtr(convertToBigNumber(nullptr, y)).get(), nullptr) <= 0)
        return nullptr;

    if (EC_KEY_set_public_key(key.get(), point.get()) <= 0)
        return nullptr;

    if (EC_KEY_set_private_key(key.get(), BIGNUMPtr(convertToBigNumber(nullptr, d)).get()) <= 0)
        return nullptr;

    if (EC_KEY_check_key(key.get()) <= 0)
        return nullptr;

    auto pkey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0)
        return nullptr;

    return create(identifier, curve, CryptoKeyType::Private, WTFMove(pkey), extractable, usages);
}

static const ASN1_OBJECT* ecPublicKeyIdentifier()
{
    static ASN1_OBJECT* oid = OBJ_txt2obj("1.2.840.10045.2.1", 1);
    return oid;
}

static const ASN1_OBJECT* ecDHIdentifier()
{
    static ASN1_OBJECT* oid = OBJ_txt2obj("1.3.132.1.12", 1);
    return oid;
}

static bool supportedAlgorithmIdentifier(CryptoAlgorithmIdentifier identifier, const ASN1_OBJECT* oid)
{
    switch (identifier) {
    case CryptoAlgorithmIdentifier::ECDSA:
        // ECDSA only supports id-ecPublicKey algorithms for imported keys.
        if (!OBJ_cmp(oid, ecPublicKeyIdentifier()))
            return true;
        return false;
    case CryptoAlgorithmIdentifier::ECDH:
        // ECDH supports both id-ecPublicKey and id-ecDH algorithms for imported keys.
        if (!OBJ_cmp(oid, ecPublicKeyIdentifier()))
            return true;
        if (!OBJ_cmp(oid, ecDHIdentifier()))
            return true;
        return false;
    default:
        ASSERT_NOT_REACHED();
        return false;
    }
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportSpki(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    // In this function we extract the subjectPublicKey after verifying that the algorithm in the SPKI data
    // match the given identifier and curve. Then construct an EC key with the named curve and set the public key.

    // SubjectPublicKeyInfo  ::=  SEQUENCE  {
    //   algorithm         AlgorithmIdentifier,
    //   subjectPublicKey  BIT STRING
    // }

    const uint8_t* ptr = keyData.data();
    auto subjectPublicKeyInfo = ASN1SequencePtr(d2i_ASN1_SEQUENCE_ANY(nullptr, &ptr, keyData.size()));
    if (!subjectPublicKeyInfo)
        return nullptr;
    if (ptr - keyData.data() != (ptrdiff_t)keyData.size())
        return nullptr;

    if (sk_ASN1_TYPE_num(subjectPublicKeyInfo.get()) != 2)
        return nullptr;

    ASN1_TYPE* value = sk_ASN1_TYPE_value(subjectPublicKeyInfo.get(), 0);
    if (value->type != V_ASN1_SEQUENCE)
        return nullptr;

    // AlgorithmIdentifier  ::=  SEQUENCE  {
    //     algorithm   OBJECT IDENTIFIER,
    //     parameters  ANY DEFINED BY algorithm OPTIONAL
    // }

    ptr = value->value.sequence->data;
    auto algorithm = ASN1SequencePtr(d2i_ASN1_SEQUENCE_ANY(nullptr, &ptr, value->value.sequence->length));
    if (!algorithm)
        return nullptr;

    if (sk_ASN1_TYPE_num(algorithm.get()) != 2)
        return nullptr;

    value = sk_ASN1_TYPE_value(algorithm.get(), 0);
    if (value->type != V_ASN1_OBJECT)
        return nullptr;
    
    if (!supportedAlgorithmIdentifier(identifier, value->value.object))
        return nullptr;

    // ECParameters ::= CHOICE {
    //  namedCurve         OBJECT IDENTIFIER
    //  -- implicitCurve   null
    //  -- specifiedCurve  SpecifiedECDomain
    // }
    //
    // Only "namedCurve" is supported. 
    value = sk_ASN1_TYPE_value(algorithm.get(), 1);
    if (value->type != V_ASN1_OBJECT)
        return nullptr;

    int curveNID = OBJ_obj2nid(value->value.object);
    if (curveNID != curveIdentifier(curve))
        return nullptr;
    
    // subjectPublicKey must be a BIT STRING.
    value = sk_ASN1_TYPE_value(subjectPublicKeyInfo.get(), 1);
    if (value->type != V_ASN1_BIT_STRING)
        return nullptr;

    ASN1_BIT_STRING* bitString = value->value.bit_string;

    // The SPKI data has been verified at this point. We prepare platform data next.
    auto key = createECKey(curve);
    if (!key)
        return nullptr;

    auto group = EC_KEY_get0_group(key.get());
    if (!group)
        return nullptr;

    auto point = ECPointPtr(EC_POINT_new(group));
    if (!point)
        return nullptr;

    if (EC_POINT_oct2point(group, point.get(), bitString->data, bitString->length, 0) <= 0)
        return nullptr;

    if (EC_KEY_set_public_key(key.get(), point.get()) <= 0)
        return nullptr;

    if (EC_KEY_check_key(key.get()) <= 0)
        return nullptr;

    EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE);

    auto pkey = EvpPKeyPtr(EVP_PKEY_new());
    if (EVP_PKEY_set1_EC_KEY(pkey.get(), key.get()) <= 0)
        return nullptr;

    return adoptRef(new CryptoKeyEC(identifier, curve, CryptoKeyType::Public, WTFMove(pkey), extractable, usages));
}

RefPtr<CryptoKeyEC> CryptoKeyEC::platformImportPkcs8(CryptoAlgorithmIdentifier identifier, NamedCurve curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap usages)
{
    // We need a local pointer variable to pass to d2i (DER to internal) functions().
    const uint8_t* ptr = keyData.data();

    // We use d2i_PKCS8_PRIV_KEY_INFO() to import a private key.
    auto p8inf = PKCS8PrivKeyInfoPtr(d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, keyData.size()));
    if (!p8inf)
        return nullptr;
    if (ptr - keyData.data() != (ptrdiff_t)keyData.size())
        return nullptr;

    auto pkey = EvpPKeyPtr(EVP_PKCS82PKEY(p8inf.get()));
    if (!pkey || EVP_PKEY_type(pkey->type) != EVP_PKEY_EC)
        return nullptr;

    auto ecKey = EVP_PKEY_get0_EC_KEY(pkey.get());
    if (!ecKey)
        return nullptr;

    if (EC_KEY_check_key(ecKey) <= 0)
        return nullptr;

    if (!verifyCurve(EC_KEY_get0_group(ecKey), curve))
        return nullptr;

    EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE);

    return adoptRef(new CryptoKeyEC(identifier, curve, CryptoKeyType::Private, WTFMove(pkey), extractable, usages));
}

Vector<uint8_t> CryptoKeyEC::platformExportRaw() const
{
    EC_KEY* key = EVP_PKEY_get0_EC_KEY(platformKey());
    if (!key)
        return { };
    
    const EC_POINT* point = EC_KEY_get0_public_key(key);
    const EC_GROUP* group = EC_KEY_get0_group(key);
    size_t keyDataSize = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
    if (!keyDataSize)
        return { };

    Vector<uint8_t> keyData(keyDataSize);
    if (EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, keyData.data(), keyData.size(), nullptr) != keyDataSize)
        return { };

    return keyData;
}

bool CryptoKeyEC::platformAddFieldElements(JsonWebKey& jwk) const
{
    size_t keySizeInBytes = (keySizeInBits() + 7) / 8;

    EC_KEY* key = EVP_PKEY_get0_EC_KEY(platformKey());
    if (!key)
        return false;

    const EC_POINT* publicKey = EC_KEY_get0_public_key(key);
    if (publicKey) {
        auto ctx = BNCtxPtr(BN_CTX_new());
        auto x = BIGNUMPtr(BN_new());
        auto y = BIGNUMPtr(BN_new());
        if (1 == EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key), publicKey, x.get(), y.get(), ctx.get())) {
            jwk.x = base64URLEncodeToString(convertToBytesExpand(x.get(), keySizeInBytes));
            jwk.y = base64URLEncodeToString(convertToBytesExpand(y.get(), keySizeInBytes));
        }
    }

    if (type() == Type::Private) {
        const BIGNUM* privateKey = EC_KEY_get0_private_key(key);
        if (privateKey)
            jwk.d = base64URLEncodeToString(convertToBytes(privateKey));
    }
    return true;
}

Vector<uint8_t> CryptoKeyEC::platformExportSpki() const
{
    if (type() != CryptoKeyType::Public)
        return { };

    int len = i2d_PUBKEY(platformKey(), nullptr);
    if (len < 0)
        return { };

    Vector<uint8_t> keyData(len);
    auto ptr = keyData.data();
    if (i2d_PUBKEY(platformKey(), &ptr) < 0)
        return { };

    return keyData;
}

Vector<uint8_t> CryptoKeyEC::platformExportPkcs8() const
{
    if (type() != CryptoKeyType::Private)
        return { };

    auto p8inf = PKCS8PrivKeyInfoPtr(EVP_PKEY2PKCS8(platformKey()));
    if (!p8inf)
        return { };

    int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), nullptr);
    if (len < 0)
        return { };

    Vector<uint8_t> keyData(len);
    auto ptr = keyData.data();
    if (i2d_PKCS8_PRIV_KEY_INFO(p8inf.get(), &ptr) < 0)
        return { };

    return keyData;
}

} // namespace WebCore

#endif // ENABLE(WEB_CRYPTO)
