[meshcop] support Thread 1.2 Security Policy flags (#6320)

This commit is contained in:
kangping
2021-04-14 08:16:08 -07:00
committed by GitHub
parent 7d008f6c76
commit 423575fceb
22 changed files with 478 additions and 311 deletions
+13 -15
View File
@@ -131,22 +131,20 @@ typedef struct otPskc otPskc;
*/
typedef struct otSecurityPolicy
{
uint16_t mRotationTime; ///< The value for thrKeyRotation in units of hours
uint8_t mFlags; ///< Flags as defined in Thread 1.1 Section 8.10.1.15
} otSecurityPolicy;
uint16_t mRotationTime; ///< The value for thrKeyRotation in units of hours.
/**
* This enumeration defines the Security Policy TLV flags.
*
*/
enum
{
OT_SECURITY_POLICY_OBTAIN_MASTER_KEY = 1 << 7, ///< Obtaining the Master Key
OT_SECURITY_POLICY_NATIVE_COMMISSIONING = 1 << 6, ///< Native Commissioning
OT_SECURITY_POLICY_ROUTERS = 1 << 5, ///< Routers enabled
OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER = 1 << 4, ///< External Commissioner allowed
OT_SECURITY_POLICY_BEACONS = 1 << 3, ///< Beacons enabled
};
bool mObtainMasterKeyEnabled : 1; ///< Obtaining the Master Key for out-of-band commissioning is enabled
bool mNativeCommissioningEnabled : 1; ///< Native Commissioning using PSKc is allowed
bool mRoutersEnabled : 1; ///< Thread 1.0/1.1.x Routers are enabled
bool mExternalCommissioningEnabled : 1; ///< External Commissioner authentication is allowed
bool mBeaconsEnabled : 1; ///< Thread 1.0/1.1.x Beacons are enabled
bool mCommercialCommissioningEnabled : 1; ///< Commercial Commissioning is enabled
bool mAutonomousEnrollmentEnabled : 1; ///< Autonomous Enrollment is enabled
bool mMasterKeyProvisioningEnabled : 1; ///< Network Master-key Provisioning is enabled
bool mTobleLinkEnabled : 1; ///< ToBLE link is enabled
bool mNonCcmRoutersEnabled : 1; ///< Non-CCM Routers enabled
uint8_t mVersionThresholdForRouting : 3; ///< Version-threshold for Routing
} otSecurityPolicy;
/**
* This type represents Channel Mask.
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (99)
#define OPENTHREAD_API_VERSION (100)
/**
* @addtogroup api-instance
+7 -3
View File
@@ -366,7 +366,7 @@ Usage: `dataset mgmtgetcommand <active|pending> [address <destination>] [TLV lis
Send MGMT_ACTIVE_GET or MGMT_PENDING_GET.
```bash
> dataset mgmtgetcommand active address fdde:ad00:beef:0:558:f56b:d688:799 activetimestamp -x 0c030001ff
> dataset mgmtgetcommand active address fdde:ad00:beef:0:558:f56b:d688:799 activetimestamp securitypolicy
Done
```
@@ -377,7 +377,7 @@ Usage: `dataset mgmtsetcommand <active|pending> [TLV Type list] [-x]`
Send MGMT_ACTIVE_SET or MGMT_PENDING_SET.
```bash
> dataset mgmtsetcommand active activetimestamp 123 -x 0c030001ff
> dataset mgmtsetcommand active activetimestamp 123 securitypolicy 1 onrcb
Done
```
@@ -496,7 +496,7 @@ Done
### securitypolicy
Usage: `dataset securitypolicy [<rotationtime> [onrcb]]`
Usage: `dataset securitypolicy [<rotationtime> [onrcbCepR]]`
Get security policy.
@@ -513,6 +513,10 @@ Set security policy.
- r: Thread 1.x Routers are enabled.
- c: External Commissioner authentication is allowed using PSKc.
- b: Thread 1.x Beacons are enabled.
- C: Thread 1.2 Commercial Commissioning is enabled.
- e: Thread 1.2 Autonomous Enrollment is enabled.
- p: Thread 1.2 Network Master Key Provisioning is enabled.
- R: Non-CCM routers are allowed in Thread 1.2 CCM networks.
```bash
> dataset securitypolicy 672 onrcb
+130 -89
View File
@@ -126,33 +126,8 @@ otError Dataset::Print(otOperationalDataset &aDataset)
if (aDataset.mComponents.mIsSecurityPolicyPresent)
{
mInterpreter.OutputFormat("Security Policy: %d, ", aDataset.mSecurityPolicy.mRotationTime);
if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY)
{
mInterpreter.OutputFormat("o");
}
if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_NATIVE_COMMISSIONING)
{
mInterpreter.OutputFormat("n");
}
if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_ROUTERS)
{
mInterpreter.OutputFormat("r");
}
if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER)
{
mInterpreter.OutputFormat("c");
}
if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_BEACONS)
{
mInterpreter.OutputFormat("b");
}
mInterpreter.OutputFormat("Security Policy: ", aDataset.mSecurityPolicy.mRotationTime);
OutputSecurityPolicy(aDataset.mSecurityPolicy);
mInterpreter.OutputLine("");
}
@@ -620,6 +595,14 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[])
dataset.mComponents.mIsChannelMaskPresent = true;
SuccessOrExit(error = ParseAsUint32(aArgs[index], dataset.mChannelMask));
}
else if (strcmp(aArgs[index], "securitypolicy") == 0)
{
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = ParseSecurityPolicy(dataset.mSecurityPolicy, aArgs[index],
index + 1 < aArgsLength ? aArgs[index + 1] : nullptr));
dataset.mComponents.mIsSecurityPolicyPresent = true;
++index;
}
else if (strcmp(aArgs[index], "-x") == 0)
{
uint16_t length;
@@ -703,6 +686,10 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[])
{
datasetComponents.mIsChannelPresent = true;
}
else if (strcmp(aArgs[index], "securitypolicy") == 0)
{
datasetComponents.mIsSecurityPolicyPresent = true;
}
else if (strcmp(aArgs[index], "-x") == 0)
{
uint16_t length;
@@ -784,6 +771,119 @@ exit:
return error;
}
void Dataset::OutputSecurityPolicy(const otSecurityPolicy &aSecurityPolicy)
{
mInterpreter.OutputFormat("%d ", aSecurityPolicy.mRotationTime);
if (aSecurityPolicy.mObtainMasterKeyEnabled)
{
mInterpreter.OutputFormat("o");
}
if (aSecurityPolicy.mNativeCommissioningEnabled)
{
mInterpreter.OutputFormat("n");
}
if (aSecurityPolicy.mRoutersEnabled)
{
mInterpreter.OutputFormat("r");
}
if (aSecurityPolicy.mExternalCommissioningEnabled)
{
mInterpreter.OutputFormat("c");
}
if (aSecurityPolicy.mBeaconsEnabled)
{
mInterpreter.OutputFormat("b");
}
if (aSecurityPolicy.mCommercialCommissioningEnabled)
{
mInterpreter.OutputFormat("C");
}
if (aSecurityPolicy.mAutonomousEnrollmentEnabled)
{
mInterpreter.OutputFormat("e");
}
if (aSecurityPolicy.mMasterKeyProvisioningEnabled)
{
mInterpreter.OutputFormat("p");
}
if (aSecurityPolicy.mNonCcmRoutersEnabled)
{
mInterpreter.OutputFormat("R");
}
}
Error Dataset::ParseSecurityPolicy(otSecurityPolicy &aSecurityPolicy, const char *aRotation, const char *aFlags)
{
Error error;
otSecurityPolicy policy;
memset(&policy, 0, sizeof(policy));
SuccessOrExit(error = ParseAsUint16(aRotation, policy.mRotationTime));
VerifyOrExit(aFlags != nullptr);
for (const char *flag = aFlags; *flag != '\0'; flag++)
{
switch (*flag)
{
case 'o':
policy.mObtainMasterKeyEnabled = true;
break;
case 'n':
policy.mNativeCommissioningEnabled = true;
break;
case 'r':
policy.mRoutersEnabled = true;
break;
case 'c':
policy.mExternalCommissioningEnabled = true;
break;
case 'b':
policy.mBeaconsEnabled = true;
break;
case 'C':
policy.mCommercialCommissioningEnabled = true;
break;
case 'e':
policy.mAutonomousEnrollmentEnabled = true;
break;
case 'p':
policy.mMasterKeyProvisioningEnabled = true;
break;
case 'R':
policy.mNonCcmRoutersEnabled = true;
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
exit:
if (error == kErrorNone)
{
aSecurityPolicy = policy;
}
return error;
}
otError Dataset::ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
@@ -792,73 +892,14 @@ otError Dataset::ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[])
{
if (sDataset.mComponents.mIsSecurityPolicyPresent)
{
mInterpreter.OutputFormat("%d ", sDataset.mSecurityPolicy.mRotationTime);
if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY)
{
mInterpreter.OutputFormat("o");
}
if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_NATIVE_COMMISSIONING)
{
mInterpreter.OutputFormat("n");
}
if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_ROUTERS)
{
mInterpreter.OutputFormat("r");
}
if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER)
{
mInterpreter.OutputFormat("c");
}
if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_BEACONS)
{
mInterpreter.OutputFormat("b");
}
OutputSecurityPolicy(sDataset.mSecurityPolicy);
mInterpreter.OutputLine("");
}
}
else
{
SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mSecurityPolicy.mRotationTime));
sDataset.mSecurityPolicy.mFlags = 0;
if (aArgsLength > 1)
{
for (char *arg = aArgs[1]; *arg != '\0'; arg++)
{
switch (*arg)
{
case 'o':
sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_OBTAIN_MASTER_KEY;
break;
case 'n':
sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_NATIVE_COMMISSIONING;
break;
case 'r':
sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_ROUTERS;
break;
case 'c':
sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER;
break;
case 'b':
sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_BEACONS;
break;
default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}
}
SuccessOrExit(
error = ParseSecurityPolicy(sDataset.mSecurityPolicy, aArgs[0], aArgsLength > 1 ? aArgs[1] : nullptr));
sDataset.mComponents.mIsSecurityPolicyPresent = true;
}
+3
View File
@@ -105,6 +105,9 @@ private:
void HandleDatasetUpdater(otError aError);
#endif
void OutputSecurityPolicy(const otSecurityPolicy &aSecurityPolicy);
Error ParseSecurityPolicy(otSecurityPolicy &aSecurityPolicy, const char *aRotation, const char *aFlags);
static constexpr Command sCommands[] = {
{"active", &Dataset::ProcessActive},
{"activetimestamp", &Dataset::ProcessActiveTimestamp},
+1 -1
View File
@@ -931,7 +931,7 @@ TxFrame *Mac::PrepareBeacon(void)
beaconPayload = reinterpret_cast<BeaconPayload *>(beacon->GetPayload());
if (Get<KeyManager>().IsThreadBeaconEnabled())
if (Get<KeyManager>().GetSecurityPolicy().mBeaconsEnabled)
{
beaconPayload->Init();
+11 -14
View File
@@ -67,12 +67,11 @@ Error Dataset::Info::GenerateRandom(Instance &aInstance)
Clear();
mActiveTimestamp = 1;
mChannel = preferredChannels.ChooseRandomChannel();
mChannelMask = supportedChannels.GetMask();
mSecurityPolicy.mRotationTime = KeyManager::kDefaultKeyRotationTime;
mSecurityPolicy.mFlags = KeyManager::kDefaultSecurityPolicyFlags;
mPanId = Mac::GenerateRandomPanId();
mActiveTimestamp = 1;
mChannel = preferredChannels.ChooseRandomChannel();
mChannelMask = supportedChannels.GetMask();
mPanId = Mac::GenerateRandomPanId();
static_cast<SecurityPolicy &>(mSecurityPolicy).SetToDefault();
SuccessOrExit(error = static_cast<MasterKey &>(mMasterKey).GenerateRandom());
SuccessOrExit(error = static_cast<Pskc &>(mPskc).GenerateRandom());
@@ -137,9 +136,7 @@ bool Dataset::Info::IsSubsetOf(const Info &aOther) const
if (IsSecurityPolicyPresent())
{
VerifyOrExit(aOther.IsSecurityPolicyPresent() &&
GetSecurityPolicy().mRotationTime == aOther.GetSecurityPolicy().mRotationTime &&
GetSecurityPolicy().mFlags == aOther.GetSecurityPolicy().mFlags);
VerifyOrExit(aOther.IsSecurityPolicyPresent() && GetSecurityPolicy() == aOther.GetSecurityPolicy());
}
if (IsChannelMaskPresent())
@@ -249,7 +246,8 @@ void Dataset::ConvertTo(Info &aDatasetInfo) const
case Tlv::kSecurityPolicy:
{
const SecurityPolicyTlv *tlv = static_cast<const SecurityPolicyTlv *>(cur);
aDatasetInfo.SetSecurityPolicy(tlv->GetRotationTime(), tlv->GetFlags());
aDatasetInfo.SetSecurityPolicy(tlv->GetSecurityPolicy());
break;
}
@@ -363,9 +361,9 @@ Error Dataset::SetFrom(const Info &aDatasetInfo)
if (aDatasetInfo.IsSecurityPolicyPresent())
{
SecurityPolicyTlv tlv;
tlv.Init();
tlv.SetRotationTime(aDatasetInfo.GetSecurityPolicy().mRotationTime);
tlv.SetFlags(aDatasetInfo.GetSecurityPolicy().mFlags);
tlv.SetSecurityPolicy(aDatasetInfo.GetSecurityPolicy());
IgnoreError(SetTlv(tlv));
}
@@ -593,8 +591,7 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdated
case Tlv::kSecurityPolicy:
{
const SecurityPolicyTlv *securityPolicy = static_cast<const SecurityPolicyTlv *>(cur);
IgnoreError(keyManager.SetKeyRotation(securityPolicy->GetRotationTime()));
keyManager.SetSecurityPolicyFlags(securityPolicy->GetFlags());
keyManager.SetSecurityPolicy(securityPolicy->GetSecurityPolicy());
break;
}
+3 -14
View File
@@ -534,20 +534,9 @@ public:
* @returns The Security Policy in the Dataset.
*
*/
const otSecurityPolicy &GetSecurityPolicy(void) const { return mSecurityPolicy; }
/**
* This method sets the Security Policy in the Dataset.
*
* @param[in] aRotationTime A value for Key Rotation (in units of hours).
* @param[in] aFlags Security policy flags
*
*/
void SetSecurityPolicy(uint16_t aRotationTime, uint8_t aFlags)
const SecurityPolicy &GetSecurityPolicy(void) const
{
mSecurityPolicy.mRotationTime = aRotationTime;
mSecurityPolicy.mFlags = aFlags;
mComponents.mIsSecurityPolicyPresent = true;
return static_cast<const SecurityPolicy &>(mSecurityPolicy);
}
/**
@@ -556,7 +545,7 @@ public:
* @param[in] aSecurityPolicy A Security Policy to set in Dataset.
*
*/
void SetSecurityPolicy(const otSecurityPolicy &aSecurityPolicy)
void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
{
mSecurityPolicy = aSecurityPolicy;
mComponents.mIsSecurityPolicyPresent = true;
+4 -2
View File
@@ -416,7 +416,8 @@ void DatasetManager::SendGetResponse(const Coap::Message & aRequest,
{
for (const Tlv *cur = dataset.GetTlvsStart(); cur < dataset.GetTlvsEnd(); cur = cur->GetNext())
{
if (cur->GetType() != Tlv::kNetworkMasterKey || Get<KeyManager>().IsObtainMasterKeyEnabled())
if (cur->GetType() != Tlv::kNetworkMasterKey ||
Get<KeyManager>().GetSecurityPolicy().mObtainMasterKeyEnabled)
{
SuccessOrExit(error = cur->AppendTo(*message));
}
@@ -428,7 +429,8 @@ void DatasetManager::SendGetResponse(const Coap::Message & aRequest,
{
const Tlv *tlv;
if (aTlvs[index] == Tlv::kNetworkMasterKey && !Get<KeyManager>().IsObtainMasterKeyEnabled())
if (aTlvs[index] == Tlv::kNetworkMasterKey &&
!Get<KeyManager>().GetSecurityPolicy().mObtainMasterKeyEnabled)
{
continue;
}
+2 -2
View File
@@ -387,9 +387,9 @@ Error ActiveDataset::GenerateLocal(void)
if (dataset.GetTlv<SecurityPolicyTlv>() == nullptr)
{
SecurityPolicyTlv tlv;
tlv.Init();
tlv.SetRotationTime(static_cast<uint16_t>(Get<KeyManager>().GetKeyRotation()));
tlv.SetFlags(Get<KeyManager>().GetSecurityPolicyFlags());
tlv.SetSecurityPolicy(Get<KeyManager>().GetSecurityPolicy());
IgnoreError(dataset.SetTlv(tlv));
}
+27
View File
@@ -145,6 +145,33 @@ void SteeringDataTlv::CopyTo(SteeringData &aSteeringData) const
memcpy(aSteeringData.GetData(), mSteeringData, GetSteeringDataLength());
}
bool SecurityPolicyTlv::IsValid(void) const
{
return GetLength() >= sizeof(mRotationTime) && GetRotationTime() >= SecurityPolicy::kMinKeyRotationTime &&
GetFlagsLength() >= kThread11FlagsLength;
}
SecurityPolicy SecurityPolicyTlv::GetSecurityPolicy(void) const
{
OT_ASSERT(IsValid());
SecurityPolicy securityPolicy;
uint8_t length = OT_MIN(static_cast<uint8_t>(sizeof(mFlags)), GetFlagsLength());
securityPolicy.mRotationTime = GetRotationTime();
securityPolicy.SetFlags(mFlags, length);
return securityPolicy;
}
void SecurityPolicyTlv::SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
{
SetRotationTime(aSecurityPolicy.mRotationTime);
aSecurityPolicy.GetFlags(mFlags, sizeof(mFlags));
OT_ASSERT(IsValid());
}
bool ChannelTlv::IsValid(void) const
{
bool ret = false;
+22 -33
View File
@@ -971,52 +971,41 @@ public:
* @retval FALSE If the TLV does not appear to be well-formed.
*
*/
bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(Tlv); }
bool IsValid(void) const;
/**
* This method returns the Rotation Time value.
* This method returns the Security Policy.
*
* @returns The Rotation Time value.
* @returns The Security Policy.
*
*/
uint16_t GetRotationTime(void) const { return HostSwap16(mRotationTime); }
SecurityPolicy GetSecurityPolicy(void) const;
/**
* This method sets the Rotation Time value.
* This method sets the Security Policy.
*
* @param[in] aRotationTime The Rotation Time value.
* @param[in] aSecurityPolicy The Security Policy which will be set.
*
*/
void SetRotationTime(uint16_t aRotationTime) { mRotationTime = HostSwap16(aRotationTime); }
enum
{
kObtainMasterKeyFlag = OT_SECURITY_POLICY_OBTAIN_MASTER_KEY, ///< Obtaining the Master Key
kNativeCommissioningFlag = OT_SECURITY_POLICY_NATIVE_COMMISSIONING, ///< Native Commissioning
kRoutersFlag = OT_SECURITY_POLICY_ROUTERS, ///< Routers enabled
kExternalCommissionerFlag = OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER, ///< External Commissioner allowed
kBeaconsFlag = OT_SECURITY_POLICY_BEACONS, ///< Beacons enabled
};
/**
* This method returns the Flags value.
*
* @returns The Flags value.
*
*/
uint8_t GetFlags(void) const { return mFlags; }
/**
* This method sets the Flags value.
*
* @param[in] aFlags The Flags value.
*
*/
void SetFlags(uint8_t aFlags) { mFlags = aFlags; }
void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy);
private:
enum : uint8_t
{
kThread11FlagsLength = 1, ///< The Thread 1.1 Security Policy Flags length.
kThread12FlagsLength = 2, ///< The Thread 1.2 Security Policy Flags length.
};
void SetRotationTime(uint16_t aRotationTime) { mRotationTime = HostSwap16(aRotationTime); }
uint16_t GetRotationTime(void) const { return HostSwap16(mRotationTime); }
uint8_t GetFlagsLength(void) const { return GetLength() - sizeof(mRotationTime); }
uint16_t mRotationTime;
uint8_t mFlags;
#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
uint8_t mFlags[kThread12FlagsLength];
#else
uint8_t mFlags[kThread11FlagsLength];
#endif
} OT_TOOL_PACKED_END;
/**
+114 -16
View File
@@ -56,6 +56,116 @@ const uint8_t KeyManager::kTrelInfoString[] = {'T', 'h', 'r', 'e', 'a', 'd', 'O'
'r', 'I', 'n', 'f', 'r', 'a', 'K', 'e', 'y'};
#endif
void SecurityPolicy::SetToDefault(void)
{
mRotationTime = kDefaultKeyRotationTime;
SetToDefaultFlags();
}
void SecurityPolicy::SetToDefaultFlags(void)
{
mObtainMasterKeyEnabled = true;
mNativeCommissioningEnabled = true;
mRoutersEnabled = true;
mExternalCommissioningEnabled = true;
mBeaconsEnabled = true;
mCommercialCommissioningEnabled = false;
mAutonomousEnrollmentEnabled = false;
mMasterKeyProvisioningEnabled = false;
mTobleLinkEnabled = true;
mNonCcmRoutersEnabled = false;
mVersionThresholdForRouting = 0;
}
void SecurityPolicy::SetFlags(const uint8_t *aFlags, uint8_t aFlagsLength)
{
OT_ASSERT(aFlagsLength > 0);
SetToDefaultFlags();
mObtainMasterKeyEnabled = aFlags[0] & kObtainMasterKeyMask;
mNativeCommissioningEnabled = aFlags[0] & kNativeCommissioningMask;
mRoutersEnabled = aFlags[0] & kRoutersMask;
mExternalCommissioningEnabled = aFlags[0] & kExternalCommissioningMask;
mBeaconsEnabled = aFlags[0] & kBeaconsMask;
mCommercialCommissioningEnabled = (aFlags[0] & kCommercialCommissioningMask) == 0;
mAutonomousEnrollmentEnabled = (aFlags[0] & kAutonomousEnrollmentMask) == 0;
mMasterKeyProvisioningEnabled = (aFlags[0] & kMasterKeyProvisioningMask) == 0;
VerifyOrExit(aFlagsLength > sizeof(aFlags[0]));
mTobleLinkEnabled = aFlags[1] & kTobleLinkMask;
mNonCcmRoutersEnabled = (aFlags[1] & kNonCcmRoutersMask) == 0;
mVersionThresholdForRouting = aFlags[1] & kVersionThresholdForRoutingMask;
exit:
return;
}
void SecurityPolicy::GetFlags(uint8_t *aFlags, uint8_t aFlagsLength) const
{
OT_ASSERT(aFlagsLength > 0);
memset(aFlags, 0, aFlagsLength);
if (mObtainMasterKeyEnabled)
{
aFlags[0] |= kObtainMasterKeyMask;
}
if (mNativeCommissioningEnabled)
{
aFlags[0] |= kNativeCommissioningMask;
}
if (mRoutersEnabled)
{
aFlags[0] |= kRoutersMask;
}
if (mExternalCommissioningEnabled)
{
aFlags[0] |= kExternalCommissioningMask;
}
if (mBeaconsEnabled)
{
aFlags[0] |= kBeaconsMask;
}
if (!mCommercialCommissioningEnabled)
{
aFlags[0] |= kCommercialCommissioningMask;
}
if (!mAutonomousEnrollmentEnabled)
{
aFlags[0] |= kAutonomousEnrollmentMask;
}
if (!mMasterKeyProvisioningEnabled)
{
aFlags[0] |= kMasterKeyProvisioningMask;
}
VerifyOrExit(aFlagsLength > sizeof(aFlags[0]));
if (mTobleLinkEnabled)
{
aFlags[1] |= kTobleLinkMask;
}
if (!mNonCcmRoutersEnabled)
{
aFlags[1] |= kNonCcmRoutersMask;
}
aFlags[1] |= kReservedMask;
aFlags[1] |= mVersionThresholdForRouting;
exit:
return;
}
KeyManager::KeyManager(Instance &aInstance)
: InstanceLocator(aInstance)
, mKeySequence(0)
@@ -63,12 +173,10 @@ KeyManager::KeyManager(Instance &aInstance)
, mStoredMacFrameCounter(0)
, mStoredMleFrameCounter(0)
, mHoursSinceKeyRotation(0)
, mKeyRotationTime(kDefaultKeyRotationTime)
, mKeySwitchGuardTime(kDefaultKeySwitchGuardTime)
, mKeySwitchGuardEnabled(false)
, mKeyRotationTimer(aInstance, KeyManager::HandleKeyRotationTimer)
, mKekFrameCounter(0)
, mSecurityPolicyFlags(kDefaultSecurityPolicyFlags)
, mIsPskcSet(false)
{
Error error = mMasterKey.GenerateRandom();
@@ -298,21 +406,11 @@ void KeyManager::SetKek(const uint8_t *aKek)
mKekFrameCounter = 0;
}
Error KeyManager::SetKeyRotation(uint32_t aKeyRotation)
void KeyManager::SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy)
{
Error result = kErrorNone;
OT_ASSERT(aSecurityPolicy.mRotationTime >= SecurityPolicy::kMinKeyRotationTime);
VerifyOrExit(aKeyRotation >= static_cast<uint32_t>(kMinKeyRotationTime), result = kErrorInvalidArgs);
mKeyRotationTime = aKeyRotation;
exit:
return result;
}
void KeyManager::SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags)
{
IgnoreError(Get<Notifier>().Update(mSecurityPolicyFlags, aSecurityPolicyFlags, kEventSecurityPolicyChanged));
IgnoreError(Get<Notifier>().Update(mSecurityPolicy, aSecurityPolicy, kEventSecurityPolicyChanged));
}
void KeyManager::StartKeyRotationTimer(void)
@@ -339,7 +437,7 @@ void KeyManager::HandleKeyRotationTimer(void)
mKeyRotationTimer.StartAt(mKeyRotationTimer.GetFireTime(), kOneHourIntervalInMsec);
if (mHoursSinceKeyRotation >= mKeyRotationTime)
if (mHoursSinceKeyRotation >= mSecurityPolicy.mRotationTime)
{
SetCurrentKeySequence(mKeySequence + 1);
}
+79 -103
View File
@@ -41,6 +41,7 @@
#include <openthread/dataset.h>
#include "common/clearable.hpp"
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
@@ -61,6 +62,72 @@ namespace ot {
* @{
*/
/**
* This class represents Security Policy Rotation and Flags.
*
*/
class SecurityPolicy : public otSecurityPolicy, public Equatable<SecurityPolicy>
{
public:
enum : uint16_t
{
kMinKeyRotationTime = 1, ///< The minimum Key Rotation Time in hours.
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:
enum : uint8_t
{
kDefaultFlags = 0xff,
kObtainMasterKeyMask = 1 << 7,
kNativeCommissioningMask = 1 << 6,
kRoutersMask = 1 << 5,
kExternalCommissioningMask = 1 << 4,
kBeaconsMask = 1 << 3,
kCommercialCommissioningMask = 1 << 2,
kAutonomousEnrollmentMask = 1 << 1,
kMasterKeyProvisioningMask = 1 << 0,
kTobleLinkMask = 1 << 7,
kNonCcmRoutersMask = 1 << 6,
kReservedMask = 0x38,
kVersionThresholdForRoutingMask = 0x07,
};
void SetToDefaultFlags(void);
};
/**
* This class represents a Thread Master Key.
*
@@ -115,16 +182,6 @@ typedef Mac::Key Kek;
class KeyManager : public InstanceLocator, private NonCopyable
{
public:
enum : uint16_t
{
kDefaultKeyRotationTime = 672, ///< Default Key Rotation Time (in unit of hours).
};
enum : uint8_t
{
kDefaultSecurityPolicyFlags = 0xff, ///< Default Security Policy Flags.
};
/**
* This constructor initializes the object.
*
@@ -365,29 +422,6 @@ public:
*/
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 kErrorNone KeyRotation time updated.
* @retval kErrorInvalidArgs @p aKeyRotation is out of range.
*
*/
Error SetKeyRotation(uint32_t aKeyRotation);
/**
* This method returns the KeySwitchGuardTime.
*
@@ -409,82 +443,26 @@ public:
void SetKeySwitchGuardTime(uint32_t aKeySwitchGuardTime) { mKeySwitchGuardTime = aKeySwitchGuardTime; }
/**
* This method returns the Security Policy Flags.
* This method returns the Security Policy.
*
* The Security Policy Flags specifies network administrator preferences for which
* security-related operations are allowed or disallowed.
* The Security Policy specifies Key Rotation Time and network administrator preferences
* for which security-related operations are allowed or disallowed.
*
* @returns The SecurityPolicy Flags.
* @returns The SecurityPolicy.
*
*/
uint8_t GetSecurityPolicyFlags(void) const { return mSecurityPolicyFlags; }
const SecurityPolicy &GetSecurityPolicy(void) const { return mSecurityPolicy; }
/**
* This method sets the Security Policy Flags.
* This method sets the Security Policy.
*
* The Security Policy Flags specifies network administrator preferences for which
* security-related operations are allowed or disallowed.
* The Security Policy specifies Key Rotation Time and network administrator preferences
* for which security-related operations are allowed or disallowed.
*
* @param[in] aSecurityPolicyFlags The Security Policy Flags.
* @param[in] aSecurityPolicy The Security Policy.
*
*/
void SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags);
/**
* This method indicates whether or not obtaining Master key for out-of-band is enabled.
*
* @retval TRUE If obtaining Master key for out-of-band is enabled.
* @retval FALSE If obtaining Master key for out-of-band is not enabled.
*
*/
bool IsObtainMasterKeyEnabled(void) const
{
return (mSecurityPolicyFlags & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY) != 0;
}
/**
* This method indicates whether or not Native Commissioning using PSKc is allowed.
*
* @retval TRUE If Native Commissioning using PSKc is allowed.
* @retval FALSE If Native Commissioning using PSKc is not allowed.
*
*/
bool IsNativeCommissioningAllowed(void) const
{
return (mSecurityPolicyFlags & OT_SECURITY_POLICY_NATIVE_COMMISSIONING) != 0;
}
/**
* This method indicates whether or not Thread 1.1 Routers are enabled.
*
* @retval TRUE If Thread 1.1 Routers are enabled.
* @retval FALSE If Thread 1.1 Routers are not enabled.
*
*/
bool IsRouterEnabled(void) const { return (mSecurityPolicyFlags & OT_SECURITY_POLICY_ROUTERS) != 0; }
/**
* This method indicates whether or not external Commissioner authentication is allowed using PSKc.
*
* @retval TRUE If the commissioning sessions by an external Commissioner based on the PSKc are allowed
* to be established and that changes to the Commissioner Dataset by on-mesh nodes are allowed.
* @retval FALSE If the commissioning sessions by an external Commissioner based on the PSKc are not allowed
* to be established and that changes to the Commissioner Dataset by on-mesh nodes are not allowed.
*
*/
bool IsExternalCommissionerAllowed(void) const
{
return (mSecurityPolicyFlags & OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER) != 0;
}
/**
* This method indicates whether or not Thread Beacons are enabled.
*
* @retval TRUE If Thread Beacons are enabled.
* @retval FALSE If Thread Beacons are not enabled.
*
*/
bool IsThreadBeaconEnabled(void) const { return (mSecurityPolicyFlags & OT_SECURITY_POLICY_BEACONS) != 0; }
void SetSecurityPolicy(const SecurityPolicy &aSecurityPolicy);
/**
* This method updates the MAC keys and MLE key.
@@ -503,7 +481,6 @@ public:
private:
enum
{
kMinKeyRotationTime = 1,
kDefaultKeySwitchGuardTime = 624,
kOneHourIntervalInMsec = 3600u * 1000u,
};
@@ -555,7 +532,6 @@ private:
uint32_t mStoredMleFrameCounter;
uint32_t mHoursSinceKeyRotation;
uint32_t mKeyRotationTime;
uint32_t mKeySwitchGuardTime;
bool mKeySwitchGuardEnabled;
TimerMilli mKeyRotationTimer;
@@ -566,8 +542,8 @@ private:
Kek mKek;
uint32_t mKekFrameCounter;
uint8_t mSecurityPolicyFlags;
bool mIsPskcSet : 1;
SecurityPolicy mSecurityPolicy;
bool mIsPskcSet : 1;
};
/**
+1 -1
View File
@@ -1584,7 +1584,7 @@ void Mle::HandleNotifierEvents(Events aEvents)
if (aEvents.Contains(kEventSecurityPolicyChanged))
{
Get<Ip6::Filter>().AllowNativeCommissioner(Get<KeyManager>().IsNativeCommissioningAllowed());
Get<Ip6::Filter>().AllowNativeCommissioner(Get<KeyManager>().GetSecurityPolicy().mNativeCommissioningEnabled);
}
exit:
+1 -1
View File
@@ -2907,7 +2907,7 @@ Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const M
discoveryResponse.Init();
discoveryResponse.SetVersion(kThreadVersion);
if (Get<KeyManager>().IsNativeCommissioningAllowed())
if (Get<KeyManager>().GetSecurityPolicy().mNativeCommissioningEnabled)
{
SuccessOrExit(error = Tlv::Append<MeshCoP::CommissionerUdpPortTlv>(*message, MeshCoP::kBorderAgentUdpPort));
+11 -1
View File
@@ -52,6 +52,7 @@
#include "meshcop/dataset.hpp"
#include "meshcop/meshcop_tlvs.hpp"
#include "radio/radio.hpp"
#include "thread/key_manager.hpp"
#ifndef MS_PER_S
#define MS_PER_S 1000
@@ -699,8 +700,17 @@ otError RadioSpinel<InterfaceType, ProcessContextType>::ThreadDatasetHandler(con
case SPINEL_PROP_DATASET_SECURITY_POLICY:
{
uint8_t flags[2];
uint8_t flagsLength = 1;
SuccessOrExit(error = decoder.ReadUint16(opDataset.mSecurityPolicy.mRotationTime));
SuccessOrExit(error = decoder.ReadUint8(opDataset.mSecurityPolicy.mFlags));
SuccessOrExit(error = decoder.ReadUint8(flags[0]));
if (otThreadGetVersion() >= OT_THREAD_VERSION_1_2 && decoder.GetRemainingLengthInStruct() > 0)
{
SuccessOrExit(error = decoder.ReadUint8(flags[1]));
++flagsLength;
}
static_cast<SecurityPolicy &>(opDataset.mSecurityPolicy).SetFlags(flags, flagsLength);
opDataset.mComponents.mIsSecurityPolicyPresent = true;
break;
}
+3 -1
View File
@@ -2783,7 +2783,7 @@ enum
SPINEL_PROP_DATASET_DELAY_TIMER = SPINEL_PROP_THREAD_EXT__BEGIN + 30,
/// Operational Dataset Security Policy
/** Format: `SC` - No direct read or write
/** Format: `SD` - No direct read or write
*
* It can only be included in one of the Dataset related properties below:
*
@@ -2797,6 +2797,8 @@ enum
* Content is
* `S` : Key Rotation Time (in units of hour)
* `C` : Security Policy Flags (as specified in Thread 1.1 Section 8.10.1.15)
* `C` : Optional Security Policy Flags extension (as specified in Thread 1.2 Section 8.10.1.15).
* 0xf8 is used if this field is missing.
*
*/
SPINEL_PROP_DATASET_SECURITY_POLICY = SPINEL_PROP_THREAD_EXT__BEGIN + 31,
+18 -2
View File
@@ -1343,10 +1343,17 @@ otError NcpBase::EncodeOperationalDataset(const otOperationalDataset &aDataset)
if (aDataset.mComponents.mIsSecurityPolicyPresent)
{
uint8_t flags[2];
static_cast<const SecurityPolicy &>(aDataset.mSecurityPolicy).GetFlags(flags, sizeof(flags));
SuccessOrExit(error = mEncoder.OpenStruct());
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_PROP_DATASET_SECURITY_POLICY));
SuccessOrExit(error = mEncoder.WriteUint16(aDataset.mSecurityPolicy.mRotationTime));
SuccessOrExit(error = mEncoder.WriteUint8(aDataset.mSecurityPolicy.mFlags));
SuccessOrExit(error = mEncoder.WriteUint8(flags[0]));
if (otThreadGetVersion() >= OT_THREAD_VERSION_1_2)
{
SuccessOrExit(error = mEncoder.WriteUint8(flags[1]));
}
SuccessOrExit(error = mEncoder.CloseStruct());
}
@@ -1546,8 +1553,17 @@ otError NcpBase::DecodeOperationalDataset(otOperationalDataset &aDataset,
if (!aAllowEmptyValues || !mDecoder.IsAllReadInStruct())
{
uint8_t flags[2];
uint8_t flagsLength = 1;
SuccessOrExit(error = mDecoder.ReadUint16(aDataset.mSecurityPolicy.mRotationTime));
SuccessOrExit(error = mDecoder.ReadUint8(aDataset.mSecurityPolicy.mFlags));
SuccessOrExit(error = mDecoder.ReadUint8(flags[0]));
if (otThreadGetVersion() >= OT_THREAD_VERSION_1_2 && mDecoder.GetRemainingLengthInStruct() > 0)
{
SuccessOrExit(error = mDecoder.ReadUint8(flags[1]));
++flagsLength;
}
static_cast<SecurityPolicy &>(aDataset.mSecurityPolicy).SetFlags(flags, flagsLength);
}
aDataset.mComponents.mIsSecurityPolicyPresent = true;
@@ -137,7 +137,7 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
# Disabling O-Bit security_policy = [3600, 0b01111000]
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
active_timestamp=15,
binary='0c030e1078',
security_policy=[3600, 'nrcb'],
)
self.simulator.go(5)
@@ -148,10 +148,9 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
# Step 9
# Disabling N-Bit security_policy = [3600, 0b10111000]
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
active_timestamp=20,
binary='0c030e10b8',
security_policy=[3600, 'orcb'],
)
self.simulator.go(5)
@@ -166,7 +165,7 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
# Disabling B-Bit security_policy = [3600, 0b11110000]
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
active_timestamp=25,
binary='0c030e10f0',
security_policy=[3600, 'onrc'],
)
self.simulator.go(5)
@@ -181,7 +180,7 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
# Disabling R-Bit security_policy = [3600, 0b11011000]
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
active_timestamp=30,
binary='0c030e10d8',
security_policy=[3600, 'oncb'],
)
self.simulator.go(5)
@@ -218,7 +217,13 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
pkts.filter_wpan_src64(LEADER).\
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
filter(lambda p: p.thread_meshcop.tlv.unknown == '0e10f8').\
filter(lambda p: (p.thread_meshcop.tlv.sec_policy_rot == 3600 and
p.thread_meshcop.tlv.sec_policy_o == 1 and
p.thread_meshcop.tlv.sec_policy_n == 1 and
p.thread_meshcop.tlv.sec_policy_r == 1 and
p.thread_meshcop.tlv.sec_policy_c == 1 and
p.thread_meshcop.tlv.sec_policy_b == 1) or
(p.thread_meshcop.tlv.unknown == '0e10ff')).\
must_next()
# Step 5: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
@@ -237,7 +242,8 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
NM_SECURITY_POLICY_TLV
} == set(p.thread_meshcop.tlv.type) and\
p.thread_meshcop.tlv.active_tstamp == 15 and\
p.thread_meshcop.tlv.unknown == '0e1078').\
(p.thread_meshcop.tlv.sec_policy_o == 0 or
p.thread_meshcop.tlv.unknown == '0e107f')).\
must_next()
# Step 6: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -289,7 +295,8 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
NM_SECURITY_POLICY_TLV
} == set(p.thread_meshcop.tlv.type) and\
p.thread_meshcop.tlv.active_tstamp == 20 and\
p.thread_meshcop.tlv.unknown == '0e10b8').\
(p.thread_meshcop.tlv.sec_policy_n == 0 or
p.thread_meshcop.tlv.unknown == '0e10bf')).\
must_next()
# Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -326,7 +333,8 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
NM_SECURITY_POLICY_TLV
} == set(p.thread_meshcop.tlv.type) and\
p.thread_meshcop.tlv.active_tstamp == 25 and\
p.thread_meshcop.tlv.unknown == '0e10f0').\
(p.thread_meshcop.tlv.sec_policy_b == 0 or
p.thread_meshcop.tlv.unknown == '0e10f7')).\
must_next()
# Step 14: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -371,7 +379,8 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
NM_SECURITY_POLICY_TLV
} == set(p.thread_meshcop.tlv.type) and\
p.thread_meshcop.tlv.active_tstamp == 30 and\
p.thread_meshcop.tlv.unknown == '0e10d8').\
(p.thread_meshcop.tlv.sec_policy_r == 0 or
p.thread_meshcop.tlv.unknown == '0e10df')).\
must_next()
# Step 18: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
@@ -401,7 +410,8 @@ class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
filter_mle_cmd(MLE_DATA_RESPONSE).\
filter(lambda p:
p.mle.tlv.active_tstamp == 30 and\
p.thread_meshcop.tlv.unknown == '0e10d8').\
(p.thread_meshcop.tlv.sec_policy_r == 0 or
p.thread_meshcop.tlv.unknown == '0e10df')).\
must_next()
+5
View File
@@ -1927,6 +1927,7 @@ class NodeImpl:
master_key=None,
mesh_local=None,
network_name=None,
security_policy=None,
binary=None,
):
cmd = 'dataset mgmtsetcommand active '
@@ -1955,6 +1956,10 @@ class NodeImpl:
if network_name is not None:
cmd += 'networkname %s ' % self._escape_escapable(network_name)
if security_policy is not None:
rotation, flags = security_policy
cmd += 'securitypolicy %d %s ' % (rotation, flags)
if binary is not None:
cmd += '-x %s ' % binary
+1 -1
View File
@@ -1287,7 +1287,7 @@ class OTCI(object):
elif key == 'PSKc':
dataset['pskc'] = val
elif key == 'Security Policy':
rotation_time, flags = val.split(', ')
rotation_time, flags = val.split(' ')
rotation_time = int(rotation_time)
dataset['security_policy'] = SecurityPolicy(rotation_time, flags)
else: