/*
 * 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(), convertToBigNumber(x).get(), convertToBigNumber(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(), convertToBigNumber(x).get(), convertToBigNumber(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(), convertToBigNumber(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_base_id(pkey.get()) != 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)
