/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *
 *    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
 *      Platform agnostic implementation of CHIP crypto algorithms
 */

#include "CHIPCryptoPAL.h"

#include "SessionKeystore.h"

#include <lib/asn1/ASN1.h>
#include <lib/asn1/ASN1Macros.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/support/BufferReader.h>
#include <lib/support/BufferWriter.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/Span.h>
#include <stdint.h>
#include <string.h>

using chip::ByteSpan;
using chip::MutableByteSpan;
using chip::Encoding::BufferWriter;
using chip::Encoding::LittleEndian::Reader;

using namespace chip::ASN1;

namespace chip {
namespace Crypto {
namespace {

constexpr uint8_t kIntegerTag         = 0x02u;
constexpr uint8_t kSeqTag             = 0x30u;
constexpr size_t kMinSequenceOverhead = 1 /* tag */ + 1 /* length */ + 1 /* actual data or second length byte*/;

/**
 * @brief Utility to convert DER-encoded INTEGER into a raw integer buffer in big-endian order
 *        with leading zeroes if the output buffer is larger than needed.
 * @param[in] reader Reader instance from which the input will be read
 * @param[out] raw_integer_out Buffer to receive the DER-encoded integer
 * @return CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise
 */
CHIP_ERROR ReadDerUnsignedIntegerIntoRaw(Reader & reader, MutableByteSpan raw_integer_out)
{
    uint8_t cur_byte = 0;

    ReturnErrorOnFailure(reader.Read8(&cur_byte).StatusCode());

    // We expect first tag to be INTEGER
    VerifyOrReturnError(cur_byte == kIntegerTag, CHIP_ERROR_INVALID_ARGUMENT);

    // Read the length
    size_t integer_len = 0;
    ReturnErrorOnFailure(chip::Crypto::ReadDerLength(reader, integer_len));

    // Clear the destination buffer, so we can blit the unsigned value into place
    memset(raw_integer_out.data(), 0, raw_integer_out.size());

    // Check for pseudo-zero to mark unsigned value
    // This means we have too large an integer (should be at most 1 byte too large), it's invalid
    VerifyOrReturnError(integer_len <= (raw_integer_out.size() + 1), CHIP_ERROR_INVALID_ARGUMENT);

    if (integer_len == (raw_integer_out.size() + 1u))
    {
        // Means we had a 0x00 byte stuffed due to MSB being high in original integer
        ReturnErrorOnFailure(reader.Read8(&cur_byte).StatusCode());

        // The extra byte must be a leading zero
        VerifyOrReturnError(cur_byte == 0, CHIP_ERROR_INVALID_ARGUMENT);
        --integer_len;
    }

    // We now have the rest of the tag that is a "minimal length" unsigned integer.
    // Blit it at the correct offset, since the order we use is MSB first for
    // both ASN.1 and EC curve raw points.
    size_t offset = raw_integer_out.size() - integer_len;
    return reader.ReadBytes(raw_integer_out.data() + offset, integer_len).StatusCode();
}

CHIP_ERROR ConvertIntegerRawToDerInternal(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer,
                                          bool include_tag_and_length)
{
    if (raw_integer.empty() || out_der_integer.empty())
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    Reader reader(raw_integer);
    BufferWriter writer(out_der_integer);

    bool needs_leading_zero_byte = false;

    uint8_t cur_byte = 0;
    while ((reader.Remaining() > 0) && (reader.Read8(&cur_byte).StatusCode() == CHIP_NO_ERROR) && (cur_byte == 0))
    {
        // Omit all leading zeros
    }

    if ((cur_byte & 0x80u) != 0)
    {
        // If overall MSB (from leftmost byte) is set, we will need to push out a zero to avoid it being
        // considered a negative number.
        needs_leading_zero_byte = true;
    }

    // The + 1 is to account for the last consumed byte of the loop to skip leading zeros
    size_t length = reader.Remaining() + 1 + (needs_leading_zero_byte ? 1 : 0);

    if (length > 127)
    {
        // We do not support length over more than 1 bytes.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    if (include_tag_and_length)
    {
        // Put INTEGER tag
        writer.Put(kIntegerTag);

        // Put length over 1 byte (i.e. MSB clear)
        writer.Put(static_cast<uint8_t>(length));
    }

    // If leading zero or no more bytes remaining, must ensure we start with at least a zero byte
    if (needs_leading_zero_byte)
    {
        writer.Put(static_cast<uint8_t>(0u));
    }

    // Put first consumed byte from last read iteration of leading zero suppression
    writer.Put(cur_byte);

    // Fill the rest from the input in order
    while (reader.Read8(&cur_byte).StatusCode() == CHIP_NO_ERROR)
    {
        // Emit all other bytes as-is
        writer.Put(cur_byte);
    }

    size_t actually_written = 0;
    if (!writer.Fit(actually_written))
    {
        return CHIP_ERROR_BUFFER_TOO_SMALL;
    }

    out_der_integer = out_der_integer.SubSpan(0, actually_written);

    return CHIP_NO_ERROR;
}

/**
 * @brief Find a 4 uppercase hex digit hex value after a prefix string. Used to implement
 *        fallback CN VID/PID encoding for PAA/PAI/DAC.
 *
 * @param[in] buffer - buffer in which to find the substring.
 * @param[in] prefix - prefix to match, which must be followed by 4 uppercase hex characters
 * @param[out] out_hex_value - on CHIP_NO_ERROR return, this will be the 16-bit hex value decoded.
 * @return CHIP_NO_ERROR on success, CHIP_ERROR_NOT_FOUND if not detected and
 *         CHIP_ERROR_WRONG_CERT_DN if we saw the prefix but no valid hex string.
 */
CHIP_ERROR Find16BitUpperCaseHexAfterPrefix(const ByteSpan & buffer, const char * prefix, uint16_t & out_hex_value)
{
    chip::CharSpan prefix_span = chip::CharSpan::fromCharString(prefix);

    bool found_prefix_at_least_once = false;

    // Scan string from left to right, to find the desired full matching substring.
    //
    // IMPORTANT NOTE: We are trying to find the equivalent of prefix + [0-9A-F]{4}.
    // The appearance of the full prefix, but not followed by the hex value, must
    // be detected, as it is illegal if there isn't a valid prefix within the string.
    // This is why we first check for the prefix and then maybe check for the hex
    // value, rather than doing a single check of making sure there is enough space
    // for both.
    for (size_t start_idx = 0; start_idx < buffer.size(); start_idx++)
    {
        const uint8_t * cursor = buffer.data() + start_idx;
        size_t remaining       = buffer.size() - start_idx;

        if (remaining < prefix_span.size())
        {
            // We can't possibly match prefix if not enough bytes left.
            break;
        }

        // Try to match the prefix at current position.
        if (memcmp(cursor, prefix_span.data(), prefix_span.size()) != 0)
        {
            // Did not find prefix, move to next position.
            continue;
        }

        // Otherwise, found prefix, skip to possible hex value.
        found_prefix_at_least_once = true;
        cursor += prefix_span.size();
        remaining -= prefix_span.size();

        constexpr size_t expected_hex_len = HEX_ENCODED_LENGTH(sizeof(uint16_t));
        if (remaining < expected_hex_len)
        {
            // We can't possibly match the hex values if not enough bytes left.
            break;
        }

        char hex_buf[expected_hex_len];
        memcpy(&hex_buf[0], cursor, sizeof(hex_buf));

        if (Encoding::UppercaseHexToUint16(&hex_buf[0], sizeof(hex_buf), out_hex_value) != 0)
        {
            // Found first full valid match, return success, out_hex_value already updated.
            return CHIP_NO_ERROR;
        }

        // Otherwise, did not find what we were looking for, try next position until exhausted.
    }

    return found_prefix_at_least_once ? CHIP_ERROR_WRONG_CERT_DN : CHIP_ERROR_NOT_FOUND;
}

} // namespace

using HKDF_sha_crypto = HKDF_sha;

CHIP_ERROR Spake2p::InternalHash(const uint8_t * in, size_t in_len)
{
    const uint64_t u64_len = in_len;

    uint8_t lb[8];
    lb[0] = static_cast<uint8_t>((u64_len >> 0) & 0xff);
    lb[1] = static_cast<uint8_t>((u64_len >> 8) & 0xff);
    lb[2] = static_cast<uint8_t>((u64_len >> 16) & 0xff);
    lb[3] = static_cast<uint8_t>((u64_len >> 24) & 0xff);
    lb[4] = static_cast<uint8_t>((u64_len >> 32) & 0xff);
    lb[5] = static_cast<uint8_t>((u64_len >> 40) & 0xff);
    lb[6] = static_cast<uint8_t>((u64_len >> 48) & 0xff);
    lb[7] = static_cast<uint8_t>((u64_len >> 56) & 0xff);

    ReturnErrorOnFailure(Hash(lb, sizeof(lb)));
    if (in != nullptr)
    {
        ReturnErrorOnFailure(Hash(in, in_len));
    }

    return CHIP_NO_ERROR;
}

Spake2p::Spake2p(size_t _fe_size, size_t _point_size, size_t _hash_size)
{
    fe_size    = _fe_size;
    point_size = _point_size;
    hash_size  = _hash_size;

    Kca = &Kcab[0];
    Kcb = &Kcab[hash_size / 2];
    Ka  = &Kae[0];
    Ke  = &Kae[hash_size / 2];

    M  = nullptr;
    N  = nullptr;
    G  = nullptr;
    X  = nullptr;
    Y  = nullptr;
    L  = nullptr;
    Z  = nullptr;
    V  = nullptr;
    w0 = nullptr;
    w1 = nullptr;
    xy = nullptr;

    order  = nullptr;
    tempbn = nullptr;
}

CHIP_ERROR Spake2p::Init(const uint8_t * context, size_t context_len)
{
    if (state != CHIP_SPAKE2P_STATE::PREINIT)
    {
        Clear();
    }

    ReturnErrorOnFailure(InitImpl());
    ReturnErrorOnFailure(PointLoad(spake2p_M_p256, sizeof(spake2p_M_p256), M));
    ReturnErrorOnFailure(PointLoad(spake2p_N_p256, sizeof(spake2p_N_p256), N));
    ReturnErrorOnFailure(InternalHash(context, context_len));

    state = CHIP_SPAKE2P_STATE::INIT;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::WriteMN()
{
    ReturnErrorOnFailure(InternalHash(spake2p_M_p256, sizeof(spake2p_M_p256)));
    ReturnErrorOnFailure(InternalHash(spake2p_N_p256, sizeof(spake2p_N_p256)));

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
                                  size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin,
                                  size_t Lin_len)
{
    VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::INIT, CHIP_ERROR_INTERNAL);

    ReturnErrorOnFailure(InternalHash(peer_identity, peer_identity_len));
    ReturnErrorOnFailure(InternalHash(my_identity, my_identity_len));
    ReturnErrorOnFailure(WriteMN());
    ReturnErrorOnFailure(FELoad(w0in, w0in_len, w0));
    ReturnErrorOnFailure(PointLoad(Lin, Lin_len, L));

    state = CHIP_SPAKE2P_STATE::STARTED;
    role  = CHIP_SPAKE2P_ROLE::VERIFIER;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
                                size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in,
                                size_t w1in_len)
{
    VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::INIT, CHIP_ERROR_INTERNAL);

    ReturnErrorOnFailure(InternalHash(my_identity, my_identity_len));
    ReturnErrorOnFailure(InternalHash(peer_identity, peer_identity_len));
    ReturnErrorOnFailure(WriteMN());
    ReturnErrorOnFailure(FELoad(w0in, w0in_len, w0));
    ReturnErrorOnFailure(FELoad(w1in, w1in_len, w1));

    state = CHIP_SPAKE2P_STATE::STARTED;
    role  = CHIP_SPAKE2P_ROLE::PROVER;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len)
{
    CHIP_ERROR error = CHIP_ERROR_INTERNAL;
    void * MN        = nullptr; // Choose M if a prover, N if a verifier
    void * XY        = nullptr; // Choose X if a prover, Y if a verifier

    VerifyOrExit(state == CHIP_SPAKE2P_STATE::STARTED, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(*out_len >= point_size, error = CHIP_ERROR_INTERNAL);

    ReturnErrorOnFailure(FEGenerate(xy));

    if (role == CHIP_SPAKE2P_ROLE::PROVER)
    {
        MN = M;
        XY = X;
    }
    else if (role == CHIP_SPAKE2P_ROLE::VERIFIER)
    {
        MN = N;
        XY = Y;
    }
    VerifyOrExit(MN != nullptr, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(XY != nullptr, error = CHIP_ERROR_INTERNAL);

    SuccessOrExit(error = PointAddMul(XY, G, xy, MN, w0));
    SuccessOrExit(error = PointWrite(XY, out, *out_len));

    state = CHIP_SPAKE2P_STATE::R1;
    error = CHIP_NO_ERROR;
exit:
    *out_len = point_size;
    return error;
}

CHIP_ERROR Spake2p::ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len)
{
    CHIP_ERROR error = CHIP_ERROR_INTERNAL;
    MutableByteSpan out_span{ out, *out_len };
    uint8_t point_buffer[kMAX_Point_Length];
    void * MN        = nullptr; // Choose N if a prover, M if a verifier
    void * XY        = nullptr; // Choose Y if a prover, X if a verifier
    uint8_t * Kcaorb = nullptr; // Choose Kca if a prover, Kcb if a verifier

    VerifyOrExit(*out_len >= hash_size, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(state == CHIP_SPAKE2P_STATE::R1, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(in_len == point_size, error = CHIP_ERROR_INTERNAL);

    if (role == CHIP_SPAKE2P_ROLE::PROVER)
    {
        SuccessOrExit(error = PointWrite(X, point_buffer, point_size));
        SuccessOrExit(error = InternalHash(point_buffer, point_size));
        SuccessOrExit(error = InternalHash(in, in_len));

        MN     = N;
        XY     = Y;
        Kcaorb = Kca;
    }
    else if (role == CHIP_SPAKE2P_ROLE::VERIFIER)
    {
        SuccessOrExit(error = InternalHash(in, in_len));
        SuccessOrExit(error = PointWrite(Y, point_buffer, point_size));
        SuccessOrExit(error = InternalHash(point_buffer, point_size));

        MN     = M;
        XY     = X;
        Kcaorb = Kcb;
    }
    VerifyOrExit(MN != nullptr, error = CHIP_ERROR_INTERNAL);
    VerifyOrExit(XY != nullptr, error = CHIP_ERROR_INTERNAL);

    SuccessOrExit(error = PointLoad(in, in_len, XY));
    SuccessOrExit(error = PointIsValid(XY));
    SuccessOrExit(error = FEMul(tempbn, xy, w0));
    SuccessOrExit(error = PointInvert(MN));
    SuccessOrExit(error = PointAddMul(Z, XY, xy, MN, tempbn));
    SuccessOrExit(error = PointCofactorMul(Z));

    if (role == CHIP_SPAKE2P_ROLE::PROVER)
    {
        SuccessOrExit(error = FEMul(tempbn, w1, w0));
        SuccessOrExit(error = PointAddMul(V, XY, w1, MN, tempbn));
    }
    else if (role == CHIP_SPAKE2P_ROLE::VERIFIER)
    {
        SuccessOrExit(error = PointMul(V, L, xy));
    }

    SuccessOrExit(error = PointCofactorMul(V));
    SuccessOrExit(error = PointWrite(Z, point_buffer, point_size));
    SuccessOrExit(error = InternalHash(point_buffer, point_size));

    SuccessOrExit(error = PointWrite(V, point_buffer, point_size));
    SuccessOrExit(error = InternalHash(point_buffer, point_size));

    SuccessOrExit(error = FEWrite(w0, point_buffer, fe_size));
    SuccessOrExit(error = InternalHash(point_buffer, fe_size));

    SuccessOrExit(error = GenerateKeys());

    SuccessOrExit(error = Mac(Kcaorb, hash_size / 2, in, in_len, out_span));
    VerifyOrExit(out_span.size() == hash_size, error = CHIP_ERROR_INTERNAL);

    state = CHIP_SPAKE2P_STATE::R2;
    error = CHIP_NO_ERROR;
exit:
    *out_len = hash_size;
    return error;
}

CHIP_ERROR Spake2p::GenerateKeys()
{
    static const uint8_t info_keyconfirm[16] = { 'C', 'o', 'n', 'f', 'i', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'K', 'e', 'y', 's' };

    MutableByteSpan Kae_span{ &Kae[0], sizeof(Kae) };

    ReturnErrorOnFailure(HashFinalize(Kae_span));
    ReturnErrorOnFailure(KDF(Ka, hash_size / 2, nullptr, 0, info_keyconfirm, sizeof(info_keyconfirm), Kcab, hash_size));

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::KeyConfirm(const uint8_t * in, size_t in_len)
{
    uint8_t point_buffer[kP256_Point_Length];
    void * XY        = nullptr; // Choose X if a prover, Y if a verifier
    uint8_t * Kcaorb = nullptr; // Choose Kcb if a prover, Kca if a verifier

    VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::R2, CHIP_ERROR_INTERNAL);

    if (role == CHIP_SPAKE2P_ROLE::PROVER)
    {
        XY     = X;
        Kcaorb = Kcb;
    }
    else if (role == CHIP_SPAKE2P_ROLE::VERIFIER)
    {
        XY     = Y;
        Kcaorb = Kca;
    }
    VerifyOrReturnError(XY != nullptr, CHIP_ERROR_INTERNAL);
    VerifyOrReturnError(Kcaorb != nullptr, CHIP_ERROR_INTERNAL);

    ReturnErrorOnFailure(PointWrite(XY, point_buffer, point_size));

    CHIP_ERROR err = MacVerify(Kcaorb, hash_size / 2, in, in_len, point_buffer, point_size);
    if (err == CHIP_ERROR_INTERNAL)
    {
        ChipLogError(SecureChannel, "Failed to verify peer's MAC. This can happen when setup code is incorrect.");
    }
    ReturnErrorOnFailure(err);

    state = CHIP_SPAKE2P_STATE::KC;
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p::GetKeys(SessionKeystore & keystore, HkdfKeyHandle & key)
{
    VerifyOrReturnError(state == CHIP_SPAKE2P_STATE::KC, CHIP_ERROR_INTERNAL);

    return keystore.CreateKey(ByteSpan(Ke, hash_size / 2), key);
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitImpl()
{
    ReturnErrorOnFailure(sha256_hash_ctx.Begin());
    ReturnErrorOnFailure(InitInternal());
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Hash(const uint8_t * in, size_t in_len)
{
    ReturnErrorOnFailure(sha256_hash_ctx.AddData(ByteSpan{ in, in_len }));
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::HashFinalize(MutableByteSpan & out_span)
{
    ReturnErrorOnFailure(sha256_hash_ctx.Finish(out_span));
    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::KDF(const uint8_t * ikm, const size_t ikm_len, const uint8_t * salt,
                                              const size_t salt_len, const uint8_t * info, const size_t info_len, uint8_t * out,
                                              size_t out_len)
{
    HKDF_sha_crypto mHKDF;

    ReturnErrorOnFailure(mHKDF.HKDF_SHA256(ikm, ikm_len, salt, salt_len, info, info_len, out, out_len));

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeW0(uint8_t * w0out, size_t * w0_len, const uint8_t * w0sin, size_t w0sin_len)
{
    ReturnErrorOnFailure(FELoad(w0sin, w0sin_len, w0));
    ReturnErrorOnFailure(FEWrite(w0, w0out, *w0_len));

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Serialize(MutableByteSpan & outSerialized) const
{
    VerifyOrReturnError(outSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

    memcpy(&outSerialized.data()[0], mW0, sizeof(mW0));
    memcpy(&outSerialized.data()[sizeof(mW0)], mL, sizeof(mL));

    outSerialized.reduce_size(kSpake2p_VerifierSerialized_Length);

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Deserialize(const ByteSpan & inSerialized)
{
    VerifyOrReturnError(inSerialized.size() >= kSpake2p_VerifierSerialized_Length, CHIP_ERROR_INVALID_ARGUMENT);

    memcpy(mW0, &inSerialized.data()[0], sizeof(mW0));
    memcpy(mL, &inSerialized.data()[sizeof(mW0)], sizeof(mL));

    return CHIP_NO_ERROR;
}

CHIP_ERROR Spake2pVerifier::Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin)
{
    uint8_t serializedWS[kSpake2p_WS_Length * 2] = { 0 };
    ReturnErrorOnFailure(ComputeWS(pbkdf2IterCount, salt, setupPin, serializedWS, sizeof(serializedWS)));

    CHIP_ERROR err = CHIP_NO_ERROR;
    size_t len;

    // Create local Spake2+ object for w0 and L computations.
    Spake2p_P256_SHA256_HKDF_HMAC spake2p;
    uint8_t context[kSHA256_Hash_Length] = { 0 };
    SuccessOrExit(err = spake2p.Init(context, sizeof(context)));

    // Compute w0
    len = sizeof(mW0);
    SuccessOrExit(err = spake2p.ComputeW0(mW0, &len, &serializedWS[0], kSpake2p_WS_Length));
    VerifyOrExit(len == sizeof(mW0), err = CHIP_ERROR_INTERNAL);

    // Compute L
    len = sizeof(mL);
    SuccessOrExit(err = spake2p.ComputeL(mL, &len, &serializedWS[kSpake2p_WS_Length], kSpake2p_WS_Length));
    VerifyOrExit(len == sizeof(mL), err = CHIP_ERROR_INTERNAL);

exit:
    spake2p.Clear();
    return err;
}

CHIP_ERROR Spake2pVerifier::ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws,
                                      uint32_t ws_len)
{
    PBKDF2_sha256 pbkdf2;
    uint8_t littleEndianSetupPINCode[sizeof(uint32_t)];
    Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setupPin);

    VerifyOrReturnError(salt.size() >= kSpake2p_Min_PBKDF_Salt_Length && salt.size() <= kSpake2p_Max_PBKDF_Salt_Length,
                        CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(pbkdf2IterCount >= kSpake2p_Min_PBKDF_Iterations && pbkdf2IterCount <= kSpake2p_Max_PBKDF_Iterations,
                        CHIP_ERROR_INVALID_ARGUMENT);

    return pbkdf2.pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt.data(), salt.size(),
                                pbkdf2IterCount, ws_len, ws);
}

CHIP_ERROR ReadDerLength(Reader & reader, size_t & length)
{
    length = 0;

    uint8_t cur_byte = 0;
    ReturnErrorOnFailure(reader.Read8(&cur_byte).StatusCode());

    if ((cur_byte & (1u << 7)) == 0)
    {
        // 7 bit length, the rest of the byte is the length.
        length = cur_byte & 0x7Fu;
        return CHIP_NO_ERROR;
    }

    CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT;

    // Did not early return: > 7 bit length, the number of bytes of the length is provided next.
    uint8_t length_bytes = cur_byte & 0x7Fu;
    VerifyOrReturnError((length_bytes >= 1) && (length_bytes <= sizeof(size_t)), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(reader.HasAtLeast(length_bytes), CHIP_ERROR_BUFFER_TOO_SMALL);

    for (uint8_t i = 0; i < length_bytes; i++)
    {
        uint8_t cur_length_byte = 0;
        err                     = reader.Read8(&cur_length_byte).StatusCode();
        if (err != CHIP_NO_ERROR)
            break;

        // Cannot have zero padding on multi-byte lengths in DER, so first
        // byte must always be > 0.
        if ((i == 0) && (cur_length_byte == 0))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        length <<= 8;
        length |= cur_length_byte;
    }

    // Single-byte long length cannot be < 128: DER always encodes on smallest size
    // possible, so length zero should have been a single byte short length.
    if ((length_bytes == 1) && (length < 128))
    {
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer)
{
    return ConvertIntegerRawToDerInternal(raw_integer, out_der_integer, /* include_tag_and_length = */ false);
}

CHIP_ERROR ConvertIntegerRawToDer(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer)
{
    return ConvertIntegerRawToDerInternal(raw_integer, out_der_integer, /* include_tag_and_length = */ true);
}

CHIP_ERROR EcdsaRawSignatureToAsn1(size_t fe_length_bytes, const ByteSpan & raw_sig, MutableByteSpan & out_asn1_sig)
{
    VerifyOrReturnError(fe_length_bytes > 0, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(raw_sig.size() == (2u * fe_length_bytes), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(out_asn1_sig.size() >= (raw_sig.size() + kMax_ECDSA_X9Dot62_Asn1_Overhead), CHIP_ERROR_BUFFER_TOO_SMALL);

    // Write both R an S integers past the overhead, we will shift them back later if we only needed 2 size bytes.
    uint8_t * cursor = out_asn1_sig.data() + kMinSequenceOverhead;
    size_t remaining = out_asn1_sig.size() - kMinSequenceOverhead;

    size_t integers_length = 0;

    // Write R (first `fe_length_bytes` block of raw signature)
    {
        MutableByteSpan out_der_integer(cursor, remaining);
        ReturnErrorOnFailure(ConvertIntegerRawToDer(raw_sig.SubSpan(0, fe_length_bytes), out_der_integer));
        VerifyOrReturnError(out_der_integer.size() <= remaining, CHIP_ERROR_INTERNAL);

        integers_length += out_der_integer.size();
        remaining -= out_der_integer.size();
        cursor += out_der_integer.size();
    }

    // Write S (second `fe_length_bytes` block of raw signature)
    {
        MutableByteSpan out_der_integer(cursor, remaining);
        ReturnErrorOnFailure(ConvertIntegerRawToDer(raw_sig.SubSpan(fe_length_bytes, fe_length_bytes), out_der_integer));
        VerifyOrReturnError(out_der_integer.size() <= remaining, CHIP_ERROR_INTERNAL);
        integers_length += out_der_integer.size();
    }

    // We only support outputs that would use 1 or 2 bytes of DER length after the SEQUENCE tag
    VerifyOrReturnError(integers_length <= UINT8_MAX, CHIP_ERROR_INVALID_ARGUMENT);

    // We now know the length of both variable sized integers in the sequence, so we
    // can write the tag and length.
    BufferWriter writer(out_asn1_sig);

    // Put SEQUENCE tag
    writer.Put(kSeqTag);

    // Put the length over 1 or two bytes depending on case
    constexpr uint8_t kExtendedLengthMarker = 0x80u;
    if (integers_length > 127u)
    {
        writer.Put(static_cast<uint8_t>(kExtendedLengthMarker | 1)); // Length is extended length, over 1 subsequent byte
        writer.Put(static_cast<uint8_t>(integers_length));
    }
    else
    {
        // Length is directly in the first byte with MSB clear if <= 127.
        writer.Put(static_cast<uint8_t>(integers_length));
    }

    // Put the contents of the integers previously serialized in the buffer.
    // The writer.Put is memmove-safe, so the shifting will happen from the read
    // of the same buffer where the write is taking place.
    writer.Put(out_asn1_sig.data() + kMinSequenceOverhead, integers_length);

    size_t actually_written = 0;
    VerifyOrReturnError(writer.Fit(actually_written), CHIP_ERROR_BUFFER_TOO_SMALL);

    out_asn1_sig = out_asn1_sig.SubSpan(0, actually_written);
    return CHIP_NO_ERROR;
}

CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1_sig, MutableByteSpan & out_raw_sig)
{
    VerifyOrReturnError(fe_length_bytes > 0, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(asn1_sig.size() > kMinSequenceOverhead, CHIP_ERROR_BUFFER_TOO_SMALL);

    // Output raw signature is <r,s> both of which are of fe_length_bytes (see SEC1).
    VerifyOrReturnError(out_raw_sig.size() >= (2u * fe_length_bytes), CHIP_ERROR_BUFFER_TOO_SMALL);

    Reader reader(asn1_sig);

    // Make sure we have a starting Sequence
    uint8_t tag = 0;
    ReturnErrorOnFailure(reader.Read8(&tag).StatusCode());
    VerifyOrReturnError(tag == kSeqTag, CHIP_ERROR_INVALID_ARGUMENT);

    // Read length of sequence
    size_t tag_len = 0;
    ReturnErrorOnFailure(ReadDerLength(reader, tag_len));

    // Length of sequence must match what is left of signature
    VerifyOrReturnError(tag_len == reader.Remaining(), CHIP_ERROR_INVALID_ARGUMENT);

    // Can now clear raw signature integers r,s one by one
    uint8_t * raw_cursor = out_raw_sig.data();

    // Read R
    ReturnErrorOnFailure(ReadDerUnsignedIntegerIntoRaw(reader, MutableByteSpan{ raw_cursor, fe_length_bytes }));

    raw_cursor += fe_length_bytes;

    // Read S
    ReturnErrorOnFailure(ReadDerUnsignedIntegerIntoRaw(reader, MutableByteSpan{ raw_cursor, fe_length_bytes }));

    out_raw_sig = out_raw_sig.SubSpan(0, (2u * fe_length_bytes));

    return CHIP_NO_ERROR;
}

CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128KeyHandle & key, const uint8_t * nonce,
                         size_t nonce_length, uint8_t * output)
{
    // Discard tag portion of CCM to apply only CTR mode encryption/decryption.
    constexpr size_t kTagLen = Crypto::kAES_CCM128_Tag_Length;
    uint8_t tag[kTagLen];

    return AES_CCM_encrypt(input, input_length, nullptr, 0, key, nonce, nonce_length, output, tag, kTagLen);
}

CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & root_public_key, uint64_t fabric_id,
                                      MutableByteSpan & out_compressed_fabric_id)
{
    VerifyOrReturnError(root_public_key.IsUncompressed(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(out_compressed_fabric_id.size() >= kCompressedFabricIdentifierSize, CHIP_ERROR_BUFFER_TOO_SMALL);

    // Ensure proper endianness for Fabric ID (i.e. big-endian as it appears in certificates)
    uint8_t fabric_id_as_big_endian_salt[kCompressedFabricIdentifierSize];
    chip::Encoding::BigEndian::Put64(&fabric_id_as_big_endian_salt[0], fabric_id);

    // Compute Compressed fabric reference per spec pseudocode
    //   CompressedFabricIdentifier =
    //     CHIP_Crypto_KDF(
    //       inputKey := TargetOperationalRootPublicKey,
    //       salt:= TargetOperationalFabricID,
    //       info := CompressedFabricInfo,
    //       len := 64)
    //
    // NOTE: len=64 bits is implied by output buffer size when calling HKDF_sha::HKDF_SHA256.

    constexpr uint8_t kCompressedFabricInfo[16] = /* "CompressedFabric" */
        { 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x46, 0x61, 0x62, 0x72, 0x69, 0x63 };
    HKDF_sha hkdf;

    // Must drop uncompressed point form format specifier (first byte), per spec method
    ByteSpan input_key_span(root_public_key.ConstBytes() + 1, root_public_key.Length() - 1);

    CHIP_ERROR status = hkdf.HKDF_SHA256(
        input_key_span.data(), input_key_span.size(), &fabric_id_as_big_endian_salt[0], sizeof(fabric_id_as_big_endian_salt),
        &kCompressedFabricInfo[0], sizeof(kCompressedFabricInfo), out_compressed_fabric_id.data(), kCompressedFabricIdentifierSize);

    // Resize output to final bounds on success
    if (status == CHIP_NO_ERROR)
    {
        out_compressed_fabric_id = out_compressed_fabric_id.SubSpan(0, kCompressedFabricIdentifierSize);
    }

    return status;
}

CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & rootPublicKey, uint64_t fabricId, uint64_t & compressedFabricId)
{
    uint8_t allocated[sizeof(fabricId)];
    MutableByteSpan span(allocated);
    ReturnErrorOnFailure(GenerateCompressedFabricId(rootPublicKey, fabricId, span));
    // Decode compressed fabric ID accounting for endianness, as GenerateCompressedFabricId()
    // returns a binary buffer and is agnostic of usage of the output as an integer type.
    compressedFabricId = Encoding::BigEndian::Get64(allocated);
    return CHIP_NO_ERROR;
}

/* Operational Group Key Group, Security Info: "GroupKey v1.0" */
static const uint8_t kGroupSecurityInfo[] = { 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30 };

/* Group Key Derivation Function, Info: "GroupKeyHash" ” */
static const uint8_t kGroupKeyHashInfo[]  = { 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x48, 0x61, 0x73, 0x68 };
static const uint8_t kGroupKeyHashSalt[0] = {};

/*
    OperationalGroupKey =
        Crypto_KDF
        (
            InputKey = Epoch Key,
            Salt = CompressedFabricIdentifier,
            Info = "GroupKey v1.0",
            Length = CRYPTO_SYMMETRIC_KEY_LENGTH_BITS
        )
*/
CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id, MutableByteSpan & out_key)
{
    VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == epoch_key.size(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES <= out_key.size(), CHIP_ERROR_INVALID_ARGUMENT);

    Crypto::HKDF_sha crypto;
    return crypto.HKDF_SHA256(epoch_key.data(), epoch_key.size(), compressed_fabric_id.data(), compressed_fabric_id.size(),
                              kGroupSecurityInfo, sizeof(kGroupSecurityInfo), out_key.data(),
                              Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);
}

/*
    GKH = Crypto_KDF (
        InputKey = OperationalGroupKey,
        Salt = [],
        Info = "GroupKeyHash",
        Length = 16)
*/
CHIP_ERROR DeriveGroupSessionId(const ByteSpan & operational_key, uint16_t & session_id)
{
    VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == operational_key.size(), CHIP_ERROR_INVALID_ARGUMENT);
    Crypto::HKDF_sha crypto;
    uint8_t out_key[sizeof(uint16_t)];

    ReturnErrorOnFailure(crypto.HKDF_SHA256(operational_key.data(), operational_key.size(), kGroupKeyHashSalt,
                                            sizeof(kGroupKeyHashSalt), kGroupKeyHashInfo, sizeof(kGroupKeyHashInfo), out_key,
                                            sizeof(out_key)));
    session_id = Encoding::BigEndian::Get16(out_key);
    return CHIP_NO_ERROR;
}

/* Operational Group Key Group, PrivacyKey Info: "PrivacyKey" */
static const uint8_t kGroupPrivacyInfo[] = { 'P', 'r', 'i', 'v', 'a', 'c', 'y', 'K', 'e', 'y' };

/*
    PrivacyKey =
         Crypto_KDF
         (
            InputKey = EncryptionKey,
            Salt = [],
            Info = "PrivacyKey",
            Length = CRYPTO_SYMMETRIC_KEY_LENGTH_BITS
         )
*/
CHIP_ERROR DeriveGroupPrivacyKey(const ByteSpan & encryption_key, MutableByteSpan & out_key)
{
    VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == encryption_key.size(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES <= out_key.size(), CHIP_ERROR_INVALID_ARGUMENT);

    constexpr ByteSpan null_span = ByteSpan();

    Crypto::HKDF_sha crypto;
    return crypto.HKDF_SHA256(encryption_key.data(), encryption_key.size(), null_span.data(), null_span.size(), kGroupPrivacyInfo,
                              sizeof(kGroupPrivacyInfo), out_key.data(), Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);
}

CHIP_ERROR DeriveGroupOperationalCredentials(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id,
                                             GroupOperationalCredentials & operational_credentials)
{
    MutableByteSpan encryption_key(operational_credentials.encryption_key);
    MutableByteSpan privacy_key(operational_credentials.privacy_key);

    ReturnErrorOnFailure(Crypto::DeriveGroupOperationalKey(epoch_key, compressed_fabric_id, encryption_key));
    ReturnErrorOnFailure(Crypto::DeriveGroupSessionId(encryption_key, operational_credentials.hash));
    ReturnErrorOnFailure(Crypto::DeriveGroupPrivacyKey(encryption_key, privacy_key));

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractVIDPIDFromAttributeString(DNAttrType attrType, const ByteSpan & attr,
                                            AttestationCertVidPid & vidpidFromMatterAttr, AttestationCertVidPid & vidpidFromCNAttr)
{
    VerifyOrReturnError(attrType != DNAttrType::kUnspecified, CHIP_NO_ERROR);
    VerifyOrReturnError(!attr.empty(), CHIP_ERROR_INVALID_ARGUMENT);

    if (attrType == DNAttrType::kMatterVID || attrType == DNAttrType::kMatterPID)
    {
        uint16_t matterAttr;
        VerifyOrReturnError(attr.size() == kVIDandPIDHexLength, CHIP_ERROR_WRONG_CERT_DN);
        VerifyOrReturnError(Encoding::UppercaseHexToUint16(reinterpret_cast<const char *>(attr.data()), attr.size(), matterAttr) ==
                                sizeof(matterAttr),
                            CHIP_ERROR_WRONG_CERT_DN);

        if (attrType == DNAttrType::kMatterVID)
        {
            // Not more than one VID attribute can be present.
            VerifyOrReturnError(!vidpidFromMatterAttr.mVendorId.HasValue(), CHIP_ERROR_WRONG_CERT_DN);
            vidpidFromMatterAttr.mVendorId.SetValue(static_cast<VendorId>(matterAttr));
        }
        else
        {
            // Not more than one PID attribute can be present.
            VerifyOrReturnError(!vidpidFromMatterAttr.mProductId.HasValue(), CHIP_ERROR_WRONG_CERT_DN);
            vidpidFromMatterAttr.mProductId.SetValue(matterAttr);
        }
    }
    // Otherwise, it is a CommonName attribute.
    else if (!vidpidFromCNAttr.Initialized())
    {
        ByteSpan attr_source_span{ attr };
        if (attr_source_span.size() > chip::Crypto::kMax_CommonNameAttr_Length)
        {
            attr_source_span.reduce_size(chip::Crypto::kMax_CommonNameAttr_Length);
        }

        // Try to find a valid Vendor ID encoded in fallback method.
        uint16_t vid   = 0;
        CHIP_ERROR err = Find16BitUpperCaseHexAfterPrefix(attr_source_span, kVIDPrefixForCNEncoding, vid);
        if (err == CHIP_NO_ERROR)
        {
            vidpidFromCNAttr.mVendorId.SetValue(static_cast<VendorId>(vid));
        }
        else if (err != CHIP_ERROR_NOT_FOUND)
        {
            // This indicates a bad/ambiguous format.
            return err;
        }

        // Try to find a valid Product ID encoded in fallback method.
        uint16_t pid = 0;
        err          = Find16BitUpperCaseHexAfterPrefix(attr_source_span, kPIDPrefixForCNEncoding, pid);
        if (err == CHIP_NO_ERROR)
        {
            vidpidFromCNAttr.mProductId.SetValue(pid);
        }
        else if (err != CHIP_ERROR_NOT_FOUND)
        {
            // This indicates a bad/ambiguous format.
            return err;
        }
    }

    return CHIP_NO_ERROR;
}

// Generates the to-be-signed portion of a PKCS#10 CSR (`CertificationRequestInformation`)
// that contains the
static CHIP_ERROR GenerateCertificationRequestInformation(ASN1Writer & writer, const Crypto::P256PublicKey & pubkey)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    /**
     *
     *  CertificationRequestInfo ::=
     *     SEQUENCE {
     *        version       INTEGER { v1(0) } (v1,...),
     *        subject       Name,
     *        subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
     *        attributes    [0] Attributes{{ CRIAttributes }}
     * }
     */
    ASN1_START_SEQUENCE
    {
        ASN1_ENCODE_INTEGER(0); // version INTEGER { v1(0) }

        // subject Name
        ASN1_START_SEQUENCE
        {
            ASN1_START_SET
            {
                ASN1_START_SEQUENCE
                {
                    // Any subject, placeholder is good, since this
                    // is going to usually be ignored
                    ASN1_ENCODE_OBJECT_ID(kOID_AttributeType_OrganizationalUnitName);
                    ASN1_ENCODE_STRING(kASN1UniversalTag_UTF8String, "CSA", static_cast<uint16_t>(strlen("CSA")));
                }
                ASN1_END_SEQUENCE;
            }
            ASN1_END_SET;
        }
        ASN1_END_SEQUENCE;

        // subjectPKInfo
        ASN1_START_SEQUENCE
        {
            ASN1_START_SEQUENCE
            {
                ASN1_ENCODE_OBJECT_ID(kOID_PubKeyAlgo_ECPublicKey);
                ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
            }
            ASN1_END_SEQUENCE;
            ReturnErrorOnFailure(writer.PutBitString(0, pubkey, static_cast<uint8_t>(pubkey.Length())));
        }
        ASN1_END_SEQUENCE;

        // attributes [0]
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            // Using a plain empty attributes request
            ASN1_START_SEQUENCE
            {
                ASN1_ENCODE_OBJECT_ID(kOID_Extension_CSRRequest);
                ASN1_START_SET
                {
                    ASN1_START_SEQUENCE {}
                    ASN1_END_SEQUENCE;
                }
                ASN1_END_SET;
            }
            ASN1_END_SEQUENCE;
        }
        ASN1_END_CONSTRUCTED;
    }
    ASN1_END_SEQUENCE;
exit:
    return err;
}

CHIP_ERROR GenerateCertificateSigningRequest(const P256Keypair * keypair, MutableByteSpan & csr_span)
{
    VerifyOrReturnError(keypair != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(csr_span.size() >= kMIN_CSR_Buffer_Size, CHIP_ERROR_BUFFER_TOO_SMALL);

    // First pass: Generate the CertificatioRequestInformation inner
    // encoding one time, to sign it, before re-generating it within the
    // full ASN1 writer later, since it's easier than trying to
    // figure-out the span we need to sign of the overall object.
    P256ECDSASignature signature;

    {
        // The first pass will just generate a signature, so we can use the
        // output buffer as scratch to avoid needing more stack space. There
        // are no secrets here and the contents is not reused since all we
        // need is the signature which is already separately stored.
        ASN1Writer toBeSignedWriter;
        toBeSignedWriter.Init(csr_span);
        CHIP_ERROR err = GenerateCertificationRequestInformation(toBeSignedWriter, keypair->Pubkey());
        ReturnErrorOnFailure(err);

        size_t encodedLen = (uint16_t) toBeSignedWriter.GetLengthWritten();
        // This should not/will not happen
        if (encodedLen > csr_span.size())
        {
            return CHIP_ERROR_INTERNAL;
        }

        err = keypair->ECDSA_sign_msg(csr_span.data(), encodedLen, signature);
        ReturnErrorOnFailure(err);
    }

    // Second pass: Generate the entire CSR body, restarting a new write
    // of the CertificationRequestInformation (cheap) and adding the
    // signature.
    //
    // See RFC2986 for ASN.1 module, repeated here in snippets
    CHIP_ERROR err = CHIP_NO_ERROR;

    ASN1Writer writer;
    writer.Init(csr_span);

    ASN1_START_SEQUENCE
    {

        /*  CertificationRequestInfo ::=
         *     SEQUENCE {
         *        version       INTEGER { v1(0) } (v1,...),
         *        subject       Name,
         *        subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
         *        attributes    [0] Attributes{{ CRIAttributes }}
         *     }
         */
        GenerateCertificationRequestInformation(writer, keypair->Pubkey());

        // algorithm  AlgorithmIdentifier
        ASN1_START_SEQUENCE
        {
            // See RFC5480 sec 2.1
            ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
        }
        ASN1_END_SEQUENCE;

        // signature  BIT STRING --> ECDSA-with-SHA256 signature with P256 key with R,S integers format
        // (see RFC3279 sec 2.2.3 ECDSA Signature Algorithm)
        ASN1_START_BIT_STRING_ENCAPSULATED
        {
            // Convert raw signature to embedded signature
            FixedByteSpan<Crypto::kP256_ECDSA_Signature_Length_Raw> rawSig(signature.Bytes());

            uint8_t derInt[kP256_FE_Length + kEmitDerIntegerWithoutTagOverhead];

            // Ecdsa-Sig-Value ::= SEQUENCE
            ASN1_START_SEQUENCE
            {
                using P256IntegerSpan = FixedByteSpan<Crypto::kP256_FE_Length>;
                // r INTEGER
                {
                    MutableByteSpan derIntSpan(derInt, sizeof(derInt));
                    ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data()), derIntSpan));
                    ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false,
                                                         derIntSpan.data(), static_cast<uint16_t>(derIntSpan.size())));
                }

                // s INTEGER
                {
                    MutableByteSpan derIntSpan(derInt, sizeof(derInt));
                    ReturnErrorOnFailure(
                        ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data() + kP256_FE_Length), derIntSpan));
                    ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false,
                                                         derIntSpan.data(), static_cast<uint16_t>(derIntSpan.size())));
                }
            }
            ASN1_END_SEQUENCE;
        }
        ASN1_END_ENCAPSULATED;
    }
    ASN1_END_SEQUENCE;

exit:
    // Update size of output buffer on success
    if (err == CHIP_NO_ERROR)
    {
        csr_span.reduce_size(writer.GetLengthWritten());
    }
    return err;
}

CHIP_ERROR VerifyCertificateSigningRequestFormat(const uint8_t * csr, size_t csr_length)
{
    // Ensure we have enough size to validate header, and that our assumptions are met
    // for some tag computations below. A csr_length > 65535 would never be seen in
    // practice.
    VerifyOrReturnError((csr_length >= 16) && (csr_length <= 65535), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);

    Reader reader(csr, csr_length);

    // Ensure we have an outermost SEQUENCE
    uint8_t seq_header = 0;
    ReturnErrorOnFailure(reader.Read8(&seq_header).StatusCode());
    VerifyOrReturnError(seq_header == kSeqTag, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);

    size_t seq_length = 0;
    VerifyOrReturnError(ReadDerLength(reader, seq_length) == CHIP_NO_ERROR, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
    // Ensure that outer length matches sequence length + tag overhead, otherwise
    // we have trailing garbage
    size_t header_overhead = (seq_length <= 127) ? 2 : ((seq_length <= 255) ? 3 : 4);
    VerifyOrReturnError(csr_length == (seq_length + header_overhead), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);

    return CHIP_NO_ERROR;
}

} // namespace Crypto
} // namespace chip
