From 03aba30cd5b3c6ac6158163aaae8b8f31525b604 Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Fri, 3 Apr 2020 22:17:02 +0800 Subject: [PATCH] [meshcop] generate PSKc from passphrase (#4766) --- include/openthread/commissioner.h | 19 ----------- include/openthread/dataset.h | 19 +++++++++++ src/cli/README.md | 16 ++++++++++ src/cli/README_DATASET.md | 10 ++++-- src/cli/cli.cpp | 16 +++++++++- src/cli/cli_dataset.cpp | 32 ++++++++++++++----- src/core/api/commissioner_api.cpp | 8 ----- src/core/api/dataset_api.cpp | 12 +++++++ src/core/crypto/pbkdf2_cmac.cpp | 4 +-- src/core/meshcop/commissioner.cpp | 37 ---------------------- src/core/meshcop/commissioner.hpp | 19 ----------- src/core/meshcop/meshcop.cpp | 40 ++++++++++++++++++++++++ src/core/meshcop/meshcop.hpp | 23 ++++++++++++++ src/ncp/ncp_base_ftd.cpp | 4 +-- tests/unit/test_pskc.cpp | 52 +++++++++++++++++++++---------- 15 files changed, 197 insertions(+), 114 deletions(-) diff --git a/include/openthread/commissioner.h b/include/openthread/commissioner.h index 169ac1ec4..85743620f 100644 --- a/include/openthread/commissioner.h +++ b/include/openthread/commissioner.h @@ -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); - /** * @} * diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 35a4f15af..9e8568db1 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -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); + /** * @} * diff --git a/src/cli/README.md b/src/cli/README.md index 5dccb8482..82ad5d3ee 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -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] \|\ + +With `-p` generate pskc from \ (UTF-8 encoded) together with **current** network name and extended PAN ID, otherwise set pskc as \ (hex format). + +```bash +> pskc 67c0c203aa0b042bfb5381c47aef4d9e +Done +> pskc -p 123456 +Done +``` + ### preferrouterid \ Prefer a Router ID when solicit router id from Leader. diff --git a/src/cli/README_DATASET.md b/src/cli/README_DATASET.md index 518a5de67..7a02510dd 100644 --- a/src/cli/README_DATASET.md +++ b/src/cli/README_DATASET.md @@ -256,6 +256,8 @@ Usage: `dataset 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 ` 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 ` +Usage: `pskc [-p] |` -Set pskc with hex format. +With `-p`(**only for FTD**) generate pskc from \ (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 \ (hex format). ```bash > dataset pskc 67c0c203aa0b042bfb5381c47aef4d9e Done +> dataset pskc -p 123456 +Done ``` ### securitypolicy diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 1efd910f3..e2e1bfdb6 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -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(otThreadGetNetworkName(mInstance)), + otThreadGetExtendedPanId(mInstance), &pskc)); + } + else + { + ExitNow(error = OT_ERROR_INVALID_ARGS); + } + SuccessOrExit(error = otThreadSetPskc(mInstance, &pskc)); } diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 35614280c..9d7187b8e 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -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((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(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; diff --git a/src/core/api/commissioner_api.cpp b/src/core/api/commissioner_api.cpp index 57aaa2f2b..7cbdde9c9 100644 --- a/src/core/api/commissioner_api.cpp +++ b/src/core/api/commissioner_api.cpp @@ -181,12 +181,4 @@ otCommissionerState otCommissionerGetState(otInstance *aInstance) return instance.Get().GetState(); } -otError otCommissionerGeneratePskc(const char * aPassPhrase, - const char * aNetworkName, - const otExtendedPanId *aExtPanId, - otPskc * aPskc) -{ - return MeshCoP::Commissioner::GeneratePskc( - aPassPhrase, aNetworkName, *static_cast(aExtPanId), *static_cast(aPskc)); -} #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE diff --git a/src/core/api/dataset_api.cpp b/src/core/api/dataset_api.cpp index 0452b4992..b0e133aba 100644 --- a/src/core/api/dataset_api.cpp +++ b/src/core/api/dataset_api.cpp @@ -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().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(aNetworkName), + *static_cast(aExtPanId), *static_cast(aPskc)); +} +#endif // OPENTHREAD_FTD diff --git a/src/core/crypto/pbkdf2_cmac.cpp b/src/core/crypto/pbkdf2_cmac.cpp index f70112e39..e46dc14e1 100644 --- a/src/core/crypto/pbkdf2_cmac.cpp +++ b/src/core/crypto/pbkdf2_cmac.cpp @@ -39,7 +39,7 @@ #include -#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 diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 97b89e7b8..8e5b4e7f5 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -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(StringLength(aPassPhrase, OT_COMMISSIONING_PASSPHRASE_MAX_SIZE + 1)); - networkNameLen = static_cast(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(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(aPassPhrase), passphraseLen, reinterpret_cast(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) diff --git a/src/core/meshcop/commissioner.hpp b/src/core/meshcop/commissioner.hpp index de7026d8a..67b10075c 100644 --- a/src/core/meshcop/commissioner.hpp +++ b/src/core/meshcop/commissioner.hpp @@ -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. * diff --git a/src/core/meshcop/meshcop.cpp b/src/core/meshcop/meshcop.cpp index f7c5f23f0..f0277b728 100644 --- a/src/core/meshcop/meshcop.cpp +++ b/src/core/meshcop/meshcop.cpp @@ -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(StringLength(aPassPhrase, OT_COMMISSIONING_PASSPHRASE_MAX_SIZE + 1)); + networkNameLen = static_cast(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(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(aPassPhrase), passphraseLen, reinterpret_cast(salt), + saltLen, 16384, OT_PSKC_MAX_SIZE, aPskc.m8); + +exit: + return error; +} +#endif // OPENTHREAD_FTD + } // namespace MeshCoP } // namespace ot diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp index d39b79d26..1515d55a4 100644 --- a/src/core/meshcop/meshcop.hpp +++ b/src/core/meshcop/meshcop.hpp @@ -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. * diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index 89db40c3e..e4c845943 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -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(extPanIdData), &pskc)); + SuccessOrExit(error = otDatasetGeneratePskc(passPhrase, reinterpret_cast(networkName), + reinterpret_cast(extPanIdData), &pskc)); SuccessOrExit( error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC)); diff --git a/tests/unit/test_pskc.cpp b/tests/unit/test_pskc.cpp index e80d0cdb3..da708ab88 100644 --- a/tests/unit/test_pskc.cpp +++ b/tests/unit/test_pskc.cpp @@ -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(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("OpenThread"), + static_cast(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(sXPanId), pskc), + SuccessOrQuit(ot::MeshCoP::GeneratePskc(passphrase, *reinterpret_cast("OpenThread"), + static_cast(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("Test Network"), + static_cast(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