blob: a8e2e32d8011a654e50e0f37aa6a74cd0d7d85b9 [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 <openthread/platform/crypto.h>
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/random.hpp"
#include "common/timer.hpp"
#include "crypto/hmac_sha256.hpp"
#include "mac/mac_types.hpp"
#include "thread/mle_types.hpp"
namespace ot {
/**
* @addtogroup core-security
*
* @brief
* This module includes definitions for Thread security material generation.
*
* @{
*/
/**
* This class represents Security Policy Rotation and Flags.
*
*/
class SecurityPolicy : public otSecurityPolicy, public Equatable<SecurityPolicy>
{
public:
/**
* Offset between the Thread Version and the Version-threshold valid for Routing.
*
*/
static constexpr uint8_t kVersionThresholdOffsetVersion = 3;
static constexpr uint16_t kMinKeyRotationTime = 1; ///< The minimum Key Rotation Time in hours.
static constexpr uint16_t kDefaultKeyRotationTime = 672; ///< Default Key Rotation Time (in unit of hours).
/**
* This constructor initializes the object with default Key Rotation Time
* and Security Policy Flags.
*
*/
SecurityPolicy(void) { SetToDefault(); }
/**
* This method sets the Security Policy to default values.
*
*/
void SetToDefault(void);
/**
* This method sets the Security Policy Flags.
*
* @param[in] aFlags The Security Policy Flags.
* @param[in] aFlagsLength The length of the Security Policy Flags, 1 byte for
* Thread 1.1 devices, and 2 bytes for Thread 1.2 or higher.
*
*/
void SetFlags(const uint8_t *aFlags, uint8_t aFlagsLength);
/**
* This method returns the Security Policy Flags.
*
* @param[out] aFlags A pointer to the Security Policy Flags buffer.
* @param[in] aFlagsLength The length of the Security Policy Flags buffer.
*
*/
void GetFlags(uint8_t *aFlags, uint8_t aFlagsLength) const;
private:
static constexpr uint8_t kDefaultFlags = 0xff;
static constexpr uint8_t kObtainNetworkKeyMask = 1 << 7;
static constexpr uint8_t kNativeCommissioningMask = 1 << 6;
static constexpr uint8_t kRoutersMask = 1 << 5;
static constexpr uint8_t kExternalCommissioningMask = 1 << 4;
static constexpr uint8_t kBeaconsMask = 1 << 3;
static constexpr uint8_t kCommercialCommissioningMask = 1 << 2;
static constexpr uint8_t kAutonomousEnrollmentMask = 1 << 1;
static constexpr uint8_t kNetworkKeyProvisioningMask = 1 << 0;
static constexpr uint8_t kTobleLinkMask = 1 << 7;
static constexpr uint8_t kNonCcmRoutersMask = 1 << 6;
static constexpr uint8_t kReservedMask = 0x38;
static constexpr uint8_t kVersionThresholdForRoutingMask = 0x07;
void SetToDefaultFlags(void);
};
/**
* This class represents a Thread Network Key.
*
*/
OT_TOOL_PACKED_BEGIN
class NetworkKey : public otNetworkKey, public Equatable<NetworkKey>, public Clearable<NetworkKey>
{
public:
static constexpr uint8_t kSize = OT_NETWORK_KEY_SIZE; ///< Size of the Thread Network Key (in bytes).
#if !OPENTHREAD_RADIO
/**
* This method generates a cryptographically secure random sequence to populate the Thread Network Key.
*
* @retval kErrorNone Successfully generated a random Thread Network Key.
* @retval kErrorFailed Failed to generate random sequence.
*
*/
Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
#endif
} OT_TOOL_PACKED_END;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
/**
* Provides a representation for Network Key reference.
*
*/
typedef otNetworkKeyRef NetworkKeyRef;
#endif
/**
* This class represents a Thread Pre-Shared Key for the Commissioner (PSKc).
*
*/
OT_TOOL_PACKED_BEGIN
class Pskc : public otPskc, public Equatable<Pskc>, public Clearable<Pskc>
{
public:
static constexpr uint8_t kSize = OT_PSKC_MAX_SIZE; ///< Size (number of bytes) of the PSKc.
#if !OPENTHREAD_RADIO
/**
* This method generates a cryptographically secure random sequence to populate the Thread PSKc.
*
* @retval kErrorNone Successfully generated a random Thread PSKc.
*
*/
Error GenerateRandom(void) { return Random::Crypto::FillBuffer(m8, sizeof(m8)); }
#endif
} OT_TOOL_PACKED_END;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
/**
* Provides a representation for Network Key reference.
*
*/
typedef otPskcRef PskcRef;
#endif
/**
*
* This class represents a Key Encryption Key (KEK).
*
*/
typedef Mac::Key Kek;
/**
*
* This class represents a Key Material for Key Encryption Key (KEK).
*
*/
typedef Mac::KeyMaterial KekKeyMaterial;
/**
* This class defines Thread Key Manager.
*
*/
class KeyManager : public InstanceLocator, private NonCopyable
{
public:
/**
* 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 gets the Thread Network Key.
*
* @param[out] aNetworkKey A reference to a `NetworkKey` to output the Thread Network Key.
*
*/
void GetNetworkKey(NetworkKey &aNetworkKey) const;
/**
* This method sets the Thread Network Key.
*
* @param[in] aNetworkKey A Thread Network Key.
*
*/
void SetNetworkKey(const NetworkKey &aNetworkKey);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
/**
* This method returns a Key Ref to Thread Network Key.
*
* @returns A key reference to the Thread Network Key.
*
*/
NetworkKeyRef GetNetworkKeyRef(void) { return mNetworkKeyRef; }
/**
* This method sets the Thread Network Key using Key Reference.
*
* @param[in] aKeyRef Reference to Thread Network Key.
*
*/
void SetNetworkKeyRef(NetworkKeyRef aKeyRef);
#endif
/**
* 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 gets the PKSc.
*
* @param[out] aPskc A reference to a `Pskc` to return the PSKc.
*
*/
void GetPskc(Pskc &aPskc) const;
/**
* This method sets the PSKc.
*
* @param[in] aPskc A reference to the PSKc.
*
*/
void SetPskc(const Pskc &aPskc);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
/**
* This method returns a Key Ref to PSKc.
*
* @returns A key reference to the PSKc.
*
*/
const PskcRef &GetPskcRef(void) { return mPskcRef; }
/**
* This method sets the PSKc as a Key reference.
*
* @param[in] aPskc A reference to the PSKc.
*
*/
void SetPskcRef(PskcRef aKeyRef);
#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);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
* This method returns the current MAC key for TREL radio link.
*
* @returns The current TREL MAC key.
*
*/
const Mac::KeyMaterial &GetCurrentTrelMacKey(void) const { return mTrelKey; }
/**
* This method returns a temporary MAC key for TREL radio link computed from the given key sequence.
*
* @param[in] aKeySequence The key sequence value.
*
* @returns The temporary TREL MAC key.
*
*/
const Mac::KeyMaterial &GetTemporaryTrelMacKey(uint32_t aKeySequence);
#endif
/**
* This method returns the current MLE key Material.
*
* @returns The current MLE key.
*
*/
const Mle::KeyMaterial &GetCurrentMleKey(void) const { return mMleKey; }
/**
* This method returns a temporary MLE key Material computed from the given key sequence.
*
* @param[in] aKeySequence The key sequence value.
*
* @returns The temporary MLE key.
*
*/
const Mle::KeyMaterial &GetTemporaryMleKey(uint32_t aKeySequence);
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
/**
* This method returns the current MAC Frame Counter value for 15.4 radio link.
*
* @returns The current MAC Frame Counter value.
*
*/
uint32_t Get154MacFrameCounter(void) const { return mMacFrameCounters.Get154(); }
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
/**
* This method returns the current MAC Frame Counter value for TREL radio link.
*
* @returns The current MAC Frame Counter value for TREL radio link.
*
*/
uint32_t GetTrelMacFrameCounter(void) const { return mMacFrameCounters.GetTrel(); }
/**
* This method increments the current MAC Frame Counter value for TREL radio link.
*
*/
void IncrementTrelMacFrameCounter(void);
#endif
/**
* This method gets the maximum MAC Frame Counter among all supported radio links.
*
* @return The maximum MAC frame Counter among all supported radio links.
*
*/
uint32_t GetMaximumMacFrameCounter(void) const { return mMacFrameCounters.GetMaximum(); }
/**
* This method sets the current MAC Frame Counter value for all radio links.
*
* @param[in] aMacFrameCounter The MAC Frame Counter value.
*
*/
void SetAllMacFrameCounters(uint32_t 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 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 as `KekKeyMaterail`
*
* @returns The KEK as `KekKeyMaterial`.
*
*/
const KekKeyMaterial &GetKek(void) const { return mKek; }
/**
* This method retrieves the KEK as literal `Kek` key.
*
* @param[out] aKek A reference to a `Kek` to output the retrieved KEK.
*
*/
void ExtractKek(Kek &aKek) { mKek.ExtractKey(aKek); }
/**
* This method sets the KEK.
*
* @param[in] aKek A KEK.
*
*/
void SetKek(const Kek &aKek);
/**
* This method sets the KEK.
*
* @param[in] aKekBytes A pointer to the KEK bytes.
*
*/
void SetKek(const uint8_t *aKekBytes) { SetKek(*reinterpret_cast<const Kek *>(aKekBytes)); }
/**
* 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 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.
*
* The Security Policy specifies Key Rotation Time and network administrator preferences
* for which security-related operations are allowed or disallowed.
*
* @returns The SecurityPolicy.
*
*/
const SecurityPolicy &GetSecurityPolicy(void) const { return mSecurityPolicy; }
/**
* This method sets the Security Policy.
*
* The Security Policy specifies Key Rotation Time and network administrator preferences
* for which security-related operations are allowed or disallowed.
*
* @param[in] aSecurityPolicy The Security Policy.
*
*/
void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy);
/**
* This method updates the MAC keys and MLE key.
*
*/
void UpdateKeyMaterial(void);
/**
* This method handles MAC frame counter changes (callback from `SubMac` for 15.4 security frame change).
*
* This is called to indicate the @p aMacFrameCounter value is now used.
*
* @param[in] aMacFrameCounter The 15.4 link MAC frame counter value.
*
*/
void MacFrameCounterUsed(uint32_t aMacFrameCounter);
private:
static constexpr uint32_t kDefaultKeySwitchGuardTime = 624;
static constexpr uint32_t kOneHourIntervalInMsec = 3600u * 1000u;
static constexpr bool kExportableMacKeys = OPENTHREAD_CONFIG_PLATFORM_MAC_KEYS_EXPORTABLE_ENABLE;
OT_TOOL_PACKED_BEGIN
struct Keys
{
Mle::Key mMleKey;
Mac::Key mMacKey;
} OT_TOOL_PACKED_END;
union HashKeys
{
Crypto::HmacSha256::Hash mHash;
Keys mKeys;
const Mle::Key &GetMleKey(void) const { return mKeys.mMleKey; }
const Mac::Key &GetMacKey(void) const { return mKeys.mMacKey; }
};
void ComputeKeys(uint32_t aKeySequence, HashKeys &aHashKeys);
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
void ComputeTrelKey(uint32_t aKeySequence, Mac::Key &aKey);
#endif
void StartKeyRotationTimer(void);
static void HandleKeyRotationTimer(Timer &aTimer);
void HandleKeyRotationTimer(void);
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
void StoreNetworkKey(const NetworkKey &aNetworkKey, bool aOverWriteExisting);
void StorePskc(const Pskc &aPskc);
#endif
void ResetFrameCounters(void);
static const uint8_t kThreadString[];
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
static const uint8_t kHkdfExtractSaltString[];
static const uint8_t kTrelInfoString[];
#endif
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
NetworkKeyRef mNetworkKeyRef;
#else
NetworkKey mNetworkKey;
#endif
uint32_t mKeySequence;
Mle::KeyMaterial mMleKey;
Mle::KeyMaterial mTemporaryMleKey;
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
Mac::KeyMaterial mTrelKey;
Mac::KeyMaterial mTemporaryTrelKey;
#endif
Mac::LinkFrameCounters mMacFrameCounters;
uint32_t mMleFrameCounter;
uint32_t mStoredMacFrameCounter;
uint32_t mStoredMleFrameCounter;
uint32_t mHoursSinceKeyRotation;
uint32_t mKeySwitchGuardTime;
bool mKeySwitchGuardEnabled;
TimerMilli mKeyRotationTimer;
#if OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
PskcRef mPskcRef;
#else
Pskc mPskc;
#endif
KekKeyMaterial mKek;
uint32_t mKekFrameCounter;
SecurityPolicy mSecurityPolicy;
bool mIsPskcSet : 1;
};
/**
* @}
*/
DefineCoreType(otSecurityPolicy, SecurityPolicy);
DefineCoreType(otNetworkKey, NetworkKey);
DefineCoreType(otPskc, Pskc);
} // namespace ot
#endif // KEY_MANAGER_HPP_