/*
 *
 *    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::AppKeys;

#if WEAVE_CONFIG_SECURITY_TEST_MODE

#define EXCLS "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
#pragma message (EXCLS "\n!!!! WARNING - WEAVE SECURITY TEST MODE ENABLED !!!!" EXCLS)
#undef EXCLS

#endif

#ifndef DEFINE_ALIGNED_VAR
#define DEFINE_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;
    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));
}

/**
 * fn bool WeaveSessionKey::IsAllocated() const
 *
 * Returns true if the WeaveSessionKey object is allocated.
 */

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

/**
 * fn bool WeaveSessionKey::IsLocallyInitiated() const
 *
 * Returns 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.
 */

/*
 * fn bool WeaveSessionKey::IsSharedSession() const
 *
 * Returns true the session is a 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.
 */

/**
 * fn bool WeaveSessionKey::IsRemoveOnIdle() const
 *
 * Returns 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.
 */

/**
 * fn bool WeaveSessionKey::IsRecentlyActive() const
 *
 * Returns 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 DEFINE_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

    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;

    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);

    SetSessionKey(sessionKey, encType, authMode, encKey);

exit:
    return err;
}

void WeaveFabricState::SetSessionKey(WeaveSessionKey *sessionKey, uint8_t encType, WeaveAuthMode authMode, const WeaveEncryptionKey *encKey)
{
    sessionKey->MsgEncKey.EncType = encType;
    sessionKey->MsgEncKey.EncKey = *encKey;
    sessionKey->NextMsgId.Init(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
}

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);

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);

    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));
            }
        }
    }

    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, endNodeId, 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;
}

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.UnencRcvFlags[peerIndex]);
        }
        else
            outSessionState = WeaveSessionState(NULL, kWeaveAuthMode_Unauthenticated, &NextUnencTCPMsgId, NULL, NULL);
        break;

    case WeaveKeyId::kType_Session:
        WeaveSessionKey *sessionKey;
        err = FindSessionKey(keyId, remoteNodeId, false, sessionKey);
        if (err != WEAVE_NO_ERROR)
            return err;
        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->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, &PeerStates.MaxGroupKeyMsgIdRcvd[peerIndex], &PeerStates.GroupKeyRcvFlags[peerIndex]);
        else
            outSessionState = WeaveSessionState(applicationKey, authMode, &NextGroupKeyMsgId, NULL, NULL);
        break;
    }
#endif

    default:
        ExitNow(err = WEAVE_ERROR_UNKNOWN_KEY_TYPE);
    }

exit:
    return err;
}

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::MakeIPv6Multicast(kIPv6MulticastScope_Link, kIPV6MulticastGroup_AllNodes);
    }
    else
    {
        return IPAddress::MakeULA(FabricId, subnetId, WeaveNodeIdToIPv6InterfaceId(nodeId));
    }
}

IPAddress WeaveFabricState::SelectNodeAddress(uint64_t nodeId) const
{
    return WeaveFabricState::SelectNodeAddress(nodeId, DefaultSubnet);
}

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

#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.
 *
 * @retval None.
 *
 */
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.
 *
 * @retval None.
 *
 */
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[ouy]  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;
}

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)
        {
            RemoveSessionKey(sessionKey);
        }
    }
}

// WeaveSessionState Members

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

WeaveSessionState::WeaveSessionState(WeaveMsgEncryptionKey *msgEncKey, WeaveAuthMode authMode,
                                     MonotonicallyIncreasingCounter *nextMsgId, uint32_t *maxMsgIdRcvd, ReceiveFlagsType *rcvFlags)
{
    MsgEncKey = msgEncKey;
    AuthMode = authMode;
    NextMsgId = nextMsgId;
    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;
            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
