/*
 *
 *    Copyright (c) 2019 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
 *          Provides an implementation of the Weave GroupKeyStore interface
 *          for platforms based on the Silicon Labs SDK.
 */

#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/EFR32/GroupKeyStoreImpl.h>

using namespace ::nl;
using namespace ::nl::Weave;
using namespace ::nl::Weave::Profiles::Security::AppKeys;

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

WEAVE_ERROR GroupKeyStoreImpl::RetrieveGroupKey(uint32_t keyId, WeaveGroupKey &key)
{
    WEAVE_ERROR err;

    // Iterate over all the GroupKey nvm3 records looking for a matching key...
    err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
                        [keyId, &key](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
                            WEAVE_ERROR err2;
                            size_t      keyLen;
                            uint8_t     buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
                            uint32_t    curKeyId;

                            // Read the nvm3 obj binary data data into the buffer.
                            err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);

                            // Decode the Weave key id for the current key.
                            err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
                            SuccessOrExit(err2);

                            // If it matches the key we're looking for...
                            if (curKeyId == keyId)
                            {
                                // Decode the associated key data.
                                err2 = DecodeGroupKey(buf, keyLen, key);
                                SuccessOrExit(err2);

                                // End the iteration by returning a WEAVE_END_OF_INPUT result.
                                ExitNow(err2 = WEAVE_END_OF_INPUT);
                            }

                        exit:
                            return err2;
                        });

    // Modify error code for return.
    switch (err)
    {
    case WEAVE_END_OF_INPUT:
        err = WEAVE_NO_ERROR; // Match found.
        break;
    case WEAVE_NO_ERROR:
        err = WEAVE_ERROR_KEY_NOT_FOUND; // Match not found.
        break;
    default:
        break;
    }

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::StoreGroupKey(const WeaveGroupKey &key)
{
    WEAVE_ERROR err;

    // Delete any existing group key with the same id (this may or may not exit).
    DeleteGroupKey(key.KeyId); // no error checking here.

    // Iterate over all the GroupKey nvm3 records looking for the first
    // empty nvm3 key where we can store the data. (Note- use arg addNewrecord=true)
    err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, true,
                        [&key](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
                            WEAVE_ERROR err2;
                            size_t      keyLen;
                            uint8_t     buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)

                            // Encode the key for storage in an nvm3 record.
                            err2 = EncodeGroupKey(key, buf, sizeof(buf), keyLen);
                            SuccessOrExit(err2);

                            // Write the encoded binary data into the nvm3 object.
                            err2 = WriteConfigValueBin(nvm3Key, buf, keyLen);
                            SuccessOrExit(err2);

                            // End the iteration by returning a WEAVE_END_OF_INPUT result.
                            ExitNow(err2 = WEAVE_END_OF_INPUT);

                        exit:
                            return err2;
                        });

    // Modify error code for return.
    switch (err)
    {
    case WEAVE_END_OF_INPUT:
        err = WEAVE_NO_ERROR; // Key entry was stored.
        break;
    case WEAVE_NO_ERROR:
        err = WEAVE_ERROR_KEY_NOT_FOUND; // Key entry was not stored.
        break;
    default:
        break;
    }

    if (err == WEAVE_NO_ERROR)
    {
#if WEAVE_PROGRESS_LOGGING
        {
            char extraKeyInfo[32];
            if (WeaveKeyId::IsAppEpochKey(key.KeyId))
            {
                snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", start time %" PRId32, key.StartTime);
            }
            else if (WeaveKeyId::IsAppGroupMasterKey(key.KeyId))
            {
                snprintf(extraKeyInfo, sizeof(extraKeyInfo), ", global id 0x%08" PRIX32, key.GlobalId);
            }
            else
            {
                extraKeyInfo[0] = 0;
            }

#if WEAVE_CONFIG_SECURITY_TEST_MODE
            WeaveLogProgress(SecurityManager,
                             "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 ", data 0x%02" PRIX8
                             "...%s",
                             key.KeyId, WeaveKeyId::DescribeKey(key.KeyId), key.KeyLen, key.Key[0], extraKeyInfo);
#else
            WeaveLogProgress(SecurityManager, "GroupKeyStore: storing key 0x%08" PRIX32 " (%s), len %" PRId8 "%s",
                             key.KeyId, WeaveKeyId::DescribeKey(key.KeyId), key.KeyLen, extraKeyInfo);
#endif
        }

#endif // WEAVE_PROGRESS_LOGGING
    }

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::DeleteGroupKey(uint32_t keyId)
{
    WEAVE_ERROR err;

    // Iterate over all the GroupKey nvm3 records looking for a matching key...
    err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
                        [keyId](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
                            WEAVE_ERROR err2;
                            size_t      keyLen;
                            uint8_t     buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
                            uint32_t    curKeyId;

                            // Read the nvm3 obj binary data data into the buffer.
                            err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
                            SuccessOrExit(err2);

                            // Decode the Weave key id for the current group key.
                            err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
                            SuccessOrExit(err2);

                            // If it matches the key we are looking for, delete the nvm3 record.
                            if (curKeyId == keyId)
                            {
                                err2 = ClearConfigValue(nvm3Key);
                                WeaveLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);

                                // End the iteration by returning a WEAVE_END_OF_INPUT result.
                                ExitNow(err2 = WEAVE_END_OF_INPUT);
                            }

                        exit:
                            return err2;
                        });

    // Modify error code for return.
    switch (err)
    {
    case WEAVE_END_OF_INPUT:
        err = WEAVE_NO_ERROR; // Key entry was deleted.
        break;
    case WEAVE_NO_ERROR:
        err = WEAVE_ERROR_KEY_NOT_FOUND; // Key entry was not deleted.
        break;
    default:
        break;
    }

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::DeleteGroupKeysOfAType(uint32_t keyType)
{
    WEAVE_ERROR err;

    // Iterate over all the GroupKey nvm3 records looking for a matching key...
    err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
                        [keyType](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
                            WEAVE_ERROR err2;
                            size_t      keyLen;
                            uint8_t     buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
                            uint32_t    curKeyId;

                            // Read the nvm3 obj binary data data into the buffer.
                            err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
                            SuccessOrExit(err2);

                            // Decode the Weave key id for the current group key.
                            err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
                            SuccessOrExit(err2);

                            // If the current key matches the type we are looking for, delete the nvm3 record.
                            if (WeaveKeyId::GetType(curKeyId) == keyType)
                            {
                                err2 = ClearConfigValue(nvm3Key);
                                WeaveLogProgress(DeviceLayer, "GroupKeyStore: deleting key 0x%08" PRIX32, curKeyId);
                            }

                        exit:
                            return err2;
                        });

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::EnumerateGroupKeys(uint32_t  keyType,
                                                  uint32_t *keyIds,
                                                  uint8_t   keyIdsArraySize,
                                                  uint8_t & keyCount)
{
    WEAVE_ERROR err;

    keyCount = 0;

    // Iterate over all the GroupKey records looking for keys of the specified type...
    err = ForEachRecord(
        kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
        [keyType, keyIds, keyIdsArraySize, &keyCount](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
            WEAVE_ERROR err2;
            size_t      keyLen;
            uint8_t     buf[kMaxEncodedKeySize]; // (buf length == 45 bytes)
            uint32_t    curKeyId;

            // Read the nvm3 obj binary data data into the buffer.
            err2 = ReadConfigValueBin(nvm3Key, buf, sizeof(buf), keyLen);
            SuccessOrExit(err2);

            // Decode the Weave key id for the current group key.
            err2 = DecodeGroupKeyId(buf, keyLen, curKeyId);
            SuccessOrExit(err2);

            // If the current key matches the type we're looking for, add it to the keyIds array.
            if ((keyType == WeaveKeyId::kType_None) || (WeaveKeyId::GetType(curKeyId) == keyType))
            {
                keyIds[keyCount++] = curKeyId;

                // Stop iterating if there's no more room in the keyIds array.
                VerifyOrExit(keyCount < keyIdsArraySize, err2 = WEAVE_ERROR_BUFFER_TOO_SMALL);
            }

        exit:
            return err2;
        });

    // Simply return a truncated list if there are more matching keys than will fit in the array.
    if (err == WEAVE_ERROR_BUFFER_TOO_SMALL)
    {
        err = WEAVE_NO_ERROR;
    }

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::Clear(void)
{
    WEAVE_ERROR err;

    // Iterate over all the GroupKey nvm3 records deleting each one...
    err = ForEachRecord(kConfigKey_GroupKeyBase, kConfigKey_GroupKeyMax, false,
                        [](const Key &nvm3Key, const size_t &length) -> WEAVE_ERROR {
                            WEAVE_ERROR err2;

                            err2 = ClearConfigValue(nvm3Key);
                            SuccessOrExit(err2);

                        exit:
                            return err2;
                        });

    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::RetrieveLastUsedEpochKeyId(void)
{
    WEAVE_ERROR err;

    err = ReadConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
    if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        LastUsedEpochKeyId = WeaveKeyId::kNone;
        err                = WEAVE_NO_ERROR;
    }
    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::StoreLastUsedEpochKeyId(void)
{
    return WriteConfigValue(kConfigKey_LastUsedEpochKeyId, LastUsedEpochKeyId);
}

WEAVE_ERROR GroupKeyStoreImpl::Init()
{
    // Nothing to do
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR GroupKeyStoreImpl::EncodeGroupKey(const WeaveGroupKey &key,
                                              uint8_t *            buf,
                                              size_t               bufSize,
                                              size_t &             encodedKeyLen)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    uint8_t *   p   = buf;

    VerifyOrExit(bufSize >= kFixedEncodedKeySize + key.KeyLen, err = WEAVE_ERROR_BUFFER_TOO_SMALL);

    Encoding::LittleEndian::Write32(p, key.KeyId);
    Encoding::LittleEndian::Write32(p, key.StartTime);
    Encoding::Write8(p, key.KeyLen);
    memcpy(p, key.Key, key.KeyLen);
    p += key.KeyLen;

    encodedKeyLen = p - buf;

exit:
    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::DecodeGroupKeyId(const uint8_t *encodedKey, size_t encodedKeyLen, uint32_t &keyId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);

    keyId = Encoding::LittleEndian::Get32(encodedKey);

exit:
    return err;
}

WEAVE_ERROR GroupKeyStoreImpl::DecodeGroupKey(const uint8_t *encodedKey, size_t encodedKeyLen, WeaveGroupKey &key)
{
    WEAVE_ERROR    err = WEAVE_NO_ERROR;
    const uint8_t *p   = encodedKey;

    VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize, err = WEAVE_ERROR_INVALID_ARGUMENT);

    key.KeyId     = Encoding::LittleEndian::Read32(p);
    key.StartTime = Encoding::LittleEndian::Read32(p);
    key.KeyLen    = Encoding::Read8(p);

    VerifyOrExit(encodedKeyLen >= kFixedEncodedKeySize + key.KeyLen, err = WEAVE_ERROR_INVALID_ARGUMENT);

    memcpy(key.Key, p, key.KeyLen);

exit:
    return err;
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl
