/*
 *
 *    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 managing the active node
 *      state necessary to participate in a Weave fabric.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif // __STDC_LIMIT_MACROS
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif // __STDC_FORMAT_MACROS

#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>

#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveKeyIds.h>
#include <Weave/Profiles/security/WeaveApplicationKeys.h>
#include <Weave/Profiles/security/WeaveDummyGroupKeyStore.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Support/crypto/WeaveCrypto.h>
#include <Weave/Profiles/fabric-provisioning/FabricProvisioning.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Support/RandUtils.h>
#include <Weave/Support/logging/WeaveLogging.h>

#if HAVE_NEW
#include <new>
#else
inline void * operator new     (size_t, void * p) throw() { return p; }
inline void * operator new[]   (size_t, void * p) throw() { return p; }
#endif

namespace nl {
namespace Weave {

using namespace nl::Weave::TLV;
using namespace nl::Weave::Encoding;
using namespace nl::Weave::Crypto;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::FabricProvisioning;
using namespace nl::Weave::Profiles::Security;
using namespace nl::Weave::Profiles::Security::AppKeys;

#if WEAVE_CONFIG_SECURITY_TEST_MODE
#pragma message "\n \
                 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n \
                 !!!!    WARNING - SECURITY_TEST_MODE IS ENABLED    !!!!\n \
                 !!!! BASIC WEAVE SECURITY / ENCRYPTION IS CRIPPLED !!!!\n \
                 !!!!        DEVELOPMENT ONLY -- DO NOT SHIP        !!!!\n \
                 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n \
                 "
#endif

#if !WEAVE_CONFIG_REQUIRE_AUTH
#pragma message "\n \
                 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n \
                 !!!!  WARNING - REQUIRE_AUTH IS DISABLED   !!!!\n \
                 !!!! CLIENT AUTHENTICATION IS NOT REQUIRED !!!!\n \
                 !!!!    DEVELOPMENT ONLY -- DO NOT SHIP    !!!!\n \
                 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n \
                 "
#endif

#ifndef nlDEFINE_ALIGNED_VAR
#define nlDEFINE_ALIGNED_VAR(varName, bytes, alignment_type) \
  alignment_type varName[(((bytes)+(sizeof(alignment_type)-1))/sizeof(alignment_type))]
#endif

// Identifies the scheme used to rotate fabric secret. The use of this
// identifier is deprecated because fabric secret value never rotates.
//
// NOTE: This value is communicated over the wire--do not renumber.
//
typedef uint8_t FabricSecretRotationScheme;

enum
{
    kDeprecatedRotationScheme                           = 0x00
};

// Key diversifier used for Weave message encryption key derivation.
const uint8_t kWeaveMsgEncAppKeyDiversifier[] = { 0xB1, 0x1D, 0xAE, 0x5B };

/**
 * Initialize a WeaveSessionKey object.
 */
void WeaveSessionKey::Init(void)
{
    NodeId = kNodeIdNotSpecified;
    NextMsgId.Init(0);
    MaxRcvdMsgId = 0;
    InitialSendMsgId = 0;
    InitialRcvdMsgId = 0;
    ResumptionSendMsgId = 0;
    ResumptionRecvMsgId = 0;
    BoundCon = NULL;
    RcvFlags = 0;
    AuthMode = kWeaveAuthMode_NotSpecified;
    memset(&MsgEncKey, 0, sizeof(MsgEncKey));
    ReserveCount = 0;
    Flags = 0;
}

/**
 * Reset a WeaveSessionKey object.
 */
void WeaveSessionKey::Clear(void)
{
    Init();
    ClearSecretData((uint8_t *)&MsgEncKey.EncKey, sizeof(MsgEncKey.EncKey));
}

void WeaveSessionKey::ComputeNextResumptionMsgIds(void)
{
     // When calculating the resumption message ids, it needs to be ensured that the next resumption message id is always ahead of the current message ids.
     while (ResumptionSendMsgId < NextMsgId.GetValue())
     {
         ResumptionSendMsgId = (ResumptionSendMsgId == 0) ? InitialSendMsgId + WEAVE_CONFIG_TUNNEL_SESSION_RESUMPTION_MSG_ID_OFFSET :
                                ResumptionSendMsgId + WEAVE_CONFIG_TUNNEL_SESSION_RESUMPTION_MSG_ID_OFFSET;
     }

     while (ResumptionRecvMsgId < MaxRcvdMsgId)
     {
         ResumptionRecvMsgId = (ResumptionRecvMsgId == 0) ? InitialRcvdMsgId + WEAVE_CONFIG_TUNNEL_SESSION_RESUMPTION_MSG_ID_OFFSET - 1:
                                ResumptionRecvMsgId + WEAVE_CONFIG_TUNNEL_SESSION_RESUMPTION_MSG_ID_OFFSET;
     }
}

/**
 * @fn bool WeaveSessionKey::IsAllocated() const
 *
 * @return True if the WeaveSessionKey object is allocated.
 */

/**
 * @fn bool WeaveSessionKey::IsKeySet() const
 *
 * @return True if the encryption key value has been set in a WeaveSessionKey object.
 */

/**
 * @fn bool WeaveSessionKey::IsLocallyInitiated() const
 *
 * @return True if the session was initiated by the local node.
 */

/*
 * @fn void WeaveSessionKey::SetLocallyInitiated(bool val)
 *
 * Sets a flag indicating whether the session was initiated by the local node.
 *
 * @param[in] val The value to set the kFlag_IsLocallyInitiated flag to.
 */

/*
 * @fn bool WeaveSessionKey::IsSharedSession() const
 *
 * @return True if the session is shared--i.e. can be used for multiplexed communication with different peer node ids.
 */

/**
 * @fn void WeaveSessionKey::SetSharedSession(bool val)
 *
 * Sets a flag indicating whether the session is a shared session.
 *
 * @param[in] val The value to set the kFlag_IsSharedSession flag to.
 */

/**
 * @fn bool WeaveSessionKey::IsRemoveOnIdle() const
 *
 * @return True if the session is flagged for automatic removal when idle for a period of time.
 */

/**
 * @fn void WeaveSessionKey::SetRemoveOnIdle(bool val)
 *
 * Sets a flag indicating whether the session should be automatically removed after a period of idle time.
 *
 * @param[in] val The value to set the kFlag_IsRemoveOnIdle flag to.
 */

/**
 * @fn bool WeaveSessionKey::IsRecentlyActive() const
 *
 * @return True if the session has been active in the recent past.
 */

/**
 * @fn void WeaveSessionKey::MarkRecentlyActive()
 *
 * Signals the session as having been active in the recent past.
 */

/**
 * @fn void WeaveSessionKey::ClearRecentlyActive()
 *
 * Signals the session as NOT having been active in the recent past.
 */

WeaveFabricState::WeaveFabricState()
{
    State = kState_NotInitialized;
}

WEAVE_ERROR WeaveFabricState::Init()
{
    static nlDEFINE_ALIGNED_VAR(sDummyGroupKeyStore, sizeof(DummyGroupKeyStore), void*);

    return Init(new (&sDummyGroupKeyStore) DummyGroupKeyStore());
}

WEAVE_ERROR WeaveFabricState::Init(GroupKeyStoreBase *groupKeyStore)
{
    if (State != kState_NotInitialized)
        return WEAVE_ERROR_INCORRECT_STATE;

    if (groupKeyStore == NULL)
        return WEAVE_ERROR_INVALID_ARGUMENT;

#ifdef WEAVE_NON_PRODUCTION_MARKER
    // This is a trick to force the linker to include the WEAVE_NON_PRODUCTION_MARKER symbol
    // in the linked output.  (Note that the test will never evaluate to true).
    if (WEAVE_NON_PRODUCTION_MARKER[0] == 0)
        return WEAVE_ERROR_INCORRECT_STATE;
#endif

    GroupKeyStore = groupKeyStore;

    FabricId = kFabricIdNotSpecified;
    LocalNodeId = 1;
    PairingCode = NULL;
    DefaultSubnet = kWeaveSubnetId_PrimaryWiFi;
    PeerCount = 0;
    NextUnencUDPMsgId.Init(GetRandU32());
    NextUnencTCPMsgId.Init(0);
    for (int i = 0; i < WEAVE_CONFIG_MAX_SESSION_KEYS; i++)
        SessionKeys[i].Init();
#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
    WEAVE_ERROR err = NextGroupKeyMsgId.Init(WEAVE_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_ID, WEAVE_CONFIG_PERSISTED_STORAGE_ENC_MSG_CNTR_EPOCH);
    if (err != WEAVE_NO_ERROR)
        return err;

    GroupKeyMsgIdFreshWindowStart = 0;
    MsgCounterSyncStatus = 0;
    AppKeyCache.Init();
#endif
    memset(&PeerStates, 0, sizeof(PeerStates));
    Delegate = NULL;
    memset(SharedSessionsNodes, 0, sizeof(SharedSessionsNodes));

#if WEAVE_CONFIG_SECURITY_TEST_MODE
    DebugFabricId = 0;
    LogKeys = false;
    UseTestKey = false; // DEPRECATED -- Temporarily retained for API compatibility
    AutoCreateKeys = false; // DEPRECATED -- Temporarily retained for API compatibility
#endif // WEAVE_CONFIG_SECURITY_TEST_MODE

#if WEAVE_CONFIG_ENABLE_TARGETED_LISTEN

    ListenIPv4Addr = IPAddress::Any;
    ListenIPv6Addr = IPAddress::Any;

#if defined(DEBUG) && !WEAVE_SYSTEM_CONFIG_USE_LWIP
    {
        const char *envVal = getenv("WEAVE_IPV6_LISTEN_ADDR");
        if (envVal != NULL)
            IPAddress::FromString(envVal, ListenIPv6Addr);
        envVal = getenv("WEAVE_IPV4_LISTEN_ADDR");
        if (envVal != NULL)
            IPAddress::FromString(envVal, ListenIPv4Addr);
    }
#endif

#endif

    sessionEndCallbackList = NULL;

    BoundConnectionClosedForSession = NULL;

    State = kState_Initialized;

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveFabricState::Shutdown()
{
    State = kState_NotInitialized;

#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
    AppKeyCache.Shutdown();
#endif

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveFabricState::AllocSessionKey(uint64_t peerNodeId, uint16_t keyId, WeaveConnection *boundCon, WeaveSessionKey *& sessionKey)
{
    WEAVE_ERROR err;
    bool chooseRandomKeyId = (keyId == WeaveKeyId::kNone);

    while (true)
    {
        if (chooseRandomKeyId)
            keyId = WeaveKeyId::MakeSessionKeyId(GetRandU16());
        err = FindSessionKey(keyId, peerNodeId, true, sessionKey);
        if (err != WEAVE_NO_ERROR)
            return err;
        if (!sessionKey->IsAllocated())
            break;
        if (!chooseRandomKeyId)
            return WEAVE_ERROR_DUPLICATE_KEY_ID;
    }

    sessionKey->MsgEncKey.KeyId = keyId;
    sessionKey->NodeId = peerNodeId;
    sessionKey->MsgEncKey.EncType = kWeaveEncryptionType_None;
    sessionKey->NextMsgId.Init(UINT32_MAX);
    sessionKey->MaxRcvdMsgId = UINT32_MAX;
    sessionKey->BoundCon = boundCon;
    sessionKey->RcvFlags = 0;
    sessionKey->Flags = WeaveSessionKey::kFlag_RecentlyActive;
    sessionKey->ReserveCount = 1;

    if (boundCon)
    {
        sessionKey->SetUsedOverConnection(true);
    }

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveFabricState::SetSessionKey(uint16_t keyId, uint64_t peerNodeId, uint8_t encType, WeaveAuthMode authMode, const WeaveEncryptionKey *encKey)
{
    WEAVE_ERROR err;
    WeaveSessionKey *sessionKey;

    err = FindSessionKey(keyId, peerNodeId, false, sessionKey);
    SuccessOrExit(err);

    err = SetSessionKey(sessionKey, encType, authMode, encKey);
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR WeaveFabricState::SetSessionKey(WeaveSessionKey *sessionKey, uint8_t encType, WeaveAuthMode authMode, const WeaveEncryptionKey *encKey)
{
    WEAVE_ERROR err;
    uint32_t msgId;

    // Randomize the initial 32-bit message counter on session establishment.
    // This value should be secure random to prevent man-in-the-middle adversary
    // guessing this number.
    err = nl::Weave::Platform::Security::GetSecureRandomData(reinterpret_cast<uint8_t *>(&msgId), sizeof(msgId));
    SuccessOrExit(err);

    sessionKey->MsgEncKey.EncType = encType;
    sessionKey->MsgEncKey.EncKey = *encKey;
    sessionKey->NextMsgId.Init(msgId);
    sessionKey->InitialSendMsgId = msgId;
    sessionKey->InitialRcvdMsgId = 0;
    sessionKey->MaxRcvdMsgId = 0;
    sessionKey->RcvFlags = 0;
    sessionKey->AuthMode = authMode;

#if WEAVE_CONFIG_SECURITY_TEST_MODE && WEAVE_DETAIL_LOGGING
    if (LogKeys)
    {
        char keyString[kMaxEncKeyStringSize];
        WeaveEncryptionKeyToString(encType, *encKey, keyString, sizeof(keyString));
        WeaveLogDetail(MessageLayer, "Message Encryption Key: Id=%04" PRIX16 " Type=SessionKey Peer=%016" PRIX64 " EncType=%02" PRIX8 " Key=%s",
                sessionKey->MsgEncKey.KeyId, sessionKey->NodeId, encType, keyString);
    }
#endif // WEAVE_CONFIG_SECURITY_TEST_MODE

exit:
    return err;
}

WEAVE_ERROR WeaveFabricState::RemoveSessionKey(uint16_t keyId, uint64_t peerNodeId)
{
    WEAVE_ERROR err;
    WeaveSessionKey *sessionKey;

    err = FindSessionKey(keyId, peerNodeId, false, sessionKey);
    SuccessOrExit(err);

    RemoveSessionKey(sessionKey);

    NotifySessionEndSubscribers(keyId, peerNodeId);

exit:
    return err;
}

void WeaveFabricState::RemoveSessionKey(WeaveSessionKey *sessionKey, bool wasIdle)
{
    WeaveLogDetail(MessageLayer, "Removing %ssession key: Id=%04" PRIX16 " Peer=%016" PRIX64,
            (wasIdle) ? "idle " : "", sessionKey->MsgEncKey.KeyId, sessionKey->NodeId);

    RemoveSharedSessionEndNodes(sessionKey);
    sessionKey->Clear();
}

WEAVE_ERROR WeaveFabricState::GetSessionKey(uint16_t keyId, uint64_t peerNodeId, WeaveSessionKey *& outSessionKey)
{
    return FindSessionKey(keyId, peerNodeId, false, outSessionKey);
}

/**
 * Search the session keys table for an established shared session key that targets the specified
 * terminating node and matches the given auth mode and encryption type.
 *
 * @param[in]  terminatingNodeId  The node identifier of the session terminator.
 * @param[in]  authMode           The desired session authentication mode.
 * @param[in]  encType            The desired message encryption type.
 *
 * @retval     WeaveSessionKey *  A pointer to a WeaveSessionKey object representing the matching
 *                                shared session; or NULL if no matching session was found.
 *
 */
WeaveSessionKey *WeaveFabricState::FindSharedSession(uint64_t terminatingNodeId, WeaveAuthMode authMode, uint8_t encType)
{
    WeaveSessionKey *sessionKey;

    // Search the session keys table for an established shared session key that targets the specified
    // terminating node and matches the given auth mode and encryption type.
    sessionKey = SessionKeys;
    for (int i = 0; i < WEAVE_CONFIG_MAX_SESSION_KEYS; i++, sessionKey++)
    {
        if (sessionKey->IsAllocated() && sessionKey->IsKeySet() && sessionKey->IsSharedSession() &&
            sessionKey->NodeId == terminatingNodeId && sessionKey->AuthMode == authMode &&
            sessionKey->MsgEncKey.EncType == encType)
        {
            return sessionKey;
        }
    }

    return NULL;
}

/**
 * This method checks whether secure session associated with the specified peer and keyId is shared.
 *
 * @param[in]  keyId              The session key identifier.
 * @param[in]  peerNodeId         The node identifier of the peer.
 *
 * @retval     bool               Whether or not specified session is shared.
 *
 */
bool WeaveFabricState::IsSharedSession(uint16_t keyId, uint64_t peerNodeId)
{
    WEAVE_ERROR err;
    WeaveSessionKey *sessionKey;
    bool retVal = false;

    err = FindSessionKey(keyId, peerNodeId, false, sessionKey);
    SuccessOrExit(err);

    retVal = sessionKey->IsSharedSession();

exit:
    return retVal;
}

/**
 * This method checks whether end node already recorded and returns true if
 * node is found in the shared end node list.
 *
 * @param[in]  endNodeId          Identifier of the session end node.
 * @param[in]  sessionKey         A pointer to the session key object.
 *
 * @retval     bool               Whether or not end node exists in the
 *                                shared end nodes list.
 *
 */
bool WeaveFabricState::FindSharedSessionEndNode(uint64_t endNodeId, const WeaveSessionKey *sessionKey)
{
    SharedSessionEndNode *endNode = SharedSessionsNodes;
    bool retVal = false;

    for (int i = 0; i < WEAVE_CONFIG_MAX_SHARED_SESSIONS_END_NODES; i++, endNode++)
    {
        if (endNode->SessionKey == sessionKey && endNode->EndNodeId == endNodeId)
        {
            retVal = true;
            break;
        }
    }

    return retVal;
}

WEAVE_ERROR WeaveFabricState::AddSharedSessionEndNode(uint64_t endNodeId, uint64_t terminatingNodeId, uint16_t keyId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveSessionKey *sessionKey;

    err = FindSessionKey(keyId, terminatingNodeId, false, sessionKey);
    SuccessOrExit(err);

    err = AddSharedSessionEndNode(sessionKey, endNodeId);
    SuccessOrExit(err);

exit:
    return err;
}

/**
 * This method adds new end node to the shared end nodes record.
 *
 * @param[in]  sessionKey         The WeaveSessionKey object representing the session for which the new
 *                                end node should be added.
 * @param[in]  endNodeId          The node id of the session end node to be added.
 *
 * @retval #WEAVE_ERROR_TOO_MANY_SHARED_SESSION_END_NODES
 *                                If there is no free space for a new entry in the shared end nodes list.
 * @retval #WEAVE_NO_ERROR        On success.
 *
 */
WEAVE_ERROR WeaveFabricState::AddSharedSessionEndNode(WeaveSessionKey *sessionKey, uint64_t endNodeId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    SharedSessionEndNode *endNode = SharedSessionsNodes;
    SharedSessionEndNode *freeEndNode = NULL;
    uint8_t endNodeCount = 0;

    // No need to add new shared entry record if the end node is also the terminating node.
    VerifyOrExit(endNodeId != sessionKey->NodeId, /* Exit without error. */);

    // Check if entry already exists.
    for (int i = 0; i < WEAVE_CONFIG_MAX_SHARED_SESSIONS_END_NODES; i++, endNode++)
    {
        if (endNode->SessionKey == sessionKey)
        {
            if (endNode->EndNodeId == endNodeId)
            {
                ExitNow();
            }
            else
            {
                endNodeCount++;
            }
        }
        else if (endNode->EndNodeId == kNodeIdNotSpecified && freeEndNode == NULL)
        {
            freeEndNode = endNode;
        }
    }

    // Verify that there is free entry in the list and that we don't exit maximum
    // allowed number of end nodes per single shared session.
    VerifyOrExit(freeEndNode != NULL && endNodeCount <= WEAVE_CONFIG_MAX_END_NODES_PER_SHARED_SESSION,
                 err = WEAVE_ERROR_TOO_MANY_SHARED_SESSION_END_NODES);

    // Add new end node.
    freeEndNode->EndNodeId = endNodeId;
    freeEndNode->SessionKey = sessionKey;

exit:
    return err;
}

/**
 * This method returns all end node IDs that share specified session.
 *
 * @param[in]  sessionKey         A pointer to the session key object.
 * @param[in]  endNodeIds         A pointer to buffer of node IDs.
 * @param[in]  endNodeIdsMaxCount The maximum number of node IDs that can fit in the buffer.
 * @param[out] endNodeIdsCount    Number of found end node IDs that share specified session.
 *
 * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL
 *                                If provided end node Ids buffer is not big enough.
 * @retval #WEAVE_NO_ERROR        On success.
 *
 */
WEAVE_ERROR WeaveFabricState::GetSharedSessionEndNodeIds(const WeaveSessionKey *sessionKey, uint64_t *endNodeIds,
                                                         uint8_t endNodeIdsMaxCount, uint8_t& endNodeIdsCount)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    SharedSessionEndNode *endNode = SharedSessionsNodes;

    endNodeIdsCount = 0;

    for (int i = 0; i < WEAVE_CONFIG_MAX_SHARED_SESSIONS_END_NODES; i++, endNode++)
    {
        if (endNode->SessionKey == sessionKey)
        {
            VerifyOrExit(endNodeIdsCount < endNodeIdsMaxCount, err = WEAVE_ERROR_BUFFER_TOO_SMALL);

            endNodeIds[endNodeIdsCount] = endNode->EndNodeId;
            endNodeIdsCount++;
        }
    }

exit:
    return err;
}

void WeaveFabricState::RemoveSharedSessionEndNodes(const WeaveSessionKey *sessionKey)
{
    if (sessionKey->IsSharedSession())
    {
        SharedSessionEndNode *endNode = SharedSessionsNodes;

        // Clear all information about shared session end nodes.
        for (int i = 0; i < WEAVE_CONFIG_MAX_SHARED_SESSIONS_END_NODES; i++, endNode++)
        {
            if (endNode->SessionKey == sessionKey)
            {
                memset((uint8_t *)endNode, 0, sizeof(SharedSessionEndNode));
            }
        }
    }
}

/**
 * Suspend and serialize the state of an active Weave security session.
 *
 * Serializes the state of an identified Weave security session into the supplied buffer
 * and suspends the session such that no further messages can be sent or received.
 *
 * This method is intended to be used by devices that do not retain RAM while sleeping,
 * allowing them to persist the state of an active session and thereby avoid the need to
 * re-establish the session when they wake.
 */
WEAVE_ERROR WeaveFabricState::SuspendSession(uint16_t keyId, uint64_t peerNodeId, uint8_t * buf, uint16_t bufSize, uint16_t & serializedSessionLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveSessionKey * sessionKey;

    // Lookup the specified session.
    err = GetSessionKey(keyId, peerNodeId, sessionKey);
    SuccessOrExit(err);

    // Assert various requirements about the session.
    VerifyOrExit(sessionKey->IsKeySet(), err = WEAVE_ERROR_KEY_NOT_FOUND);
    VerifyOrExit(!sessionKey->IsSuspended(), err = WEAVE_ERROR_SESSION_KEY_SUSPENDED);
    VerifyOrExit(IsCertAuthMode(sessionKey->AuthMode), err = WEAVE_ERROR_INVALID_USE_OF_SESSION_KEY);

    {
        TLVWriter writer;
        TLVType container;

        writer.Init(buf, bufSize);

        // Begin encoding a Security:SerializedSession TLV structure.
        err = writer.StartContainer(ProfileTag(kWeaveProfile_Security, kTag_SerializedSession), kTLVType_Structure, container);
        SuccessOrExit(err);

        // Encode various information about the session, in tag order.
        err = writer.Put(ContextTag(kTag_SerializedSession_KeyId), sessionKey->MsgEncKey.KeyId);
        SuccessOrExit(err);
        err = writer.Put(ContextTag(kTag_SerializedSession_PeerNodeId), sessionKey->NodeId);
        SuccessOrExit(err);
        err = writer.Put(ContextTag(kTag_SerializedSession_NextMessageId), sessionKey->NextMsgId.GetValue());
        SuccessOrExit(err);
        err = writer.Put(ContextTag(kTag_SerializedSession_MaxRcvdMessageId), sessionKey->MaxRcvdMsgId);
        SuccessOrExit(err);
        err = writer.Put(ContextTag(kTag_SerializedSession_MessageRcvdFlags), sessionKey->RcvFlags);
        SuccessOrExit(err);
        err = writer.PutBoolean(ContextTag(kTag_SerializedSession_IsLocallyInitiated), sessionKey->IsLocallyInitiated());
        SuccessOrExit(err);
        err = writer.PutBoolean(ContextTag(kTag_SerializedSession_IsShared), sessionKey->IsSharedSession());
        SuccessOrExit(err);

        // If the session is shared...
        if (sessionKey->IsSharedSession())
        {
            SharedSessionEndNode *endNode = SharedSessionsNodes;
            TLVType container2;

            // Begin encoding an array containing the alternate node ids for the peer.
            err = writer.StartContainer(ContextTag(kTag_SerializedSession_SharedSessionAltNodeIds), kTLVType_Array, container2);
            SuccessOrExit(err);

            for (int i = 0; i < WEAVE_CONFIG_MAX_SHARED_SESSIONS_END_NODES; i++, endNode++)
            {
                if (endNode->SessionKey == sessionKey)
                {
                    err = writer.Put(AnonymousTag, endNode->EndNodeId);
                    SuccessOrExit(err);
                }
            }

            // End the array.
            err = writer.EndContainer(container2);
            SuccessOrExit(err);
        }

        // For a CASE-based session, encode the certificate type presented by the peer.
        err = writer.Put(ContextTag(kTag_SerializedSession_CASE_PeerCertType), CertTypeFromAuthMode(sessionKey->AuthMode));
        SuccessOrExit(err);

        // Encode the encryption type used to encrypt messages via this session.
        err = writer.Put(ContextTag(kTag_SerializedSession_EncryptionType), sessionKey->MsgEncKey.EncType);
        SuccessOrExit(err);

        // Encode the encryption key(s) associated with the session.
        switch (sessionKey->MsgEncKey.EncType)
        {
        case kWeaveEncryptionType_AES128CTRSHA1:
            err = writer.PutBytes(ContextTag(kTag_SerializedSession_AES128CTRSHA1_DataKey),
                    sessionKey->MsgEncKey.EncKey.AES128CTRSHA1.DataKey, WeaveEncryptionKey_AES128CTRSHA1::DataKeySize);
            SuccessOrExit(err);
            err = writer.PutBytes(ContextTag(kTag_SerializedSession_AES128CTRSHA1_IntegrityKey),
                    sessionKey->MsgEncKey.EncKey.AES128CTRSHA1.IntegrityKey, WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize);
            SuccessOrExit(err);
            break;
        default:
            ExitNow(err = WEAVE_ERROR_UNSUPPORTED_ENCRYPTION_TYPE);
        }

        err = writer.PutBoolean(ContextTag(kTag_SerializedSession_AreResumptionMsgIdsValid),
                         sessionKey->AreResumptionMsgIdsValid());
        SuccessOrExit(err);

        if (sessionKey->AreResumptionMsgIdsValid())
        {
            // Generate a new set of resumption msg ids
            sessionKey->ComputeNextResumptionMsgIds();

            err = writer.Put(ContextTag(kTag_SerializedSession_ResumptionSendMessageId),
                             sessionKey->ResumptionSendMsgId);
            SuccessOrExit(err);

            err = writer.Put(ContextTag(kTag_SerializedSession_ResumptionRecvMessageId),
                             sessionKey->ResumptionRecvMsgId);
            SuccessOrExit(err);
        }

        err = writer.PutBoolean(ContextTag(kTag_SerializedSession_IsUsedOverConnection),
                                sessionKey->IsUsedOverConnection());
        SuccessOrExit(err);

        // End the Security:SerializedSession TLV structure and finalize the encoding.
        err = writer.EndContainer(container);
        SuccessOrExit(err);
        err = writer.Finalize();
        SuccessOrExit(err);

        serializedSessionLen = (uint16_t)writer.GetLengthWritten();
    }

    // Mark the session key as suspended.
    sessionKey->MarkSuspended();

    // Wipe the key.
    sessionKey->MsgEncKey.EncType = kWeaveEncryptionType_None;
    ClearSecretData((uint8_t *)&sessionKey->MsgEncKey.EncKey, sizeof(sessionKey->MsgEncKey.EncKey));

exit:
    // If something goes wrong, make sure we don't leave any key material behind.
    if (err != WEAVE_NO_ERROR)
    {
        ClearSecretData(buf, bufSize);
    }
    return err;
}

/**
 * Restore a previously suspended Weave Security Session from a serialized state.
 *
 */
WEAVE_ERROR WeaveFabricState::RestoreSession(uint8_t * serializedSession, uint16_t serializedSessionLen, WeaveConnection *con)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    TLVReader reader;
    TLVType container;
    uint16_t keyId;
    uint64_t peerNodeId;
    WeaveSessionKey * sessionKey = NULL;
    bool removeSessionOnError = false;

    reader.Init(serializedSession, serializedSessionLen);

    // Look for and enter the Security:SerializedSession TLV structure.
    err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_Security, kTag_SerializedSession));
    SuccessOrExit(err);
    err = reader.EnterContainer(container);
    SuccessOrExit(err);

    // Read the key id and peer node id.
    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_KeyId));
    SuccessOrExit(err);
    err = reader.Get(keyId);
    SuccessOrExit(err);
    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_PeerNodeId));
    SuccessOrExit(err);
    err = reader.Get(peerNodeId);
    SuccessOrExit(err);

    // Look for / create a session key entry for the given key id and peer node.
    err = FindSessionKey(keyId, peerNodeId, true, sessionKey);
    SuccessOrExit(err);
    if (!sessionKey->IsAllocated())
    {
        sessionKey->MsgEncKey.KeyId = keyId;
        sessionKey->NodeId = peerNodeId;
        sessionKey->BoundCon = NULL;
        sessionKey->ReserveCount = 0;
        sessionKey->Flags = 0;
    }
    else
    {
        // If the key id / peer node matches an existing session that is NOT suspended, fail with an error.
        VerifyOrExit(sessionKey->IsSuspended(), err = WEAVE_ERROR_DUPLICATE_KEY_ID);
    }
    sessionKey->SetRemoveOnIdle(true);
    sessionKey->MarkRecentlyActive();

    // After this point, if an error occurs, remove the session key.
    removeSessionOnError = true;

    // If the key id / peer node matched a suspended session key, clear the suspended flag.
    sessionKey->ClearSuspended();

    // Clear any alternate end node ids associated with the session key.
    RemoveSharedSessionEndNodes(sessionKey);

    // Read the encoded session information in tag order and restore it into the session key entry.
    {
        uint32_t nextMsgId;
        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_NextMessageId));
        SuccessOrExit(err);
        err = reader.Get(nextMsgId);
        SuccessOrExit(err);
        err = sessionKey->NextMsgId.Init(nextMsgId);
        SuccessOrExit(err);
    }
    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_MaxRcvdMessageId));
    SuccessOrExit(err);
    err = reader.Get(sessionKey->MaxRcvdMsgId);
    SuccessOrExit(err);
    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_MessageRcvdFlags));
    SuccessOrExit(err);
    err = reader.Get(sessionKey->RcvFlags);
    SuccessOrExit(err);
    {
        bool b;
        err = reader.Next(kTLVType_Boolean, ContextTag(kTag_SerializedSession_IsLocallyInitiated));
        SuccessOrExit(err);
        err = reader.Get(b);
        SuccessOrExit(err);
        sessionKey->SetLocallyInitiated(b);
        err = reader.Next(kTLVType_Boolean, ContextTag(kTag_SerializedSession_IsShared));
        SuccessOrExit(err);
        err = reader.Get(b);
        SuccessOrExit(err);
        sessionKey->SetSharedSession(b);
    }

    // If the session is a shared session, restore the list of alternate end node ids.
    if (sessionKey->IsSharedSession())
    {
        TLVType container2;

        err = reader.Next(kTLVType_Array, ContextTag(kTag_SerializedSession_SharedSessionAltNodeIds));
        SuccessOrExit(err);
        err = reader.EnterContainer(container2);
        SuccessOrExit(err);

        while ((err = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == WEAVE_NO_ERROR)
        {
            uint64_t altNodeId;

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

            err = AddSharedSessionEndNode(sessionKey, altNodeId);
            SuccessOrExit(err);
        }

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

    // Read and restore the session AuthMode.
    {
        uint8_t certType;
        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_CASE_PeerCertType));
        SuccessOrExit(err);
        err = reader.Get(certType);
        SuccessOrExit(err);
        sessionKey->AuthMode = CASEAuthMode(certType);
    }

    // Restore the session message encryption type.
    err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_EncryptionType));
    SuccessOrExit(err);
    err = reader.Get(sessionKey->MsgEncKey.EncType);
    SuccessOrExit(err);

    // Based on the encryption type, restore the associated keys.
    switch (sessionKey->MsgEncKey.EncType)
    {
    case kWeaveEncryptionType_AES128CTRSHA1:
        err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerializedSession_AES128CTRSHA1_DataKey));
        SuccessOrExit(err);
        VerifyOrExit(reader.GetLength() == WeaveEncryptionKey_AES128CTRSHA1::DataKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);
        err = reader.GetBytes(sessionKey->MsgEncKey.EncKey.AES128CTRSHA1.DataKey, WeaveEncryptionKey_AES128CTRSHA1::DataKeySize);
        SuccessOrExit(err);
        err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerializedSession_AES128CTRSHA1_IntegrityKey));
        SuccessOrExit(err);
        VerifyOrExit(reader.GetLength() == WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);
        err = reader.GetBytes(sessionKey->MsgEncKey.EncKey.AES128CTRSHA1.IntegrityKey, WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize);
        SuccessOrExit(err);
        break;
    default:
        ExitNow(err = WEAVE_ERROR_UNSUPPORTED_ENCRYPTION_TYPE);
    }

    bool resumptionMsgIdsValid;

    err = reader.Next(kTLVType_Boolean, ContextTag(kTag_SerializedSession_AreResumptionMsgIdsValid));
    SuccessOrExit(err);
    err = reader.Get(resumptionMsgIdsValid);
    SuccessOrExit(err);

    sessionKey->SetResumptionMsgIdsValid(resumptionMsgIdsValid);

    // Get the resumptionMsgIds;
    if (resumptionMsgIdsValid)
    {
        err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SerializedSession_ResumptionSendMessageId));
        SuccessOrExit(err);

        err = reader.Get(sessionKey->ResumptionSendMsgId);
        SuccessOrExit(err);

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

        err = reader.Get(sessionKey->ResumptionRecvMsgId);
        SuccessOrExit(err);

        WeaveLogDetail(MessageLayer, "Prev Next MsgId:%016" PRIX64 "\n", sessionKey->NextMsgId.GetValue());
        WeaveLogDetail(MessageLayer, "Prev MaxRcvMsgId:%016" PRIX64 "\n", sessionKey->MaxRcvdMsgId);

#if WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
        if (con && !con->IsRepaired)
#endif // WEAVE_CONFIG_TCP_CONN_REPAIR_SUPPORTED
        {
            // Assign resumption message ids to the session key
            sessionKey->NextMsgId.Init(sessionKey->ResumptionSendMsgId);
            sessionKey->MaxRcvdMsgId = sessionKey->ResumptionRecvMsgId;
        }

        WeaveLogDetail(MessageLayer, "New Next MsgId:%016" PRIX64 "\n", sessionKey->NextMsgId.GetValue());
        WeaveLogDetail(MessageLayer, "New MaxRcvMsgId:%016" PRIX64 "\n", sessionKey->MaxRcvdMsgId);
    }

    bool usedOverConnection;

    err = reader.Next(kTLVType_Boolean, ContextTag(kTag_SerializedSession_IsUsedOverConnection));
    SuccessOrExit(err);

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

    sessionKey->SetUsedOverConnection(usedOverConnection);

    // If a connection object has been passed to be bound to a restored session,
    // ensure that the AuthMode is CASE and the resumed session was previously
    // used over a connection.
    if (con && IsCASEAuthMode(con->AuthMode) && sessionKey->IsUsedOverConnection())
    {
        // Bind the connection to the restored session
        sessionKey->BoundCon = con;
        con->DefaultKeyId = sessionKey->MsgEncKey.KeyId;
        con->DefaultEncryptionType = sessionKey->MsgEncKey.EncType;
        con->PeerNodeId = sessionKey->NodeId;
    }

    // Verify no other data in the serialized session structure.
    err = reader.VerifyEndOfContainer();
    SuccessOrExit(err);
    err = reader.ExitContainer(container);
    SuccessOrExit(err);

exit:
    if (removeSessionOnError && err != WEAVE_NO_ERROR)
    {
        RemoveSessionKey(sessionKey, false);
    }
    return err;
}

WEAVE_ERROR WeaveFabricState::GetSessionState(uint64_t remoteNodeId,
                                              uint16_t keyId,
                                              uint8_t encType,
                                              WeaveConnection *con,
                                              WeaveSessionState& outSessionState)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    PeerIndexType peerIndex;

    switch (WeaveKeyId::GetType(keyId))
    {
    case WeaveKeyId::kType_None:
        if (keyId != WeaveKeyId::kNone)
            return WEAVE_ERROR_INVALID_KEY_ID;

        if (encType != kWeaveEncryptionType_None)
            return WEAVE_ERROR_WRONG_ENCRYPTION_TYPE;

        if (con == NULL)
        {
            FindOrAllocPeerEntry(remoteNodeId, true, peerIndex);
            outSessionState = WeaveSessionState(NULL, kWeaveAuthMode_Unauthenticated, &NextUnencUDPMsgId, &PeerStates.MaxUnencUDPMsgIdRcvd[peerIndex],
                                                &PeerStates.MaxUnencUDPMsgIdRcvd[peerIndex], &PeerStates.UnencRcvFlags[peerIndex]);
        }
        else
            outSessionState = WeaveSessionState(NULL, kWeaveAuthMode_Unauthenticated, &NextUnencTCPMsgId, NULL, NULL, NULL);
        break;

    case WeaveKeyId::kType_Session:
        WeaveSessionKey *sessionKey;
        err = FindSessionKey(keyId, remoteNodeId, false, sessionKey);
        if (err != WEAVE_NO_ERROR)
            return err;
        if (sessionKey->IsSuspended())
            return WEAVE_ERROR_SESSION_KEY_SUSPENDED;
        if (sessionKey->MsgEncKey.EncType != encType)
            return (sessionKey->MsgEncKey.EncType == kWeaveEncryptionType_None) ? WEAVE_ERROR_KEY_NOT_FOUND : WEAVE_ERROR_WRONG_ENCRYPTION_TYPE;
        if (sessionKey->BoundCon != NULL && sessionKey->BoundCon != con)
            return WEAVE_ERROR_INVALID_USE_OF_SESSION_KEY;
        outSessionState = WeaveSessionState(&sessionKey->MsgEncKey, sessionKey->AuthMode, &sessionKey->NextMsgId, &sessionKey->InitialRcvdMsgId, &sessionKey->MaxRcvdMsgId, &sessionKey->RcvFlags);
        break;

#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
    case WeaveKeyId::kType_AppStaticKey:
    case WeaveKeyId::kType_AppRotatingKey:
    {
        WeaveMsgEncryptionKey *applicationKey;
        err = FindMsgEncAppKey(keyId, encType, applicationKey);
        SuccessOrExit(err);

        WeaveAuthMode authMode = GroupKeyAuthMode(keyId);

        if (FindOrAllocPeerEntry(remoteNodeId, false, peerIndex))
            outSessionState = WeaveSessionState(applicationKey, authMode, &NextGroupKeyMsgId, NULL, &PeerStates.MaxGroupKeyMsgIdRcvd[peerIndex], &PeerStates.GroupKeyRcvFlags[peerIndex]);
        else
            outSessionState = WeaveSessionState(applicationKey, authMode, &NextGroupKeyMsgId, NULL, NULL, NULL);
        break;
    }
#endif

    default:
        ExitNow(err = WEAVE_ERROR_UNKNOWN_KEY_TYPE);
    }

exit:
    return err;
}

/**
 * Returns an IPAddress containing a Weave ULA for a specified node.
 *
 * This variant allows for a subnet to be specified.
 *
 * @param[in] nodeId            The Node ID number of the node in question.
 *
 * @param[in] subnet            The desired subnet of the ULA.
 *
 * @retval IPAddress            An IPAddress object.
 */
IPAddress WeaveFabricState::SelectNodeAddress(uint64_t nodeId, uint16_t subnetId) const
{
    // Translate 'any' node id to the IPv6 link-local all-nodes multicast address.
    if (nodeId == kAnyNodeId)
    {
        return IPAddress::MakeIPv6WellKnownMulticast(kIPv6MulticastScope_Link, kIPV6MulticastGroup_AllNodes);
    }
    else
    {
        return IPAddress::MakeULA(FabricId, subnetId, WeaveNodeIdToIPv6InterfaceId(nodeId));
    }
}

/**
 * Returns an IPAddress containing a Weave ULA for a specified node.
 *
 * This variant uses the local node's default subnet.
 *
 * @param[in] nodeId            The Node ID number of the node in question.
 *
 * @retval IPAddress            An IPAddress object.
 */
IPAddress WeaveFabricState::SelectNodeAddress(uint64_t nodeId) const
{
    return WeaveFabricState::SelectNodeAddress(nodeId, DefaultSubnet);
}

/**
 * Determines if an IP address represents an address of a node within the local Weave fabric.
 */
bool WeaveFabricState::IsFabricAddress(const IPAddress &addr) const
{
    return (FabricId != kFabricIdNotSpecified &&
            addr.IsIPv6ULA() &&
            addr.GlobalId() == WeaveFabricIdToIPv6GlobalId(FabricId));
}

/**
 * Determines if an IP address represents a Weave fabric address for the local node.
 */
bool WeaveFabricState::IsLocalFabricAddress(const IPAddress &addr) const
{
    return (IsFabricAddress(addr) &&
            IPv6InterfaceIdToWeaveNodeId(addr.InterfaceId()) == LocalNodeId);
}

#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
/**
 * This method verifies that information received in the message counter synchronization
 * message is valid (i.e. requestor message counter is fresh). On success, it initializes
 * group key entry in the peer state table.
 *
 * @param[in] peerNodeId          The node identifier of the peer.
 * @param[in] peerMsgId           Identifier of the received MsgCounterSync message.
 * @param[in] requestorMsgCounter Requestor message counter field from the message counter
 *                                synchronization message.
 *
 */
void WeaveFabricState::OnMsgCounterSyncRespRcvd(uint64_t peerNodeId, uint32_t peerMsgId, uint32_t requestorMsgCounter)
{
    PeerIndexType peerIndex;

    // If requestor message counter is fresh.
    if (IsMsgCounterSyncReqInProgress() &&
        (requestorMsgCounter >= GroupKeyMsgIdFreshWindowStart) &&
        (requestorMsgCounter < NextGroupKeyMsgId.GetValue()))
    {
        FindOrAllocPeerEntry(peerNodeId, true, peerIndex);

        // If not already synchronized.
        if ((PeerStates.GroupKeyRcvFlags[peerIndex] & WeaveSessionState::kReceiveFlags_MessageIdSynchronized) == 0)
        {
            // Initialize group key entry in the peer state table.
            PeerStates.GroupKeyRcvFlags[peerIndex] = WeaveSessionState::kReceiveFlags_MessageIdSynchronized;
            PeerStates.MaxGroupKeyMsgIdRcvd[peerIndex] = peerMsgId;

#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
            // Clear MsgCounterSyncReq flag for all pending messages to that peer.
            MessageLayer->ExchangeMgr->ClearMsgCounterSyncReq(peerNodeId);
#endif
        }
    }

    return;
}

// Start message counter synchronization timer.
void WeaveFabricState::StartMsgCounterSyncTimer(void)
{
    // Arm timer to call MsgCounterSyncRespTimeout after WEAVE_CONFIG_MSG_COUNTER_SYNC_RESP_TIMEOUT.
    WEAVE_ERROR res = MessageLayer->SystemLayer->StartTimer((uint32_t)WEAVE_CONFIG_MSG_COUNTER_SYNC_RESP_TIMEOUT, OnMsgCounterSyncRespTimeout, this);
    VerifyOrDie(res == WEAVE_NO_ERROR);
}

/**
 * This method is called when message counter synchronization request is sent.
 *
 * @param[in] messageId         Identification of the message with which message
 *                              counter synchronization request is sent.
 *
 */
void WeaveFabricState::OnMsgCounterSyncReqSent(uint32_t messageId)
{
    // Set ReqSentThisPeriod flag.
    MsgCounterSyncStatus |= kFlag_ReqSentThisPeriod;

    // If no message counter synchronization request in progress.
    if (!IsMsgCounterSyncReqInProgress())
    {
        // Set ReqInProgress flag.
        MsgCounterSyncStatus |= kFlag_ReqInProgress;

        // Set fresh window start field.
        GroupKeyMsgIdFreshWindowStart = messageId;

        // Arm timer.
        StartMsgCounterSyncTimer();

        // Enable fast-poll mode for SEDs if not already enabled.
        MessageLayer->SignalMessageLayerActivityChanged();
    }

    return;
}

// Handle MsgCounterSyncRespTimeout.
void WeaveFabricState::OnMsgCounterSyncRespTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError)
{
    WeaveFabricState* fabricState = reinterpret_cast<WeaveFabricState*>(aAppState);
    uint32_t freshWindoWidth;

    VerifyOrDie(fabricState != NULL && fabricState->MessageLayer->SystemLayer == aSystemLayer);

    // If message counter synchronization request was sent this period.
    if (fabricState->MsgCounterSyncStatus & fabricState->kFlag_ReqSentThisPeriod)
    {
        fabricState->GroupKeyMsgIdFreshWindowStart += (fabricState->MsgCounterSyncStatus & fabricState->kMask_GroupKeyMsgIdFreshWindowWidth);

        freshWindoWidth = fabricState->NextGroupKeyMsgId.GetValue() - fabricState->GroupKeyMsgIdFreshWindowStart;

        // If fresh window exceeds highest supported width.
        if (freshWindoWidth > fabricState->kMask_GroupKeyMsgIdFreshWindowWidth)
        {
            // Adjust fresh window start value.
            fabricState->GroupKeyMsgIdFreshWindowStart += (freshWindoWidth - fabricState->kMask_GroupKeyMsgIdFreshWindowWidth);

            // Set the highest supported fresh window width.
            freshWindoWidth = fabricState->kMask_GroupKeyMsgIdFreshWindowWidth;
        }

        // Set fresh window width field.
        fabricState->MsgCounterSyncStatus |= (freshWindoWidth & fabricState->kMask_GroupKeyMsgIdFreshWindowWidth);

        // Clear ReqSentThisPeriod flag.
        fabricState->MsgCounterSyncStatus &= ~fabricState->kFlag_ReqSentThisPeriod;

        // Arm timer.
        fabricState->StartMsgCounterSyncTimer();
    }
    else
    {
        // Clear status fields.
        fabricState->MsgCounterSyncStatus = 0;

        // Disable fast-poll mode for SEDs if needed.
        fabricState->MessageLayer->SignalMessageLayerActivityChanged();
    }

    return;
}

/**
 * Get the key ID to be used to encrypt messages for a specific Weave Application Group.
 *
 * @param[in]   appGroupGlobalId
 *                              The global ID of the application group for which the encryption
 *                              key ID should be returned.
 * @param[in]   rootKeyId       The root key used to derive encryption keys for the specified
 *                              Weave Application Group.
 * @param[in]   useRotatingKey  True if the Weave Application Group uses rotating message keys.
 * @param[out]  keyId           The key ID to be used to encrypt messages for the specified
 *                              Weave Application Group.
 */
WEAVE_ERROR WeaveFabricState::GetMsgEncKeyIdForAppGroup(uint32_t appGroupGlobalId, uint32_t rootKeyId, bool useRotatingKey, uint32_t& keyId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint32_t masterKeyId;

    // Lookup the master key id for the specified Application Group Global Id.
    err = GetAppGroupMasterKeyId(appGroupGlobalId, GroupKeyStore, masterKeyId);
    SuccessOrExit(err);

    // Form the appropriate message encryption key id.
    if (useRotatingKey)
    {
        keyId = WeaveKeyId::MakeAppRotatingKeyId(rootKeyId, 0, masterKeyId, true);
    }
    else
    {
        keyId = WeaveKeyId::MakeAppStaticKeyId(rootKeyId, masterKeyId);
    }

exit:
    return err;
}

/**
 * Ensure that a Weave message was encrypted using the message encryption key for a specific
 * Weave Application Group key.
 *
 * @param[in]   msgInfo         A pointer to a WeaveMessageInfo structure containing information
 *                              about the received message.
 * @param[in]   appGroupGlobalId
 *                              The global ID of the application group for which the message is
 *                              expected to be encrypted.
 * @param[in]   rootKeyId       The root key used to derive encryption keys for the specified
 *                              Weave Application Group.
 * @param[in]   requireRotatingKey
 *                              True if the Weave Application Group uses rotating message keys.
 */
WEAVE_ERROR WeaveFabricState::CheckMsgEncForAppGroup(const WeaveMessageInfo *msgInfo, uint32_t appGroupGlobalId, uint32_t rootKeyId, bool requireRotatingKey)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint32_t expectedMasterKeyId;

    // Verify that the message was encrypted with a group key.
    VerifyOrExit(WeaveKeyId::IsAppGroupKey(msgInfo->KeyId), err = WEAVE_ERROR_WRONG_KEY_TYPE);

    // Verify that the message encryption key was derived from the specified root key.
    VerifyOrExit(WeaveKeyId::GetRootKeyId(msgInfo->KeyId) == rootKeyId, err = WEAVE_ERROR_WRONG_KEY_TYPE);

    // If requested, verify that the message was encrypted with a rotating key.
    VerifyOrExit(!requireRotatingKey || WeaveKeyId::IsAppRotatingKey(msgInfo->KeyId), err = WEAVE_ERROR_WRONG_KEY_TYPE);

    // Lookup the master key id for the specified Application Group.
    err = GetAppGroupMasterKeyId(appGroupGlobalId, GroupKeyStore, expectedMasterKeyId);
    SuccessOrExit(err);

    // Verify that the message was encrypted using the master key for the specified Application Group.
    VerifyOrExit(WeaveKeyId::GetAppGroupMasterKeyId(msgInfo->KeyId) == expectedMasterKeyId, err = WEAVE_ERROR_WRONG_KEY_TYPE);

exit:
    return err;
}

#endif // WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC

/**
 * This method finds, allocates (optional), and returns index to the peer entry in the peer state table.
 *
 * @param[in]  peerNodeId       The node identifier of the peer.
 * @param[in]  allocEntry       A boolean value indicating whether new entry should be
 *                              allocated for the specified peer if not found in the table.
 * @param[out] retPeerIndex     Index to the specified peer entry in the peer state table.
 *
 * @retval bool                 Whether or not peer's entry found in the peer state table.
 *                              Note, that function always returns true if entry allocation
 *                              was requested.
 *
 */
bool WeaveFabricState::FindOrAllocPeerEntry(uint64_t peerNodeId, bool allocEntry, PeerIndexType& retPeerIndex)
{
    uint16_t i;
    bool retVal = false;

    // Find peer entry in the peer state table.
    for (i = 0; i < PeerCount; i++)
    {
        retPeerIndex = PeerStates.MostRecentlyUsedIndexes[i];
        if (PeerStates.NodeId[retPeerIndex] == peerNodeId)
        {
            retVal = true;
            break;
        }
    }

    // If peer entry is not found in the peer state table and allocation was requested.
    if (!retVal && allocEntry)
    {
        // If PeerStates table is full then the least recently used entry is discarded
        // and allocated for the new peer node. The replacement algorithms tries to find
        // least recently used entry that didn't use encryption to avoid future
        // complexity associated with encrypted message counter synchronization.
        if (PeerCount == WEAVE_CONFIG_MAX_PEER_NODES)
        {
            // Choose the least recently used peer entry by default.
            i = WEAVE_CONFIG_MAX_PEER_NODES - 1;

#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
            // Try to find the least recently used peer entry that didn't use encryption.
            for (int j = WEAVE_CONFIG_MAX_PEER_NODES - 1; j >= 0; j--)
            {
                PeerIndexType peerInd = PeerStates.MostRecentlyUsedIndexes[j];
                if ((PeerStates.GroupKeyRcvFlags[peerInd] & WeaveSessionState::kReceiveFlags_MessageIdSynchronized) == 0)
                {
                    i = j;
                    break;
                }
            }
#endif

            // The peer index chosen for replacement.
            retPeerIndex = PeerStates.MostRecentlyUsedIndexes[i];
        }

        // If PeerStates table is not full then the next available entry is "i".
        // Entries in the table are allocated sequentially and never discarded until
        // the table is full. Only when table is full the least recently used entry
        // is discarded and replaced with the new entry.
        else
        {
            PeerCount++;
            retPeerIndex = i;
        }

        PeerStates.NodeId[retPeerIndex] = peerNodeId;
        PeerStates.MaxUnencUDPMsgIdRcvd[retPeerIndex] = 0;
#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
        PeerStates.MaxGroupKeyMsgIdRcvd[retPeerIndex] = 0;
        PeerStates.GroupKeyRcvFlags[retPeerIndex] = 0;
#endif
        PeerStates.UnencRcvFlags[retPeerIndex] = 0;
        retVal = true;
    }

    // Move the requested entry to the top of the most recently used indexes list.
    if (retVal)
    {
        memmove(&PeerStates.MostRecentlyUsedIndexes[1],
                &PeerStates.MostRecentlyUsedIndexes[0],
                i * sizeof(PeerIndexType));
        PeerStates.MostRecentlyUsedIndexes[0] = retPeerIndex;
    }

    return retVal;
}

/*
 * This method is used by provisioning servers to register callbacks with the
 * WeaveFabricState to be notified when the current session is closed.
 *
 * @param[in]  sessionEndCb       The context containing the callback function
 *                                pointer.
 *
 * @retval WEAVE_ERROR            Weave error encountered.
 *
 */
WEAVE_ERROR WeaveFabricState::RegisterSessionEndCallback(SessionEndCbCtxt *sessionEndCb)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    SessionEndCbCtxt *iter = sessionEndCallbackList;

    VerifyOrExit(sessionEndCb, err = WEAVE_ERROR_INVALID_ARGUMENT);

    sessionEndCb->next = NULL;
    if (sessionEndCallbackList == NULL)
    {
        sessionEndCallbackList = sessionEndCb;
        ExitNow();
    }

    while (iter->next)
    {
        iter = iter->next;
    }

    iter->next = sessionEndCb;

exit:
    return err;
}

/*
 * Notify the registered callbacks when the given session is closed and removed
 * from the session table.
 */
void WeaveFabricState::NotifySessionEndSubscribers(uint16_t keyId, uint64_t peerNodeId)
{
    SessionEndCbCtxt *iter = sessionEndCallbackList;

    while (iter)
    {
        if (iter->OnSessionRemoved)
        {
            iter->OnSessionRemoved(keyId, peerNodeId, iter->context);
        }
        iter = iter->next;
    }
}

WEAVE_ERROR WeaveFabricState::GetPassword(uint8_t pwSrc, const char *& ps, uint16_t& pwLen)
{
    switch (pwSrc)
    {
    case kPasswordSource_PairingCode:
        if (PairingCode == NULL)
            return WEAVE_ERROR_INVALID_ARGUMENT; // TODO: use proper error code
        ps = PairingCode;
        pwLen = (uint16_t)strlen(PairingCode);
        return WEAVE_NO_ERROR;
    default:
        return WEAVE_ERROR_INVALID_ARGUMENT; // TODO: use proper error code
    }
}

WEAVE_ERROR WeaveFabricState::CreateFabric()
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WeaveGroupKey fabricSecret;

    // Fail if the node is already a member of a fabric.
    if (FabricId != 0)
        return WEAVE_ERROR_INCORRECT_STATE;

    // Make sure the fabric state is cleared.
    ClearFabricState();

#if WEAVE_CONFIG_SECURITY_TEST_MODE
    if (DebugFabricId == 0)
#endif
    {
        // Generate a unique id for the new fabric, being careful to
        // avoid reserved ids.
        //
        // NOTE: The fabric id is used to form the global ids that
        // make up the fabric IPv6 unique local addresses, as
        // described in RFC 4193. The mechanism used here to create
        // the fabric id (essentially a CSRNG) is different from the
        // algorithm described in the RFC.  However the algorithm in
        // the RFC is a suggestion and this algorithm is more
        // straightforward and is sufficient to produce the required
        // uniqueness.
        do
        {
            err = nl::Weave::Platform::Security::GetSecureRandomData((unsigned char *)&FabricId, sizeof(FabricId));
            SuccessOrExit(err);
        } while (FabricId == kFabricIdNotSpecified || FabricId >= kReservedFabricIdStart);
    }
#if WEAVE_CONFIG_SECURITY_TEST_MODE
    else
    {
        // Use our debug fabric ID.
        FabricId = DebugFabricId;
    }
#endif

    // Create an initial fabric secret.
    fabricSecret.KeyId = WeaveKeyId::kFabricSecret;
    fabricSecret.KeyLen = kWeaveFabricSecretSize;
    err = nl::Weave::Platform::Security::GetSecureRandomData(fabricSecret.Key, kWeaveFabricSecretSize);
    SuccessOrExit(err);

    err = GroupKeyStore->StoreGroupKey(fabricSecret);
    SuccessOrExit(err);

    if (Delegate != NULL)
        Delegate->DidJoinFabric(this, FabricId);

exit:
    if (err != WEAVE_NO_ERROR)
        ClearFabricState();

    ClearSecretData((uint8_t *)&fabricSecret, sizeof(fabricSecret));

    return err;
}

void WeaveFabricState::ClearFabricState()
{
    uint64_t oldFabricId;

    oldFabricId = FabricId;
    FabricId = kFabricIdNotSpecified;
    GroupKeyStore->Clear();

    if (oldFabricId != kFabricIdNotSpecified)
    {
        if (Delegate != NULL)
            Delegate->DidLeaveFabric(this, oldFabricId);
    }

}

WEAVE_ERROR WeaveFabricState::GetFabricState(uint8_t *buf, uint32_t bufSize, uint32_t &fabricStateLen)
{
    WEAVE_ERROR err;
    TLVWriter writer;
    TLVType containerType;

    // Fail if the node is not a member of a fabric.
    if (FabricId == 0)
        return WEAVE_ERROR_INCORRECT_STATE;

    // IMPORTANT NOTE: As a convenience to readers, all elements in a FabricConfig
    // must be encoded in numeric tag order, at all levels.

    writer.Init(buf, bufSize);

    err = writer.StartContainer(ProfileTag(kWeaveProfile_FabricProvisioning, kTag_FabricConfig), kTLVType_Structure, containerType);
    SuccessOrExit(err);

    err = writer.Put(ContextTag(kTag_FabricId), FabricId);
    SuccessOrExit(err);

    {
        TLVType containerType2;

        err = writer.StartContainer(ContextTag(kTag_FabricKeys), kTLVType_Array, containerType2);
        SuccessOrExit(err);

        {
            TLVType containerType3;
            WeaveGroupKey fabricSecret;

            err = GroupKeyStore->RetrieveGroupKey(WeaveKeyId::kFabricSecret, fabricSecret);
            SuccessOrExit(err);

            err = writer.StartContainer(AnonymousTag, kTLVType_Structure, containerType3);
            SuccessOrExit(err);

            err = writer.Put(ContextTag(kTag_FabricKeyId), (uint16_t)(fabricSecret.KeyId));
            SuccessOrExit(err);

            err = writer.Put(ContextTag(kTag_EncryptionType), (uint8_t)kWeaveEncryptionType_AES128CTRSHA1);
            SuccessOrExit(err);

            err = writer.PutBytes(ContextTag(kTag_DataKey), fabricSecret.Key, WeaveEncryptionKey_AES128CTRSHA1::DataKeySize);
            SuccessOrExit(err);

            err = writer.PutBytes(ContextTag(kTag_IntegrityKey), fabricSecret.Key + WeaveEncryptionKey_AES128CTRSHA1::DataKeySize, WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize);
            SuccessOrExit(err);

            err = writer.Put(ContextTag(kTag_KeyScope), (FabricSecretScope)kFabricSecretScope_All);
            SuccessOrExit(err);

            err = writer.Put(ContextTag(kTag_RotationScheme), (FabricSecretRotationScheme)kDeprecatedRotationScheme);
            SuccessOrExit(err);

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

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

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

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

    fabricStateLen = writer.GetLengthWritten();

exit:
    return err;
}

WEAVE_ERROR WeaveFabricState::JoinExistingFabric(const uint8_t *fabricState, uint32_t fabricStateLen)
{
    WEAVE_ERROR err;
    TLVReader reader;

    // Fail if the node is already a member of a fabric.
    if (FabricId != 0)
        return WEAVE_ERROR_INCORRECT_STATE;

    // Make sure the fabric state is cleared.
    ClearFabricState();

    reader.Init(fabricState, fabricStateLen);

    err = reader.Next(kTLVType_Structure, ProfileTag(kWeaveProfile_FabricProvisioning, kTag_FabricConfig));
    SuccessOrExit(err);

    {
        TLVType containerType;

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

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

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

        err = reader.Next(kTLVType_Array, ContextTag(kTag_FabricKeys));
        SuccessOrExit(err);

        {
            TLVType containerType2;

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

            err = reader.Next(kTLVType_Structure, AnonymousTag);
            SuccessOrExit(err);

            {
                TLVType containerType3;
                WeaveGroupKey fabricSecret;
                uint16_t keyId;
                uint8_t encType;
                FabricSecretScope keyScope;
                FabricSecretRotationScheme rotationScheme;

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

                err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_FabricKeyId));
                SuccessOrExit(err);
                err = reader.Get(keyId);
                SuccessOrExit(err);
                VerifyOrExit(keyId == WeaveKeyId::kFabricSecret, err = WEAVE_ERROR_INVALID_KEY_ID);
                fabricSecret.KeyId = keyId;

                err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_EncryptionType));
                SuccessOrExit(err);
                err = reader.Get(encType);
                SuccessOrExit(err);
                VerifyOrExit(encType == kWeaveEncryptionType_AES128CTRSHA1, err = WEAVE_ERROR_UNSUPPORTED_ENCRYPTION_TYPE);

                err = reader.Next(kTLVType_ByteString, ContextTag(kTag_DataKey));
                SuccessOrExit(err);
                VerifyOrExit(reader.GetLength() == WeaveEncryptionKey_AES128CTRSHA1::DataKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);
                err = reader.GetBytes(fabricSecret.Key, WeaveEncryptionKey_AES128CTRSHA1::DataKeySize);
                SuccessOrExit(err);

                err = reader.Next(kTLVType_ByteString, ContextTag(kTag_IntegrityKey));
                SuccessOrExit(err);
                VerifyOrExit(reader.GetLength() == WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);
                err = reader.GetBytes(fabricSecret.Key + WeaveEncryptionKey_AES128CTRSHA1::DataKeySize, WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize);
                SuccessOrExit(err);

                fabricSecret.KeyLen = kWeaveFabricSecretSize;

                err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_KeyScope));
                SuccessOrExit(err);
                err = reader.Get(keyScope);
                SuccessOrExit(err);
                VerifyOrExit(keyScope == kFabricSecretScope_All, err = WEAVE_ERROR_INVALID_ARGUMENT);

                err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_RotationScheme));
                SuccessOrExit(err);
                err = reader.Get(rotationScheme);
                SuccessOrExit(err);
                VerifyOrExit(rotationScheme == kDeprecatedRotationScheme, err = WEAVE_ERROR_INVALID_ARGUMENT);

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

                err = GroupKeyStore->StoreGroupKey(fabricSecret);
                SuccessOrExit(err);
            }

            err = reader.Next(kTLVType_Structure, AnonymousTag);
            VerifyOrExit(err == WEAVE_END_OF_TLV, /* no action */);

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

    if (Delegate != NULL)
        Delegate->DidJoinFabric(this, FabricId);

exit:
    if (err != WEAVE_NO_ERROR)
        ClearFabricState();

    return err;
}

void WeaveFabricState::HandleConnectionClosed(WeaveConnection *con)
{
    WeaveSessionKey *sessionKey;

    // Remove any session keys that are bound to the closed connection.
    sessionKey = SessionKeys;
    for (int i = 0; i < WEAVE_CONFIG_MAX_SESSION_KEYS; i++, sessionKey++)
    {
        if (sessionKey->IsAllocated() && SessionKeys[i].BoundCon == con)
        {
            // Call application callback to notify about session connection
            // closure
            if (BoundConnectionClosedForSession)
            {
                BoundConnectionClosedForSession(con);
            }

            RemoveSessionKey(sessionKey);
        }
    }
}

// WeaveSessionState Members

WeaveSessionState::WeaveSessionState(void)
{
    MsgEncKey = NULL;
    AuthMode = kWeaveAuthMode_NotSpecified;
    NextMsgId = NULL;
    InitialMsgIdRcvd = NULL;
    MaxMsgIdRcvd = NULL;
    RcvFlags = NULL;
}

WeaveSessionState::WeaveSessionState(WeaveMsgEncryptionKey *msgEncKey, WeaveAuthMode authMode,
                                     MonotonicallyIncreasingCounter *nextMsgId, uint32_t *initialRcvdMsgId,
                                     uint32_t *maxMsgIdRcvd, ReceiveFlagsType *rcvFlags)
{
    MsgEncKey = msgEncKey;
    AuthMode = authMode;
    NextMsgId = nextMsgId;
    InitialMsgIdRcvd = initialRcvdMsgId;
    MaxMsgIdRcvd = maxMsgIdRcvd;
    RcvFlags = rcvFlags;
}

uint32_t WeaveSessionState::NewMessageId(void)
{
    uint32_t newMsgId = NextMsgId->GetValue();

    NextMsgId->Advance();

    return newMsgId;
}

bool WeaveSessionState::MessageIdNotSynchronized(void)
{
    return (RcvFlags == NULL) || (((*RcvFlags) & kReceiveFlags_MessageIdSynchronized) == 0);
}

bool WeaveSessionState::IsDuplicateMessage(uint32_t msgId)
{
    bool isDup = false;
    int32_t delta;
    ReceiveFlagsType msgIdFlags;

    // This algorithm relies on two values to determine whether a message has been received before:
    //
    //    *MaxMsgIdRcvd is the maximum message id received from from the peer node.
    //
    //    *RcvFlags is a set of flags describing the history of message reception from the peer.
    //
    //        The top-most bit in *RcvFlags indicates whether any messages have ever been received from the peer.
    //
    //            The remaining bits represent individual message ids that have been received prior to the
    //        message identified by *MaxMsgIdRcvd.  Specifically, bit 0 represents the message immediately
    //        prior to the max id message (i.e. *MaxMsgIdRcvd - 1), bit 1 represents the message immediately
    //        prior to that message, and so on.

    // If message Id is not synchronized.
    if (MessageIdNotSynchronized())
    {
        // Return immediately if duplicate message detection is disabled for this session.
        //
        // This happens for unencrypted messages sent over TCP. Such messages provide no security against replay
        // attacks (since they are not encrypted) and are not subject to message reordering in the network layer
        // (since TCP eliminates such reorderings). Thus duplicate message detection is unnecessary in this case.
        if (MsgEncKey == NULL && RcvFlags == NULL)
        {
            ExitNow();
        }
#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
        // Mark message as a duplicate and exit if it was encrypted with application group key.
        // In this case, peer's message counter synchronization can only be done by
        // WeaveSecurityManager::HandleMsgCounterSyncRespMsg() function.
        else if (MsgEncKey != NULL && WeaveKeyId::IsAppGroupKey(MsgEncKey->KeyId))
        {
            ExitNow(isDup = true);
        }
#endif
        // Otherwise mark message as synchronized and initialize peer's max counter.
        else
        {
            *RcvFlags = kReceiveFlags_MessageIdSynchronized;
            *MaxMsgIdRcvd = msgId;
            *InitialMsgIdRcvd = msgId;
            ExitNow();
        }
    }

    // Extract the message id flags from the receive flags field.
    msgIdFlags = (*RcvFlags) & kReceiveFlags_MessageIdFlagsMask;

    // Determine the difference between the id of the newly received message (msgId) and the maximum message
    // id received so far (*MaxMsgIdRcvd).
    //
    // Note that the math here is designed to accommodate wrapping of message ids.  Specifically, any newly
    // received message with an id in the range (*MaxMsgIdRcvd + 1) to ((*MaxMsgIdRcvd + 2^31 - 1) mod 2^32)
    // will be considered to be later than the max id message (i.e. delta > 0), and thus cannot be a duplicate.
    // Conversely any message with an id not in this range (i.e. delta <= 0) represents an earlier message
    // (or the same message) and thus may be a duplicate.
    //
    // This approach ensures that duplicates will continue to be detected for an amount of time equal to
    // (send-rate * 2^31) past a message's original send time, while allowing (send-rate * (2^31 - 1)) time
    // between message arrivals before a new message will be mistakenly considered a duplicate.
    //
    delta = (int32_t) (msgId - *MaxMsgIdRcvd);

    // If the new message was sent after the max id message...
    if (delta > 0)
    {
        // Shift the message received flags by the delta (or simply set the flags to zero if the delta is larger
        // than the number of flags).
        if (delta < kReceiveFlags_NumMessageIdFlags)
            msgIdFlags = ((msgIdFlags << 1) | 1) << (delta - 1);
        else
            msgIdFlags = 0;

        // Update the max received message id.
        *MaxMsgIdRcvd = msgId;
    }

    // If the new id is the same as the max id message, the message is a duplicate.
    else if (delta == 0) {
        ExitNow(isDup = true);
    }
    // Otherwise the new message was sent earlier than the max id message...
    else
    {
        // Make the delta positive.
        delta = -delta;

        // If the delta is within the range of the message id flags, form the appropriate mask
        // and check if the message has already been received. If not, set the corresponding flag.
        if (delta <= kReceiveFlags_NumMessageIdFlags)
        {
            ReceiveFlagsType mask = 1 << (delta - 1);
            if ((msgIdFlags & mask) == 0)
                msgIdFlags |= mask;
            else {
                ExitNow(isDup = true);
            }
        }

        // If the delta is greater than the range of the message id flags...
        else
        {
            // If the message was encrypted then assume the message is a duplicate.
            if (MsgEncKey != NULL) {
                ExitNow(isDup = true);
            }

            // Otherwise the message is not encrypted, so assume the message is valid and reset the received state.
            //
            // Senders of unencrypted messages are not required to preserve message id ordering across restarts.
            // Since duplicate message detection for unencrypted messages is only to eliminate duplicates created
            // in the network layer, we allow message ids for unencrypted messages from the same peer to go backwards.
            else
            {
                msgIdFlags = 0;
                *MaxMsgIdRcvd = msgId;
            }
        }
    }

    // Update the message id flags within the receive flags value and set the MessageIdIsSynchronized flag.
    *RcvFlags = kReceiveFlags_MessageIdSynchronized | msgIdFlags | (*RcvFlags & ~kReceiveFlags_MessageIdFlagsMask);

exit:
    return isDup;
}

/**
 * This method finds session key entry.
 *
 * @param[in] keyId               Weave key identifier.
 * @param[in] peerNodeId          The node identifier of the peer.
 * @param[in] create              A boolean value indicating whether new key should be created
 *                                if the specified key is not found.
 * @param[out] retRec             A pointer reference to a WeaveSessionKey object.
 *
 * @retval #WEAVE_ERROR_WRONG_KEY_TYPE     If specified key is not a session key type.
 * @retval #WEAVE_ERROR_INVALID_ARGUMENT   If input arguments have wrong values.
 * @retval #WEAVE_ERROR_KEY_NOT_FOUND      If specified key is not found.
 * @retval #WEAVE_ERROR_TOO_MANY_KEYS      If there is no free entry to create new session key.
 * @retval #WEAVE_NO_ERROR                 On success.
 *
 */
WEAVE_ERROR WeaveFabricState::FindSessionKey(uint16_t keyId, uint64_t peerNodeId, bool create, WeaveSessionKey *& retRec)
{
    WeaveSessionKey *curRec = SessionKeys;
    WeaveSessionKey *freeRec = NULL;

    if (!WeaveKeyId::IsSessionKey(keyId))
        return WEAVE_ERROR_WRONG_KEY_TYPE;

    if (peerNodeId == kNodeIdNotSpecified || peerNodeId == kAnyNodeId)
        return WEAVE_ERROR_INVALID_ARGUMENT;

    for (int i = 0; i < WEAVE_CONFIG_MAX_SESSION_KEYS; i++, curRec++)
    {
        if (!curRec->IsAllocated())
        {
            if (freeRec == NULL)
                freeRec = curRec;
        }
        else if (curRec->MsgEncKey.KeyId == keyId &&
                 (curRec->NodeId == peerNodeId ||
                  (curRec->IsSharedSession() && FindSharedSessionEndNode(peerNodeId, curRec))))
        {
            retRec = curRec;
            return WEAVE_NO_ERROR;
        }
    }

    if (!create)
        return WEAVE_ERROR_KEY_NOT_FOUND;

    if (freeRec == NULL)
        return WEAVE_ERROR_TOO_MANY_KEYS;

    retRec = freeRec;

    return WEAVE_NO_ERROR;
}

#if WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC
WEAVE_ERROR WeaveFabricState::FindMsgEncAppKey(uint16_t keyId, uint8_t encType, WeaveMsgEncryptionKey *& retRec)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // Find key or allocate empty key entry in the key cache.
    retRec = AppKeyCache.FindOrAllocateKeyEntry(keyId, encType);

    // Derive application key if it's not in the key cache.
    if (retRec->KeyId == WeaveKeyId::kNone)
    {
        uint32_t appGroupGlobalId;

        err = DeriveMsgEncAppKey(keyId, encType, *retRec, appGroupGlobalId);
        SuccessOrExit(err);

#if WEAVE_CONFIG_SECURITY_TEST_MODE && WEAVE_DETAIL_LOGGING
        if (LogKeys)
        {
            char keyString[kMaxEncKeyStringSize];
            WeaveEncryptionKeyToString(encType, retRec->EncKey, keyString, sizeof(keyString));
            WeaveLogDetail(MessageLayer, "Message Encryption Key: Id=%04" PRIX16 " Type=GroupKey(%08" PRIX32 ") EncType=%02" PRIX8 " Key=%s", keyId, appGroupGlobalId, encType, keyString);
        }
#endif
    }

exit:
    return err;
}

/**
 * Derives message encryption application key.
 * Three types of message encryption application keys can be requested: current application
 * key, rotating application key, and static application key. When current application key
 * is requested, the function finds and uses the current epoch key based on the current system
 * time and the start time parameter of each epoch key.
 *
 * @param[in]    keyId              The requested key ID.
 * @param[in]    encType            The type of the requested message encryption key.
 * @param[out]   appKey             A reference to the message encryption key object.
 * @param[out]   appGroupGlobalId   The application group global ID of the associated key.
 *
 * @retval #WEAVE_NO_ERROR          On success.
 * @retval #WEAVE_ERROR_UNSUPPORTED_WEAVE_FEATURE
 *                                  If group key store functionality is not implemented.
 * @retval #WEAVE_ERROR_UNSUPPORTED_ENCRYPTION_TYPE
 *                                  If the requested encryption type is not supported.
 * @retval #WEAVE_ERROR_INVALID_KEY_ID
 *                                  If the requested key has an invalid key ID.
 * @retval #WEAVE_ERROR_INVALID_ARGUMENT
 *                                  If the platform key store returns invalid key parameters.
 * @retval other                    Other platform-specific errors returned by the platform
 *                                  key store APIs.
 *
 */
WEAVE_ERROR WeaveFabricState::DeriveMsgEncAppKey(uint32_t keyId, uint8_t encType, WeaveMsgEncryptionKey& appKey, uint32_t& appGroupGlobalId)
{
    WEAVE_ERROR err;
    uint8_t keyData[WeaveEncryptionKey_AES128CTRSHA1::KeySize];
    uint8_t keyDiversifier[kWeaveMsgEncAppKeyDiversifierSize];

    // Verify supported key type.
    VerifyOrExit(encType == kWeaveEncryptionType_AES128CTRSHA1, err = WEAVE_ERROR_UNSUPPORTED_ENCRYPTION_TYPE);

    // Set application key size and info value.
    memcpy(keyDiversifier, kWeaveMsgEncAppKeyDiversifier, sizeof(kWeaveMsgEncAppKeyDiversifier));
    keyDiversifier[sizeof(kWeaveMsgEncAppKeyDiversifier)] = encType;

    // Derive application key data.
    err = GroupKeyStore->DeriveApplicationKey(keyId, NULL, 0, keyDiversifier, kWeaveMsgEncAppKeyDiversifierSize,
                                              keyData, sizeof(keyData), WeaveEncryptionKey_AES128CTRSHA1::KeySize,
                                              appGroupGlobalId);
    SuccessOrExit(err);

    // Copy the generated key data to the appropriate destinations.
    memcpy(appKey.EncKey.AES128CTRSHA1.DataKey,
           keyData,
           WeaveEncryptionKey_AES128CTRSHA1::DataKeySize);
    memcpy(appKey.EncKey.AES128CTRSHA1.IntegrityKey,
           keyData + WeaveEncryptionKey_AES128CTRSHA1::DataKeySize,
           WeaveEncryptionKey_AES128CTRSHA1::IntegrityKeySize);

    // Set key parameters.
    appKey.KeyId = keyId;
    appKey.EncType = encType;

exit:
    ClearSecretData(keyData, sizeof(keyData));

    return err;
}
#endif // WEAVE_CONFIG_USE_APP_GROUP_KEYS_FOR_MSG_ENC

void WeaveFabricState::SetDelegate(FabricStateDelegate *aDelegate)
{
    Delegate = aDelegate;
}

bool WeaveFabricState::RemoveIdleSessionKeys()
{
    WeaveSessionKey *sessionKey;
    bool potentialIdleSessionsExist = false;

    // For each allocated session key...
    sessionKey = SessionKeys;
    for (int i = 0; i < WEAVE_CONFIG_MAX_SESSION_KEYS; i++, sessionKey++)
        if (sessionKey->IsAllocated())
        {
            // Ignore the session if it is still in the process of being established.
            if (!sessionKey->IsKeySet())
                continue;

            // Capture and clear the recently active flag.
            bool recentlyActive = sessionKey->IsRecentlyActive();
            sessionKey->ClearRecentlyActive();

            // Ignore the session if it is bound to a connection. (Connection bound
            // sessions persist until their connections close).
            if (sessionKey->BoundCon != NULL)
                continue;

            // If the session is marked for remove-on-idle and is not currently reserved...
            if (sessionKey->IsRemoveOnIdle() && sessionKey->ReserveCount == 0)
            {
                // Remove the session if it hasn't been active since the last time RemoveIdleSessionKeys()
                // was called.
                if (!recentlyActive)
                {
                    RemoveSessionKey(sessionKey, true);
                }

                // Otherwise, tell the caller that unreserved, remove-on-idle sessions exist which may
                // need to be removed on a future call to RemoveIdleSessionKeys().
                else
                {
                    potentialIdleSessionsExist = true;
                }
            }
        }

    return potentialIdleSessionsExist;
}



// ============================================================
// Weave Message Encryption Application Key Cache.
// ============================================================

void WeaveMsgEncryptionKeyCache::Init()
{
    Reset();
}

void WeaveMsgEncryptionKeyCache::Shutdown()
{
    Reset();
}

void WeaveMsgEncryptionKeyCache::Reset()
{
    for (uint8_t keyEntry = 0; keyEntry < WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS; keyEntry++)
        Clear(keyEntry);
    memset(mMostRecentlyUsedKeyEntries, 0, sizeof(mMostRecentlyUsedKeyEntries));
}

// Clear key cache entry.
void WeaveMsgEncryptionKeyCache::Clear(uint8_t keyEntryIndex)
{
    ClearSecretData((uint8_t *)(&mKeyCache[keyEntryIndex]), sizeof(WeaveMsgEncryptionKey));
    mKeyCache[keyEntryIndex].KeyId = WeaveKeyId::kNone;
    mKeyCache[keyEntryIndex].EncType = kWeaveEncryptionType_None;
}

// If the key is found in the cache then function returns pointer to the key.
// If the key is not found in the cache then function allocates and returns pointer to the empty key entry in the cache.
WeaveMsgEncryptionKey *WeaveMsgEncryptionKeyCache::FindOrAllocateKeyEntry(uint16_t keyId, uint8_t encType)
{
    WeaveMsgEncryptionKey *keyEntry;
    uint8_t retKeyEntryIndex = WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS;
    uint8_t i;

    // Find if key is in the cache.
    for (i = 0, keyEntry = mKeyCache; i < WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS; i++, keyEntry++)
    {
        if (keyEntry->KeyId == keyId && keyEntry->EncType == encType)
        {
            retKeyEntryIndex = i;
            break;
        }
        else if (retKeyEntryIndex == WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS && keyEntry->KeyId == WeaveKeyId::kNone)
        {
            retKeyEntryIndex = i;
        }
    }

    // If cache is full and specified key was not found in the cache then replace the least-recently used key entry.
    if (retKeyEntryIndex == WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS)
    {
        // Chose the least-recently used entry in the key cache.
        retKeyEntryIndex = mMostRecentlyUsedKeyEntries[WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS - 1];

        // Clear replaced key cache entry.
        Clear(retKeyEntryIndex);
    }

    // Find key entry index in the most-recently used list of entries.
    for (i = 0; i < WEAVE_CONFIG_MAX_CACHED_MSG_ENC_APP_KEYS; i++)
        if (mMostRecentlyUsedKeyEntries[i] == retKeyEntryIndex)
            break;

    // Mark selected key entry as most-recently used by moving it to the top of the most-recently used key entries list.
    memmove(&mMostRecentlyUsedKeyEntries[1], &mMostRecentlyUsedKeyEntries[0], i * sizeof(uint8_t));
    mMostRecentlyUsedKeyEntries[0] = retKeyEntryIndex;

    return &mKeyCache[retKeyEntryIndex];
}


#if WEAVE_CONFIG_SECURITY_TEST_MODE

static inline char ToHex(const uint8_t data)
{
    return (data < 10) ? '0' + data : 'A' + (data - 10);
}

static void ToHexString(const uint8_t *data, size_t dataLen, char *& outBuf, size_t& outBufSize)
{
    for (; dataLen > 0 && outBufSize >= 2; data++, dataLen--, outBuf += 2, outBufSize -= 2)
    {
        outBuf[0] = ToHex(*data >> 4);
        outBuf[1] = ToHex(*data & 0xF);
    }
}

void WeaveEncryptionKeyToString(uint8_t encType, const WeaveEncryptionKey& key, char *buf, size_t bufSize)
{
    if (encType == kWeaveEncryptionType_AES128CTRSHA1)
    {
        bufSize -= 2; // Reserve size for the comma and null terminator.
        ToHexString(key.AES128CTRSHA1.DataKey, sizeof(key.AES128CTRSHA1.DataKey), buf, bufSize);
        *buf++ = ',';
        ToHexString(key.AES128CTRSHA1.IntegrityKey, sizeof(key.AES128CTRSHA1.IntegrityKey), buf, bufSize);
    }

    *buf = 0;
}

#endif // WEAVE_CONFIG_SECURITY_TEST_MODE

} // namespace Weave
} // namespace nl
