/*
 *    Copyright (c) 2025 Project CHIP Authors
 *    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.
 */

#include "EleManagerImpl.h"
#include <lib/support/BufferWriter.h>

constexpr uint8_t kTlvHeader = 0x02;

/* Used for CSR generation */
// Organisation info.
constexpr const char * SUBJECT_STR      = "CSR";
constexpr uint8_t ASN1_BIT_STRING       = 0x03;
constexpr uint8_t ASN1_NULL             = 0x05;
constexpr uint8_t ASN1_OID              = 0x06;
constexpr uint8_t ASN1_SEQUENCE         = 0x10;
constexpr uint8_t ASN1_SET              = 0x11;
constexpr uint8_t ASN1_UTF8_STRING      = 0x0C;
constexpr uint8_t ASN1_CONSTRUCTED      = 0x20;
constexpr uint8_t ASN1_CONTEXT_SPECIFIC = 0x80;

namespace chip {
namespace Credentials {
namespace ele {

static bool add_tlv(uint8_t * buf, size_t buf_size, size_t buf_index, uint8_t tag, size_t len, uint8_t * val)
{
    if (buf == nullptr || (buf_index + kTlvHeader + len) > buf_size)
    {
        return false;
    }

    buf[buf_index++] = (uint8_t) tag;
    buf[buf_index++] = (uint8_t) len;

    if (len > 0 && val != nullptr)
    {
        memcpy(&buf[buf_index], val, len);
    }

    return true;
}

std::weak_ptr<EleManagerKeystore> EleManagerKeystore::mWeakInstance;
std::weak_ptr<EleManagerAttestation> EleManagerAttestation::mWeakInstance;

EleManagerKeystore::EleManagerKeystore()
{
    hsm_err_t err;

    // Step 1: open session
    open_session_args_t open_session_args = { 0 };
    open_session_args.mu_type             = HSM1;
    err                                   = hsm_open_session(&open_session_args, &hsm_session_hdl);
    if (err != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "ELE keystore session open failed: 0x%x\n", err);
        return;
    }
    ChipLogDetail(Crypto, "ELE keystore session open successfully.\n");

    // Step 2: open keystore
    open_svc_key_store_args_t open_svc_key_store_args = { 0 };
    open_svc_key_store_args.key_store_identifier      = kKeyStoreId;
    open_svc_key_store_args.authentication_nonce      = kAuthenNonce;
    // try to create a new keystore, if it already exist, open it
    open_svc_key_store_args.flags = (HSM_SVC_KEY_STORE_FLAGS_CREATE | HSM_SVC_KEY_STORE_FLAGS_STRICT_OPERATION);
    err                           = hsm_open_key_store_service(hsm_session_hdl, &open_svc_key_store_args, &key_store_hdl);
    if (err == HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "ELE keystore service created successfully.\n");
    }
    else if (err == HSM_KEY_STORE_CONFLICT)
    {
        ChipLogDetail(Crypto, "ELE keystore service already existed, open it...\n");
        open_svc_key_store_args.flags = HSM_SVC_KEY_STORE_FLAGS_LOAD;
        if (hsm_open_key_store_service(hsm_session_hdl, &open_svc_key_store_args, &key_store_hdl) != HSM_NO_ERROR)
        {
            ChipLogDetail(Crypto, "ELE keystore service load failed.\n");
            hsm_close_session(hsm_session_hdl);
            hsm_session_hdl = 0;
            return;
        }
        ChipLogDetail(Crypto, "ELE keystore service load successfully.\n");
    }
    else
    {
        ChipLogDetail(Crypto, "ELE keystore service open failed. ret:0x%x\n", err);
        return;
    }

    // Step 3: open key managerment service
    open_svc_key_management_args_t key_mgmt_args = { 0 };
    err                                          = hsm_open_key_management_service(key_store_hdl, &key_mgmt_args, &key_mgmt_hdl);
    if (err != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "ELE key management service open failed. ret:0x%x\n", err);
        hsm_close_key_store_service(key_store_hdl);
        hsm_close_session(hsm_session_hdl);
        key_store_hdl   = 0;
        hsm_session_hdl = 0;
        return;
    }
    ChipLogDetail(Crypto, "ELE key management service open successfully.\n");

    ele_service_ready = true;
}

EleManagerKeystore::~EleManagerKeystore()
{
    hsm_close_key_management_service(key_mgmt_hdl);
    ChipLogDetail(Crypto, "Close key management service.\n");
    key_mgmt_hdl = 0;

    hsm_close_key_store_service(key_store_hdl);
    ChipLogDetail(Crypto, "Close keystore service.\n");
    key_store_hdl = 0;

    hsm_close_session(hsm_session_hdl);
    ChipLogDetail(Crypto, "Close keystore session.\n");
    hsm_session_hdl = 0;

    ele_service_ready = false;
}

std::shared_ptr<EleManagerKeystore> EleManagerKeystore::getInstance()
{
    auto shared_EleManager = mWeakInstance.lock();
    if (!shared_EleManager)
    {
        struct make_shared_enabler : public EleManagerKeystore
        {
        };
        shared_EleManager = std::make_shared<make_shared_enabler>();
        if (shared_EleManager->ele_service_ready)
            mWeakInstance = shared_EleManager;
        else
            ChipLogDetail(Crypto, "Ele keystore service open failed, continue...\n");
    }

    /* Return constructed object whatever construction was successful or not,
     * aims to avoid process crash caused by access null pointer.
     */
    return shared_EleManager;
}

EleManagerAttestation::EleManagerAttestation()
{
    hsm_err_t err;

    // Step 1: Open session
    open_session_args_t open_session_args = { 0 };
    open_session_args.mu_type             = HSM1;
    err                                   = hsm_open_session(&open_session_args, &hsm_session_hdl);
    if (err != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "ELE device attestation session open failed: 0x%x\n", err);
        return;
    }
    ChipLogDetail(Crypto, "ELE device attestation session open successfully.\n");

    // Step 2: open keystore
    open_svc_key_store_args_t open_svc_key_store_args = { 0 };
    open_svc_key_store_args.key_store_identifier      = kKeyStoreId;
    open_svc_key_store_args.authentication_nonce      = kAuthenNonce;
    // try to create a new keystore, if it already exist, open it
    open_svc_key_store_args.flags = (HSM_SVC_KEY_STORE_FLAGS_CREATE | HSM_SVC_KEY_STORE_FLAGS_STRICT_OPERATION);
    err                           = hsm_open_key_store_service(hsm_session_hdl, &open_svc_key_store_args, &key_store_hdl);
    if (err == HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "ELE device attestation keystore created successfully.\n");
    }
    else if (err == HSM_KEY_STORE_CONFLICT)
    {
        ChipLogDetail(Crypto, "ELE device attestation service already existed, load it...\n");
        open_svc_key_store_args.flags = HSM_SVC_KEY_STORE_FLAGS_LOAD;
        if (hsm_open_key_store_service(hsm_session_hdl, &open_svc_key_store_args, &key_store_hdl) != HSM_NO_ERROR)
        {
            ChipLogDetail(Crypto, "ELE device attestation service load failed.\n");
            hsm_close_session(hsm_session_hdl);
            hsm_session_hdl = 0;
            return;
        }
        ChipLogDetail(Crypto, "ELE device attestation keystore load successfully.\n");
    }
    else
    {
        ChipLogDetail(Crypto, "ELE device attestation keystore created failed. ret:0x%x\n", err);
        return;
    }

    ele_service_ready = true;
}

EleManagerAttestation::~EleManagerAttestation()
{
    ChipLogDetail(Crypto, "Close device attestation service.\n");
    hsm_close_key_store_service(key_store_hdl);
    key_store_hdl = 0;

    ChipLogDetail(Crypto, "Close device attestation session.\n");
    hsm_close_session(hsm_session_hdl);
    hsm_session_hdl = 0;

    ele_service_ready = false;
}

std::shared_ptr<EleManagerAttestation> EleManagerAttestation::getInstance()
{
    auto shared_EleManager = mWeakInstance.lock();
    if (!shared_EleManager)
    {
        struct make_shared_enabler : public EleManagerAttestation
        {
        };
        shared_EleManager = std::make_shared<make_shared_enabler>();
        if (shared_EleManager->ele_service_ready)
            mWeakInstance = shared_EleManager;
        else
            ChipLogDetail(Crypto, "Ele device attestation service open failed, continue...\n");
    }

    /* Return constructed object whatever construction was successful or not,
     * aims to avoid process crash caused by access null pointer.
     */
    return shared_EleManager;
}

hsm_err_t EleManagerImpl::EleDeleteKey(uint32_t keyId)
{
    if (!ele_service_ready)
    {
        ChipLogDetail(Crypto, "Ele service has not been instantiated yet.\n");
        return HSM_GENERAL_ERROR;
    }

    hsm_err_t err;
    op_delete_key_args_t del_args;

    memset(&del_args, 0, sizeof(del_args));
    del_args.key_identifier = keyId;
    del_args.flags          = 0;

    err = hsm_delete_key(key_mgmt_hdl, &del_args);
    if (err != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "Delete key %d failed. ret:0x%x\n", keyId, err);
    }
    else
    {
        ChipLogDetail(Crypto, "Delete key %d successfully.\n", keyId);
    }

    return err;
}

CHIP_ERROR EleManagerImpl::EleGenerateCSR(uint32_t keyId, uint8_t * csr, size_t & csrLength)
{
    if (!ele_service_ready)
    {
        ChipLogDetail(Crypto, "Ele service has not been instantiated yet.\n");
        return CHIP_ERROR_INTERNAL;
    }

    CHIP_ERROR error = CHIP_ERROR_INTERNAL;
    hsm_err_t hsmret = HSM_NO_ERROR;

    uint8_t data_to_hash[128] = { 0 };
    size_t data_to_hash_len   = sizeof(data_to_hash);
    uint8_t pubKey[128]       = { 0 };
    size_t pubKeyLen          = 0;
    uint8_t signature[128]    = { 0 };
    size_t signature_len      = 0x44;
    int signature_index       = 0;
    uint8_t signature_data[64];
    size_t csrIndex     = 0;
    size_t buffer_index = data_to_hash_len;

    uint8_t organisation_oid[3] = { 0x55, 0x04, 0x0a };
    // Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
    uint8_t version[3]            = { 0x02, 0x01, 0x00 };
    uint8_t signature_oid[8]      = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02 };
    uint8_t nist256_header[]      = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
                                      0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00 };
    uint8_t signature_header_t1[] = { 0x02, 0x20 };
    uint8_t signature_header_t2[] = { 0x02, 0x21, 0x00 };

    // No extensions are copied
    buffer_index -= kTlvHeader;
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, (ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC), 0, NULL),
                 error = CHIP_ERROR_INTERNAL);

    // Copy public key (with header)
    {
        // copy header first
        memcpy(pubKey, nist256_header, sizeof(nist256_header));
        pubKeyLen = pubKeyLen + sizeof(nist256_header);

        // public key size is 65
        pubKey[pubKeyLen] = 0x04;
        pubKeyLen++;

        op_pub_key_recovery_args_t args = { 0 };
        args.key_identifier             = keyId;
        args.out_key_size               = 64;
        args.out_key                    = (pubKey + pubKeyLen);
        hsmret                          = hsm_pub_key_recovery(key_store_hdl, &args);
        VerifyOrExit(hsmret == HSM_NO_ERROR, error = CHIP_ERROR_HSM);
        pubKeyLen += 64;
    }

    buffer_index -= pubKeyLen;
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    memcpy((void *) &data_to_hash[buffer_index], pubKey, pubKeyLen);

    // Copy subject (in the current implementation only organisation name info is added) and organisation OID
    buffer_index -= (kTlvHeader + sizeof(SUBJECT_STR) - 1);
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, ASN1_UTF8_STRING, sizeof(SUBJECT_STR) - 1, (uint8_t *) SUBJECT_STR),
                 error = CHIP_ERROR_INTERNAL);

    buffer_index -= (kTlvHeader + sizeof(organisation_oid));
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, ASN1_OID, sizeof(organisation_oid), organisation_oid),
                 error = CHIP_ERROR_INTERNAL);

    // Add length
    buffer_index -= kTlvHeader;
    // Subject TLV ==> 1 + 1 + len(subject)
    // Org OID TLV ==> 1 + 1 + len(organisation_oid)
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
                         ((2 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL),
                 error = CHIP_ERROR_INTERNAL);

    buffer_index -= kTlvHeader;
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, (ASN1_CONSTRUCTED | ASN1_SET),
                         ((3 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL),
                 error = CHIP_ERROR_INTERNAL);

    buffer_index -= kTlvHeader;
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
                         ((4 * kTlvHeader) + (sizeof(SUBJECT_STR) - 1) + sizeof(organisation_oid)), NULL),
                 error = CHIP_ERROR_INTERNAL);

    buffer_index -= 3;
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    memcpy((void *) &data_to_hash[buffer_index], version, sizeof(version));

    buffer_index -= kTlvHeader;
    VerifyOrExit(buffer_index > 0, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(data_to_hash, 128, buffer_index, (ASN1_CONSTRUCTED | ASN1_SEQUENCE),
                         (data_to_hash_len - buffer_index - kTlvHeader), NULL),
                 error = CHIP_ERROR_INTERNAL);

    // TLV data is created by copying from backwards. move it to start of buffer.
    data_to_hash_len = (data_to_hash_len - buffer_index);
    memmove(data_to_hash, (data_to_hash + buffer_index), data_to_hash_len);

    hsmret = EleSignMessage(keyId, (uint8_t *) data_to_hash, data_to_hash_len, signature_data, sizeof(signature_data));
    VerifyOrExit(hsmret == HSM_NO_ERROR, error = CHIP_ERROR_HSM);

    if (signature_data[0] > 0x7F)
    {
        signature_len += 1;
        memcpy(signature, signature_header_t2, sizeof(signature_header_t2));
        signature_index += 3;
    }
    else
    {
        memcpy(signature, signature_header_t1, sizeof(signature_header_t1));
        signature_index += 2;
    }
    memcpy(&signature[signature_index], signature_data, 32);
    signature_index += 32;
    if (signature_data[32] > 0x7F)
    {
        signature_len += 1;
        memcpy(&signature[signature_index], signature_header_t2, 3);
        signature_index += 3;
    }
    else
    {
        memcpy(&signature[signature_index], signature_header_t1, 2);
        signature_index += 2;
    }
    memcpy(&signature[signature_index], &signature_data[32], 32);

    VerifyOrExit((csrIndex + 3) <= csrLength, error = CHIP_ERROR_INTERNAL);
    csr[csrIndex++] = (ASN1_CONSTRUCTED | ASN1_SEQUENCE);
    if ((data_to_hash_len + 14 + kTlvHeader + signature_len) >= 0x80)
        csr[csrIndex++] = 0x81;
    csr[csrIndex++] = (uint8_t) (data_to_hash_len + sizeof(signature_oid) + (kTlvHeader * 2) + 5 + signature_len);

    VerifyOrExit((csrIndex + data_to_hash_len) <= csrLength, error = CHIP_ERROR_INTERNAL);
    memcpy((csr + csrIndex), data_to_hash, data_to_hash_len);
    csrIndex = csrIndex + data_to_hash_len;

    // ECDSA SHA256 Signature OID TLV ==> 1 + 1 + len(signature_oid) (8)
    // ASN_NULL ==> 1 + 1
    VerifyOrExit((csrIndex + kTlvHeader) <= csrLength, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(csr, csrLength, csrIndex, (ASN1_CONSTRUCTED | ASN1_SEQUENCE), 0x0A, NULL), error = CHIP_ERROR_INTERNAL);
    csrIndex = csrIndex + kTlvHeader;

    VerifyOrExit((csrIndex + sizeof(signature_oid) + kTlvHeader) <= csrLength, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(add_tlv(csr, csrLength, csrIndex, ASN1_OID, sizeof(signature_oid), signature_oid), error = CHIP_ERROR_INTERNAL);
    csrIndex = csrIndex + kTlvHeader + sizeof(signature_oid);

    // VerifyOrExit((csrIndex + kTlvHeader) <= csrLength, error = CHIP_ERROR_INTERNAL);
    // VerifyOrExit(add_tlv(csr, csrLength, csrIndex, ASN1_NULL, 0x00, NULL), error = CHIP_ERROR_INTERNAL);
    // csrIndex = csrIndex + kTlvHeader;

    VerifyOrExit((csrIndex + 5) <= csrLength, error = CHIP_ERROR_INTERNAL);
    csr[csrIndex++] = ASN1_BIT_STRING;
    csr[csrIndex++] = (uint8_t) signature_len + 3;
    csr[csrIndex++] = 0x00;
    csr[csrIndex++] = (ASN1_CONSTRUCTED | ASN1_SEQUENCE);
    csr[csrIndex++] = (uint8_t) signature_len;

    VerifyOrExit((csrIndex + signature_len) <= csrLength, error = CHIP_ERROR_INTERNAL);
    memcpy(&csr[csrIndex], signature, signature_len);
    csrLength = (csrIndex + signature_len);

    error = CHIP_NO_ERROR;

exit:
    return error;
}

hsm_err_t EleManagerImpl::EleSignMessage(uint32_t keyId, const uint8_t * msg, size_t msgSize, uint8_t * sig, size_t sigSize)
{
    if (!ele_service_ready)
    {
        ChipLogDetail(Crypto, "Ele service has not been instantiated yet.\n");
        return HSM_GENERAL_ERROR;
    }

    open_svc_sign_gen_args_t open_sig_gen_args;
    op_generate_sign_args_t sig_gen_args;
    hsm_hdl_t sig_gen_hdl;
    hsm_err_t hsmret;

    if ((msg == nullptr) || (sig == nullptr) || (sigSize == 0))
    {
        ChipLogDetail(Crypto, "Invalid parameters for generating signature.\n");
        return HSM_INVALID_PARAM;
    }

    // open signature generation service
    memset(&open_sig_gen_args, 0, sizeof(open_sig_gen_args));
    hsmret = hsm_open_signature_generation_service(key_store_hdl, &open_sig_gen_args, &sig_gen_hdl);
    if (hsmret != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "open signature generation service failed. ret:0x%x\n", hsmret);
        return hsmret;
    }

    // generate signature
    memset(&sig_gen_args, 0, sizeof(sig_gen_args));
    sig_gen_args.key_identifier = keyId;
    sig_gen_args.scheme_id      = HSM_SIGNATURE_SCHEME_ECDSA_SHA256;
    sig_gen_args.message        = (uint8_t *) msg;
    sig_gen_args.signature      = sig;
    sig_gen_args.message_size   = (uint32_t) msgSize;
    sig_gen_args.signature_size = (uint16_t) sigSize;
    sig_gen_args.flags          = HSM_OP_GENERATE_SIGN_FLAGS_INPUT_MESSAGE;
    hsmret                      = hsm_generate_signature(sig_gen_hdl, &sig_gen_args);
    if (hsmret != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "generate signature failed. ret:0x%x\n", hsmret);
        return hsmret;
    }

    // close signature generation service
    hsmret = hsm_close_signature_generation_service(sig_gen_hdl);
    if (hsmret != HSM_NO_ERROR)
    {
        ChipLogDetail(Crypto, "close signature generation service failed. ret:0x%x\n", hsmret);
    }

    return hsmret;
}

} // namespace ele
} // namespace Credentials
} // namespace chip
