/*
 *
 *    Copyright (c) 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
 *      Implementation of KeyExportConfig object, which provides an implementation of the WeaveKeyExportDelegate
 *      interface for use in test applications.
 *
 */

#include "stdio.h"

#include "ToolCommon.h"
#include <Weave/Support/CodeUtils.h>
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/security/WeaveAccessToken.h>
#include <Weave/Profiles/security/WeaveSig.h>
#include <Weave/Profiles/security/WeaveSecurityDebug.h>
#include <Weave/Profiles/service-provisioning/ServiceProvisioning.h>
#include <Weave/Support/NestCerts.h>
#include <Weave/Support/ErrorStr.h>
#include <Weave/Support/ASN1.h>
#include "KeyExportOptions.h"

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

static uint8_t sAccessToken[] =
{
    /*
    -----BEGIN ACCESS TOKEN-----
    1QAABAAJADUBMAEITi8yS0HXOtskAgQ3AyyBEERVTU1ZLUFDQ09VTlQtSUQYJgTLqPobJgVLNU9C
    NwYsgRBEVU1NWS1BQ0NPVU5ULUlEGCQHAiYIJQBaIzAKOQQr2dtaYu+6sVMqD5ljt4owxYpBKaUZ
    TksL837axemzNfB1GG1JXYbERCUHQbTTqe/utCrWCl2d4DWDKQEYNYIpASQCBRg1hCkBNgIEAgQB
    GBg1gTACCEI8lV9GHlLbGDWAMAIIQjyVX0YeUtsYNQwwAR0AimGGYj0XstLP0m05PeQlaeCR6gVq
    dc7dReuDzzACHHS0K6RtFGW3t3GaWq9k0ohgbrOxoDHKkm/K8kMYGDUCJgElAFojMAIcuvzjT4a/
    fDgScCv5oxC/T5vz7zAPpURNQjpnajADOQQr2dtaYu+6sVMqD5ljt4owxYpBKaUZTksL837axemz
    NfB1GG1JXYbERCUHQbTTqe/utCrWCl2d4BgY
    -----END ACCESS TOKEN-----
    */
    0xd5, 0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x35, 0x01, 0x30, 0x01, 0x08, 0x4e, 0x2f, 0x32, 0x4b,
    0x41, 0xd7, 0x3a, 0xdb, 0x24, 0x02, 0x04, 0x37, 0x03, 0x2c, 0x81, 0x10, 0x44, 0x55, 0x4d, 0x4d,
    0x59, 0x2d, 0x41, 0x43, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x2d, 0x49, 0x44, 0x18, 0x26, 0x04, 0xcb,
    0xa8, 0xfa, 0x1b, 0x26, 0x05, 0x4b, 0x35, 0x4f, 0x42, 0x37, 0x06, 0x2c, 0x81, 0x10, 0x44, 0x55,
    0x4d, 0x4d, 0x59, 0x2d, 0x41, 0x43, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x2d, 0x49, 0x44, 0x18, 0x24,
    0x07, 0x02, 0x26, 0x08, 0x25, 0x00, 0x5a, 0x23, 0x30, 0x0a, 0x39, 0x04, 0x2b, 0xd9, 0xdb, 0x5a,
    0x62, 0xef, 0xba, 0xb1, 0x53, 0x2a, 0x0f, 0x99, 0x63, 0xb7, 0x8a, 0x30, 0xc5, 0x8a, 0x41, 0x29,
    0xa5, 0x19, 0x4e, 0x4b, 0x0b, 0xf3, 0x7e, 0xda, 0xc5, 0xe9, 0xb3, 0x35, 0xf0, 0x75, 0x18, 0x6d,
    0x49, 0x5d, 0x86, 0xc4, 0x44, 0x25, 0x07, 0x41, 0xb4, 0xd3, 0xa9, 0xef, 0xee, 0xb4, 0x2a, 0xd6,
    0x0a, 0x5d, 0x9d, 0xe0, 0x35, 0x83, 0x29, 0x01, 0x18, 0x35, 0x82, 0x29, 0x01, 0x24, 0x02, 0x05,
    0x18, 0x35, 0x84, 0x29, 0x01, 0x36, 0x02, 0x04, 0x02, 0x04, 0x01, 0x18, 0x18, 0x35, 0x81, 0x30,
    0x02, 0x08, 0x42, 0x3c, 0x95, 0x5f, 0x46, 0x1e, 0x52, 0xdb, 0x18, 0x35, 0x80, 0x30, 0x02, 0x08,
    0x42, 0x3c, 0x95, 0x5f, 0x46, 0x1e, 0x52, 0xdb, 0x18, 0x35, 0x0c, 0x30, 0x01, 0x1d, 0x00, 0x8a,
    0x61, 0x86, 0x62, 0x3d, 0x17, 0xb2, 0xd2, 0xcf, 0xd2, 0x6d, 0x39, 0x3d, 0xe4, 0x25, 0x69, 0xe0,
    0x91, 0xea, 0x05, 0x6a, 0x75, 0xce, 0xdd, 0x45, 0xeb, 0x83, 0xcf, 0x30, 0x02, 0x1c, 0x74, 0xb4,
    0x2b, 0xa4, 0x6d, 0x14, 0x65, 0xb7, 0xb7, 0x71, 0x9a, 0x5a, 0xaf, 0x64, 0xd2, 0x88, 0x60, 0x6e,
    0xb3, 0xb1, 0xa0, 0x31, 0xca, 0x92, 0x6f, 0xca, 0xf2, 0x43, 0x18, 0x18, 0x35, 0x02, 0x26, 0x01,
    0x25, 0x00, 0x5a, 0x23, 0x30, 0x02, 0x1c, 0xba, 0xfc, 0xe3, 0x4f, 0x86, 0xbf, 0x7c, 0x38, 0x12,
    0x70, 0x2b, 0xf9, 0xa3, 0x10, 0xbf, 0x4f, 0x9b, 0xf3, 0xef, 0x30, 0x0f, 0xa5, 0x44, 0x4d, 0x42,
    0x3a, 0x67, 0x6a, 0x30, 0x03, 0x39, 0x04, 0x2b, 0xd9, 0xdb, 0x5a, 0x62, 0xef, 0xba, 0xb1, 0x53,
    0x2a, 0x0f, 0x99, 0x63, 0xb7, 0x8a, 0x30, 0xc5, 0x8a, 0x41, 0x29, 0xa5, 0x19, 0x4e, 0x4b, 0x0b,
    0xf3, 0x7e, 0xda, 0xc5, 0xe9, 0xb3, 0x35, 0xf0, 0x75, 0x18, 0x6d, 0x49, 0x5d, 0x86, 0xc4, 0x44,
    0x25, 0x07, 0x41, 0xb4, 0xd3, 0xa9, 0xef, 0xee, 0xb4, 0x2a, 0xd6, 0x0a, 0x5d, 0x9d, 0xe0, 0x18,
    0x18,
};

static uint16_t sAccessTokenLength = sizeof(sAccessToken);

KeyExportOptions gKeyExportOptions;

// Parse a sequence of zero or more unsigned integers corresponding to a list
// of allowed KeyExport configurations.  Integer values must be separated by either
// a comma or a space.
bool ParseAllowedKeyExportConfigs(const char *strConst, uint8_t& output)
{
    bool res = true;
    char *str = strdup(strConst);
    uint32_t configNum;

    output = 0;

    for (char *p = str; p != NULL; )
    {
        char *sep = strchr(p, ',');
        if (sep == NULL)
            sep = strchr(p, ' ');

        if (sep != NULL)
            *sep = 0;

        if (!ParseInt(p, configNum))
        {
            res = false;
            break;
        }

        if (configNum == 1)
            output |= kKeyExportSupportedConfig_Config1;
        else if (configNum == 2)
            output |= kKeyExportSupportedConfig_Config2;
        else
        {
            res = false;
            break;
        }

        p = (sep != NULL) ? sep + 1 : NULL;
    }

    free(str);

    return res;
}

KeyExportOptions::KeyExportOptions()
{
    static OptionDef optionDefs[] =
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR || WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        { "allowed-key-export-configs", kArgumentRequired,      kToolCommonOpt_AllowedKeyExportConfigs },
        { "access-token",               kArgumentRequired,      kToolCommonOpt_AccessToken             },
#endif
        { }
    };
    OptionDefs = optionDefs;

    HelpGroupName = "KEY EXPORT OPTIONS";

    OptionHelp =
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR || WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        "  --allowed-key-export-configs <int>[,<int>]\n"
        "       Accept the specified set of key export configurations when either initiating or\n"
        "       responding to a key export request.\n"
        "\n"
        "  --access-token <access-token-file>\n"
        "       File containing a Weave Access Token to be used to authenticate the key\n"
        "       export request. (Must be in Weave TLV format). In not specified the default\n"
        "       test access token is used.\n"
        "\n"
#endif
      "";

    // Defaults
    AllowedKeyExportConfigs = 0; // 0 causes code to use default value provided by WeaveSecurityManager
    mAccessToken = NULL;
    mAccessTokenLength = 0;
}

bool KeyExportOptions::HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
{
    uint32_t len;

    switch (id)
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR || WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
    case kToolCommonOpt_AllowedKeyExportConfigs:
        if (!ParseAllowedKeyExportConfigs(arg, AllowedKeyExportConfigs))
        {
            PrintArgError("%s: Invalid value specified for allowed KeyExport configs: %s\n", progName, arg);
            return false;
        }
        break;
    case kToolCommonOpt_AccessToken:
        mAccessToken = ReadFileArg(arg, len);
        if (mAccessToken == NULL)
            return false;
        mAccessTokenLength = len;
        break;
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR || WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER

    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
        return false;
    }

    return true;
}

enum
{
    // Max Device Private Key Size -- Size of the temporary buffer used to hold
    // a device's TLV encoded private key.
    kMaxDevicePrivateKeySize = 300,

    // Max Validation Certs -- This controls the maximum number of certificates
    // that can be involved in the validation of an image signature. It must
    // include room for the signing cert, the trust anchors and any intermediate
    // certs included in the signature object.
    kMaxCerts = 10,

    // Certificate Decode Buffer Size -- Size of the temporary buffer used to decode
    // certs. The buffer must be big enough to hold the ASN1 DER encoding of the
    // TBSCertificate portion of the largest cert involved in signature verification.
    // Note that all certificates included in the signature are decoded using this
    // buffer, even if they are ultimately not involved in verifying the image
    // signature.
    kCertDecodeBufferSize = 1024
};

#if !WEAVE_CONFIG_LEGACY_KEY_EXPORT_DELEGATE

WEAVE_ERROR KeyExportOptions::GetNodeCertSet(WeaveKeyExport * keyExport, WeaveCertificateSet & certSet)
{
    return GetNodeCertSet(keyExport->IsInitiator(), certSet);
}

WEAVE_ERROR KeyExportOptions::ReleaseNodeCertSet(WeaveKeyExport * keyExport, WeaveCertificateSet & certSet)
{
    return ReleaseNodeCertSet(keyExport->IsInitiator(), certSet);
}

WEAVE_ERROR KeyExportOptions::GenerateNodeSignature(WeaveKeyExport * keyExport, const uint8_t * msgHash, uint8_t msgHashLen,
    TLVWriter & writer)
{
    WEAVE_ERROR err;
    const uint8_t * privKey = NULL;
    uint16_t privKeyLen;

    err = GetNodePrivateKey(keyExport->IsInitiator(), privKey, privKeyLen);
    SuccessOrExit(err);

    err = GenerateAndEncodeWeaveECDSASignature(writer, TLV::ContextTag(kTag_WeaveSignature_ECDSASignatureData), msgHash, msgHashLen, privKey, privKeyLen);
    SuccessOrExit(err);

exit:
    if (privKey != NULL)
    {
        WEAVE_ERROR relErr = ReleaseNodePrivateKey(keyExport->IsInitiator(), privKey);
        err = (err == WEAVE_NO_ERROR) ? relErr : err;
    }
    return err;
}

WEAVE_ERROR KeyExportOptions::BeginCertValidation(WeaveKeyExport * keyExport, ValidationContext & validCtx,
        WeaveCertificateSet & certSet)
{
    return BeginCertValidation(keyExport->IsInitiator(), certSet, validCtx);
}

WEAVE_ERROR KeyExportOptions::HandleCertValidationResult(WeaveKeyExport * keyExport, ValidationContext & validCtx,
        WeaveCertificateSet & certSet, uint32_t requestedKeyId)
{
    return HandleCertValidationResult(keyExport->IsInitiator(), certSet, validCtx, NULL, keyExport->MessageInfo(), requestedKeyId);
}

WEAVE_ERROR KeyExportOptions::EndCertValidation(WeaveKeyExport * keyExport, ValidationContext & validCtx,
        WeaveCertificateSet & certSet)
{
    return EndCertValidation(keyExport->IsInitiator(), certSet, validCtx);
}

WEAVE_ERROR KeyExportOptions::ValidateUnsignedKeyExportMessage(WeaveKeyExport * keyExport, uint32_t requestedKeyId)
{
    // Unsigned key export messages are not supported.
    return keyExport->IsInitiator()
            ? WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_RESPONSE
            : WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_REQUEST;
}

#endif // !WEAVE_CONFIG_LEGACY_KEY_EXPORT_DELEGATE

// Get the key export certificate set for the local node.
// This method is responsible for initializing certificate set and loading all certificates
// that will be included in the signature of the message.
WEAVE_ERROR KeyExportOptions::GetNodeCertSet(bool isInitiator, WeaveCertificateSet& certSet)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveCertificateData *cert;
    bool certSetInitialized = false;

    err = certSet.Init(kMaxCerts, kCertDecodeBufferSize, nl::Weave::Platform::Security::MemoryAlloc, nl::Weave::Platform::Security::MemoryFree);
    SuccessOrExit(err);
    certSetInitialized = true;

    if (isInitiator)
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        const uint8_t *accessToken = mAccessToken;
        uint16_t accessTokenLen = mAccessTokenLength;

        if (accessToken == NULL || accessTokenLen == 0)
        {
            accessToken = sAccessToken;
            accessTokenLen = sAccessTokenLength;
        }

        err = LoadAccessTokenCerts(accessToken, accessTokenLen, certSet, 0, cert);
        SuccessOrExit(err);

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
    }
    else
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        // Responder uses the same device certificate that is specified for CASE.
        const uint8_t *nodeCert = gCASEOptions.NodeCert;
        uint16_t nodeCertLen = gCASEOptions.NodeCertLength;

        if (nodeCert == NULL || nodeCertLen == 0)
        {
            GetTestNodeCert(FabricState.LocalNodeId, nodeCert, nodeCertLen);
        }
        if (nodeCert == NULL || nodeCertLen == 0)
        {
            printf("ERROR: Node certificate not configured\n");
            ExitNow(err = WEAVE_ERROR_CERT_NOT_FOUND);
        }

        err = certSet.LoadCert(nodeCert, nodeCertLen, 0, cert);
        SuccessOrExit(err);

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
    }

exit:
    if (err != WEAVE_NO_ERROR && certSetInitialized)
        certSet.Release();

    return err;
}

// Called when the key export engine is done with the certificate set returned by GetNodeCertSet().
WEAVE_ERROR KeyExportOptions::ReleaseNodeCertSet(bool isInitiator, WeaveCertificateSet& certSet)
{
    certSet.Release();

    return WEAVE_NO_ERROR;
}

// Get the local node's private key.
WEAVE_ERROR KeyExportOptions::GetNodePrivateKey(bool isInitiator, const uint8_t *& weavePrivKey, uint16_t& weavePrivKeyLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint8_t *privKeyBuf = NULL;

    if (isInitiator)
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        const uint8_t *accessToken = mAccessToken;
        uint16_t accessTokenLen = mAccessTokenLength;

        if (accessToken == NULL || accessTokenLen == 0)
        {
            accessToken = sAccessToken;
            accessTokenLen = sAccessTokenLength;
        }

        // Allocate a buffer to hold the private key.
        privKeyBuf = (uint8_t *)nl::Weave::Platform::Security::MemoryAlloc(kMaxDevicePrivateKeySize);
        VerifyOrExit(privKeyBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

        // Extract the private key from the access token, converting the encoding to a EllipticCurvePrivateKey TLV object.
        err = ExtractPrivateKeyFromAccessToken(accessToken, accessTokenLen, privKeyBuf, accessTokenLen, weavePrivKeyLen);
        SuccessOrExit(err);

        // Pass the extracted key back to the caller.
        weavePrivKey = privKeyBuf;
        privKeyBuf = NULL;

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
    }
    else
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        // Responder uses the same device private key that was specified for CASE authentication.
        weavePrivKey = gCASEOptions.NodePrivateKey;
        weavePrivKeyLen = gCASEOptions.NodePrivateKeyLength;

        if (weavePrivKey == NULL || weavePrivKeyLen == 0)
        {
            GetTestNodePrivateKey(FabricState.LocalNodeId, weavePrivKey, weavePrivKeyLen);
        }
        if (weavePrivKey == NULL || weavePrivKeyLen == 0)
        {
            printf("ERROR: Node private key not configured\n");
            ExitNow(err = WEAVE_ERROR_KEY_NOT_FOUND);
        }

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
    }

exit:
    if (privKeyBuf != NULL)
        nl::Weave::Platform::Security::MemoryFree(privKeyBuf);

    return err;
}

// Called when the key export engine is done with the buffer returned by GetNodePrivateKey().
WEAVE_ERROR KeyExportOptions::ReleaseNodePrivateKey(bool isInitiator, const uint8_t *& weavePrivKey)
{
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
    if (isInitiator && weavePrivKey != NULL)
    {
        nl::Weave::Platform::Security::MemoryFree((void *)weavePrivKey);
        weavePrivKey = NULL;
    }
#endif

    return WEAVE_NO_ERROR;
}

// Prepare the supplied certificate set and validation context for use in validating the certificate of a peer.
// This method is responsible for loading the trust anchors into the certificate set.
WEAVE_ERROR KeyExportOptions::BeginCertValidation(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
    WEAVE_ERROR err;
    WeaveCertificateData *cert;
    bool certSetInitialized = false;

    err = certSet.Init(kMaxCerts, kCertDecodeBufferSize, nl::Weave::Platform::Security::MemoryAlloc, nl::Weave::Platform::Security::MemoryFree);
    SuccessOrExit(err);
    certSetInitialized = true;

    if (isInitiator)
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        err = certSet.LoadCert(nl::NestCerts::Development::Root::Cert, nl::NestCerts::Development::Root::CertLength, 0, cert);
        SuccessOrExit(err);
        cert->CertFlags |= kCertFlag_IsTrusted;

        err = certSet.LoadCert(nl::NestCerts::Production::Root::Cert, nl::NestCerts::Production::Root::CertLength, 0, cert);
        SuccessOrExit(err);
        cert->CertFlags |= kCertFlag_IsTrusted;

        err = certSet.LoadCert(nl::NestCerts::Development::DeviceCA::Cert, nl::NestCerts::Development::DeviceCA::CertLength, kDecodeFlag_GenerateTBSHash, cert);
        SuccessOrExit(err);

        err = certSet.LoadCert(nl::NestCerts::Production::DeviceCA::Cert, nl::NestCerts::Production::DeviceCA::CertLength, kDecodeFlag_GenerateTBSHash, cert);
        SuccessOrExit(err);

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
    }
    else
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        const uint8_t *accessToken = mAccessToken;
        uint16_t accessTokenLen = mAccessTokenLength;

        if (accessToken == NULL || accessTokenLen == 0)
        {
            accessToken = sAccessToken;
            accessTokenLen = sAccessTokenLength;
        }

        err = LoadAccessTokenCerts(accessToken, accessTokenLen, certSet, 0, cert);
        SuccessOrExit(err);
        cert->CertFlags |= kCertFlag_IsTrusted;

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
    }

    // Initialize the validation context.
    memset(&validContext, 0, sizeof(validContext));
    validContext.EffectiveTime = SecondsSinceEpochToPackedCertTime(time(NULL));
    validContext.RequiredKeyUsages = kKeyUsageFlag_DigitalSignature;
    validContext.ValidateFlags = kValidateFlag_IgnoreNotAfter;

exit:
    if (err != WEAVE_NO_ERROR && certSetInitialized)
        certSet.Release();

    return err;
}

// Called with the results of validating the peer's certificate.
// Responder verifies that requestor is authorized to export the specified key.
WEAVE_ERROR KeyExportOptions::HandleCertValidationResult(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext,
                                                         const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo, uint32_t requestedKeyId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveCertificateData *peerCert = validContext.SigningCert;

    if (isInitiator)
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        // Verify that it is device certificate and its subject matches the responder node id.
        VerifyOrExit(peerCert->SubjectDN.AttrOID == ASN1::kOID_AttributeType_WeaveDeviceId &&
                     peerCert->SubjectDN.AttrValue.WeaveId == msgInfo->SourceNodeId, err = WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_RESPONSE);

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_INITIATOR
    }
    else
    {
#if WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        // Verify that requested key is Client Root Key and that peer's signing certificate
        // has all the correct attributes of access token certificate:
        //   -- it is trusted.
        //   -- it is self-signed.
        //   -- it has CommonName attribute type.
        VerifyOrExit((requestedKeyId == WeaveKeyId::kClientRootKey) &&
                     (peerCert->CertFlags & kCertFlag_IsTrusted) &&
                     peerCert->IssuerDN.IsEqual(peerCert->SubjectDN) &&
                     peerCert->AuthKeyId.IsEqual(peerCert->SubjectKeyId) &&
                     peerCert->SubjectDN.AttrOID == ASN1::kOID_AttributeType_CommonName, err = WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_REQUEST);

#else // !WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_KEY_EXPORT_RESPONDER
    }

exit:
    return err;
}

// Called when peer certificate validation is complete.
WEAVE_ERROR KeyExportOptions::EndCertValidation(bool isInitiator, WeaveCertificateSet& certSet, ValidationContext& validContext)
{
    certSet.Release();

    return WEAVE_NO_ERROR;
}

// Called by requestor and responder to verify that received message was appropriately secured when the message isn't signed.
WEAVE_ERROR KeyExportOptions::ValidateUnsignedKeyExportMessage(bool isInitiator, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo, uint32_t requestedKeyId)
{
    // Unsigned key export messages are not supported.
    return isInitiator ? WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_RESPONSE :
                         WEAVE_ERROR_UNAUTHORIZED_KEY_EXPORT_REQUEST;
}
