[meshcop] generate PSKc from passphrase (#4766)

This commit is contained in:
Yakun Xu
2020-04-03 07:17:02 -07:00
committed by GitHub
parent 787d6d3763
commit 03aba30cd5
15 changed files with 197 additions and 114 deletions
-19
View File
@@ -402,25 +402,6 @@ uint16_t otCommissionerGetSessionId(otInstance *aInstance);
*/
otCommissionerState otCommissionerGetState(otInstance *aInstance);
/**
* This helper function generates PSKc from a given pass-phrase, network name, and extended PAN Id.
*
* PSKc is used to establish the Commissioner Session.
*
* @param[in] aPassPhrase The commissioning pass-phrase.
* @param[in] aNetworkName The network name for PSKc computation.
* @param[in] aExtPanId The extended PAN ID for PSKc computation.
* @param[out] aPskc A pointer to variable to output the generated PSKc.
*
* @retval OT_ERROR_NONE Successfully generate PSKc.
* @retval OT_ERROR_INVALID_ARGS If any of the input arguments is invalid.
*
*/
otError otCommissionerGeneratePskc(const char * aPassPhrase,
const char * aNetworkName,
const otExtendedPanId *aExtPanId,
otPskc * aPskc);
/**
* @}
*
+19
View File
@@ -426,6 +426,25 @@ otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
const uint8_t * aTlvs,
uint8_t aLength);
/**
* This function generates PSKc from a given pass-phrase, network name, and extended PAN ID.
*
* PSKc is used to establish the Commissioner Session.
*
* @param[in] aPassPhrase The commissioning pass-phrase.
* @param[in] aNetworkName The network name for PSKc computation.
* @param[in] aExtPanId The extended PAN ID for PSKc computation.
* @param[out] aPskc A pointer to variable to output the generated PSKc.
*
* @retval OT_ERROR_NONE Successfully generate PSKc.
* @retval OT_ERROR_INVALID_ARGS If any of the input arguments is invalid.
*
*/
otError otDatasetGeneratePskc(const char * aPassPhrase,
const otNetworkName * aNetworkName,
const otExtendedPanId *aExtPanId,
otPskc * aPskc);
/**
* @}
*
+16
View File
@@ -80,6 +80,7 @@ Done
* [preferrouterid](#preferrouterid-routerid)
* [prefix](#prefix-add-prefix-pvdcsr-prf)
* [promiscuous](#promiscuous)
* [pskc](#pskc--p-keypassphrase)
* [releaserouterid](#releaserouterid-routerid)
* [reset](#reset)
* [rloc16](#rloc16)
@@ -599,6 +600,8 @@ Done
Get the Thread Extended PAN ID value.
**NOTE** The current commissioning credential becomes stale after changing this value. Use [pskc](#pskc--p-keypassphrase) to reset.
```bash
> extpanid
dead00beef00cafe
@@ -1059,6 +1062,8 @@ Done
Set the Thread Network Name.
**NOTE** The current commissioning credential becomes stale after changing this value. Use [pskc](#pskc--p-keypassphrase) to reset.
```bash
> networkname OpenThread
Done
@@ -1166,6 +1171,17 @@ Set the customized data poll period for sleepy end device (milliseconds >= 10ms)
Done
```
### pskc [-p] \<key\>|\<passphrase\>
With `-p` generate pskc from \<passphrase\> (UTF-8 encoded) together with **current** network name and extended PAN ID, otherwise set pskc as \<key\> (hex format).
```bash
> pskc 67c0c203aa0b042bfb5381c47aef4d9e
Done
> pskc -p 123456
Done
```
### preferrouterid \<routerid\>
Prefer a Router ID when solicit router id from Leader.
+8 -2
View File
@@ -256,6 +256,8 @@ Usage: `dataset extpanid <extpanid>`
Set extended panid.
**NOTE** The commissioning credential in the dataset buffer becomes stale after changing this value. Use [pskc](#pskc) to reset.
```bash
> dataset extpanid 000db80123456789
Done
@@ -322,6 +324,8 @@ Usage: `dataset networkname <name>`
Set network name.
**NOTE** The commissioning credential in the dataset buffer becomes stale after changing this value. Use [pskc](#pskc) to reset.
```bash
> dataset networkname OpenThread
Done
@@ -374,13 +378,15 @@ Done
### pskc
Usage: `dataset pskc <key>`
Usage: `pskc [-p] <key>|<passphrase>`
Set pskc with hex format.
With `-p`(**only for FTD**) generate pskc from \<passphrase\> (UTF-8 encoded) together with network name and extended PAN ID in the dataset buffer if set or values in the current stack if not, otherwise set pskc as \<key\> (hex format).
```bash
> dataset pskc 67c0c203aa0b042bfb5381c47aef4d9e
Done
> dataset pskc -p 123456
Done
```
### securitypolicy
+15 -1
View File
@@ -1740,7 +1740,21 @@ void Interpreter::ProcessPskc(uint8_t aArgsLength, char *aArgs[])
{
otPskc pskc;
VerifyOrExit(Hex2Bin(aArgs[0], pskc.m8, sizeof(pskc)) == OT_PSKC_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
if (aArgsLength == 1)
{
VerifyOrExit(Hex2Bin(aArgs[0], pskc.m8, sizeof(pskc)) == sizeof(pskc), error = OT_ERROR_INVALID_ARGS);
}
else if (!strcmp(aArgs[0], "-p"))
{
SuccessOrExit(error = otDatasetGeneratePskc(
aArgs[1], reinterpret_cast<const otNetworkName *>(otThreadGetNetworkName(mInstance)),
otThreadGetExtendedPanId(mInstance), &pskc));
}
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
SuccessOrExit(error = otThreadSetPskc(mInstance, &pskc));
}
+25 -7
View File
@@ -677,14 +677,32 @@ exit:
otError Dataset::ProcessPskc(uint8_t aArgsLength, char *aArgs[])
{
otError error = OT_ERROR_NONE;
uint16_t length;
otError error = OT_ERROR_NONE;
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
length = static_cast<uint16_t>((strlen(aArgs[0]) + 1) / 2);
VerifyOrExit(length <= OT_PSKC_MAX_SIZE, error = OT_ERROR_NO_BUFS);
VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], sDataset.mPskc.m8 + OT_PSKC_MAX_SIZE - length, length) == length,
error = OT_ERROR_INVALID_ARGS);
if (aArgsLength == 1)
{
VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], sDataset.mPskc.m8, sizeof(sDataset.mPskc)) ==
sizeof(sDataset.mPskc),
error = OT_ERROR_INVALID_ARGS);
}
#if OPENTHREAD_FTD
else if (aArgsLength == 2 && !strcmp(aArgs[0], "-p"))
{
SuccessOrExit(
error = otDatasetGeneratePskc(
aArgs[1],
(sDataset.mComponents.mIsNetworkNamePresent
? &sDataset.mNetworkName
: reinterpret_cast<const otNetworkName *>(otThreadGetNetworkName(mInterpreter.mInstance))),
(sDataset.mComponents.mIsExtendedPanIdPresent ? &sDataset.mExtendedPanId
: otThreadGetExtendedPanId(mInterpreter.mInstance)),
&sDataset.mPskc));
}
#endif
else
{
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
sDataset.mComponents.mIsPskcPresent = true;
-8
View File
@@ -181,12 +181,4 @@ otCommissionerState otCommissionerGetState(otInstance *aInstance)
return instance.Get<MeshCoP::Commissioner>().GetState();
}
otError otCommissionerGeneratePskc(const char * aPassPhrase,
const char * aNetworkName,
const otExtendedPanId *aExtPanId,
otPskc * aPskc)
{
return MeshCoP::Commissioner::GeneratePskc(
aPassPhrase, aNetworkName, *static_cast<const Mac::ExtendedPanId *>(aExtPanId), *static_cast<Pskc *>(aPskc));
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+12
View File
@@ -38,6 +38,7 @@
#include "common/instance.hpp"
#include "common/locator-getters.hpp"
#include "meshcop/dataset_manager.hpp"
#include "meshcop/meshcop.hpp"
using namespace ot;
@@ -133,3 +134,14 @@ otError otDatasetSendMgmtPendingSet(otInstance * aInstance,
return instance.Get<MeshCoP::PendingDataset>().SendSetRequest(*aDataset, aTlvs, aLength);
}
#if OPENTHREAD_FTD
otError otDatasetGeneratePskc(const char * aPassPhrase,
const otNetworkName * aNetworkName,
const otExtendedPanId *aExtPanId,
otPskc * aPskc)
{
return MeshCoP::GeneratePskc(aPassPhrase, *static_cast<const Mac::NetworkName *>(aNetworkName),
*static_cast<const Mac::ExtendedPanId *>(aExtPanId), *static_cast<Pskc *>(aPskc));
}
#endif // OPENTHREAD_FTD
+2 -2
View File
@@ -39,7 +39,7 @@
#include <mbedtls/cmac.h>
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
#if OPENTHREAD_FTD
void otPbkdf2Cmac(const uint8_t *aPassword,
uint16_t aPasswordLen,
@@ -106,4 +106,4 @@ void otPbkdf2Cmac(const uint8_t *aPassword,
}
}
#endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
#endif // OPENTHREAD_FTD
-37
View File
@@ -1081,43 +1081,6 @@ exit:
return error;
}
otError Commissioner::GeneratePskc(const char * aPassPhrase,
const char * aNetworkName,
const Mac::ExtendedPanId &aExtPanId,
Pskc & aPskc)
{
otError error = OT_ERROR_NONE;
const char saltPrefix[] = "Thread";
uint8_t salt[OT_PBKDF2_SALT_MAX_LEN];
uint16_t saltLen = 0;
uint16_t passphraseLen;
uint8_t networkNameLen;
passphraseLen = static_cast<uint16_t>(StringLength(aPassPhrase, OT_COMMISSIONING_PASSPHRASE_MAX_SIZE + 1));
networkNameLen = static_cast<uint8_t>(StringLength(aNetworkName, OT_NETWORK_NAME_MAX_SIZE + 1));
VerifyOrExit((passphraseLen >= OT_COMMISSIONING_PASSPHRASE_MIN_SIZE) &&
(passphraseLen <= OT_COMMISSIONING_PASSPHRASE_MAX_SIZE) &&
(networkNameLen <= OT_NETWORK_NAME_MAX_SIZE),
error = OT_ERROR_INVALID_ARGS);
memset(salt, 0, sizeof(salt));
memcpy(salt, saltPrefix, sizeof(saltPrefix) - 1);
saltLen += static_cast<uint16_t>(sizeof(saltPrefix) - 1);
memcpy(salt + saltLen, aExtPanId.m8, sizeof(aExtPanId));
saltLen += OT_EXT_PAN_ID_SIZE;
memcpy(salt + saltLen, aNetworkName, networkNameLen);
saltLen += networkNameLen;
otPbkdf2Cmac(reinterpret_cast<const uint8_t *>(aPassPhrase), passphraseLen, reinterpret_cast<const uint8_t *>(salt),
saltLen, 16384, OT_PSKC_MAX_SIZE, aPskc.m8);
exit:
return error;
}
// LCOV_EXCL_START
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MLE == 1)
-19
View File
@@ -213,25 +213,6 @@ public:
const uint8_t * aTlvs,
uint8_t aLength);
/**
* This static method generates PSKc.
*
* PSKc is used to establish the Commissioner Session.
*
* @param[in] aPassPhrase The commissioning passphrase.
* @param[in] aNetworkName The network name for PSKc computation.
* @param[in] aExtPanId The extended pan id for PSKc computation.
* @param[out] aPskc A reference to a PSKc where the generated PSKc will be placed.
*
* @retval OT_ERROR_NONE Successfully generate PSKc.
* @retval OT_ERROR_INVALID_ARGS If the length of passphrase is out of range.
*
*/
static otError GeneratePskc(const char * aPassPhrase,
const char * aNetworkName,
const Mac::ExtendedPanId &aExtPanId,
Pskc & aPskc);
/**
* This method returns a reference to the AnnounceBeginClient instance.
*
+40
View File
@@ -32,6 +32,7 @@
*/
#include "common/locator-getters.hpp"
#include "crypto/pbkdf2_cmac.h"
#include "crypto/sha256.hpp"
#include "mac/mac_types.hpp"
#include "thread/thread_netif.hpp"
@@ -67,5 +68,44 @@ exit:
return error;
}
#if OPENTHREAD_FTD
otError GeneratePskc(const char * aPassPhrase,
const Mac::NetworkName & aNetworkName,
const Mac::ExtendedPanId &aExtPanId,
Pskc & aPskc)
{
otError error = OT_ERROR_NONE;
const char saltPrefix[] = "Thread";
uint8_t salt[OT_PBKDF2_SALT_MAX_LEN];
uint16_t saltLen = 0;
uint16_t passphraseLen;
uint8_t networkNameLen;
passphraseLen = static_cast<uint16_t>(StringLength(aPassPhrase, OT_COMMISSIONING_PASSPHRASE_MAX_SIZE + 1));
networkNameLen = static_cast<uint8_t>(StringLength(aNetworkName.GetAsCString(), OT_NETWORK_NAME_MAX_SIZE + 1));
VerifyOrExit((passphraseLen >= OT_COMMISSIONING_PASSPHRASE_MIN_SIZE) &&
(passphraseLen <= OT_COMMISSIONING_PASSPHRASE_MAX_SIZE) &&
(networkNameLen <= OT_NETWORK_NAME_MAX_SIZE),
error = OT_ERROR_INVALID_ARGS);
memset(salt, 0, sizeof(salt));
memcpy(salt, saltPrefix, sizeof(saltPrefix) - 1);
saltLen += static_cast<uint16_t>(sizeof(saltPrefix) - 1);
memcpy(salt + saltLen, aExtPanId.m8, sizeof(aExtPanId));
saltLen += OT_EXT_PAN_ID_SIZE;
memcpy(salt + saltLen, aNetworkName.GetAsCString(), networkNameLen);
saltLen += networkNameLen;
otPbkdf2Cmac(reinterpret_cast<const uint8_t *>(aPassPhrase), passphraseLen, reinterpret_cast<const uint8_t *>(salt),
saltLen, 16384, OT_PSKC_MAX_SIZE, aPskc.m8);
exit:
return error;
}
#endif // OPENTHREAD_FTD
} // namespace MeshCoP
} // namespace ot
+23
View File
@@ -42,8 +42,12 @@
#include "coap/coap.hpp"
#include "common/message.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/meshcop_tlvs.hpp"
namespace ot {
class ThreadNetif;
namespace MeshCoP {
enum
@@ -62,6 +66,25 @@ inline Coap::Message *NewMeshCoPMessage(Coap::CoapBase &aCoap)
return aCoap.NewMessage(&settings);
}
/**
* This function generates PSKc.
*
* PSKc is used to establish the Commissioner Session.
*
* @param[in] aPassPhrase The commissioning passphrase.
* @param[in] aNetworkName The network name for PSKc computation.
* @param[in] aExtPanId The extended PAN ID for PSKc computation.
* @param[out] aPskc A reference to a PSKc where the generated PSKc will be placed.
*
* @retval OT_ERROR_NONE Successfully generate PSKc.
* @retval OT_ERROR_INVALID_ARGS If the length of passphrase is out of range.
*
*/
otError GeneratePskc(const char * aPassPhrase,
const Mac::NetworkName & aNetworkName,
const Mac::ExtendedPanId &aExtPanId,
Pskc & aPskc);
/**
* This function computes the Joiner ID from a factory-assigned IEEE EUI-64.
*
+2 -2
View File
@@ -773,8 +773,8 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSK
SuccessOrExit(error = mDecoder.ReadDataWithLen(extPanIdData, length));
VerifyOrExit(length == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);
SuccessOrExit(error = otCommissionerGeneratePskc(passPhrase, networkName,
reinterpret_cast<const otExtendedPanId *>(extPanIdData), &pskc));
SuccessOrExit(error = otDatasetGeneratePskc(passPhrase, reinterpret_cast<const otNetworkName *>(networkName),
reinterpret_cast<const otExtendedPanId *>(extPanIdData), &pskc));
SuccessOrExit(
error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC));
+35 -17
View File
@@ -29,23 +29,23 @@
#include "common/logging.hpp"
#include "meshcop/commissioner.hpp"
#include "meshcop/meshcop.hpp"
#include "test_platform.h"
#include "test_util.h"
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
static const otExtendedPanId sXPanId = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
#if OPENTHREAD_FTD
void TestMinimumPassphrase(void)
{
ot::Pskc pskc;
const uint8_t expectedPskc[] = {0x44, 0x98, 0x8e, 0x22, 0xcf, 0x65, 0x2e, 0xee,
ot::Pskc pskc;
const uint8_t expectedPskc[] = {0x44, 0x98, 0x8e, 0x22, 0xcf, 0x65, 0x2e, 0xee,
0xcc, 0xd1, 0xe4, 0xc0, 0x1d, 0x01, 0x54, 0xf8};
const char passphrase[] = "123456";
otInstance * instance = testInitInstance();
SuccessOrQuit(ot::MeshCoP::Commissioner::GeneratePskc(passphrase, "OpenThread",
static_cast<const ot::Mac::ExtendedPanId &>(sXPanId), pskc),
const otExtendedPanId xpanid = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
const char passphrase[] = "123456";
otInstance * instance = testInitInstance();
SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("OpenThread"),
static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc),
"TestMinimumPassphrase failed to generate PSKc");
VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0, "TestMinimumPassphrase got wrong pskc");
testFreeInstance(instance);
@@ -53,10 +53,11 @@ void TestMinimumPassphrase(void)
void TestMaximumPassphrase(void)
{
ot::Pskc pskc;
const uint8_t expectedPskc[] = {0x9e, 0x81, 0xbd, 0x35, 0xa2, 0x53, 0x76, 0x2f,
ot::Pskc pskc;
const uint8_t expectedPskc[] = {0x9e, 0x81, 0xbd, 0x35, 0xa2, 0x53, 0x76, 0x2f,
0x80, 0xee, 0x04, 0xff, 0x2f, 0xa2, 0x85, 0xe9};
const char passphrase[] = "1234567812345678"
const otExtendedPanId xpanid = {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}};
const char passphrase[] = "1234567812345678"
"1234567812345678"
"1234567812345678"
"1234567812345678"
@@ -74,27 +75,44 @@ void TestMaximumPassphrase(void)
"123456781234567";
otInstance *instance = testInitInstance();
SuccessOrQuit(ot::MeshCoP::Commissioner::GeneratePskc(passphrase, "OpenThread",
static_cast<const ot::Mac::ExtendedPanId &>(sXPanId), pskc),
SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("OpenThread"),
static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc),
"TestMaximumPassphrase failed to generate PSKc");
VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0, "TestMaximumPassphrase got wrong pskc");
testFreeInstance(instance);
}
void TestExampleInSpec(void)
{
ot::Pskc pskc;
const uint8_t expectedPskc[] = {0xc3, 0xf5, 0x93, 0x68, 0x44, 0x5a, 0x1b, 0x61,
0x06, 0xbe, 0x42, 0x0a, 0x70, 0x6d, 0x4c, 0xc9};
const otExtendedPanId xpanid = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}};
const char passphrase[] = "12SECRETPASSWORD34";
otInstance *instance = testInitInstance();
SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast<const ot::Mac::NetworkName *>("Test Network"),
static_cast<const ot::Mac::ExtendedPanId &>(xpanid), pskc),
"ExampleInSpec failed to generate PSKc");
VerifyOrQuit(memcmp(pskc.m8, expectedPskc, sizeof(pskc)) == 0, "TestExampleInSpec got wrong pskc");
testFreeInstance(instance);
}
int main(void)
{
TestMinimumPassphrase();
TestMaximumPassphrase();
TestExampleInSpec();
printf("All tests passed\n");
return 0;
}
#else // #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
#else // #if OPENTHREAD_FTD
int main(void)
{
printf("Commissioenr role disabled\n");
printf("PSKc generation is not supported on non-ftd build\n");
return 0;
}
#endif // #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
#endif // #if OPENTHREAD_FTD