/*
 *
 *    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 "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);

    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::unique_ptr<uint8_t[]>(new 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::unique_ptr<uint8_t[]>(new 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;
}
