blob: c8dfa99e87f99e1d9ce10b5b3eda424c4ef8a04a [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for Thread security material generation.
*/
#ifndef KEY_MANAGER_HPP_
#define KEY_MANAGER_HPP_
#include "openthread-core-config.h"
#include <stdint.h>
#include <openthread/dataset.h>
#include "common/locator.hpp"
#include "common/random.hpp"
#include "common/timer.hpp"
#include "crypto/hmac_sha256.hpp"
#include "mac/mac_types.hpp"
namespace ot {
/**
* @addtogroup core-security
*
* @brief
* This module includes definitions for Thread security material generation.
*
* @{
*/
/**
* This class represents a Thread Master Key.
*
*/
OT_TOOL_PACKED_BEGIN
class MasterKey : public otMasterKey
{
public:
/**
* This method evaluates whether or not the Thread Master Keys match.
*
* @param[in] aOther The Thread Master Key to compare.
*
* @retval TRUE If the Thread Master Keys match.
* @retval FALSE If the Thread Master Keys do not match.
*
*/
bool operator==(const MasterKey &aOther) const { return memcmp(m8, aOther.m8, sizeof(MasterKey)) == 0; }
/**
* This method evaluates whether or not the Thread Master Keys match.
*
* @param[in] aOther The Thread Master Key to compare.
*
* @retval TRUE If the Thread Master Keys do not match.
* @retval FALSE If the Thread Master Keys match.
*
*/
bool operator!=(const MasterKey &aOther) const { return !(*this == aOther); }
} OT_TOOL_PACKED_END;
/**
* This class represents a Thread Pre-Shared Key for the Commissioner (PSKc).
*
*/
OT_TOOL_PACKED_BEGIN
class Pskc : public otPskc
{
public:
/**
* This method clears the PSKc (sets all bytes to zero).
*
*/
void Clear(void) { memset(this, 0, sizeof(*this)); }
/**
* This method evaluates whether or not the Thread PSKc values match.
*
* @param[in] aOther The Thread PSKc to compare.
*
* @retval TRUE If the Thread PSKc values match.
* @retval FALSE If the Thread PSKc values do not match.
*
*/
bool operator==(const Pskc &aOther) const { return memcmp(m8, aOther.m8, sizeof(Pskc)) == 0; }
/**
* This method evaluates whether or not the Thread PSKc values match.
*
* @param[in] aOther The Thread PSKc to compare.
*
* @retval TRUE If the Thread PSKc values do not match.
* @retval FALSE If the Thread PSKc values match.
*
*/
bool operator!=(const Pskc &aOther) const { return !(*this == aOther); }
#if !OPENTHREAD_RADIO
/**
* This method generates a cryptographically secure random sequence to populate the Thread PSKc.
*
* @retval OT_ERROR_NONE Successfully generated a random Thread PSKc.
*
*/
otError GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(Pskc)); }
#endif
} OT_TOOL_PACKED_END;
/**
* This class defines Thread Key Manager.
*
*/
class KeyManager : public InstanceLocator
{
public:
enum
{
kMaxKeyLength = 16,
kNonceSize = 13, ///< Size of IEEE 802.15.4 Nonce (bytes).
};
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit KeyManager(Instance &aInstance);
/**
* This method starts KeyManager rotation timer and sets guard timer to initial value.
*
*/
void Start(void);
/**
* This method stops KeyManager timers.
*
*/
void Stop(void);
/**
* This method returns the Thread Master Key.
*
* @returns The Thread Master Key.
*
*/
const MasterKey &GetMasterKey(void) const { return mMasterKey; }
/**
* This method sets the Thread Master Key.
*
* @param[in] aKey A Thread Master Key.
*
* @retval OT_ERROR_NONE Successfully set the Thread Master Key.
* @retval OT_ERROR_INVALID_ARGS The @p aKeyLength value was invalid.
*
*/
otError SetMasterKey(const MasterKey &aKey);
#if OPENTHREAD_FTD || OPENTHREAD_MTD
/**
* This method indicates whether the PSKc is configured.
*
* A value of all zeros indicates that the PSKc is not configured.
*
* @retval TRUE if the PSKc is configured.
* @retval FALSE if the PSKc is not not configured.
*
*/
bool IsPskcSet(void) const { return mIsPskcSet; }
/**
* This method returns a pointer to the PSKc.
*
* @returns A reference to the PSKc.
*
*/
const Pskc &GetPskc(void) const { return mPskc; }
/**
* This method sets the PSKc.
*
* @param[in] aPskc A reference to the PSKc.
*
*/
void SetPskc(const Pskc &aPskc);
#endif
/**
* This method returns the current key sequence value.
*
* @returns The current key sequence value.
*
*/
uint32_t GetCurrentKeySequence(void) const { return mKeySequence; }
/**
* This method sets the current key sequence value.
*
* @param[in] aKeySequence The key sequence value.
*
*/
void SetCurrentKeySequence(uint32_t aKeySequence);
/**
* This method returns a pointer to the current MAC key.
*
* @returns A pointer to the current MAC key.
*
*/
const uint8_t *GetCurrentMacKey(void) const { return mKey + kMacKeyOffset; }
/**
* This method returns a pointer to the current MLE key.
*
* @returns A pointer to the current MLE key.
*
*/
const uint8_t *GetCurrentMleKey(void) const { return mKey; }
/**
* This method returns a pointer to a temporary MAC key computed from the given key sequence.
*
* @param[in] aKeySequence The key sequence value.
*
* @returns A pointer to the temporary MAC key.
*
*/
const uint8_t *GetTemporaryMacKey(uint32_t aKeySequence);
/**
* This method returns a pointer to a temporary MLE key computed from the given key sequence.
*
* @param[in] aKeySequence The key sequence value.
*
* @returns A pointer to the temporary MLE key.
*
*/
const uint8_t *GetTemporaryMleKey(uint32_t aKeySequence);
/**
* This method returns the current MAC Frame Counter value.
*
* @returns The current MAC Frame Counter value.
*
*/
uint32_t GetMacFrameCounter(void) const { return mMacFrameCounter; }
/**
* This method sets the current MAC Frame Counter value.
*
* @param[in] aMacFrameCounter The MAC Frame Counter value.
*
*/
void SetMacFrameCounter(uint32_t aMacFrameCounter) { mMacFrameCounter = aMacFrameCounter; }
/**
* This method sets the MAC Frame Counter value which is stored in non-volatile memory.
*
* @param[in] aStoredMacFrameCounter The stored MAC Frame Counter value.
*
*/
void SetStoredMacFrameCounter(uint32_t aStoredMacFrameCounter) { mStoredMacFrameCounter = aStoredMacFrameCounter; }
/**
* This method increments the current MAC Frame Counter value.
*
*/
void IncrementMacFrameCounter(void);
/**
* This method returns the current MLE Frame Counter value.
*
* @returns The current MLE Frame Counter value.
*
*/
uint32_t GetMleFrameCounter(void) const { return mMleFrameCounter; }
/**
* This method sets the current MLE Frame Counter value.
*
* @param[in] aMleFrameCounter The MLE Frame Counter value.
*
*/
void SetMleFrameCounter(uint32_t aMleFrameCounter) { mMleFrameCounter = aMleFrameCounter; }
/**
* This method sets the MLE Frame Counter value which is stored in non-volatile memory.
*
* @param[in] aStoredMleFrameCounter The stored MLE Frame Counter value.
*
*/
void SetStoredMleFrameCounter(uint32_t aStoredMleFrameCounter) { mStoredMleFrameCounter = aStoredMleFrameCounter; }
/**
* This method increments the current MLE Frame Counter value.
*
*/
void IncrementMleFrameCounter(void);
/**
* This method returns the KEK.
*
* @returns A pointer to the KEK.
*
*/
const uint8_t *GetKek(void) const { return mKek; }
/**
* This method sets the KEK.
*
* @param[in] aKek A pointer to the KEK.
*
*/
void SetKek(const uint8_t *aKek);
/**
* This method returns the current KEK Frame Counter value.
*
* @returns The current KEK Frame Counter value.
*
*/
uint32_t GetKekFrameCounter(void) const { return mKekFrameCounter; }
/**
* This method increments the current KEK Frame Counter value.
*
*/
void IncrementKekFrameCounter(void) { mKekFrameCounter++; }
/**
* This method returns the KeyRotation time.
*
* The KeyRotation time is the time interval after witch security key will be automatically rotated.
*
* @returns The KeyRotation value in hours.
*/
uint32_t GetKeyRotation(void) const { return mKeyRotationTime; }
/**
* This method sets the KeyRotation time.
*
* The KeyRotation time is the time interval after witch security key will be automatically rotated.
* Its value shall be larger than or equal to kMinKeyRotationTime.
*
* @param[in] aKeyRotation The KeyRotation value in hours.
*
* @retval OT_ERROR_NONE KeyRotation time updated.
* @retval OT_ERROR_INVALID_ARGS @p aKeyRotation is out of range.
*
*/
otError SetKeyRotation(uint32_t aKeyRotation);
/**
* This method returns the KeySwitchGuardTime.
*
* The KeySwitchGuardTime is the time interval during which key rotation procedure is prevented.
*
* @returns The KeySwitchGuardTime value in hours.
*
*/
uint32_t GetKeySwitchGuardTime(void) const { return mKeySwitchGuardTime; }
/**
* This method sets the KeySwitchGuardTime.
*
* The KeySwitchGuardTime is the time interval during which key rotation procedure is prevented.
*
* @param[in] aKeySwitchGuardTime The KeySwitchGuardTime value in hours.
*
*/
void SetKeySwitchGuardTime(uint32_t aKeySwitchGuardTime) { mKeySwitchGuardTime = aKeySwitchGuardTime; }
/**
* This method returns the Security Policy Flags.
*
* The Security Policy Flags specifies network administrator preferences for which
* security-related operations are allowed or disallowed.
*
* @returns The SecurityPolicy Flags.
*
*/
uint8_t GetSecurityPolicyFlags(void) const { return mSecurityPolicyFlags; }
/**
* This method sets the Security Policy Flags.
*
* The Security Policy Flags specifies network administrator preferences for which
* security-related operations are allowed or disallowed.
*
* @param[in] aSecurityPolicyFlags The Security Policy Flags.
*
*/
void SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags);
/**
* This static method generates IEEE 802.15.4 nonce byte sequence.
*
* @param[in] aAddress An extended address.
* @param[in] aFrameCounter A frame counter.
* @param[in] aSecurityLevel A security level.
* @param[out] aNonce A buffer (with `kNonceSize` bytes) to place the generated nonce.
*
*/
static void GenerateNonce(const Mac::ExtAddress &aAddress,
uint32_t aFrameCounter,
uint8_t aSecurityLevel,
uint8_t * aNonce);
private:
enum
{
kMinKeyRotationTime = 1,
kDefaultKeyRotationTime = 672,
kDefaultKeySwitchGuardTime = 624,
kMacKeyOffset = 16,
kOneHourIntervalInMsec = 3600u * 1000u,
};
void ComputeKey(uint32_t aKeySequence, uint8_t *aKey);
void StartKeyRotationTimer(void);
static void HandleKeyRotationTimer(Timer &aTimer);
void HandleKeyRotationTimer(void);
static const uint8_t kThreadString[];
static const otMasterKey kDefaultMasterKey;
MasterKey mMasterKey;
uint32_t mKeySequence;
uint8_t mKey[Crypto::HmacSha256::kHashSize];
uint8_t mTemporaryKey[Crypto::HmacSha256::kHashSize];
uint32_t mMacFrameCounter;
uint32_t mMleFrameCounter;
uint32_t mStoredMacFrameCounter;
uint32_t mStoredMleFrameCounter;
uint32_t mHoursSinceKeyRotation;
uint32_t mKeyRotationTime;
uint32_t mKeySwitchGuardTime;
bool mKeySwitchGuardEnabled;
TimerMilli mKeyRotationTimer;
#if OPENTHREAD_MTD || OPENTHREAD_FTD
Pskc mPskc;
#endif
uint8_t mKek[kMaxKeyLength];
uint32_t mKekFrameCounter;
uint8_t mSecurityPolicyFlags;
bool mIsPskcSet : 1;
};
/**
* @}
*/
} // namespace ot
#endif // KEY_MANAGER_HPP_