/*
 *
 *    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 methods for converting a Weave
 *      TLV-encoded certificate to a standard X.509 certificate.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif
#include <stdint.h>

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

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

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

// Return true if a TLV tag represents a certificate extension.
inline bool IsCertificateExtensionTag(uint64_t tag)
{
    if (IsContextTag(tag))
    {
        uint32_t tagNum = TagNumFromTag(tag);
        return (tagNum >= kCertificateExtensionTagsStart && tagNum <= kCertificateExtensionTagsEnd);
    }
    else
        return false;
}

static WEAVE_ERROR ConvertDistinguishedName(TLVReader& reader, ASN1Writer& writer, WeaveDN& dn)
{
    WEAVE_ERROR err;
    TLVType outerContainer;
    TLVType elemType;
    uint64_t tlvTag;
    uint32_t tlvTagNum;
    OID attrOID;
    uint32_t asn1Tag;
    const uint8_t *asn1AttrVal;
    uint32_t asn1AttrValLen;
    uint8_t weaveIdStr[17];

    // Enter the Path TLV element that represents the DN in TLV format.
    err = reader.EnterContainer(outerContainer);
    SuccessOrExit(err);

    // Read the first TLV element in the Path.  This represents the first RDN in the original ASN.1 DN.
    //
    // NOTE: Although Weave certificate encoding allows for DNs containing multiple RDNs, and/or multiple
    // attributes per RDN, this implementation only supports DNs with a single RDN that contains exactly
    // one attribute.
    //
    err = reader.Next();
    SuccessOrExit(err);

    // Get the TLV tag, make sure it is a context tag and extract the context tag number.
    tlvTag = reader.GetTag();
    VerifyOrExit(IsContextTag(tlvTag), err = WEAVE_ERROR_INVALID_TLV_TAG);
    tlvTagNum = TagNumFromTag(tlvTag);

    // Get the element type.
    elemType = reader.GetType();

    // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
    // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
    // This eliminates the need for a translation table/switch statement but has the
    // effect of tying the two encodings together.
    //
    // NOTE: In the event that the computed OID value is not one that we recognize
    // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
    // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
    // will fail for lack of the OID's encoded representation.  Given this there's no
    // need to test the validity of the OID here.
    //
    attrOID = (OID)(kOIDCategory_AttributeType | (tlvTagNum & 0x7f));

    // Save the attribute OID in the caller's DN structure.
    dn.AttrOID = attrOID;

    // If the attribute is one of the Weave-defined X.509 attributes that contains a Weave id...
    if (IsWeaveIdX509Attr(attrOID))
    {
        // Verify that the underlying TLV data type is unsigned integer.
        VerifyOrExit(elemType == kTLVType_UnsignedInteger, err = WEAVE_ERROR_WRONG_TLV_TYPE);

        // Read the value of the weave id.
        uint64_t weaveId;
        err = reader.Get(weaveId);
        SuccessOrExit(err);

        // Generate the string representation of the id that will appear in the ASN.1 attribute.
        // For weave ids the string representation is *always* 16 uppercase hex characters.
        snprintf((char *)weaveIdStr, sizeof(weaveIdStr), "%016llX", (unsigned long long)weaveId);
        asn1AttrVal = weaveIdStr;
        asn1AttrValLen = 16;

        // The ASN.1 tag for Weave id attributes is always UTF8String.
        asn1Tag = kASN1UniversalTag_UTF8String;

        // Save the weave id value in the caller's DN structure.
        dn.AttrValue.WeaveId = weaveId;
    }

    // Otherwise the attribute is either one of the supported X.509 attributes or a Weave-defined
    // attribute that is *not* a Weave id...
    else
    {
        // Verify that the underlying data type is UTF8 string.
        VerifyOrExit(elemType == kTLVType_UTF8String, err = WEAVE_ERROR_WRONG_TLV_TYPE);

        // Get a pointer the underlying string data, plus its length.
        err = reader.GetDataPtr(asn1AttrVal);
        SuccessOrExit(err);
        asn1AttrValLen = reader.GetLength();

        // Determine the appropriate ASN.1 tag for the DN attribute.
        // - Weave-defined attributes are always UTF8Strings.
        // - DomainComponent is always an IA5String.
        // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
        //   is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
        if (IsWeaveX509Attr(attrOID))
            asn1Tag = kASN1UniversalTag_UTF8String;
        else if (attrOID == kOID_AttributeType_DomainComponent)
            asn1Tag = kASN1UniversalTag_IA5String;
        else
            asn1Tag = (tlvTagNum & 0x80) ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;

        // Save the string value in the caller's DN structure.
        dn.AttrValue.String.Value = asn1AttrVal;
        dn.AttrValue.String.Len = asn1AttrValLen;
    }

    // Verify that there are no further elements in the DN.
    err = reader.VerifyEndOfContainer();
    SuccessOrExit(err);

    err = reader.ExitContainer(outerContainer);
    SuccessOrExit(err);

    // Write the ASN.1 representation of the DN...

    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
    ASN1_START_SEQUENCE {

        // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
        ASN1_START_SET {

            // AttributeTypeAndValue ::= SEQUENCE
            ASN1_START_SEQUENCE {

                // type AttributeType
                // AttributeType ::= OBJECT IDENTIFIER
                ASN1_ENCODE_OBJECT_ID(attrOID);

                // value AttributeValue
                // AttributeValue ::= ANY -- DEFINED BY AttributeType
                err = writer.PutString(asn1Tag, (const char *)asn1AttrVal, asn1AttrValLen);
                SuccessOrExit(err);

            } ASN1_END_SEQUENCE;

        } ASN1_END_SET;

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertValidity(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    ASN1UniversalTime asn1Time;
    uint32_t packedTime;

    ASN1_START_SEQUENCE {

        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotBefore));
        SuccessOrExit(err);
        err = reader.Get(packedTime);
        SuccessOrExit(err);
        certData.NotBeforeDate = PackedCertTimeToDate(packedTime);
        err = UnpackCertTime(packedTime, asn1Time);
        SuccessOrExit(err);

        ASN1_ENCODE_TIME(asn1Time);

        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotAfter));
        SuccessOrExit(err);
        err = reader.Get(packedTime);
        SuccessOrExit(err);
        certData.NotAfterDate = PackedCertTimeToDate(packedTime);
        err = UnpackCertTime(packedTime, asn1Time);
        SuccessOrExit(err);

        ASN1_ENCODE_TIME(asn1Time);

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertSubjectPublicKeyInfo(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    OID pubKeyAlgoOID, pubKeyCurveOID = kOID_NotSpecified;
    uint32_t weavePubKeyAlgoId, weaveCurveId, len;

    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_PublicKeyAlgorithm));
    SuccessOrExit(err);
    err = reader.Get(weavePubKeyAlgoId);
    SuccessOrExit(err);

    pubKeyAlgoOID = (OID)(kOIDCategory_PubKeyAlgo | weavePubKeyAlgoId);
    certData.PubKeyAlgoOID = pubKeyAlgoOID;

    if (pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey ||
        pubKeyAlgoOID == kOID_PubKeyAlgo_ECDH ||
        pubKeyAlgoOID == kOID_PubKeyAlgo_ECMQV)
    {
        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_EllipticCurveIdentifier));
        SuccessOrExit(err);
        err = reader.Get(weaveCurveId);
        SuccessOrExit(err);

        // Support old form of Nest curve ids that did not include vendor.
        if (weaveCurveId < 65536)
            weaveCurveId |= (kWeaveVendor_NestLabs << 16);

        certData.PubKeyCurveId = weaveCurveId;
        pubKeyCurveOID = WeaveCurveIdToOID(certData.PubKeyCurveId);
    }

    else
        VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_RSAEncryption, err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT);

    // subjectPublicKeyInfo SubjectPublicKeyInfo,
    ASN1_START_SEQUENCE {

        // algorithm AlgorithmIdentifier,
        // AlgorithmIdentifier ::= SEQUENCE
        ASN1_START_SEQUENCE {

            // algorithm OBJECT IDENTIFIER,
            ASN1_ENCODE_OBJECT_ID(pubKeyAlgoOID);

            // parameters ANY DEFINED BY algorithm OPTIONAL
            if (pubKeyAlgoOID == kOID_PubKeyAlgo_RSAEncryption)
            {
                // Per RFC4055, RSA parameters must be an explicit NULL.
                ASN1_ENCODE_NULL;
            }
            else
            {
                // EcpkParameters ::= CHOICE {
                //     ecParameters  ECParameters,
                //     namedCurve    OBJECT IDENTIFIER,
                //     implicitlyCA  NULL }
                //
                // (Only namedCurve supported).
                //
                ASN1_ENCODE_OBJECT_ID(pubKeyCurveOID);
            }

        } ASN1_END_SEQUENCE;

        // subjectPublicKey BIT STRING
        if (pubKeyAlgoOID == kOID_PubKeyAlgo_RSAEncryption)
        {
            TLVType pubKeyOuterContainer;

            err = reader.Next(kTLVType_Structure, ContextTag(kTag_RSAPublicKey));
            SuccessOrExit(err);
            err = reader.EnterContainer(pubKeyOuterContainer);
            SuccessOrExit(err);

            // Per RFC3279, RSA public key is an encapsulated DER encoding of RSAPublicKey within
            // the subjectPublicKey BitString
            ASN1_START_BIT_STRING_ENCAPSULATED {

                // RSAPublicKey ::= SEQUENCE
                ASN1_START_SEQUENCE {

                    // modulus INTEGER
                    err = reader.Next(kTLVType_ByteString, ContextTag(kTag_RSAPublicKey_Modulus));
                    SuccessOrExit(err);
                    err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
                    SuccessOrExit(err);

                    // publicExponent INTEGER
                    err = reader.Next(kTLVType_SignedInteger, ContextTag(kTag_RSAPublicKey_PublicExponent));
                    SuccessOrExit(err);
                    int64_t exp;
                    err = reader.Get(exp);
                    SuccessOrExit(err);
                    err = writer.PutInteger(exp);
                    SuccessOrExit(err);

                } ASN1_END_SEQUENCE;

            } ASN1_END_ENCAPSULATED;

            err = reader.ExitContainer(pubKeyOuterContainer);
            SuccessOrExit(err);

            // TODO: extract RSA public key
        }

        else
        {
            err = reader.Next(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey));
            SuccessOrExit(err);

            err = reader.GetDataPtr((const uint8_t *&)certData.PublicKey.EC.ECPoint);
            SuccessOrExit(err);

            len = reader.GetLength();
            VerifyOrExit(len <= UINT16_MAX, err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT);

            certData.PublicKey.EC.ECPointLen = len;

            // For EC certs, the subjectPublicKey BIT STRING contains the X9.62 encoded EC point.
            err = writer.PutBitString(0, certData.PublicKey.EC.ECPoint, (uint16_t)certData.PublicKey.EC.ECPointLen);
            SuccessOrExit(err);
        }

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertAuthorityKeyIdentifierExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err, nextRes;
    uint32_t len;

    certData.CertFlags |= kCertFlag_ExtPresent_AuthKeyId;

    // AuthorityKeyIdentifier ::= SEQUENCE
    ASN1_START_SEQUENCE {

        // keyIdentifier [0] IMPLICIT KeyIdentifier OPTIONAL,
        // KeyIdentifier ::= OCTET STRING
        if (reader.GetTag() == ContextTag(kTag_AuthorityKeyIdentifier_KeyIdentifier))
        {
            VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = WEAVE_ERROR_WRONG_TLV_TYPE);

            err = reader.GetDataPtr(certData.AuthKeyId.Id);
            SuccessOrExit(err);

            len = reader.GetLength();
            VerifyOrExit(len <= UINT8_MAX, err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT);

            certData.AuthKeyId.Len = len;

            err = writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, certData.AuthKeyId.Id, certData.AuthKeyId.Len);
            SuccessOrExit(err);

            nextRes = reader.Next();
            VerifyOrExit(nextRes == WEAVE_NO_ERROR || nextRes == WEAVE_END_OF_TLV, err = nextRes);
        }

        // NOTE: kTag_AuthorityKeyIdentifier_Issuer and kTag_AuthorityKeyIdentifier_SerialNumber currently unsupported.

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertSubjectKeyIdentifierExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    uint32_t len;

    certData.CertFlags |= kCertFlag_ExtPresent_SubjectKeyId;

    // SubjectKeyIdentifier ::= KeyIdentifier
    // KeyIdentifier ::= OCTET STRING
    VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = WEAVE_ERROR_WRONG_TLV_TYPE);
    VerifyOrExit(reader.GetTag() == ContextTag(kTag_SubjectKeyIdentifier_KeyIdentifier), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

    len = reader.GetLength();
    VerifyOrExit(len <= UINT8_MAX, err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT);

    certData.SubjectKeyId.Len = len;

    err = reader.GetDataPtr(certData.SubjectKeyId.Id);
    SuccessOrExit(err);

    err = writer.PutOctetString(certData.SubjectKeyId.Id, certData.SubjectKeyId.Len);
    SuccessOrExit(err);

exit:
    return err;
}

static WEAVE_ERROR ConvertKeyUsageExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    uint16_t keyUsageBits;

    certData.CertFlags |= kCertFlag_ExtPresent_KeyUsage;

    // KeyUsage ::= BIT STRING
    VerifyOrExit(reader.GetTag() == ContextTag(kTag_KeyUsage_KeyUsage), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);
    err = reader.Get(keyUsageBits);
    SuccessOrExit(err);
    ASN1_ENCODE_BIT_STRING(keyUsageBits);

    certData.KeyUsageFlags = keyUsageBits;

exit:
    return err;
}

static WEAVE_ERROR ConvertBasicConstraintsExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err, nextRes;

    certData.CertFlags |= kCertFlag_ExtPresent_BasicConstraints;

    // BasicConstraints ::= SEQUENCE
    ASN1_START_SEQUENCE {

        // cA BOOLEAN DEFAULT FALSE
        if (reader.GetTag() == ContextTag(kTag_BasicConstraints_IsCA))
        {
            bool isCA;

            err = reader.Get(isCA);
            SuccessOrExit(err);

            if (isCA)
            {
                ASN1_ENCODE_BOOLEAN(true);
                certData.CertFlags |= kCertFlag_IsCA;
            }

            nextRes = reader.Next();
            VerifyOrExit(nextRes == WEAVE_NO_ERROR || nextRes == WEAVE_END_OF_TLV, err = nextRes);
        }

        // pathLenConstraint INTEGER (0..MAX) OPTIONAL
        if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
        {
            uint8_t pathLenConstraint;

            err = reader.Get(pathLenConstraint);
            SuccessOrExit(err);

            ASN1_ENCODE_INTEGER((int64_t)pathLenConstraint);

            certData.PathLenConstraint = pathLenConstraint;

            certData.CertFlags |= kCertFlag_PathLenConstPresent;
        }

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertExtendedKeyUsageExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err, nextRes;
    TLVType outerContainer;

    certData.CertFlags |= kCertFlag_ExtPresent_ExtendedKeyUsage;

    // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
    ASN1_START_SEQUENCE {

        VerifyOrExit(reader.GetTag() == ContextTag(kTag_ExtendedKeyUsage_KeyPurposes), err = WEAVE_ERROR_WRONG_TLV_TYPE);
        VerifyOrExit(reader.GetType() == kTLVType_Array, err = WEAVE_ERROR_WRONG_TLV_TYPE);

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

        while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == WEAVE_NO_ERROR)
        {
            OID keyPurposeOID;
            uint16_t weaveKeyPurposeId;

            err = reader.Get(weaveKeyPurposeId);
            SuccessOrExit(err);

            keyPurposeOID = (OID)(kOIDCategory_KeyPurpose | weaveKeyPurposeId);

            // KeyPurposeId ::= OBJECT IDENTIFIER
            ASN1_ENCODE_OBJECT_ID(keyPurposeOID);

            // TODO: eliminate switch statement and generate key purpose flag by shifting 1 by lower bits of OID.

            switch (keyPurposeOID)
            {
            case kOID_KeyPurpose_ServerAuth:       certData.KeyPurposeFlags |= kKeyPurposeFlag_ServerAuth;      break;
            case kOID_KeyPurpose_ClientAuth:       certData.KeyPurposeFlags |= kKeyPurposeFlag_ClientAuth;      break;
            case kOID_KeyPurpose_CodeSigning:      certData.KeyPurposeFlags |= kKeyPurposeFlag_CodeSigning;     break;
            case kOID_KeyPurpose_EmailProtection:  certData.KeyPurposeFlags |= kKeyPurposeFlag_EmailProtection; break;
            case kOID_KeyPurpose_TimeStamping:     certData.KeyPurposeFlags |= kKeyPurposeFlag_TimeStamping;    break;
            case kOID_KeyPurpose_OCSPSigning:      certData.KeyPurposeFlags |= kKeyPurposeFlag_OCSPSigning;     break;
            default:
                break;
            }
        }

        VerifyOrExit(nextRes == WEAVE_END_OF_TLV, err = nextRes);

        err = reader.ExitContainer(outerContainer);
        SuccessOrExit(err);

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertExtension(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err, nextRes;
    TLVType outerContainer;
    uint64_t extensionTagNum = TagNumFromTag(reader.GetTag());
    OID extensionOID;

    if (extensionTagNum == kTag_AuthorityKeyIdentifier)
        extensionOID = kOID_Extension_AuthorityKeyIdentifier;
    else if (extensionTagNum == kTag_SubjectKeyIdentifier)
        extensionOID = kOID_Extension_SubjectKeyIdentifier;
    else if (extensionTagNum == kTag_KeyUsage)
        extensionOID = kOID_Extension_KeyUsage;
    else if (extensionTagNum == kTag_BasicConstraints)
        extensionOID = kOID_Extension_BasicConstraints;
    else if (extensionTagNum == kTag_ExtendedKeyUsage)
        extensionOID = kOID_Extension_ExtendedKeyUsage;
    else
        ExitNow(err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

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

    // Extension ::= SEQUENCE
    ASN1_START_SEQUENCE {

        // extnID OBJECT IDENTIFIER,
        ASN1_ENCODE_OBJECT_ID(extensionOID);

        // critical BOOLEAN DEFAULT FALSE,
        nextRes = reader.Next();
        VerifyOrExit(nextRes == WEAVE_NO_ERROR || nextRes == WEAVE_END_OF_TLV, err = nextRes);
        if (reader.GetTag() == ContextTag(kTag_BasicConstraints_Critical))
        {
            bool critical;
            err = reader.Get(critical);
            SuccessOrExit(err);
            if (critical)
                ASN1_ENCODE_BOOLEAN(true);

            nextRes = reader.Next();
            VerifyOrExit(nextRes == WEAVE_NO_ERROR || nextRes == WEAVE_END_OF_TLV, err = nextRes);
        }

        // extnValue OCTET STRING
        //           -- contains the DER encoding of an ASN.1 value
        //           -- corresponding to the extension type identified
        //           -- by extnID
        ASN1_START_OCTET_STRING_ENCAPSULATED {

            if (extensionTagNum == kTag_AuthorityKeyIdentifier)
                err = ConvertAuthorityKeyIdentifierExtension(reader, writer, certData);
            else if (extensionTagNum == kTag_SubjectKeyIdentifier)
                err = ConvertSubjectKeyIdentifierExtension(reader, writer, certData);
            else if (extensionTagNum == kTag_KeyUsage)
                err = ConvertKeyUsageExtension(reader, writer, certData);
            else if (extensionTagNum == kTag_BasicConstraints)
                err = ConvertBasicConstraintsExtension(reader, writer, certData);
            else if (extensionTagNum == kTag_ExtendedKeyUsage)
                err = ConvertExtendedKeyUsageExtension(reader, writer, certData);
            else
                err = WEAVE_ERROR_UNSUPPORTED_CERT_FORMAT;
            SuccessOrExit(err);

        } ASN1_END_ENCAPSULATED;

    } ASN1_END_SEQUENCE;

    // Verify that all elements in the extension structure were consumed.
    err = reader.VerifyEndOfContainer();
    SuccessOrExit(err);

    err = reader.ExitContainer(outerContainer);
    SuccessOrExit(err);

exit:
    return err;
}

static WEAVE_ERROR ConvertExtensions(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    uint64_t tag;

    // extensions [3] EXPLICIT Extensions OPTIONAL
    ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3) {

        // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
        ASN1_START_SEQUENCE {

            while (true)
            {
                err = ConvertExtension(reader, writer, certData);
                SuccessOrExit(err);

                // Break the loop if the next certificate element is NOT an extension.
                err = reader.Next();
                SuccessOrExit(err);
                tag = reader.GetTag();
                if (!IsCertificateExtensionTag(tag))
                    break;
            }

        } ASN1_END_SEQUENCE;

    } ASN1_END_CONSTRUCTED;

exit:
    return err;
}

static WEAVE_ERROR ConvertRSASignature(TLVReader& reader, ASN1Writer& writer)
{
    WEAVE_ERROR err;

    VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = WEAVE_ERROR_WRONG_TLV_TYPE);
    VerifyOrExit(reader.GetTag() == ContextTag(kTag_RSASignature), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

    err = writer.PutBitString(0, reader);
    SuccessOrExit(err);

exit:
    return err;
}

static WEAVE_ERROR ConvertECDSASignature(TLVReader& reader, ASN1Writer& writer)
{
    WEAVE_ERROR err;
    EncodedECDSASignature encodedSig;

    VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

    err = DecodeWeaveECDSASignature(reader, encodedSig);
    SuccessOrExit(err);

    // signatureValue BIT STRING
    // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
    ASN1_START_BIT_STRING_ENCAPSULATED {

        // Ecdsa-Sig-Value ::= SEQUENCE
        ASN1_START_SEQUENCE {

            // r INTEGER
            err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, encodedSig.R, encodedSig.RLen);
            SuccessOrExit(err);

            // s INTEGER
            err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, encodedSig.S, encodedSig.SLen);
            SuccessOrExit(err);

        } ASN1_END_SEQUENCE;

    } ASN1_END_ENCAPSULATED;

exit:
    return err;
}

WEAVE_ERROR ConvertTBSCertificate(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    uint64_t tag;
    uint32_t weaveSigAlgo;
    OID sigAlgoOID;

    // tbsCertificate TBSCertificate,
    // TBSCertificate ::= SEQUENCE
    ASN1_START_SEQUENCE {

        // version [0] EXPLICIT Version DEFAULT v1
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0) {

            // Version ::= INTEGER { v1(0), v2(1), v3(2) }
            ASN1_ENCODE_INTEGER(2);

        } ASN1_END_CONSTRUCTED;

        err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber));
        SuccessOrExit(err);

        // serialNumber CertificateSerialNumber
        // CertificateSerialNumber ::= INTEGER
        err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
        SuccessOrExit(err);

        // signature AlgorithmIdentifier
        // AlgorithmIdentifier ::= SEQUENCE
        ASN1_START_SEQUENCE {

            err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm));
            SuccessOrExit(err);

            err = reader.Get(weaveSigAlgo);
            SuccessOrExit(err);

            sigAlgoOID = (OID)(weaveSigAlgo | kOIDCategory_SigAlgo);
            ASN1_ENCODE_OBJECT_ID(sigAlgoOID);

            // parameters ANY DEFINED BY algorithm OPTIONAL
            // Per RFC3279, parameters for RSA must be NULL, parameters for ECDSAWithSHA1 must be absent.
            if (sigAlgoOID == kOID_SigAlgo_MD2WithRSAEncryption ||
                sigAlgoOID == kOID_SigAlgo_MD5WithRSAEncryption ||
                sigAlgoOID == kOID_SigAlgo_SHA1WithRSAEncryption)
            {
                ASN1_ENCODE_NULL;
            }

            certData.SigAlgoOID = sigAlgoOID;

        } ASN1_END_SEQUENCE;

        // issuer Name
        //
        // NOTE: Accept a core tag as well as a context tag to support early Weave certificates where
        // this field was encoded incorrectly.
        //
        err = reader.Next();
        SuccessOrExit(err);
        tag = reader.GetTag();
        VerifyOrExit(tag == CommonTag(kTag_Issuer) || tag == ContextTag(kTag_Issuer), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);
        VerifyOrExit(reader.GetType() == kTLVType_Path, err = WEAVE_ERROR_WRONG_TLV_TYPE);
        err = ConvertDistinguishedName(reader, writer, certData.IssuerDN);
        SuccessOrExit(err);

        // validity Validity,
        err = ConvertValidity(reader, writer, certData);
        SuccessOrExit(err);

        // subject Name,
        //
        // NOTE: Also accept core tag here.
        //
        err = reader.Next();
        SuccessOrExit(err);
        tag = reader.GetTag();
        VerifyOrExit(tag == CommonTag(kTag_Subject) || tag == ContextTag(kTag_Subject), err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);
        VerifyOrExit(reader.GetType() == kTLVType_Path, err = WEAVE_ERROR_WRONG_TLV_TYPE);
        err = ConvertDistinguishedName(reader, writer, certData.SubjectDN);
        SuccessOrExit(err);

        // subjectPublicKeyInfo SubjectPublicKeyInfo,
        err = ConvertSubjectPublicKeyInfo(reader, writer, certData);
        SuccessOrExit(err);

        // If the next element is a certificate extension...
        err = reader.Next();
        SuccessOrExit(err);
        tag = reader.GetTag();
        if (IsCertificateExtensionTag(tag))
        {
            err = ConvertExtensions(reader, writer, certData);
            SuccessOrExit(err);
        }

    } ASN1_END_SEQUENCE;

exit:
    return err;
}

static WEAVE_ERROR ConvertCert(TLVReader& reader, ASN1Writer& writer, WeaveCertificateData& certData)
{
    WEAVE_ERROR err;
    uint64_t tag;
    TLVType containerType;

    if (reader.GetType() == kTLVType_NotSpecified)
    {
        err = reader.Next();
        SuccessOrExit(err);
    }
    VerifyOrExit(reader.GetType() == kTLVType_Structure, err = WEAVE_ERROR_WRONG_TLV_TYPE);
    tag = reader.GetTag();
    VerifyOrExit(tag == ProfileTag(kWeaveProfile_Security, kTag_WeaveCertificate) || tag == AnonymousTag,
                 err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);

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

    // Certificate ::= SEQUENCE
    ASN1_START_SEQUENCE {

        // tbsCertificate TBSCertificate,
        err = ConvertTBSCertificate(reader, writer, certData);
        SuccessOrExit(err);

        // signatureAlgorithm   AlgorithmIdentifier
        // AlgorithmIdentifier ::= SEQUENCE
        ASN1_START_SEQUENCE {

            ASN1_ENCODE_OBJECT_ID((OID)certData.SigAlgoOID);

            // parameters ANY DEFINED BY algorithm OPTIONAL
            // Per RFC3279, parameters for RSA must be NULL, parameters for ECDSAWithSHA1 must be absent.
            if (certData.SigAlgoOID == kOID_SigAlgo_MD2WithRSAEncryption ||
                certData.SigAlgoOID == kOID_SigAlgo_MD5WithRSAEncryption ||
                certData.SigAlgoOID == kOID_SigAlgo_SHA1WithRSAEncryption)
            {
                ASN1_ENCODE_NULL;
            }

        } ASN1_END_SEQUENCE;

        // signatureValue BIT STRING
        if (certData.SigAlgoOID == kOID_SigAlgo_MD2WithRSAEncryption ||
            certData.SigAlgoOID == kOID_SigAlgo_MD5WithRSAEncryption ||
            certData.SigAlgoOID == kOID_SigAlgo_SHA1WithRSAEncryption)
        {
            err = ConvertRSASignature(reader, writer);
            SuccessOrExit(err);
        }

        else
        {
            err = ConvertECDSASignature(reader, writer);
            SuccessOrExit(err);
        }

    } ASN1_END_SEQUENCE;

    // Verify no more elements in certificate.
    err = reader.VerifyEndOfContainer();
    SuccessOrExit(err);

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

exit:
    return err;
}

NL_DLL_EXPORT WEAVE_ERROR ConvertWeaveCertToX509Cert(const uint8_t *weaveCert, uint32_t weaveCertLen, uint8_t *x509CertBuf, uint32_t x509CertBufSize, uint32_t& x509CertLen)
{
    WEAVE_ERROR err;
    TLVReader reader;
    ASN1Writer writer;
    WeaveCertificateData certData;

    reader.Init(weaveCert, weaveCertLen);

    writer.Init(x509CertBuf, x509CertBufSize);

    memset(&certData, 0, sizeof(certData));

    err = ConvertCert(reader, writer, certData);
    SuccessOrExit(err);

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

    x509CertLen = writer.GetLengthWritten();

exit:
    return err;
}


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