diff --git a/include/openthread-types.h b/include/openthread-types.h index ca0e2576e..b3f507a06 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -175,6 +175,40 @@ typedef struct otMeshLocalPrefix uint8_t m8[OT_MESH_LOCAL_PREFIX_SIZE]; } otMeshLocalPrefix; +#define OT_PSKC_MAX_SIZE 16 ///< Maximum size of the PSKc (bytes) + +/** + * This structure represents PSKc. + * + */ +typedef struct otPSKc +{ + uint8_t m8[OT_PSKC_MAX_SIZE]; +} otPSKc; + +/** + * This structure represent Security Policy. + * + */ +typedef struct otSecurityPolicy +{ + uint16_t mRotationTime; + uint8_t mFlags; +} otSecurityPolicy; + +/** + * This enumeration represents flags that indicate security related behaviours within OpenThread. + * + */ +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 +}; + /** * This type represents the IEEE 802.15.4 PAN ID. * @@ -309,6 +343,8 @@ typedef struct otOperationalDataset uint32_t mDelay; ///< Delay Timer otPanId mPanId; ///< PAN ID uint16_t mChannel; ///< Channel + otPSKc mPSKc; ///< PSKc + otSecurityPolicy mSecurityPolicy; ///< Security Policy bool mIsActiveTimestampSet : 1; ///< TRUE if Active Timestamp is set, FALSE otherwise. bool mIsPendingTimestampSet : 1; ///< TRUE if Pending Timestamp is set, FALSE otherwise. @@ -319,6 +355,8 @@ typedef struct otOperationalDataset bool mIsDelaySet : 1; ///< TRUE if Delay Timer is set, FALSE otherwise. bool mIsPanIdSet : 1; ///< TRUE if PAN ID is set, FALSE otherwise. bool mIsChannelSet : 1; ///< TRUE if Channel is set, FALSE otherwise. + bool mIsPSKcSet : 1; ///< TRUE if PSKc is set, FALSE otherwise. + bool mIsSecurityPolicySet : 1; ///< TRUE if Security Policy is set, FALSE otherwise. } otOperationalDataset; /** diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 8b7df4fbc..ba51fbfbb 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -62,6 +62,8 @@ const DatasetCommand Dataset::sCommands[] = { "panid", &ProcessPanId }, { "pending", &ProcessPending }, { "pendingtimestamp", &ProcessPendingTimestamp }, + { "pskc", &ProcessPSKc }, + { "securitypolicy", &ProcessSecurityPolicy }, }; Server *Dataset::sServer; @@ -132,6 +134,45 @@ ThreadError Dataset::Print(otOperationalDataset &aDataset) sServer->OutputFormat("PAN ID: 0x%04x\r\n", aDataset.mPanId); } + if (aDataset.mIsPSKcSet) + { + sServer->OutputFormat("PSKc: "); + OutputBytes(aDataset.mPSKc.m8, sizeof(aDataset.mPSKc.m8)); + sServer->OutputFormat("\r\n"); + } + + if (aDataset.mIsSecurityPolicySet) + { + sServer->OutputFormat("Security Policy: %d, ", aDataset.mSecurityPolicy.mRotationTime); + + if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY) + { + sServer->OutputFormat("o"); + } + + if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_NATIVE_COMMISSIONING) + { + sServer->OutputFormat("n"); + } + + if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_ROUTERS) + { + sServer->OutputFormat("r"); + } + + if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER) + { + sServer->OutputFormat("c"); + } + + if (aDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_BEACONS) + { + sServer->OutputFormat("b"); + } + + sServer->OutputFormat("\r\n"); + } + return kThreadError_None; } @@ -553,5 +594,72 @@ exit: return error; } +ThreadError Dataset::ProcessPSKc(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + uint16_t length; + + VerifyOrExit(argc > 0, error = kThreadError_Parse); + + length = static_cast((strlen(argv[0]) + 1) / 2); + VerifyOrExit(length <= OT_PSKC_MAX_SIZE, error = kThreadError_NoBufs); + VerifyOrExit(Interpreter::Hex2Bin(argv[0], sDataset.mPSKc.m8 + OT_PSKC_MAX_SIZE - length, length) + == length, error = kThreadError_Parse); + + sDataset.mIsPSKcSet = true; + +exit: + return error; +} + +ThreadError Dataset::ProcessSecurityPolicy(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + long value; + + VerifyOrExit(argc > 0, error = kThreadError_Parse); + + SuccessOrExit(error = Interpreter::ParseLong(argv[0], value)); + sDataset.mSecurityPolicy.mRotationTime = static_cast(value); + sDataset.mSecurityPolicy.mFlags = 0; + + if (argc > 1) + { + for (char *arg = argv[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 = kThreadError_Parse); + } + } + } + + sDataset.mIsSecurityPolicySet = true; + +exit: + return error; +} + } // namespace Cli } // namespace Thread diff --git a/src/cli/cli_dataset.hpp b/src/cli/cli_dataset.hpp index 1c3518876..b8ae95789 100644 --- a/src/cli/cli_dataset.hpp +++ b/src/cli/cli_dataset.hpp @@ -88,6 +88,8 @@ private: static ThreadError ProcessPendingTimestamp(int argc, char *argv[]); static ThreadError ProcessMgmtSetCommand(int argc, char *argv[]); static ThreadError ProcessMgmtGetCommand(int argc, char *argv[]); + static ThreadError ProcessPSKc(int argc, char *argv[]); + static ThreadError ProcessSecurityPolicy(int argc, char *argv[]); static const DatasetCommand sCommands[]; static otOperationalDataset sDataset; diff --git a/src/core/thread/meshcop_dataset.cpp b/src/core/thread/meshcop_dataset.cpp index 077b75d90..4f3941831 100644 --- a/src/core/thread/meshcop_dataset.cpp +++ b/src/core/thread/meshcop_dataset.cpp @@ -177,6 +177,23 @@ void Dataset::Get(otOperationalDataset &aDataset) break; } + case Tlv::kPSKc: + { + const PSKcTlv *tlv = static_cast(cur); + memcpy(aDataset.mPSKc.m8, tlv->GetPSKc(), tlv->GetLength()); + aDataset.mIsPSKcSet = true; + break; + } + + case Tlv::kSecurityPolicy: + { + const SecurityPolicyTlv *tlv = static_cast(cur); + aDataset.mSecurityPolicy.mRotationTime = tlv->GetRotationTime(); + aDataset.mSecurityPolicy.mFlags = tlv->GetFlags(); + aDataset.mIsSecurityPolicySet = true; + break; + } + default: { break; @@ -270,6 +287,23 @@ ThreadError Dataset::Set(const otOperationalDataset &aDataset, bool aActive) Set(tlv); } + if (aDataset.mIsPSKcSet) + { + MeshCoP::PSKcTlv tlv; + tlv.Init(); + tlv.SetPSKc(aDataset.mPSKc.m8); + Set(tlv); + } + + if (aDataset.mIsSecurityPolicySet) + { + MeshCoP::SecurityPolicyTlv tlv; + tlv.Init(); + tlv.SetRotationTime(aDataset.mSecurityPolicy.mRotationTime); + tlv.SetFlags(aDataset.mSecurityPolicy.mFlags); + Set(tlv); + } + exit: return error; } diff --git a/src/core/thread/meshcop_tlvs.hpp b/src/core/thread/meshcop_tlvs.hpp index dcfb42146..8cabd2716 100644 --- a/src/core/thread/meshcop_tlvs.hpp +++ b/src/core/thread/meshcop_tlvs.hpp @@ -774,11 +774,11 @@ public: enum { - kObtainMasterKeyFlag = 1 << 7, ///< Obtaining the Master Key - kNativeCommissioningFlag = 1 << 6, ///< Native Commissioning - kRoutersFlag = 1 << 5, ///< Routers enabled - kExternalCommissionerFlag = 1 << 4, ///< External Commissioner allowed - kBeaconsFlag = 1 << 3, ///< Beacons enabled + 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 }; /**