Routines to initiate key establishment, handle key establishment callbacks, and print info about the security keys on the device.
License#
Copyright 2018 Silicon Laboratories Inc. www.silabs.com
The licensor of this software is Silicon Laboratories Inc. Your use of this software is governed by the terms of Silicon Labs Master Software License Agreement (MSLA) available at www.silabs.com/about-us/legal/master-software-license-agreement. This software is distributed to you in Source Code format and is governed by the sections of the MSLA applicable to Source Code.
/***************************************************************************/
#include "app/framework/util/common.h"
#include "app/framework/util/service-discovery.h"
#include "app/util/serial/command-interpreter2.h"
#include "app/framework/cli/security-cli.h"
#include "app/framework/util/af-main.h"
#include "app/framework/security/af-security.h"
#ifdef EZSP_HOST
#define setTcRejoinsUsingWellKnownKeyAllowed(allow) \
(void)ezspSetPolicy(EZSP_TC_REJOINS_USING_WELL_KNOWN_KEY_POLICY, (allow))
#define setTcRejoinsUsingWellKnownKeyTimeout(timeout) \
(void)ezspSetConfigurationValue(EZSP_CONFIG_TC_REJOINS_USING_WELL_KNOWN_KEY_TIMEOUT_S, (timeout))
#define getTransientKeyTableEntry ezspGetTransientKeyTableEntry
#else // SoC
extern uint16_t emAllowTcRejoinsUsingWellKnownKeyTimeoutSec;
#define setTcRejoinsUsingWellKnownKeyAllowed(allow) \
emberSetTcRejoinsUsingWellKnownKeyAllowed((allow))
#define setTcRejoinsUsingWellKnownKeyTimeout(timeout) \
emAllowTcRejoinsUsingWellKnownKeyTimeoutSec = (timeout)
#define getTransientKeyTableEntry emberGetTransientKeyTableEntry
#endif
//------------------------------------------------------------------------------
// Globals
EmberKeyData cliPreconfiguredLinkKey = DUMMY_KEY;
EmberKeyData cliNetworkKey = DUMMY_KEY;
#define EMBER_AF_DOXYGEN_CLI__SECURITY_CHANGEKEY_COMMANDS
#define EMBER_AF_DOXYGEN_CLI__SECURITY_CBKE_COMMANDS
#ifndef EMBER_AF_GENERATE_CLI
EmberCommandEntry changeKeyCommands[] = {
{ "link", changeKeyCommand, "b" },
{ "network", changeKeyCommand, "b" },
{ NULL }
};
#endif // EMBER_AF_GENERATE_CLI
#define EMBER_AF_DOXYGEN_CLI__SECURITY_MFG_TOKEN_COMMANDS
#ifndef EMBER_AF_HAS_SECURITY_PROFILE_NONE
void getSetMfgToken(void);
EmberCommandEntry mfgToken[] = {
emberCommandEntryAction("get", getSetMfgToken, "",
"Print the MFG security config token"),
emberCommandEntryAction("set", getSetMfgToken, "wv",
"Set the MFG Security config token. CANNOT BE UNSET BY CLI."),
emberCommandEntryTerminator(),
};
EmberCommandEntry emAfSecurityCommands[] = {
emberCommandEntrySubMenu("mfg-token", mfgToken,
"Get/set the MFG Security config token"),
emberCommandEntryTerminator(),
};
#endif
//------------------------------------------------------------------------------
// Forward Declarations
uint8_t printKeyTable(bool preconfiguredKey);
uint8_t printTransientKeyTable(void);
uint32_t getOutgoingApsFrameCounter(void);
//------------------------------------------------------------------------------
// ******************************************************
// changekey link <16 byte key>
// changekey network <16 byte key>
// ******************************************************
// Changes the default link or network key that will be used when
// forming or joining a network.
void changeKeyCommand(void)
{
if (EMBER_NO_NETWORK != emberNetworkState()) {
emberAfCorePrintln("%pstack must be down.", "ERROR: ");
} else {
emberCopyKeyArgument(0,
emberCurrentCommand->name[0] == 'l'
? &cliPreconfiguredLinkKey
: &cliNetworkKey);
emberAfDebugPrintln("set key");
}
}
// Key Establishment commands (cbke <command>) moved to
// app/framework/plugin/key-establishment/key-establishment-cli.c
void printKeyInfo(void)
{
uint8_t entriesUsed;
EmberKeyStruct nwkKey;
#ifndef EMBER_AF_HAS_SECURITY_PROFILE_NONE
{
EmberMfgSecurityStruct config;
if (EMBER_SUCCESS == emberGetMfgSecurityConfig(&config)) {
if (!(config.keySettings & EMBER_KEY_PERMISSIONS_READING_ALLOWED)) {
emberAfCorePrintln("\nWARNING: READING OF KEY VALUES DISABLED BY MFG TOKEN\n");
emberAfCoreFlush();
}
}
}
#endif
if ( EMBER_SUCCESS != emberGetKey(EMBER_CURRENT_NETWORK_KEY,
&nwkKey)) {
MEMSET((uint8_t*)&nwkKey, 0xFF, sizeof(EmberKeyStruct));
}
emberAfCorePrintln("%p out FC: %4x",
"NWK Key",
nwkKey.outgoingFrameCounter);
emberAfCorePrintln("%p seq num: 0x%x",
"NWK Key",
nwkKey.sequenceNumber);
emberAfCorePrint("%p: ",
"NWK Key");
emberAfPrintZigbeeKey(emberKeyContents(&nwkKey.key));
emberAfCorePrintln("%p out FC: %4x",
"Link Key",
getOutgoingApsFrameCounter());
emberAfCorePrintln("TC %p", "Link Key");
emberAfCoreFlush();
printKeyTable(true);
emberAfCorePrintln("%p Table", "Link Key");
emberAfCoreFlush();
entriesUsed = printKeyTable(false);
UNUSED_VAR(entriesUsed);
emberAfCorePrintln("%d/%d entries used.",
entriesUsed,
emberAfGetKeyTableSize());
emberAfCoreFlush();
emberAfCorePrintln("%p Table", "Transient Key");
emberAfCoreFlush();
entriesUsed = printTransientKeyTable();
UNUSED_VAR(entriesUsed);
emberAfCorePrintln("%d entr%s consuming %d packet buffer%s.",
entriesUsed,
entriesUsed > 1 ? "ies" : "y",
entriesUsed,
entriesUsed > 1 ? "s" : "");
emberAfCoreFlush();
}
uint8_t printKeyTable(bool preconfiguredKey)
{
uint8_t i;
uint8_t entriesUsed = 0;
uint8_t loopCount = (preconfiguredKey ? 1 : emberAfGetKeyTableSize());
emberAfCorePrintln("Index IEEE Address In FC Type Auth Key");
for (i = 0; i < loopCount; i++) {
EmberKeyStruct entry;
if (preconfiguredKey) {
i = 0xFE; // last
// Try to get whatever key type is stored in the pre-configured key slot.
if (EMBER_SUCCESS
!= emberGetKey(EMBER_TRUST_CENTER_LINK_KEY, &entry) ) {
continue;
}
} else if ( EMBER_SUCCESS != emberGetKeyTableEntry(i, &entry) ) {
continue;
} else {
// MISRA requires ..else if.. to have a terminating else.
}
if (!preconfiguredKey) {
emberAfCorePrint("%d ", i);
} else {
emberAfCorePrint("- ");
}
emberAfCoreDebugExec(emberAfPrintBigEndianEui64(entry.partnerEUI64));
emberAfCorePrint(" %4x ", entry.incomingFrameCounter);
emberAfCorePrint("L %c ",
(entry.bitmask & EMBER_KEY_IS_AUTHORIZED
? 'y'
: 'n'));
emberAfPrintZigbeeKey(emberKeyContents(&(entry.key)));
emberAfCoreFlush();
entriesUsed++;
}
return entriesUsed;
}
uint8_t printTransientKeyTable(void)
{
EmberStatus status;
EmberTransientKeyData transientKeyData;
uint8_t index = 0;
emberAfCorePrintln("Index IEEE Address NWKIndex In FC TTL(s) Flag Key ");
status = getTransientKeyTableEntry(index, &transientKeyData);
while (status == EMBER_SUCCESS) {
emberAfCorePrint("%d ", index);
emberAfCoreDebugExec(emberAfPrintBigEndianEui64(transientKeyData.eui64));
emberAfCorePrint(" %d ", transientKeyData.networkIndex);
emberAfCorePrint(" %4x ", transientKeyData.incomingFrameCounter);
emberAfCorePrint("0x%02X", transientKeyData.remainingTimeSeconds);
emberAfCorePrint(" 0x%02X ", transientKeyData.bitmask);
emberAfPrintZigbeeKey(emberKeyContents(&(transientKeyData.keyData)));
emberAfCorePrintln("");
emberAfCoreFlush();
index += 1;
status = getTransientKeyTableEntry(index, &transientKeyData);
}
return index;
}
uint32_t getOutgoingApsFrameCounter(void)
{
EmberKeyStruct entry;
if (emberGetKey(EMBER_TRUST_CENTER_LINK_KEY, &entry) != EMBER_SUCCESS) {
return 0xFFFFFFFFUL;
}
return entry.outgoingFrameCounter;
}
#ifndef EMBER_AF_HAS_SECURITY_PROFILE_NONE
void getSetMfgToken(void)
{
EmberMfgSecurityStruct config;
EmberStatus status;
if (emberCurrentCommand->name[0] == 'g') {
status = emberGetMfgSecurityConfig(&config);
if (status == EMBER_SUCCESS) {
emberAfSecurityPrintln("EmberKeySettings: 0x%2X", config.keySettings);
emberAfSecurityPrintln(" Permissions: %p",
((config.keySettings & EMBER_KEY_PERMISSIONS_READING_ALLOWED)
? "Reading Allowed"
: ((config.keySettings & EMBER_KEY_PERMISSIONS_HASHING_ALLOWED)
? "Hashing only"
: "NONE")));
} else {
emberAfSecurityPrintln("Error: Failed to get config, status: 0x%X", status);
}
} else {
uint32_t magicNumber = emberUnsignedCommandArgument(0);
config.keySettings = (EmberKeySettings)emberUnsignedCommandArgument(1);
status = emberSetMfgSecurityConfig(magicNumber, &config);
}
if (status != EMBER_SUCCESS) {
emberAfSecurityPrintln("Failed: 0x%X", status);
}
}
#endif
void optionSecurityAllowTrustCenterRejoinUsingWellKnownKey(void)
{
bool allow = (bool)emberUnsignedCommandArgument(0);
setTcRejoinsUsingWellKnownKeyAllowed(allow);
emberAfCorePrintln("Trust Center %p allow trust center rejoins using "
"well-known key.",
allow
? "WILL"
: "WILL NOT");
}
void optionSecurityAllowTrustCenterRejoinUsingWellKnownKeyTimeout(void)
{
uint16_t timeout = (uint16_t)emberUnsignedCommandArgument(0);
setTcRejoinsUsingWellKnownKeyTimeout(timeout);
emberAfCorePrintln("Set timeout for Trust Center rejoins using well-known "
"link key to %d seconds.",
timeout);
}
void optionSecuritySetKeyRequestPolicy(void)
{
#ifdef EZSP_HOST
uint8_t tcPolicy = (uint8_t)emberUnsignedCommandArgument(0);
uint8_t appPolicy = (uint8_t)emberUnsignedCommandArgument(1);
// The EZSP policies are offset by EZSP_DENY_TC_KEY_REQUESTS and
// EZSP_DENY_APP_KEY_REQUESTS, respectively
tcPolicy += EZSP_DENY_TC_KEY_REQUESTS;
appPolicy += EZSP_DENY_APP_KEY_REQUESTS;
(void)ezspSetPolicy(EZSP_TC_KEY_REQUEST_POLICY, tcPolicy);
(void)ezspSetPolicy(EZSP_APP_KEY_REQUEST_POLICY, tcPolicy);
#else // EZSP_HOST
emberTrustCenterLinkKeyRequestPolicy = (uint8_t)emberUnsignedCommandArgument(0);
emberAppLinkKeyRequestPolicy = (uint8_t)emberUnsignedCommandArgument(1);
#endif // EZSP_HOST
}
Macros#
Commands used to change the default link or network key that will be used when forming or joining a network.
Command used for key establishment.
Commands used for security.
Functions#
Macro Definition Documentation#
setTcRejoinsUsingWellKnownKeyAllowed#
#define setTcRejoinsUsingWellKnownKeyAllowedValue:
(allow)
37
of file ./app/framework/cli/security-cli.c
setTcRejoinsUsingWellKnownKeyTimeout#
#define setTcRejoinsUsingWellKnownKeyTimeoutValue:
(timeout)
39
of file ./app/framework/cli/security-cli.c
getTransientKeyTableEntry#
#define getTransientKeyTableEntryValue:
emberGetTransientKeyTableEntry
41
of file ./app/framework/cli/security-cli.c
EMBER_AF_DOXYGEN_CLI__SECURITY_CHANGEKEY_COMMANDS#
#define EMBER_AF_DOXYGEN_CLI__SECURITY_CHANGEKEY_COMMANDS
Commands used to change the default link or network key that will be used when forming or joining a network.
changekey link <key>
key - 16 byte array. The Link Key provided as a 16 byte array.
changekey network <key>
key - 16 byte array. The Network Key provided as a 16 byte array.
67
of file ./app/framework/cli/security-cli.c
EMBER_AF_DOXYGEN_CLI__SECURITY_CBKE_COMMANDS#
#define EMBER_AF_DOXYGEN_CLI__SECURITY_CBKE_COMMANDS
Command used for key establishment.
<b>cbke start <new partner id> <destination endpoint></b>
- new partner ID - uint16_t. The 2 byte node ID of the partner
with whom to start cbke.
<b>cbke interpan <pan id> <eui64></b>
- PAN ID - uint16_t. The 2 byte PAN ID that the target is located on.
- eui64 - EmberEUI64. The 8 byte EUI64 of the target (big endian)
<b>cbke partner <node id> <endpoint></b>
- node ID - uint16_t. The two byte node ID of the device
with whom to initiate key establishment.
- endpoint - uint8_t. The endpoint on which to begin
key establishment.
92
of file ./app/framework/cli/security-cli.c
EMBER_AF_DOXYGEN_CLI__SECURITY_MFG_TOKEN_COMMANDS#
#define EMBER_AF_DOXYGEN_CLI__SECURITY_MFG_TOKEN_COMMANDS
Commands used for security.
security mfg-token getsecurity mfg-token set <Magic number> <EmberKeySettings value>
Magic number - uint32_t. The 4-byte magic number EMBER_MFG_SECURITY_CONFIG_MAGIC_NUMBER to prevent accidental execution.
EmberKeySettings value - uint16_t. The 2-byte value for EmberKeySettings indicating key permissions.
119
of file ./app/framework/cli/security-cli.c
Variable Documentation#
emAllowTcRejoinsUsingWellKnownKeyTimeoutSec#
uint16_t emAllowTcRejoinsUsingWellKnownKeyTimeoutSec
36
of file ./app/framework/cli/security-cli.c
cliPreconfiguredLinkKey#
EmberKeyData cliPreconfiguredLinkKey
47
of file ./app/framework/cli/security-cli.c
cliNetworkKey#
EmberKeyData cliNetworkKey
48
of file ./app/framework/cli/security-cli.c
changeKeyCommands#
EmberCommandEntry changeKeyCommands[]
97
of file ./app/framework/cli/security-cli.c
mfgToken#
EmberCommandEntry mfgToken[]
125
of file ./app/framework/cli/security-cli.c
emAfSecurityCommands#
EmberCommandEntry emAfSecurityCommands[]
133
of file ./app/framework/cli/security-cli.c
Function Documentation#
getSetMfgToken#
void getSetMfgToken (void )
N/A |
320
of file ./app/framework/cli/security-cli.c
printKeyTable#
uint8_t printKeyTable (bool preconfiguredKey)
N/A | preconfiguredKey |
236
of file ./app/framework/cli/security-cli.c
printTransientKeyTable#
uint8_t printTransientKeyTable (void )
N/A |
282
of file ./app/framework/cli/security-cli.c
getOutgoingApsFrameCounter#
uint32_t getOutgoingApsFrameCounter (void )
N/A |
310
of file ./app/framework/cli/security-cli.c
changeKeyCommand#
void changeKeyCommand (void )
N/A |
157
of file ./app/framework/cli/security-cli.c
printKeyInfo#
void printKeyInfo (void )
N/A |
173
of file ./app/framework/cli/security-cli.c
optionSecurityAllowTrustCenterRejoinUsingWellKnownKey#
void optionSecurityAllowTrustCenterRejoinUsingWellKnownKey (void )
N/A |
350
of file ./app/framework/cli/security-cli.c
optionSecurityAllowTrustCenterRejoinUsingWellKnownKeyTimeout#
void optionSecurityAllowTrustCenterRejoinUsingWellKnownKeyTimeout (void )
N/A |
361
of file ./app/framework/cli/security-cli.c
optionSecuritySetKeyRequestPolicy#
void optionSecuritySetKeyRequestPolicy (void )
N/A |
370
of file ./app/framework/cli/security-cli.c