/*
 *   Copyright (c) 2022 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 "ToCertificateString.h"

#include <lib/support/Base64.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>

namespace {
constexpr const uint8_t kChipRawPrefix[] = { 0x15, 0x30, 0x01 };

bool IsChipCertificate(const chip::ByteSpan & source)
{
    return (source.size() > sizeof(kChipRawPrefix)) && (memcmp(source.data(), kChipRawPrefix, sizeof(kChipRawPrefix)) == 0);
}

const char * ToCertificate(const chip::ByteSpan & source, chip::MutableCharSpan destination, const char * header = "",
                           const char * footer = "")
{
    // Reset the buffer
    memset(destination.data(), '\0', destination.size());

    if (source.size() == 0)
    {
        return destination.data();
    }

    if (!chip::CanCastTo<uint16_t>(source.size()))
    {
        ChipLogError(DataManagement, "The certificate is too large to do base64 conversion on");
        return destination.data();
    }

    size_t base64DataLen = BASE64_ENCODED_LEN(source.size());
    size_t bufferLen     = base64DataLen + 1; // add one character for null-terminator
    if (bufferLen + strlen(header) + strlen(footer) > destination.size())
    {
        ChipLogError(DataManagement, "The certificate buffer is too small to hold the base64 encoded certificate");
        return destination.data();
    }

    chip::Platform::ScopedMemoryBuffer<char> str;
    str.Alloc(bufferLen);

    auto encodedLen       = chip::Base64Encode(source.data(), static_cast<uint16_t>(source.size()), str.Get());
    str.Get()[encodedLen] = '\0';

    if (IsChipCertificate(source))
    {
        // Wherever Matter Operational Certificate Encoding representation is used, all certificates SHALL NOT be longer than 400
        // bytes in their TLV form.
        if (source.size() > 400)
        {
            ChipLogError(DataManagement, "Certificate size is greater than 400 bytes");
        }

        snprintf(destination.data(), destination.size(), "%s", str.Get());
    }
    else
    {
        // All certificates SHALL NOT be longer than 600 bytes in their uncompressed DER format.
        if (source.size() > 600)
        {
            ChipLogError(DataManagement, "Certificate size is greater than 600 bytes");
        }

        size_t inIndex  = 0;
        size_t outIndex = strlen(header) + 1;

        snprintf(destination.data(), destination.size(), "%s\n", header);
        for (; inIndex < base64DataLen; inIndex += 64)
        {
            auto charsPrinted = snprintf(&destination.data()[outIndex], destination.size() - outIndex, "%.64s\n", &str[inIndex]);
            outIndex += static_cast<size_t>(charsPrinted);
        }
        snprintf(&destination.data()[outIndex], destination.size() - outIndex, "%s", footer);
    }

    return destination.data();
}

} // namespace

namespace chip {
namespace trace {
namespace logging {

const char * ToCertificateString(const ByteSpan & source, MutableCharSpan destination)
{
    constexpr const char * kCertificateHeader = "-----BEGIN CERTIFICATE-----";
    constexpr const char * kCertificateFooter = "-----END CERTIFICATE-----";

    return ToCertificate(source, destination, kCertificateHeader, kCertificateFooter);
}

const char * ToCertificateRequestString(const ByteSpan & source, MutableCharSpan destination)
{
    constexpr const char * kCertificateHeader = "-----BEGIN CERTIFICATE REQUEST-----";
    constexpr const char * kCertificateFooter = "-----END CERTIFICATE REQUEST-----";

    return ToCertificate(source, destination, kCertificateHeader, kCertificateFooter);
}

} // namespace logging
} // namespace trace
} // namespace chip
