Add support for PSKc TLV and Security Policy TLV (#558)
* Add support for PSKc TLV and Security Policy TLV
diff --git a/include/openthread-types.h b/include/openthread-types.h
index ca0e257..b3f507a 100644
--- a/include/openthread-types.h
+++ b/include/openthread-types.h
@@ -175,6 +175,40 @@
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 @@
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 @@
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 8b7df4f..ba51fbf 100644
--- a/src/cli/cli_dataset.cpp
+++ b/src/cli/cli_dataset.cpp
@@ -62,6 +62,8 @@
{ "panid", &ProcessPanId },
{ "pending", &ProcessPending },
{ "pendingtimestamp", &ProcessPendingTimestamp },
+ { "pskc", &ProcessPSKc },
+ { "securitypolicy", &ProcessSecurityPolicy },
};
Server *Dataset::sServer;
@@ -132,6 +134,45 @@
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 @@
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<uint16_t>((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<uint16_t>(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 1c35188..b8ae957 100644
--- a/src/cli/cli_dataset.hpp
+++ b/src/cli/cli_dataset.hpp
@@ -88,6 +88,8 @@
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 077b75d..4f39418 100644
--- a/src/core/thread/meshcop_dataset.cpp
+++ b/src/core/thread/meshcop_dataset.cpp
@@ -177,6 +177,23 @@
break;
}
+ case Tlv::kPSKc:
+ {
+ const PSKcTlv *tlv = static_cast<const PSKcTlv *>(cur);
+ memcpy(aDataset.mPSKc.m8, tlv->GetPSKc(), tlv->GetLength());
+ aDataset.mIsPSKcSet = true;
+ break;
+ }
+
+ case Tlv::kSecurityPolicy:
+ {
+ const SecurityPolicyTlv *tlv = static_cast<const SecurityPolicyTlv *>(cur);
+ aDataset.mSecurityPolicy.mRotationTime = tlv->GetRotationTime();
+ aDataset.mSecurityPolicy.mFlags = tlv->GetFlags();
+ aDataset.mIsSecurityPolicySet = true;
+ break;
+ }
+
default:
{
break;
@@ -270,6 +287,23 @@
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 dcfb421..8cabd27 100644
--- a/src/core/thread/meshcop_tlvs.hpp
+++ b/src/core/thread/meshcop_tlvs.hpp
@@ -774,11 +774,11 @@
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
};
/**