/*
 *
 *    Copyright (c) 2019 Google LLC.
 *    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 objects for modeling and working with
 *      Weave security certificates.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <Weave/Core/WeaveCore.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Support/ASN1.h>
#include <Weave/Support/crypto/HashAlgos.h>
#include <Weave/Support/crypto/EllipticCurve.h>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Profiles/security/WeaveCert.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Support/TimeUtils.h>

namespace nl {
namespace Weave {
namespace Profiles {
namespace Security {

using namespace nl::Weave::ASN1;
using namespace nl::Weave::TLV;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Crypto;

extern WEAVE_ERROR DecodeConvertTBSCert(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData);

#if HAVE_MALLOC && HAVE_FREE
static void *DefaultAlloc(size_t size)
{
    return malloc(size);
}

static void DefaultFree(void *p)
{
    free(p);
}
#endif // HAVE_MALLOC && HAVE_FREE

WEAVE_ERROR WeaveCertificateSet::Init(uint8_t maxCerts, uint16_t decodeBufSize)
{
#if HAVE_MALLOC && HAVE_FREE
    return Init(maxCerts, decodeBufSize, DefaultAlloc, DefaultFree);
#else
    return WEAVE_ERROR_UNSUPPORTED_WEAVE_FEATURE;
#endif // HAVE_MALLOC && HAVE_FREE
}

WeaveCertificateSet::WeaveCertificateSet()
{
    memset(this, 0, sizeof(*this));
}

WEAVE_ERROR WeaveCertificateSet::Init(uint8_t maxCerts, uint16_t decodeBufSize, AllocFunct allocFunct, FreeFunct freeFunct)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    Certs = (WeaveCertificateData *)allocFunct(sizeof(WeaveCertificateData) * maxCerts);
    VerifyOrExit(Certs != NULL, err = WEAVE_ERROR_NO_MEMORY);

    CertCount = 0;
    MaxCerts = maxCerts;

    mDecodeBuf = NULL;
    mDecodeBufSize = decodeBufSize;

    mAllocFunct = allocFunct;
    mFreeFunct = freeFunct;

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::Init(WeaveCertificateData *certsArray, uint8_t certArraySize, uint8_t *decodeBuf, uint16_t decodeBufSize)
{
    Certs = certsArray;
    CertCount = 0;
    MaxCerts = certArraySize;
    mDecodeBuf = decodeBuf;
    mDecodeBufSize = decodeBufSize;
    mAllocFunct = NULL;
    mFreeFunct = NULL;
    return WEAVE_NO_ERROR;
}

void WeaveCertificateSet::Release()
{
    if (mFreeFunct != NULL)
    {
        if (Certs != NULL)
        {
            mFreeFunct(Certs);
            Certs = NULL;
        }
        if (mDecodeBuf != NULL)
        {
            mFreeFunct(mDecodeBuf);
            mDecodeBuf = NULL;
        }
    }
}

void WeaveCertificateSet::Clear()
{
    memset(Certs, 0, sizeof(WeaveCertificateData) * MaxCerts);
    CertCount = 0;
}

WeaveCertificateData *WeaveCertificateSet::FindCert(const CertificateKeyId& subjectKeyId) const
{
    for (uint8_t i = 0; i < CertCount; i++)
    {
        WeaveCertificateData& cert = Certs[i];
        if (cert.SubjectKeyId.IsEqual(subjectKeyId))
            return &cert;
    }
    return NULL;
}

WEAVE_ERROR WeaveCertificateSet::LoadCert(const uint8_t *weaveCert, uint32_t weaveCertLen, uint16_t decodeFlags, WeaveCertificateData *& cert)
{
    WEAVE_ERROR err;
    TLVReader reader;

    reader.Init(weaveCert, weaveCertLen);
    reader.ImplicitProfileId = kWeaveProfile_Security;

    err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate));
    SuccessOrExit(err);

    err = LoadCert(reader, decodeFlags, cert);

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::LoadCert(TLVReader& reader, uint16_t decodeFlags, WeaveCertificateData *& cert)
{
    WEAVE_ERROR err;

    cert = NULL;

    // Verify we have room for the new certificate.
    VerifyOrExit(CertCount < MaxCerts, err = WEAVE_ERROR_NO_MEMORY);

    cert = &Certs[CertCount];

    err = LoadCertToElement(reader, decodeFlags, cert);
    SuccessOrExit(err);

    CertCount++;

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::LoadCertToElement(TLVReader& reader, uint16_t decodeFlags, WeaveCertificateData * cert)
{
    WEAVE_ERROR err;
    ASN1Writer writer;
    uint8_t *decodeBuf = mDecodeBuf;

    // Must be positioned on the structure element representing the certificate.
    VerifyOrExit(reader.GetType() == kTLVType_Structure, err = WEAVE_ERROR_INVALID_ARGUMENT);

    if (decodeBuf == NULL && mAllocFunct != NULL)
        decodeBuf = (uint8_t *)(mAllocFunct(mDecodeBufSize));
    VerifyOrExit(decodeBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    VerifyOrExit(cert != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
    memset(cert, 0, sizeof(*cert));

    // Record the starting point of the certificate's elements.
    cert->EncodedCert = reader.GetReadPoint();

    {
        TLVType containerType;

        // Enter the certificate structure...
        err = reader.EnterContainer(containerType);
        SuccessOrExit(err);

        // Initialize an ASN1Writer and convert the TBS (to-be-signed) portion of the certificate to ASN.1 DER
        // encoding.  At the same time, parse various components within the certificate and set the corresponding
        // fields in the CertificateData object.
        writer.Init(decodeBuf, mDecodeBufSize);
        err = DecodeConvertTBSCert(reader, writer, *cert);
        SuccessOrExit(err);

        // Verify the cert has both the Subject Key Id and Authority Key Id extensions present.
        // Only certs with both these extensions are supported for the purposes of certificate validation.
        {
            const uint16_t expectedFlags = kCertFlag_ExtPresent_SubjectKeyId | kCertFlag_ExtPresent_AuthKeyId;
            VerifyOrExit((cert->CertFlags & expectedFlags) == expectedFlags, err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT);
        }

        // Verify the cert was signed with ECDSA-SHA1 or ECDSA-SHA256. These are the only signature algorithms
        // currently supported.
        VerifyOrExit((cert->SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA1 || cert->SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256),
                     err = WEAVE_ERROR_UNSUPPORTED_SIGNATURE_TYPE);

        // If requested, generate the hash of the TBS portion of the certificate...
        if ((decodeFlags & kDecodeFlag_GenerateTBSHash) != 0)
        {
            // Finish writing the ASN.1 DER encoding of the TBS certificate.
            err = writer.Finalize();
            SuccessOrExit(err);

            // Generate a SHA hash of the encoded TBS certificate.
            if (cert->SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA1)
            {
                Platform::Security::SHA1 sha1;
                sha1.Begin();
                sha1.AddData(decodeBuf, writer.GetLengthWritten());
                sha1.Finish(cert->TBSHash);
            }
            else
            {
                Platform::Security::SHA256 sha256;
                sha256.Begin();
                sha256.AddData(decodeBuf, writer.GetLengthWritten());
                sha256.Finish(cert->TBSHash);
            }

            cert->CertFlags |= kCertFlag_TBSHashPresent;
        }

        // Extract the certificate's signature...
        {
            TLVType containerType2;

            // Verify the tag and type
            VerifyOrExit(reader.GetType() == kTLVType_Structure, err = WEAVE_ERROR_WRONG_TLV_TYPE);
            VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

            err = reader.EnterContainer(containerType2);
            SuccessOrExit(err);

            // Extract the signature r value
            err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r));
            SuccessOrExit(err);
            err = reader.GetDataPtr((const uint8_t *&)cert->Signature.EC.R);
            SuccessOrExit(err);
            cert->Signature.EC.RLen = reader.GetLength();

            // Extract the signature s value
            err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s));
            SuccessOrExit(err);
            err = reader.GetDataPtr((const uint8_t *&)cert->Signature.EC.S);
            SuccessOrExit(err);
            cert->Signature.EC.SLen = reader.GetLength();

            err = reader.ExitContainer(containerType2);
            SuccessOrExit(err);
        }

        err = reader.ExitContainer(containerType);
        SuccessOrExit(err);
    }

    // Record the overall size of the certificate.
    cert->EncodedCertLen = reader.GetReadPoint() - cert->EncodedCert;

    // If requested by the caller, mark the certificate as trusted.
    if (decodeFlags & kDecodeFlag_IsTrusted)
    {
        cert->CertFlags |= kCertFlag_IsTrusted;
    }

    // Assign a default type for the certificate based on its subject and attributes.
    err = DetermineCertType(*cert);
    SuccessOrExit(err);

exit:
    if (decodeBuf != NULL && decodeBuf != mDecodeBuf && mFreeFunct != NULL)
        mFreeFunct(decodeBuf);

    return err;
}

WEAVE_ERROR WeaveCertificateSet::ReplaceCert(const uint8_t *weaveCert, uint32_t weaveCertLen,
                                             uint16_t decodeFlags, WeaveCertificateData *& oldCert)
{
    WEAVE_ERROR err = WEAVE_ERROR_CERT_NOT_FOUND;
    VerifyOrExit(oldCert != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    TLVReader reader;

    reader.Init(weaveCert, weaveCertLen);
    reader.ImplicitProfileId = kWeaveProfile_Security;

    err = reader.Next(kTLVType_Structure,
                      ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate));
    SuccessOrExit(err);

    err = LoadCertToElement(reader, decodeFlags, oldCert);

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::LoadCerts(const uint8_t *encodedCerts, uint32_t encodedCertsLen, uint16_t decodeFlags)
{
    WEAVE_ERROR err;
    TLVReader reader;
    TLVType type;
    uint64_t tag;

    reader.Init(encodedCerts, encodedCertsLen);
    reader.ImplicitProfileId = kWeaveProfile_Security;

    err = reader.Next();
    SuccessOrExit(err);

    type = reader.GetType();
    tag = reader.GetTag();

    VerifyOrExit((type == kTLVType_Structure && tag == ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate)) ||
                 (type == kTLVType_Array && tag == ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificateList)),
                 err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

    err = LoadCerts(reader, decodeFlags);

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::LoadCerts(TLVReader& reader, uint16_t decodeFlags)
{
    WEAVE_ERROR err;
    WeaveCertificateData *cert;

    // If positioned on a structure, we assume that structure is a single certificate.
    if (reader.GetType() == kTLVType_Structure)
    {
        err = LoadCert(reader, decodeFlags, cert);
        SuccessOrExit(err);
    }

    // Other we expect to be position on an Array or Path that contains a sequence of
    // zero or more certificates...
    else
    {
        TLVType containerType;

        err = reader.EnterContainer(containerType);
        SuccessOrExit(err);

        while ((err = reader.Next()) == WEAVE_NO_ERROR)
        {
            err = LoadCert(reader, decodeFlags, cert);
            SuccessOrExit(err);
        }
        if (err != WEAVE_END_OF_TLV)
            ExitNow();

        err = reader.ExitContainer(containerType);
        SuccessOrExit(err);
    }

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::AddTrustedKey(uint64_t caId, uint32_t curveId, const EncodedECPublicKey& pubKey,
                                               const uint8_t *pubKeyId, uint16_t pubKeyIdLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveCertificateData *cert;

    // Verify we have room for the new certificate.
    VerifyOrExit(CertCount < MaxCerts, err = WEAVE_ERROR_NO_MEMORY);

    cert = &Certs[CertCount];
    memset(cert, 0, sizeof(*cert));
    cert->SubjectDN.AttrOID = kOID_AttributeType_WeaveCAId;
    cert->SubjectDN.AttrValue.WeaveId = caId;
    cert->IssuerDN = cert->SubjectDN;
    cert->PubKeyCurveId = curveId;
    cert->PublicKey.EC = pubKey;
    cert->SubjectKeyId.Id = cert->AuthKeyId.Id = pubKeyId;
    cert->SubjectKeyId.Len = cert->AuthKeyId.Len = pubKeyIdLen;
    cert->KeyUsageFlags = kKeyUsageFlag_KeyCertSign;
    cert->CertFlags = kCertFlag_AuthKeyIdPresent | kCertFlag_ExtPresent_AuthKeyId |
            kCertFlag_ExtPresent_BasicConstraints | kCertFlag_ExtPresent_SubjectKeyId |
            kCertFlag_ExtPresent_KeyUsage | kCertFlag_IsCA | kCertFlag_IsTrusted;
    cert->CertType = kCertType_CA;

    CertCount++;

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::SaveCerts(TLVWriter& writer, WeaveCertificateData *firstCert, bool includeTrusted)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (firstCert != NULL)
    {
        err = writer.PutPreEncodedContainer(AnonymousTag, kTLVType_Structure, firstCert->EncodedCert, firstCert->EncodedCertLen);
        SuccessOrExit(err);
    }

    for (uint8_t i = 0; i < CertCount; i++)
    {
        WeaveCertificateData& cert = Certs[i];
        if (cert.EncodedCert != NULL && &cert != firstCert && (includeTrusted || (cert.CertFlags & kCertFlag_IsTrusted) == 0))
        {
            err = writer.PutPreEncodedContainer(AnonymousTag, kTLVType_Structure, cert.EncodedCert, cert.EncodedCertLen);
            SuccessOrExit(err);
        }
    }

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::ValidateCert(WeaveCertificateData& cert, ValidationContext& context)
{
    WEAVE_ERROR err;

    VerifyOrExit(&cert >= Certs && &cert < &Certs[CertCount], err = WEAVE_ERROR_INVALID_ARGUMENT);

#if WEAVE_CONFIG_DEBUG_CERT_VALIDATION

    if (context.CertValidationResults != NULL)
    {
        VerifyOrExit(context.CertValidationResultsLen >= CertCount, err = WEAVE_ERROR_INVALID_ARGUMENT);

        for (uint8_t i = 0; i < context.CertValidationResultsLen; i++)
            context.CertValidationResults[i] = WEAVE_CERT_NOT_USED;
    }

#endif

    context.TrustAnchor = NULL;

    err = ValidateCert(cert, context, context.ValidateFlags, 0);

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::FindValidCert(const WeaveDN& subjectDN, const CertificateKeyId& subjectKeyId,
        ValidationContext& context, WeaveCertificateData *& cert)
{
    WEAVE_ERROR err;

#if WEAVE_CONFIG_DEBUG_CERT_VALIDATION

    if (context.CertValidationResults != NULL)
    {
        VerifyOrExit(context.CertValidationResultsLen >= CertCount, err = WEAVE_ERROR_INVALID_ARGUMENT);

        for (uint8_t i = 0; i < context.CertValidationResultsLen; i++)
            context.CertValidationResults[i] = WEAVE_CERT_NOT_USED;
    }

#endif

    context.TrustAnchor = NULL;

    err = FindValidCert(subjectDN, subjectKeyId, context, context.ValidateFlags, 0, cert);
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR WeaveCertificateSet::GenerateECDSASignature(const uint8_t *msgHash, uint8_t msgHashLen,
                                                        WeaveCertificateData& cert,
                                                        const nl::Weave::Crypto::EncodedECPrivateKey& privKey,
                                                        nl::Weave::Crypto::EncodedECDSASignature& encodedSig)
{
    return nl::Weave::Crypto::GenerateECDSASignature(WeaveCurveIdToOID(cert.PubKeyCurveId),
            msgHash, msgHashLen, privKey, encodedSig);
}

WEAVE_ERROR WeaveCertificateSet::VerifyECDSASignature(const uint8_t *msgHash, uint8_t msgHashLen,
                                                      const nl::Weave::Crypto::EncodedECDSASignature& encodedSig,
                                                      WeaveCertificateData& cert)
{
    return nl::Weave::Crypto::VerifyECDSASignature(WeaveCurveIdToOID(cert.PubKeyCurveId),
            msgHash, msgHashLen, encodedSig, cert.PublicKey.EC);
}

WEAVE_ERROR WeaveCertificateSet::ValidateCert(WeaveCertificateData& cert, ValidationContext& context, uint16_t validateFlags, uint8_t depth)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveCertificateData *caCert = NULL;
    uint8_t hashLen;
    enum { kLastSecondOfDay = kSecondsPerDay - 1 };

    // If the depth is greater than 0 then the certificate is required to be a CA certificate...
    if (depth > 0)
    {
        // Verify the isCA flag is present.
        VerifyOrExit((cert.CertFlags & kCertFlag_IsCA) != 0, err = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED);

        // Verify the key usage extension is present and contains the 'keyCertSign' flag.
        VerifyOrExit((cert.CertFlags & kCertFlag_ExtPresent_KeyUsage) != 0 &&
                     (cert.KeyUsageFlags & kKeyUsageFlag_KeyCertSign) != 0,
                     err = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED);

        // Verify that the certificate type is set to "CA".
        VerifyOrExit(cert.CertType == kCertType_CA, err = WEAVE_ERROR_WRONG_CERT_TYPE);

        // If a path length constraint was included, verify the cert depth vs. the specified constraint.
        //
        // From the RFC, the path length constraint "gives the maximum number of non-self-issued
        // intermediate certificates that may follow this certificate in a valid certification path.
        // (Note: The last certificate in the certification path is not an intermediate certificate,
        // and is not included in this limit...)"
        //
        if ((cert.CertFlags & kCertFlag_PathLenConstPresent) != 0)
            VerifyOrExit((depth - 1) <= cert.PathLenConstraint, err = WEAVE_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED);
    }

    // Otherwise verify the desired certificate usages/purposes/type given in the validation context...
    else
    {
        // If a set of desired key usages has been specified, verify that the key usage extension exists
        // in the certificate and that the corresponding usages are supported.
        if (context.RequiredKeyUsages != 0)
            VerifyOrExit((cert.CertFlags & kCertFlag_ExtPresent_KeyUsage) != 0 &&
                         (cert.KeyUsageFlags & context.RequiredKeyUsages) == context.RequiredKeyUsages,
                         err = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED);

        // If a set of desired key purposes has been specified, verify that the extended key usage extension
        // exists in the certificate and that the corresponding purposes are supported.
        if (context.RequiredKeyPurposes != 0)
            VerifyOrExit((cert.CertFlags & kCertFlag_ExtPresent_ExtendedKeyUsage) != 0 &&
                         (cert.KeyPurposeFlags & context.RequiredKeyPurposes) == context.RequiredKeyPurposes,
                         err = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED);

        // If a required certificate type has been specified, verify it against the current certificate's type.
        if (context.RequiredCertType != kCertType_NotSpecified)
            VerifyOrExit(cert.CertType == context.RequiredCertType, err = WEAVE_ERROR_WRONG_CERT_TYPE);
    }

    // Verify the validity time of the certificate, if requested.
    if (cert.NotBeforeDate != 0 && (validateFlags & kValidateFlag_IgnoreNotBefore) == 0)
        VerifyOrExit(context.EffectiveTime >= PackedCertDateToTime(cert.NotBeforeDate), err = WEAVE_ERROR_CERT_NOT_VALID_YET);
    if (cert.NotAfterDate != 0 && (validateFlags & kValidateFlag_IgnoreNotAfter) == 0)
        VerifyOrExit(context.EffectiveTime <= PackedCertDateToTime(cert.NotAfterDate) + kLastSecondOfDay, err = WEAVE_ERROR_CERT_EXPIRED);

    // If the certificate itself is trusted, then it is implicitly valid.  Record this certificate as the trust
    // anchor and return success.
    if ((cert.CertFlags & kCertFlag_IsTrusted) != 0)
    {
        context.TrustAnchor = &cert;
        ExitNow(err = WEAVE_NO_ERROR);
    }

    // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted
    // certificate known as the 'trust anchor'.

    // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and
    // it has no path we can follow to a trust anchor, it can't be considered valid.
    if (cert.IssuerDN.IsEqual(cert.SubjectDN) && cert.AuthKeyId.IsEqual(cert.SubjectKeyId))
        ExitNow(err = WEAVE_ERROR_CERT_NOT_TRUSTED);

    // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create
    // a circular chain of certificates.  Limiting the maximum depth of the certificate path prevents infinite
    // recursion in such a case.
    VerifyOrExit(depth < CertCount, err = WEAVE_ERROR_CERT_PATH_TOO_LONG);

    // Verify that a hash of the 'to-be-signed' portion of the certificate has been computed. We will need this to
    // verify the cert's signature below.
    VerifyOrExit((cert.CertFlags & kCertFlag_TBSHashPresent) != 0, err = WEAVE_ERROR_INVALID_ARGUMENT);

    // If a certificate signed with SHA-256 is required, verify the signature algorithm.
    if ((validateFlags & kValidateFlag_RequireSHA256) != 0)
        VerifyOrExit(cert.SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = WEAVE_ERROR_WRONG_CERT_SIGNATURE_ALGORITHM);

    // If the current certificate was signed with SHA-256, require that the CA certificate is also signed with SHA-256.
    if (cert.SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256)
        validateFlags |= kValidateFlag_RequireSHA256;

    // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate.
    // Fail if no acceptable certificate is found.
    err = FindValidCert(cert.IssuerDN, cert.AuthKeyId, context, validateFlags, depth + 1, caCert);
    if (err != WEAVE_NO_ERROR)
        ExitNow(err = WEAVE_ERROR_CA_CERT_NOT_FOUND);

    // Verify signature of the current certificate against public key of the CA certificate. If signature verification
    // succeeds, the current certificate is valid.
    hashLen = (cert.SigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256)
              ? (uint8_t)Platform::Security::SHA256::kHashLength
              : (uint8_t)Platform::Security::SHA1::kHashLength;
    err = VerifyECDSASignature(cert.TBSHash, hashLen, cert.Signature.EC, *caCert);
    SuccessOrExit(err);

exit:

#if WEAVE_CONFIG_DEBUG_CERT_VALIDATION
    if (context.CertValidationResults != NULL)
        context.CertValidationResults[&cert - Certs] = err;
#endif

    return err;
}

WEAVE_ERROR WeaveCertificateSet::FindValidCert(const WeaveDN& subjectDN, const CertificateKeyId& subjectKeyId,
        ValidationContext& context, uint16_t validateFlags, uint8_t depth, WeaveCertificateData *& cert)
{
    WEAVE_ERROR err;

    // Default error if we don't find any matching cert.
    err = (depth > 0) ? WEAVE_ERROR_CA_CERT_NOT_FOUND : WEAVE_ERROR_CERT_NOT_FOUND;

    // Fail immediately if neither of the input criteria are specified.
    if (subjectDN.IsEmpty() && subjectKeyId.IsEmpty())
        ExitNow();

    // For each cert in the set...
    for (uint8_t i = 0; i < CertCount; i++)
    {
        WeaveCertificateData& candidateCert = Certs[i];

        // Skip the certificate if its subject DN and key id do not match the input criteria.
        if (!subjectDN.IsEmpty() && !candidateCert.SubjectDN.IsEqual(subjectDN))
            continue;
        if (!subjectKeyId.IsEmpty() && !candidateCert.SubjectKeyId.IsEqual(subjectKeyId))
            continue;

        // Attempt to validate the cert.  If the cert is valid, return it to the caller. Otherwise,
        // save the returned error and continue searching.  If there are no other matching certs this
        // will be the error returned to the caller.
        err = ValidateCert(candidateCert, context, validateFlags, depth);
        if (err == WEAVE_NO_ERROR)
        {
            cert = &candidateCert;
            ExitNow();
        }
    }

    cert = NULL;

exit:
    return err;
}

/**
 * Determine general type of a Weave certificate.
 *
 * This function performs a general assessment of a certificate's type based
 * on the structure of its subject DN and the extensions present.  Applications
 * are free to override this assessment by setting cert.CertType to another value,
 * including an application-defined one.
 *
 * In general, applications will only trust a peer's certificate if it chains to a trusted
 * root certificate.  However, the type assigned to a certificate can influence the *nature*
 * of this trust, e.g. to allow or disallow access to certain features.  Because of this,
 * changes to this algorithm can have VERY SIGNIFICANT and POTENTIALLY CATASTROPHIC effects
 * on overall system security, and should not be made without a thorough understanding of
 * the implications.
 *
 * NOTE: Access token certificates cannot be distinguished solely by their structure.
 * Thus this function never sets cert.CertType = kCertType_AccessToken.
 */
WEAVE_ERROR DetermineCertType(WeaveCertificateData& cert)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // If the BasicConstraints isCA flag is true...
    if ((cert.CertFlags & kCertFlag_IsCA) != 0)
    {
        // Verify the key usage extension is present and contains the 'keyCertSign' flag.
        VerifyOrExit((cert.CertFlags & kCertFlag_ExtPresent_KeyUsage) != 0 &&
                     (cert.KeyUsageFlags & kKeyUsageFlag_KeyCertSign) != 0,
                     err = WEAVE_ERROR_CERT_USAGE_NOT_ALLOWED);

        // Set the certificate type to CA.
        cert.CertType = kCertType_CA;
    }

    // If the certificate subject contains a WeaveDeviceId attribute set the certificate type to Device.
    else if (cert.SubjectDN.AttrOID == kOID_AttributeType_WeaveDeviceId)
    {
        cert.CertType = kCertType_Device;
    }

    // If the certificate subject contains a WeaveServiceEndpointId attribute set the certificate type to ServiceEndpoint.
    else if (cert.SubjectDN.AttrOID == kOID_AttributeType_WeaveServiceEndpointId)
    {
        cert.CertType = kCertType_ServiceEndpoint;
    }

    // If the certificate subject contains a WeaveSoftwarePublisherId attribute set the certificate type to FirmwareSigning.
    else if (cert.SubjectDN.AttrOID == kOID_AttributeType_WeaveSoftwarePublisherId)
    {
        cert.CertType = kCertType_FirmwareSigning;
    }

    // Otherwise set the certificate type to General.
    else
    {
        cert.CertType = kCertType_General;
    }

exit:
    return err;
}

bool WeaveDN::IsEqual(const WeaveDN& other) const
{
    if (AttrOID == kOID_Unknown || AttrOID == kOID_NotSpecified || AttrOID != other.AttrOID)
        return false;

    if (IsWeaveIdX509Attr(AttrOID))
        return AttrValue.WeaveId == other.AttrValue.WeaveId;
    else
        return (AttrValue.String.Len == other.AttrValue.String.Len &&
                memcmp(AttrValue.String.Value, other.AttrValue.String.Value, AttrValue.String.Len) == 0);
}

bool CertificateKeyId::IsEqual(const CertificateKeyId& other) const
{
    return Id != NULL && other.Id != NULL && Len == other.Len && memcmp(Id, other.Id, Len) == 0;
}

/**
 * @brief
 *   Convert a certificate date/time (in the form of an ASN.1 universal time structure) into a packed
 *   certificate date/time.
 *
 * @details
 *   Packed certificate date/times provide a compact representation for the time values within a certificate
 *   (notBefore and notAfter) that does not require full calendar math to interpret.
 *
 *   A packed certificate date/time contains the fields of a calendar date/time--i.e. year, month, day, hour,
 *   minute, second--packed into an unsigned integer. The bit representation is organized such that
 *   ordinal comparisons of packed date/time values correspond to the natural ordering of the corresponding
 *   times.  To reduce their size, packed certificate date/times are limited to representing times that are on
 *   or after 2000/01/01 00:00:00.  When housed within a 32-bit unsigned integer, packed certificate
 *   date/times can represent times up to the year 2133.
 *
 * @note
 *   This function makes no attempt to verify the correct range of the input time other than year.
 *   Therefore callers must make sure the supplied values are valid prior to invocation.
 *
 * @param time
 *   The calendar date/time to be converted.
 *
 * @param packedTime
 *   A reference to an integer that will receive packed date/time.
 *
 * @retval  #WEAVE_NO_ERROR                     If the input time was successfully converted.
 * @retval  #ASN1_ERROR_UNSUPPORTED_ENCODING    If the input time contained a year value that could not
 *                                              be represented in a packed certificate time value.
 */
NL_DLL_EXPORT WEAVE_ERROR PackCertTime(const ASN1UniversalTime& time, uint32_t& packedTime)
{
    enum {
        kCertTimeBaseYear = 2000,
        kCertTimeMaxYear = kCertTimeBaseYear + UINT32_MAX / (kMonthsPerYear * kMaxDaysPerMonth * kHoursPerDay * kMinutesPerHour * kSecondsPerMinute),
        kX509NoWellDefinedExpirationDateYear = 9999
    };

    // The packed time in a Weave certificate cannot represent dates prior to 2000/01/01.
    if (time.Year < kCertTimeBaseYear)
        return ASN1_ERROR_UNSUPPORTED_ENCODING;

    // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    // We represent that as a packed time value of 0, which for simplicity's sake is assigned to any
    // date in the associated year.
    if (time.Year == kX509NoWellDefinedExpirationDateYear)
    {
        packedTime = kNullCertTime;
        return WEAVE_NO_ERROR;
    }

    // Technically packed certificate time values could grow beyond 32bits. However we restrict it here
    // to dates that fit within 32bits to reduce code size and eliminate the need for 64bit math.
    if (time.Year > kCertTimeMaxYear)
        return ASN1_ERROR_UNSUPPORTED_ENCODING;

    packedTime = time.Year - kCertTimeBaseYear;
    packedTime = packedTime * kMonthsPerYear + time.Month - 1;
    packedTime = packedTime * kMaxDaysPerMonth + time.Day - 1;
    packedTime = packedTime * kHoursPerDay + time.Hour;
    packedTime = packedTime * kMinutesPerHour + time.Minute;
    packedTime = packedTime * kSecondsPerMinute + time.Second;

    return WEAVE_NO_ERROR;
}

/**
 * @brief
 *   Unpack a packed certificate date/time into an ASN.1 universal time structure.
 *
 * @param packedTime
 *   A packed certificate time to be unpacked.
 *
 * @param time
 *   A reference to an ASN1UniversalTime structure to receive the unpacked date/time.
 *
 * @retval  #WEAVE_NO_ERROR                     If the input time was successfully unpacked.
 */
NL_DLL_EXPORT WEAVE_ERROR UnpackCertTime(uint32_t packedTime, ASN1UniversalTime& time)
{
    enum {
        kCertTimeBaseYear = 2000,
        kX509NoWellDefinedExpirationDateYear = 9999,
    };

    // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    // We represent that as a packed time value of 0.
    if (packedTime == kNullCertTime)
    {
        time.Year = kX509NoWellDefinedExpirationDateYear;
        time.Month = kMonthsPerYear;
        time.Day = kMaxDaysPerMonth;
        time.Hour = kHoursPerDay - 1;
        time.Minute = kMinutesPerHour - 1;
        time.Second = kSecondsPerMinute - 1;
    }

    else
    {
        time.Second = packedTime % kSecondsPerMinute;
        packedTime /= kSecondsPerMinute;

        time.Minute = packedTime % kMinutesPerHour;
        packedTime /= kMinutesPerHour;

        time.Hour = packedTime % kHoursPerDay;
        packedTime /= kHoursPerDay;

        time.Day = (packedTime % kMaxDaysPerMonth) + 1;
        packedTime /= kMaxDaysPerMonth;

        time.Month = (packedTime % kMonthsPerYear) + 1;
        packedTime /= kMonthsPerYear;

        time.Year = packedTime + kCertTimeBaseYear;
    }

    return WEAVE_NO_ERROR;
}

/**
 * @brief
 *   Convert a packed certificate date/time to a packed certificate date.
 *
 * @details
 *   A packed certificate date contains the fields of a calendar date--year, month, day--packed into an
 *   unsigned integer.  The bits are organized such that ordinal comparisons of packed date values
 *   correspond to the natural ordering of the corresponding dates.  To reduce their size, packed
 *   certificate dates are limited to representing dates on or after 2000/01/01.  When housed within
 *   a 16-bit unsigned integer, packed certificate dates can represent dates up to the year 2176.
 *
 * @param packedTime
 *   The packed certificate date/time to be converted.
 *
 * @return
 *   A corresponding packet certificate date.
 */
NL_DLL_EXPORT uint16_t PackedCertTimeToDate(uint32_t packedTime)
{
    return (uint16_t)(packedTime / kSecondsPerDay);
}

/**
 * @brief
 *   Convert a packed certificate date to a corresponding packed certificate date/time, where
 *   the time portion of the value is set to 00:00:00.
 *
 * @param packedDate
 *   The packed certificate date to be converted.
 *
 * @return
 *   A corresponding packet certificate date/time.
 */
NL_DLL_EXPORT uint32_t PackedCertDateToTime(uint16_t packedDate)
{
    return (uint32_t)packedDate * kSecondsPerDay;
}

/**
 * @brief
 *   Convert the number of seconds since 1970-01-01 00:00:00 UTC to a packed certificate date/time.
 *
 * @param secondsSinceEpoch
 *   Number of seconds since 1970-01-01 00:00:00 UTC.  Note: this value is compatible with
 *   *positive* values of the POSIX time_t value, up to the year 2105.
 *
 * @return
 *   A corresponding packet certificate date/time.
 */
NL_DLL_EXPORT uint32_t SecondsSinceEpochToPackedCertTime(uint32_t secondsSinceEpoch)
{
    nl::Weave::ASN1::ASN1UniversalTime asn1Time;
    uint32_t packedTime;

    // Convert seconds-since-epoch to calendar date and time and store in an ASN1UniversalTime structure.
    SecondsSinceEpochToCalendarTime(secondsSinceEpoch, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second);

    // Convert the calendar date/time to a packed certificate date/time.
    PackCertTime(asn1Time, packedTime);

    return packedTime;
}

/**
 * @brief
 *   Generate Weave operational device certificate.
 *
 * @details
 *   This function generates Weave self-signed operational certificate encoded in the Weave TLV
 *   format.
 *
 * @param  deviceId                Weave operational device Id.
 * @param  devicePubKey            Weave operational device public key.
 * @param  cert                    A pointer to a buffer where generated certificate to be written.
 * @param  certBufSize             The length in bytes of the provided certificate buffer.
 * @param  certLen                 The length in bytes of the generated certificate.
 * @param  genCertSignature        A pointer to a function that generates ECDSA signature on the given
 *                                 certificate hash using operational device private key.
 *
 * @retval #WEAVE_NO_ERROR         If Weave certificate was successfully generated.
 */
NL_DLL_EXPORT WEAVE_ERROR GenerateOperationalDeviceCert(uint64_t deviceId, EncodedECPublicKey& devicePubKey,
                                                        uint8_t *cert, uint16_t certBufSize, uint16_t& certLen,
                                                        GenerateECDSASignatureFunct genCertSignature)
{
    WEAVE_ERROR err;
    TLVWriter writer;
    TLVType containerType;
    TLVType containerType2;
    TLVType containerType3;
    uint8_t *certDecodeBuf = NULL;
    WeaveCertificateData *certData = NULL;

    VerifyOrExit(genCertSignature != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    VerifyOrExit(devicePubKey.ECPoint != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

    writer.Init(cert, certBufSize);

    err = writer.StartContainer(ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate), kTLVType_Structure, containerType);
    SuccessOrExit(err);

    // Certificate serial number.
    {
        enum
        {
            kCertSerialNumber_Length          = 8,      // Length of the certificate serial number.
            kCertSerialNumber_FirstByteMask   = 0x7F,   // Mask applied on the first byte of the key Id value.
            kCertSerialNumber_FirstBytePrefix = 0x40,   // 4-bit Type value (0100) added at the beginning of the key Id value.
        };
        uint8_t certSerialNumber[kCertSerialNumber_Length];

        // Generate a random value to be used as the serial number.
        err = nl::Weave::Platform::Security::GetSecureRandomData(certSerialNumber, kCertSerialNumber_Length);
        SuccessOrExit(err);

        // Apply mask to avoid negative numbers.
        certSerialNumber[0] &= kCertSerialNumber_FirstByteMask;

        // Apply mask to guarantee the first byte is not zero.
        certSerialNumber[0] |= kCertSerialNumber_FirstBytePrefix;

        err = writer.PutBytes(ContextTag(kTag_SerialNumber), certSerialNumber, sizeof(certSerialNumber));
        SuccessOrExit(err);
    }

    // Weave signature algorithm.
    err = writer.Put(ContextTag(kTag_SignatureAlgorithm), static_cast<uint8_t>(kOID_SigAlgo_ECDSAWithSHA256 & ~kOIDCategory_Mask));
    SuccessOrExit(err);

    // Certificate issuer distinguished name.
    {
        err = writer.StartContainer(ContextTag(kTag_Issuer), kTLVType_Path, containerType2);
        SuccessOrExit(err);

        err = writer.Put(ContextTag(kOID_AttributeType_WeaveDeviceId & kOID_Mask), deviceId);
        SuccessOrExit(err);

        err = writer.EndContainer(containerType2);
        SuccessOrExit(err);
    }

    // Certificate validity times.
    err = writer.Put(ContextTag(kTag_NotBefore), PackedCertDateToTime(WEAVE_CONFIG_OP_DEVICE_CERT_VALID_DATE_NOT_BEFORE));
    SuccessOrExit(err);

    err = writer.Put(ContextTag(kTag_NotAfter), PackedCertDateToTime(WEAVE_CONFIG_OP_DEVICE_CERT_VALID_DATE_NOT_AFTER));
    SuccessOrExit(err);

    // Certificate subject distinguished name.
    {
        err = writer.StartContainer(ContextTag(kTag_Subject), kTLVType_Path, containerType2);
        SuccessOrExit(err);

        err = writer.Put(ContextTag(kOID_AttributeType_WeaveDeviceId & kOID_Mask), deviceId);
        SuccessOrExit(err);

        err = writer.EndContainer(containerType2);
        SuccessOrExit(err);
    }

    // EC public key algorithm.
    err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), static_cast<uint8_t>(kOID_PubKeyAlgo_ECPublicKey & kOID_Mask));
    SuccessOrExit(err);

    // EC public key curve Id.
    err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), static_cast<uint32_t>(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID));
    SuccessOrExit(err);

    // EC public key.
    err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), devicePubKey.ECPoint, devicePubKey.ECPointLen);
    SuccessOrExit(err);

    // Certificate extension: basic constraints.
    {
        err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, containerType2);
        SuccessOrExit(err);

        // This extension is critical.
        err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_Critical), true);
        SuccessOrExit(err);

        err = writer.EndContainer(containerType2);
        SuccessOrExit(err);
    }

    // Certificate extension: key usage.
    {
        err = writer.StartContainer(ContextTag(kTag_KeyUsage), kTLVType_Structure, containerType2);
        SuccessOrExit(err);

        // This extension is critical.
        err = writer.PutBoolean(ContextTag(kTag_KeyUsage_Critical), true);
        SuccessOrExit(err);

        err = writer.Put(ContextTag(kTag_KeyUsage_KeyUsage), static_cast<uint16_t>(kKeyUsageFlag_DigitalSignature | kKeyUsageFlag_KeyEncipherment));
        SuccessOrExit(err);

        err = writer.EndContainer(containerType2);
        SuccessOrExit(err);
    }

    // Certificate extension: extended key usage.
    {
        err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Structure, containerType2);
        SuccessOrExit(err);

        // This extension is critical.
        err = writer.PutBoolean(ContextTag(kTag_ExtendedKeyUsage_Critical), true);
        SuccessOrExit(err);

        err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage_KeyPurposes), kTLVType_Array, containerType3);
        SuccessOrExit(err);

        // Key purpose is client authentication.
        err = writer.Put(AnonymousTag, static_cast<uint8_t>(kOID_KeyPurpose_ClientAuth & kOID_Mask));
        SuccessOrExit(err);

        // Key purpose is server authentication.
        err = writer.Put(AnonymousTag, static_cast<uint8_t>(kOID_KeyPurpose_ServerAuth & kOID_Mask));
        SuccessOrExit(err);

        err = writer.EndContainer(containerType3);
        SuccessOrExit(err);

        err = writer.EndContainer(containerType2);
        SuccessOrExit(err);
    }

    // Certificate key Id.
    {
        /* Use "truncated" SHA-1 hash. Per RFC5280:
         *
         *     "(2) The keyIdentifier is composed of a four-bit type field with the value 0100 followed
         *     by the least significant 60 bits of the SHA-1 hash of the value of the BIT STRING
         *     subjectPublicKey (excluding the tag, length, and number of unused bits)."
         */
        enum
        {
            kCertKeyId_Length          = 8,      // Length of the certificate key identifier.
            kCertKeyId_FirstByte       = Platform::Security::SHA1::kHashLength - kCertKeyId_Length,
                                                 // First byte of the SHA1 hash that used to generate certificate keyId.
            kCertKeyId_FirstByteMask   = 0x0F,   // Mask applied on the first byte of the key Id value.
            kCertKeyId_FirstBytePrefix = 0x40,   // 4-bit Type value (0100) added at the beginning of the key Id value.
        };
        Platform::Security::SHA1 sha1;
        uint8_t hash[Platform::Security::SHA1::kHashLength];
        uint8_t *certKeyId = &hash[kCertKeyId_FirstByte];

        sha1.Begin();
        sha1.AddData(devicePubKey.ECPoint, devicePubKey.ECPointLen);
        sha1.Finish(hash);

        certKeyId[0] &= kCertKeyId_FirstByteMask;
        certKeyId[0] |= kCertKeyId_FirstBytePrefix;

        // Certificate extension: subject key identifier.
        {
            err = writer.StartContainer(ContextTag(kTag_SubjectKeyIdentifier), kTLVType_Structure, containerType2);
            SuccessOrExit(err);

            err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier_KeyIdentifier), certKeyId, kCertKeyId_Length);
            SuccessOrExit(err);

            err = writer.EndContainer(containerType2);
            SuccessOrExit(err);
        }

        // Certificate extension: authority key identifier.
        {
            err = writer.StartContainer(ContextTag(kTag_AuthorityKeyIdentifier), kTLVType_Structure, containerType2);
            SuccessOrExit(err);

            err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier_KeyIdentifier), certKeyId, kCertKeyId_Length);
            SuccessOrExit(err);

            err = writer.EndContainer(containerType2);
            SuccessOrExit(err);
        }
    }

    // Start the ECDSASignature structure.
    // Note that the ECDSASignature tag is added here but the actual certificate data (S and R values)
    // will be written later. This is needed to prevent DecodeConvertTBSCert() function from failing.
    // The DecodeConvertTBSCert() function expects a tag, different from "certificate extention" tag,
    // to follow the certificate extention elements.
    err = writer.StartContainer(ContextTag(kTag_ECDSASignature), kTLVType_Structure, containerType2);
    SuccessOrExit(err);

    {
        enum
        {
            kCertDecodeBufferSize      = 1024,   // Maximum ASN1 encoded size of the operational device certificate.
        };

        TLVReader reader;
        ASN1Writer tbsWriter;
        TLVType readContainerType;

        reader.Init(cert, certBufSize);

        // Parse the beginning of the WeaveSignature structure.
        err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate));
        SuccessOrExit(err);

        // Enter the certificate structure.
        err = reader.EnterContainer(readContainerType);
        SuccessOrExit(err);

        // Allocate decode memory buffer.
        certDecodeBuf = static_cast<uint8_t *>(Platform::Security::MemoryAlloc(kCertDecodeBufferSize));
        VerifyOrExit(certDecodeBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

        // Allocate certificate data  structure.
        certData = static_cast<WeaveCertificateData *>(Platform::Security::MemoryAlloc(sizeof(WeaveCertificateData)));
        VerifyOrExit(certData != NULL, err = WEAVE_ERROR_NO_MEMORY);

        // Initialize an ASN1Writer and convert the TBS (to-be-signed) portion of
        // the certificate to ASN.1 DER encoding.
        tbsWriter.Init(certDecodeBuf, kCertDecodeBufferSize);
        err = DecodeConvertTBSCert(reader, tbsWriter, *certData);
        SuccessOrExit(err);

        // Finish writing the ASN.1 DER encoding of the TBS certificate.
        err = tbsWriter.Finalize();
        SuccessOrExit(err);

        // Generate a SHA hash of the encoded TBS certificate.
        Platform::Security::SHA256 sha256;
        sha256.Begin();
        sha256.AddData(certDecodeBuf, tbsWriter.GetLengthWritten());
        sha256.Finish(certData->TBSHash);

        // Reuse already allocated decode buffer to hold the generated signature value.
        EncodedECDSASignature ecdsaSig;
        ecdsaSig.R = certDecodeBuf;
        ecdsaSig.RLen = EncodedECDSASignature::kMaxValueLength;
        ecdsaSig.S = certDecodeBuf + EncodedECDSASignature::kMaxValueLength;
        ecdsaSig.SLen = EncodedECDSASignature::kMaxValueLength;

        // Generate an ECDSA signature for the given message hash.
        err = genCertSignature(certData->TBSHash, Platform::Security::SHA256::kHashLength, ecdsaSig);
        SuccessOrExit(err);

        // Write the R value.
        err = writer.PutBytes(ContextTag(kTag_ECDSASignature_r), ecdsaSig.R, ecdsaSig.RLen);
        SuccessOrExit(err);

        // Write the S value.
        err = writer.PutBytes(ContextTag(kTag_ECDSASignature_s), ecdsaSig.S, ecdsaSig.SLen);
        SuccessOrExit(err);
    }

    err = writer.EndContainer(containerType2);
    SuccessOrExit(err);

    err = writer.EndContainer(containerType);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    certLen = static_cast<uint16_t>(writer.GetLengthWritten());

exit:
    if (certDecodeBuf != NULL)
    {
        Platform::Security::MemoryFree(certDecodeBuf);
    }

    if (certData != NULL)
    {
        Platform::Security::MemoryFree(certData);
    }

    return err;
}

} // namespace Security
} // namespace Profiles
} // namespace Weave
} // namespace nl
