/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements utility functions for reading, parsing,
 *      encoding, and decoding CHIP key material.
 *
 */

#include <memory>
#include <utility>

#include "chip-cert.h"
#include <lib/core/CHIPEncoding.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/BytesToHex.h>
#include <protocols/Protocols.h>

using namespace chip;
using namespace chip::Encoding;
using namespace chip::Protocols;
using namespace chip::ASN1;
using namespace chip::TLV;
using namespace chip::Crypto;
using namespace chip::Encoding;

namespace {

KeyFormat DetectKeyFormat(const uint8_t * key, uint32_t keyLen)
{
    static uint32_t p256SerializedKeypairLen = kP256_PublicKey_Length + kP256_PrivateKey_Length;
    static const uint8_t chipRawPrefix[]     = { 0x04 };
    static const char chipHexPrefix[]        = "04";
    static const char chipB64Prefix[]        = "B";
    static const uint8_t derRawPrefix[]      = { 0x30, 0x77, 0x02, 0x01, 0x01, 0x04 };
    static const char derHexPrefix[]         = "307702010104";
    static const char ecPEMMarker[]          = "-----BEGIN EC PRIVATE KEY-----";
    static const char pkcs8PEMMarker[]       = "-----BEGIN PRIVATE KEY-----";
    static const char ecPUBPEMMarker[]       = "-----BEGIN PUBLIC KEY-----";

    VerifyOrReturnError(key != nullptr, kKeyFormat_Unknown);

    if ((keyLen == p256SerializedKeypairLen) && (memcmp(key, chipRawPrefix, sizeof(chipRawPrefix)) == 0))
    {
        return kKeyFormat_Chip_Raw;
    }
    if ((keyLen == HEX_ENCODED_LENGTH(p256SerializedKeypairLen)) && (memcmp(key, chipHexPrefix, strlen(chipHexPrefix)) == 0))
    {
        return kKeyFormat_Chip_Hex;
    }
    if ((keyLen == BASE64_ENCODED_LEN(p256SerializedKeypairLen)) && (memcmp(key, chipB64Prefix, strlen(chipB64Prefix)) == 0))
    {
        return kKeyFormat_Chip_Base64;
    }
    if ((keyLen == kP256_PublicKey_Length) && (memcmp(key, chipRawPrefix, sizeof(chipRawPrefix)) == 0))
    {
        return kKeyFormat_Chip_Pubkey_Raw;
    }
    if ((keyLen == (2 * kP256_PublicKey_Length)) && (memcmp(key, chipHexPrefix, strlen(chipHexPrefix)) == 0))
    {
        return kKeyFormat_Chip_Pubkey_Hex;
    }
    if ((keyLen == BASE64_ENCODED_LEN(kP256_PublicKey_Length)) && (memcmp(key, chipB64Prefix, strlen(chipB64Prefix)) == 0))
    {
        return kKeyFormat_Chip_Pubkey_Base64;
    }
    if ((keyLen > sizeof(derRawPrefix)) && (memcmp(key, derRawPrefix, sizeof(derRawPrefix)) == 0))
    {
        return kKeyFormat_X509_DER;
    }
    if ((keyLen > strlen(derHexPrefix)) && (memcmp(key, derHexPrefix, strlen(derHexPrefix)) == 0))
    {
        return kKeyFormat_X509_Hex;
    }
    if (ContainsPEMMarker(ecPEMMarker, key, keyLen) || ContainsPEMMarker(pkcs8PEMMarker, key, keyLen))
    {
        return kKeyFormat_X509_PEM;
    }
    if (ContainsPEMMarker(ecPUBPEMMarker, key, keyLen))
    {
        return kKeyFormat_X509_Pubkey_PEM;
    }

    return kKeyFormat_Unknown;
}

bool SetPublicKey(const uint8_t * pubkey, uint32_t pubkeyLen, EVP_PKEY * key)
{
    std::unique_ptr<EC_GROUP, void (*)(EC_GROUP *)> group(EC_GROUP_new_by_curve_name(gNIDChipCurveP256), &EC_GROUP_free);
    std::unique_ptr<EC_POINT, void (*)(EC_POINT *)> ecPoint(EC_POINT_new(group.get()), &EC_POINT_free);
    std::unique_ptr<EC_KEY, void (*)(EC_KEY *)> ecKey(EC_KEY_new_by_curve_name(gNIDChipCurveP256), &EC_KEY_free);

    VerifyOrReturnError(EC_POINT_oct2point(group.get(), ecPoint.get(), pubkey, pubkeyLen, nullptr) == 1, false);

    VerifyOrReturnError(EC_KEY_set_public_key(ecKey.get(), ecPoint.get()) == 1, false);

    VerifyOrReturnError(EVP_PKEY_set1_EC_KEY(key, ecKey.get()) == 1, false);

    return true;
}

bool ExtractPublicKey(EVP_PKEY * key, MutableByteSpan & pubKey)
{
    const EC_KEY * ecKey     = nullptr;
    const EC_GROUP * group   = nullptr;
    const EC_POINT * ecPoint = nullptr;

    VerifyOrReturnError(pubKey.size() >= kP256_PublicKey_Length, false);

    ecKey = EVP_PKEY_get1_EC_KEY(key);
    VerifyOrReturnError(ecKey != nullptr, false);

    group = EC_KEY_get0_group(ecKey);
    VerifyOrReturnError(group != nullptr, false);

    ecPoint = EC_KEY_get0_public_key(ecKey);
    VerifyOrReturnError(ecPoint != nullptr, false);

    VerifyOrReturnError(EC_POINT_point2oct(group, ecPoint, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(pubKey.data()),
                                           kP256_PublicKey_Length, nullptr) == kP256_PublicKey_Length,
                        false);

    pubKey.reduce_size(static_cast<size_t>(kP256_PublicKey_Length));

    return true;
}

bool DeserializeKeyPair(const uint8_t * keyPair, uint32_t keyPairLen, EVP_PKEY * key)
{
    std::unique_ptr<BIGNUM, void (*)(BIGNUM *)> privKeyBN(BN_new(), &BN_clear_free);

    ERR_clear_error();

    VerifyOrReturnError(key != nullptr, false);
    VerifyOrReturnError(keyPair != nullptr, false);
    VerifyOrReturnError(keyPairLen == kP256_PublicKey_Length + kP256_PrivateKey_Length, false);

    VerifyOrReturnError(SetPublicKey(keyPair, kP256_PublicKey_Length, key), false);

    VerifyOrReturnError(BN_bin2bn(keyPair + kP256_PublicKey_Length, kP256_PrivateKey_Length, privKeyBN.get()) != nullptr, false);

    VerifyOrReturnError(EC_KEY_set_private_key(EVP_PKEY_get1_EC_KEY(key), privKeyBN.get()) == 1, false);

    return true;
}

} // namespace

bool SerializeKeyPair(EVP_PKEY * key, P256SerializedKeypair & serializedKeypair)
{
    const EC_KEY * ecKey     = nullptr;
    const BIGNUM * privKeyBN = nullptr;
    MutableByteSpan pubKey(serializedKeypair.Bytes(), kP256_PublicKey_Length);

    VerifyOrReturnError(ExtractPublicKey(key, pubKey), false);

    ecKey = EVP_PKEY_get1_EC_KEY(key);
    VerifyOrReturnError(ecKey != nullptr, false);

    privKeyBN = EC_KEY_get0_private_key(ecKey);
    VerifyOrReturnError(privKeyBN != nullptr, false);

    VerifyOrReturnError(BN_bn2binpad(privKeyBN, serializedKeypair.Bytes() + kP256_PublicKey_Length, kP256_PrivateKey_Length) ==
                            kP256_PrivateKey_Length,
                        false);

    TEMPORARY_RETURN_IGNORED serializedKeypair.SetLength(kP256_PublicKey_Length + kP256_PrivateKey_Length);

    return true;
}

bool ReadKey(const char * fileNameOrStr, std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY *)> & key, bool ignorErrorIfUnsupportedCurve)
{
    bool res            = true;
    uint32_t keyDataLen = 0;
    KeyFormat keyFormat = kKeyFormat_Unknown;
    std::unique_ptr<uint8_t[]> keyData;

    // If fileNameOrStr is a file name
    if (access(fileNameOrStr, R_OK) == 0)
    {
        res = ReadFileIntoMem(fileNameOrStr, nullptr, keyDataLen);
        VerifyTrueOrExit(res);

        keyData = std::make_unique<uint8_t[]>(keyDataLen);

        res = ReadFileIntoMem(fileNameOrStr, keyData.get(), keyDataLen);
        VerifyTrueOrExit(res);

        keyFormat = DetectKeyFormat(keyData.get(), keyDataLen);
        if (keyFormat == kKeyFormat_Unknown)
        {
            fprintf(stderr, "Unrecognized Key Format in File: %s\n", fileNameOrStr);
            return false;
        }
    }
    // Otherwise, treat fileNameOrStr as a pointer to the key string
    else
    {
        keyDataLen = static_cast<uint32_t>(strlen(fileNameOrStr));

        keyFormat = DetectKeyFormat(reinterpret_cast<const uint8_t *>(fileNameOrStr), keyDataLen);
        if (keyFormat == kKeyFormat_Unknown)
        {
            fprintf(stderr, "Unrecognized Key Format in Input Argument: %s\n", fileNameOrStr);
            return false;
        }

        keyData = std::make_unique<uint8_t[]>(keyDataLen);
        memcpy(keyData.get(), fileNameOrStr, keyDataLen);
    }

    if ((keyFormat == kKeyFormat_X509_Hex) || (keyFormat == kKeyFormat_Chip_Hex) || (keyFormat == kKeyFormat_Chip_Pubkey_Hex))
    {
        size_t len = HexToBytes(Uint8::to_char(keyData.get()), keyDataLen, keyData.get(), keyDataLen);
        VerifyOrReturnError(CanCastTo<uint32_t>(2 * len), false);
        VerifyOrReturnError(2 * len == keyDataLen, false);
        keyDataLen = static_cast<uint32_t>(len);
    }
    else if ((keyFormat == kKeyFormat_Chip_Base64) || (keyFormat == kKeyFormat_Chip_Pubkey_Base64))
    {
        res = Base64Decode(keyData.get(), keyDataLen, keyData.get(), keyDataLen, keyDataLen);
        VerifyTrueOrExit(res);
    }
    else if (keyFormat == kKeyFormat_Chip_Hex)
    {
        const char * keyChars = reinterpret_cast<const char *>(keyData.get());

        keyDataLen = static_cast<uint32_t>(Encoding::HexToBytes(keyChars, keyDataLen, keyData.get(), keyDataLen));
        res        = (keyDataLen > 0);
        VerifyTrueOrExit(res);

        keyFormat = kKeyFormat_Chip_Raw;
    }

    if (IsChipPrivateKeyFormat(keyFormat))
    {
        res = DeserializeKeyPair(keyData.get(), keyDataLen, key.get());
        VerifyTrueOrExit(res);
    }
    else if (IsChipPublicKeyFormat(keyFormat))
    {
        res = SetPublicKey(keyData.get(), keyDataLen, key.get());
        VerifyTrueOrExit(res);
    }
    else
    {
        std::unique_ptr<BIO, void (*)(BIO *)> keyBIO(
            BIO_new_mem_buf(static_cast<const void *>(keyData.get()), static_cast<int>(keyDataLen)), &BIO_free_all);

        if (keyFormat == kKeyFormat_X509_Pubkey_PEM)
        {
            EC_KEY * ecKey = PEM_read_bio_EC_PUBKEY(keyBIO.get(), nullptr, nullptr, nullptr);
            if (ecKey == nullptr)
            {
                ReportOpenSSLErrorAndExit("PEM_read_bio_EC_PUBKEY", res = false);
            }

            if (EVP_PKEY_set1_EC_KEY(key.get(), ecKey) != 1)
            {
                ReportOpenSSLErrorAndExit("EVP_PKEY_set1_EC_KEY", res = false);
            }
        }
        else if (keyFormat == kKeyFormat_X509_PEM)
        {
            key.reset(PEM_read_bio_PrivateKey(keyBIO.get(), nullptr, nullptr, nullptr));
            if (key.get() == nullptr)
            {
                ReportOpenSSLErrorAndExit("PEM_read_bio_PrivateKey", res = false);
            }
        }
        else
        {
            key.reset(d2i_PrivateKey_bio(keyBIO.get(), nullptr));
            if (key.get() == nullptr)
            {
                ReportOpenSSLErrorAndExit("d2i_PrivateKey_bio", res = false);
            }
        }
    }

    if ((EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get1_EC_KEY(key.get()))) != gNIDChipCurveP256) &&
        !ignorErrorIfUnsupportedCurve)
    {
        fprintf(stderr, "Specified key uses unsupported Elliptic Curve\n");
        ExitNow(res = false);
    }

exit:
    return res;
}

bool GenerateKeyPair(EVP_PKEY * key)
{
    bool res = true;
    std::unique_ptr<EC_KEY, void (*)(EC_KEY *)> ecKey(EC_KEY_new_by_curve_name(gNIDChipCurveP256), &EC_KEY_free);

    VerifyOrExit(key != nullptr, res = false);

    if (!EC_KEY_generate_key(ecKey.get()))
    {
        ReportOpenSSLErrorAndExit("EC_KEY_generate_key", res = false);
    }

    if (!EVP_PKEY_set1_EC_KEY(key, ecKey.get()))
    {
        ReportOpenSSLErrorAndExit("EVP_PKEY_set1_EC_KEY", res = false);
    }

exit:
    return res;
}

bool GenerateKeyPair_Secp256k1(EVP_PKEY * key)
{
    bool res = true;
    std::unique_ptr<EC_KEY, void (*)(EC_KEY *)> ecKey(EC_KEY_new_by_curve_name(NID_secp256k1), &EC_KEY_free);

    VerifyOrExit(key != nullptr, res = false);

    if (!EC_KEY_generate_key(ecKey.get()))
    {
        ReportOpenSSLErrorAndExit("EC_KEY_generate_key", res = false);
    }

    if (!EVP_PKEY_set1_EC_KEY(key, ecKey.get()))
    {
        ReportOpenSSLErrorAndExit("EVP_PKEY_set1_EC_KEY", res = false);
    }

exit:
    return res;
}

bool WriteKey(const char * fileName, EVP_PKEY * key, KeyFormat keyFmt)
{
    bool res              = true;
    FILE * file           = nullptr;
    uint8_t * derKey      = nullptr;
    DataFormat dataFormat = kDataFormat_Unknown;

    VerifyOrExit(key != nullptr, res = false);

    if (keyFmt == kKeyFormat_X509_PEM || keyFmt == kKeyFormat_X509_Pubkey_PEM || keyFmt == kKeyFormat_X509_DER)
    {
        VerifyOrExit(OpenFile(fileName, file, true), res = false);
    }

    if (EVP_PKEY_type(EVP_PKEY_id(key)) != EVP_PKEY_EC)
    {
        fprintf(stderr, "Unsupported private key type\n");
        ExitNow(res = false);
    }

    switch (keyFmt)
    {
    case kKeyFormat_X509_PEM:
        if (PEM_write_ECPrivateKey(file, EVP_PKEY_get1_EC_KEY(key), nullptr, nullptr, 0, nullptr, nullptr) == 0)
        {
            ReportOpenSSLErrorAndExit("PEM_write_ECPrivateKey", res = false);
        }
        break;
    case kKeyFormat_X509_Pubkey_PEM:
        if (PEM_write_EC_PUBKEY(file, EVP_PKEY_get1_EC_KEY(key)) == 0)
        {
            ReportOpenSSLErrorAndExit("PEM_write_EC_PUBKEY", res = false);
        }
        break;
    case kKeyFormat_X509_DER:
        if (i2d_ECPrivateKey_fp(file, EVP_PKEY_get1_EC_KEY(key)) == 0)
        {
            ReportOpenSSLErrorAndExit("i2d_PrivateKey_fp", res = false);
        }
        break;
    case kKeyFormat_X509_Hex: {
        int derKeyLen = i2d_ECPrivateKey(EVP_PKEY_get1_EC_KEY(key), &derKey);
        if (derKeyLen < 0)
        {
            ReportOpenSSLErrorAndExit("i2d_X509", res = false);
        }
        VerifyOrExit(CanCastTo<size_t>(derKeyLen), res = false);
        VerifyOrExit(WriteDataIntoFile(fileName, derKey, static_cast<size_t>(derKeyLen), kDataFormat_Hex), res = false);
    }
    break;
    case kKeyFormat_Chip_Raw:
    case kKeyFormat_Chip_Hex:
    case kKeyFormat_Chip_Base64:
        if (keyFmt == kKeyFormat_Chip_Raw)
            dataFormat = kDataFormat_Raw;
        else if (keyFmt == kKeyFormat_Chip_Base64)
            dataFormat = kDataFormat_Base64;
        else
            dataFormat = kDataFormat_Hex;

        {
            P256SerializedKeypair serializedKeypair;
            VerifyOrExit(SerializeKeyPair(key, serializedKeypair), res = false);
            VerifyOrExit(WriteDataIntoFile(fileName, serializedKeypair.Bytes(), serializedKeypair.Length(), dataFormat),
                         res = false);
        }
        break;
    case kKeyFormat_Chip_Pubkey_Raw:
    case kKeyFormat_Chip_Pubkey_Base64:
    case kKeyFormat_Chip_Pubkey_Hex:
        if (keyFmt == kKeyFormat_Chip_Pubkey_Raw)
            dataFormat = kDataFormat_Raw;
        else if (keyFmt == kKeyFormat_Chip_Pubkey_Base64)
            dataFormat = kDataFormat_Base64;
        else
            dataFormat = kDataFormat_Hex;

        {
            uint8_t pubkey[kP256_PublicKey_Length] = { 0 };
            MutableByteSpan pubkeySpan(pubkey);
            VerifyOrExit(ExtractPublicKey(key, pubkeySpan), res = false);
            VerifyOrExit(WriteDataIntoFile(fileName, pubkeySpan.data(), pubkeySpan.size(), dataFormat), res = false);
        }
        break;
    default:
        fprintf(stderr, "Unsupported private key format\n");
        ExitNow(res = false);
    }

exit:
    CloseFile(file);
    OPENSSL_free(derKey);

    return res;
}
