4603 lines
121 KiB
C
4603 lines
121 KiB
C
|
/******************************************************************************
|
|||
|
Filename: ZDSecMgr.c
|
|||
|
Revised: $Date: 2012-02-16 13:22:48 -0800 (Thu, 16 Feb 2012) $
|
|||
|
Revision: $Revision: 29339 $
|
|||
|
|
|||
|
Description: The ZigBee Device Security Manager.
|
|||
|
|
|||
|
|
|||
|
Copyright 2005-2012 Texas Instruments Incorporated. All rights reserved.
|
|||
|
|
|||
|
IMPORTANT: Your use of this Software is limited to those specific rights
|
|||
|
granted under the terms of a software license agreement between the user
|
|||
|
who downloaded the software, his/her employer (which must be your employer)
|
|||
|
and Texas Instruments Incorporated (the "License"). You may not use this
|
|||
|
Software unless you agree to abide by the terms of the License. The License
|
|||
|
limits your use, and you acknowledge, that the Software may not be modified,
|
|||
|
copied or distributed unless embedded on a Texas Instruments microcontroller
|
|||
|
or used solely and exclusively in conjunction with a Texas Instruments radio
|
|||
|
frequency transceiver, which is integrated into your product. Other than for
|
|||
|
the foregoing purpose, you may not use, reproduce, copy, prepare derivative
|
|||
|
works of, modify, distribute, perform, display or sell this Software and/or
|
|||
|
its documentation for any purpose.
|
|||
|
|
|||
|
YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
|
|||
|
PROVIDED <EFBFBD>AS IS<EFBFBD> WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|||
|
INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
|
|||
|
NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
|
|||
|
TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
|
|||
|
NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
|
|||
|
LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
|
|||
|
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
|
|||
|
OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
|
|||
|
OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
|
|||
|
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
|
|||
|
|
|||
|
Should you have any questions regarding your right to use this Software,
|
|||
|
contact Texas Instruments Incorporated at www.TI.com.
|
|||
|
******************************************************************************/
|
|||
|
|
|||
|
#ifdef __cplusplus
|
|||
|
extern "C"
|
|||
|
{
|
|||
|
#endif
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* INCLUDES
|
|||
|
*/
|
|||
|
#include "ZComdef.h"
|
|||
|
#include "OSAL.h"
|
|||
|
#include "OSAL_NV.h"
|
|||
|
#include "ZGlobals.h"
|
|||
|
#include "ssp.h"
|
|||
|
#include "nwk_globals.h"
|
|||
|
#include "nwk.h"
|
|||
|
#include "NLMEDE.h"
|
|||
|
#include "AddrMgr.h"
|
|||
|
#include "AssocList.h"
|
|||
|
#include "APSMEDE.h"
|
|||
|
#include "ZDConfig.h"
|
|||
|
#include "ZDSecMgr.h"
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* CONSTANTS
|
|||
|
*/
|
|||
|
// maximum number of devices managed by this Security Manager
|
|||
|
#if !defined ( ZDSECMGR_DEVICE_MAX )
|
|||
|
#define ZDSECMGR_DEVICE_MAX 3
|
|||
|
#endif
|
|||
|
|
|||
|
// total number of preconfigured devices (EXT address, MASTER key)
|
|||
|
//devtag.pro.security
|
|||
|
//#define ZDSECMGR_PRECONFIG_MAX ZDSECMGR_DEVICE_MAX
|
|||
|
#define ZDSECMGR_PRECONFIG_MAX 0
|
|||
|
|
|||
|
// maximum number of MASTER keys this device may hold
|
|||
|
#define ZDSECMGR_MASTERKEY_MAX ZDSECMGR_DEVICE_MAX
|
|||
|
|
|||
|
// maximum number of LINK keys this device may store
|
|||
|
#define ZDSECMGR_ENTRY_MAX ZDSECMGR_DEVICE_MAX
|
|||
|
|
|||
|
// total number of devices under control - authentication, SKKE, etc.
|
|||
|
#define ZDSECMGR_CTRL_MAX ZDSECMGR_DEVICE_MAX
|
|||
|
|
|||
|
// total number of stored devices
|
|||
|
#if !defined ( ZDSECMGR_STORED_DEVICES )
|
|||
|
#define ZDSECMGR_STORED_DEVICES 3
|
|||
|
#endif
|
|||
|
|
|||
|
// Total number of preconfigured trust center link key
|
|||
|
#if !defined ( ZDSECMGR_TC_DEVICE_MAX )
|
|||
|
#define ZDSECMGR_TC_DEVICE_MAX 1
|
|||
|
#endif
|
|||
|
|
|||
|
#if ( ZDSECMGR_TC_DEVICE_MAX < 1 ) || ( ZDSECMGR_TC_DEVICE_MAX > 255 )
|
|||
|
#error "ZDSECMGR_TC_DEVICE_MAX shall be between 1 and 255 !"
|
|||
|
#endif
|
|||
|
|
|||
|
#define ZDSECMGR_CTRL_NONE 0
|
|||
|
#define ZDSECMGR_CTRL_INIT 1
|
|||
|
#define ZDSECMGR_CTRL_TK_MASTER 2
|
|||
|
#define ZDSECMGR_CTRL_SKKE_INIT 3
|
|||
|
#define ZDSECMGR_CTRL_SKKE_WAIT 4
|
|||
|
#define ZDSECMGR_CTRL_SKKE_DONE 5
|
|||
|
#define ZDSECMGR_CTRL_SKKE_FAIL 6
|
|||
|
#define ZDSECMGR_CTRL_TK_NWK 7
|
|||
|
|
|||
|
#define ZDSECMGR_CTRL_BASE_CNTR 1
|
|||
|
#define ZDSECMGR_CTRL_SKKE_INIT_CNTR 1
|
|||
|
#define ZDSECMGR_CTRL_TK_NWK_CNTR 1
|
|||
|
|
|||
|
// set SKA slot maximum
|
|||
|
#define ZDSECMGR_SKA_SLOT_MAX 1
|
|||
|
|
|||
|
// APSME Stub Implementations
|
|||
|
#define ZDSecMgrMasterKeyGet APSME_MasterKeyGet
|
|||
|
#define ZDSecMgrLinkKeySet APSME_LinkKeySet
|
|||
|
#define ZDSecMgrLinkKeyNVIdGet APSME_LinkKeyNVIdGet
|
|||
|
#define ZDSecMgrKeyFwdToChild APSME_KeyFwdToChild
|
|||
|
#define ZDSecMgrIsLinkKeyValid APSME_IsLinkKeyValid
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* TYPEDEFS
|
|||
|
*/
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
uint8 extAddr[Z_EXTADDR_LEN];
|
|||
|
uint8 key[SEC_KEY_LEN];
|
|||
|
} ZDSecMgrPreConfigData_t;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
uint8 key[SEC_KEY_LEN];
|
|||
|
} ZDSecMgrMasterKeyData_t;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
uint16 keyNvId; // index to the Link Key table in NV
|
|||
|
ZDSecMgr_Authentication_Option authenticateOption;
|
|||
|
} ZDSecMgrEntry_t;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
uint16 parentAddr;
|
|||
|
uint8 secure;
|
|||
|
uint8 state;
|
|||
|
uint8 cntr;
|
|||
|
} ZDSecMgrCtrl_t;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
uint16 nwkAddr;
|
|||
|
uint8* extAddr;
|
|||
|
uint16 parentAddr;
|
|||
|
uint8 secure;
|
|||
|
uint8 devStatus;
|
|||
|
ZDSecMgrCtrl_t* ctrl;
|
|||
|
} ZDSecMgrDevice_t;
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* LOCAL VARIABLES
|
|||
|
*/
|
|||
|
#if 0 // Taken out because the following functionality is only used for test
|
|||
|
// purpose. A more efficient (above) way is used. It can be put
|
|||
|
// back in if customers request for a white/black list feature.
|
|||
|
uint8 ZDSecMgrStoredDeviceList[ZDSECMGR_STORED_DEVICES][Z_EXTADDR_LEN] =
|
|||
|
{
|
|||
|
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
|
|||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|||
|
};
|
|||
|
#endif
|
|||
|
|
|||
|
uint8 ZDSecMgrTCExtAddr[Z_EXTADDR_LEN]=
|
|||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|||
|
|
|||
|
// Key data is put in CONST area for security reasons
|
|||
|
CONST uint8 ZDSecMgrTCMasterKey[SEC_KEY_LEN] =
|
|||
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|||
|
0x89,0x67,0x45,0x23,0x01,0xEF,0xCD,0xAB};
|
|||
|
|
|||
|
uint8 ZDSecMgrTCAuthenticated = FALSE;
|
|||
|
|
|||
|
//devtag.pro.security - remove this
|
|||
|
#if ( ZDSECMGR_PRECONFIG_MAX != 0 )
|
|||
|
const ZDSecMgrPreConfigData_t ZDSecMgrPreConfigData[ZDSECMGR_PRECONFIG_MAX] =
|
|||
|
{
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
// DEVICE A
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
{
|
|||
|
// extAddr
|
|||
|
{0x7C,0x01,0x12,0x13,0x14,0x15,0x16,0x17},
|
|||
|
|
|||
|
// key
|
|||
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
|
|||
|
},
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
// DEVICE B
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
{
|
|||
|
// extAddr
|
|||
|
{0x84,0x03,0x00,0x00,0x00,0x4B,0x12,0x00},
|
|||
|
|
|||
|
// key
|
|||
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
|
|||
|
},
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
// DEVICE C
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
{
|
|||
|
// extAddr
|
|||
|
{0x3E,0x01,0x12,0x13,0x14,0x15,0x16,0x17},
|
|||
|
|
|||
|
// key
|
|||
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}
|
|||
|
},
|
|||
|
};
|
|||
|
#endif // ( ZDSECMGR_PRECONFIG_MAX != 0 )
|
|||
|
|
|||
|
ZDSecMgrEntry_t* ZDSecMgrEntries = NULL;
|
|||
|
ZDSecMgrCtrl_t* ZDSecMgrCtrlData = NULL;
|
|||
|
void ZDSecMgrAddrMgrUpdate( uint16 ami, uint16 nwkAddr );
|
|||
|
void ZDSecMgrAddrMgrCB( uint8 update, AddrMgrEntry_t* newEntry, AddrMgrEntry_t* oldEntry );
|
|||
|
|
|||
|
uint8 ZDSecMgrPermitJoiningEnabled;
|
|||
|
uint8 ZDSecMgrPermitJoiningTimed;
|
|||
|
|
|||
|
APSME_TCLinkKey_t TrustCenterLinkKey;
|
|||
|
|
|||
|
APSME_ApsLinkKeyFrmCntr_t ApsLinkKeyFrmCntr[ZDSECMGR_ENTRY_MAX];
|
|||
|
APSME_TCLinkKeyFrmCntr_t TCLinkKeyFrmCntr[ZDSECMGR_TC_DEVICE_MAX];
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* PRIVATE FUNCTIONS
|
|||
|
*
|
|||
|
* ZDSecMgrMasterKeyInit
|
|||
|
* ZDSecMgrAddrStore
|
|||
|
* ZDSecMgrExtAddrStore
|
|||
|
* ZDSecMgrExtAddrLookup
|
|||
|
* ZDSecMgrMasterKeyLookup
|
|||
|
* ZDSecMgrMasterKeyStore
|
|||
|
* ZDSecMgrEntryInit
|
|||
|
* ZDSecMgrEntryLookup
|
|||
|
* ZDSecMgrEntryLookupAMI
|
|||
|
* ZDSecMgrEntryLookupExt
|
|||
|
* ZDSecMgrEntryLookupExtGetIndex
|
|||
|
* ZDSecMgrEntryFree
|
|||
|
* ZDSecMgrEntryNew
|
|||
|
* ZDSecMgrCtrlInit
|
|||
|
* ZDSecMgrCtrlRelease
|
|||
|
* ZDSecMgrCtrlLookup
|
|||
|
* ZDSecMgrCtrlSet
|
|||
|
* ZDSecMgrCtrlAdd
|
|||
|
* ZDSecMgrCtrlTerm
|
|||
|
* ZDSecMgrCtrlReset
|
|||
|
* ZDSecMgrMasterKeyLoad
|
|||
|
* ZDSecMgrAppKeyGet
|
|||
|
* ZDSecMgrAppKeyReq
|
|||
|
* ZDSecMgrEstablishKey
|
|||
|
* ZDSecMgrSendMasterKey
|
|||
|
* ZDSecMgrSendNwkKey
|
|||
|
* ZDSecMgrDeviceEntryRemove
|
|||
|
* ZDSecMgrDeviceEntryAdd
|
|||
|
* ZDSecMgrDeviceCtrlHandler
|
|||
|
* ZDSecMgrDeviceCtrlSetup
|
|||
|
* ZDSecMgrDeviceCtrlUpdate
|
|||
|
* ZDSecMgrDeviceRemove
|
|||
|
* ZDSecMgrDeviceValidateSKKE
|
|||
|
* ZDSecMgrDeviceValidateRM
|
|||
|
* ZDSecMgrDeviceValidateCM
|
|||
|
* ZDSecMgrDeviceValidate
|
|||
|
* ZDSecMgrDeviceJoin
|
|||
|
* ZDSecMgrDeviceJoinDirect
|
|||
|
* ZDSecMgrDeviceJoinFwd
|
|||
|
* ZDSecMgrDeviceNew
|
|||
|
* ZDSecMgrAssocDeviceAuth
|
|||
|
* ZDSecMgrAuthInitiate
|
|||
|
* ZDSecMgrAuthNwkKey
|
|||
|
* APSME_TCLinkKeyInit
|
|||
|
* APSME_IsDefaultTCLK
|
|||
|
*/
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// master key data
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrMasterKeyInit( void );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// address management
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
ZStatus_t ZDSecMgrAddrStore( uint16 nwkAddr, uint8* extAddr, uint16* ami );
|
|||
|
ZStatus_t ZDSecMgrExtAddrStore( uint16 nwkAddr, uint8* extAddr, uint16* ami );
|
|||
|
ZStatus_t ZDSecMgrExtAddrLookup( uint8* extAddr, uint16* ami );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Trust Center management
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
uint8 ZDSecMgrTCExtAddrCheck( uint8* extAddr );
|
|||
|
void ZDSecMgrTCDataLoad( uint8* extAddr );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// MASTER key data
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
ZStatus_t ZDSecMgrMasterKeyLookup( uint16 ami, uint16* pKeyNvId );
|
|||
|
ZStatus_t ZDSecMgrMasterKeyStore( uint16 ami, uint8* key );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// entry data
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrEntryInit(uint8 state);
|
|||
|
ZStatus_t ZDSecMgrEntryLookup( uint16 nwkAddr, ZDSecMgrEntry_t** entry );
|
|||
|
ZStatus_t ZDSecMgrEntryLookupAMI( uint16 ami, ZDSecMgrEntry_t** entry );
|
|||
|
ZStatus_t ZDSecMgrEntryLookupExt( uint8* extAddr, ZDSecMgrEntry_t** entry );
|
|||
|
ZStatus_t ZDSecMgrEntryLookupExtGetIndex( uint8* extAddr, ZDSecMgrEntry_t** entry, uint16* entryIndex );
|
|||
|
ZStatus_t ZDSecMgrEntryLookupAMIGetIndex( uint16 ami, uint16* entryIndex );
|
|||
|
void ZDSecMgrEntryFree( ZDSecMgrEntry_t* entry );
|
|||
|
ZStatus_t ZDSecMgrEntryNew( ZDSecMgrEntry_t** entry );
|
|||
|
ZStatus_t ZDSecMgrAuthenticationSet( uint8* extAddr, ZDSecMgr_Authentication_Option option );
|
|||
|
void ZDSecMgrApsLinkKeyInit(void);
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
static void ZDSecMgrWriteNV(void);
|
|||
|
static void ZDSecMgrRestoreFromNV(void);
|
|||
|
static void ZDSecMgrUpdateNV( uint16 index );
|
|||
|
#endif
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// control data
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrCtrlInit( void );
|
|||
|
void ZDSecMgrCtrlRelease( ZDSecMgrCtrl_t* ctrl );
|
|||
|
void ZDSecMgrCtrlLookup( ZDSecMgrEntry_t* entry, ZDSecMgrCtrl_t** ctrl );
|
|||
|
void ZDSecMgrCtrlSet( ZDSecMgrDevice_t* device,
|
|||
|
ZDSecMgrEntry_t* entry,
|
|||
|
ZDSecMgrCtrl_t* ctrl );
|
|||
|
ZStatus_t ZDSecMgrCtrlAdd( ZDSecMgrDevice_t* device, ZDSecMgrEntry_t* entry );
|
|||
|
void ZDSecMgrCtrlTerm( ZDSecMgrEntry_t* entry );
|
|||
|
ZStatus_t ZDSecMgrCtrlReset( ZDSecMgrDevice_t* device,
|
|||
|
ZDSecMgrEntry_t* entry );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// key support
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
ZStatus_t ZDSecMgrMasterKeyLoad( uint8* extAddr, uint8* key );
|
|||
|
ZStatus_t ZDSecMgrAppKeyGet( uint16 initNwkAddr,
|
|||
|
uint8* initExtAddr,
|
|||
|
uint16 partNwkAddr,
|
|||
|
uint8* partExtAddr,
|
|||
|
uint8** key,
|
|||
|
uint8* keyType );
|
|||
|
void ZDSecMgrAppKeyReq( ZDO_RequestKeyInd_t* ind );
|
|||
|
ZStatus_t ZDSecMgrEstablishKey( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrSendMasterKey( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrSendNwkKey( ZDSecMgrDevice_t* device );
|
|||
|
void ZDSecMgrNwkKeyInit(uint8 setDefault);
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// device entry
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrDeviceEntryRemove( ZDSecMgrEntry_t* entry );
|
|||
|
ZStatus_t ZDSecMgrDeviceEntryAdd( ZDSecMgrDevice_t* device, uint16 ami );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// device control
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrDeviceCtrlHandler( ZDSecMgrDevice_t* device );
|
|||
|
void ZDSecMgrDeviceCtrlSetup( ZDSecMgrDevice_t* device );
|
|||
|
void ZDSecMgrDeviceCtrlUpdate( uint8* extAddr, uint8 state );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// device management
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrDeviceRemove( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateSKKE( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateRM( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateCM( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceValidate( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceJoin( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceJoinDirect( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceJoinFwd( ZDSecMgrDevice_t* device );
|
|||
|
ZStatus_t ZDSecMgrDeviceNew( ZDSecMgrDevice_t* device );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// association management
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrAssocDeviceAuth( associated_devices_t* assoc );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// authentication management
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void ZDSecMgrAuthInitiate( uint8* responder );
|
|||
|
void ZDSecMgrAuthNwkKey( void );
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// APSME function
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
void APSME_TCLinkKeyInit( uint8 setDefault );
|
|||
|
uint8 APSME_IsDefaultTCLK( uint8 *extAddr );
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrMasterKeyInit ]
|
|||
|
*
|
|||
|
* @brief Initialize master key data in NV
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrMasterKeyInit( void )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
ZDSecMgrMasterKeyData_t masterKeyData;
|
|||
|
|
|||
|
masterKeyData.ami = INVALID_NODE_ADDR;
|
|||
|
|
|||
|
osal_memset( &masterKeyData.key, 0x00, SEC_KEY_LEN );
|
|||
|
|
|||
|
for ( index = 0; index < ZDSECMGR_MASTERKEY_MAX; index++ )
|
|||
|
{
|
|||
|
if ( osal_nv_item_init( (ZCD_NV_MASTER_KEY_DATA_START + index),
|
|||
|
sizeof(ZDSecMgrMasterKeyData_t), &masterKeyData) == SUCCESS)
|
|||
|
{
|
|||
|
// the item already exists in NV just needs to be set to default values
|
|||
|
osal_nv_write( (ZCD_NV_MASTER_KEY_DATA_START + index), 0,
|
|||
|
sizeof(ZDSecMgrMasterKeyData_t), &masterKeyData );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAddrStore
|
|||
|
*
|
|||
|
* @brief Store device addresses.
|
|||
|
*
|
|||
|
* @param nwkAddr - [in] NWK address
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param ami - [out] Address Manager index
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAddrStore( uint16 nwkAddr, uint8* extAddr, uint16* ami )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
|
|||
|
// add entry
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.nwkAddr = nwkAddr;
|
|||
|
AddrMgrExtAddrSet( entry.extAddr, extAddr );
|
|||
|
|
|||
|
if ( AddrMgrEntryUpdate( &entry ) == TRUE )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// return failed results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrExtAddrStore
|
|||
|
*
|
|||
|
* @brief Store EXT address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param ami - [out] Address Manager index
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrExtAddrStore( uint16 nwkAddr, uint8* extAddr, uint16* ami )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
|
|||
|
// add entry
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.nwkAddr = nwkAddr;
|
|||
|
AddrMgrExtAddrSet( entry.extAddr, extAddr );
|
|||
|
|
|||
|
if ( AddrMgrEntryUpdate( &entry ) == TRUE )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// return failed results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrExtAddrLookup
|
|||
|
*
|
|||
|
* @brief Lookup index for specified EXT address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param ami - [out] Address Manager index
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrExtAddrLookup( uint8* extAddr, uint16* ami )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
|
|||
|
// lookup entry
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
AddrMgrExtAddrSet( entry.extAddr, extAddr );
|
|||
|
|
|||
|
if ( AddrMgrEntryLookupExt( &entry ) == TRUE )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// return failed results
|
|||
|
*ami = entry.index;
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAddrClear
|
|||
|
*
|
|||
|
* @brief Clear security bit from Address Manager for specific device.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAddrClear( uint8* extAddr )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 entryAmi;
|
|||
|
|
|||
|
// get Address Manager Index
|
|||
|
status = ZDSecMgrExtAddrLookup( extAddr, &entryAmi );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
AddrMgrEntry_t addrEntry;
|
|||
|
|
|||
|
// Clear SECURITY User bit from the address manager
|
|||
|
addrEntry.user = ADDRMGR_USER_SECURITY;
|
|||
|
addrEntry.index = entryAmi;
|
|||
|
|
|||
|
if ( AddrMgrEntryRelease( &addrEntry ) != TRUE )
|
|||
|
{
|
|||
|
// return failure results
|
|||
|
status = ZFailure;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrMasterKeyLookup
|
|||
|
*
|
|||
|
* @brief Lookup MASTER key for specified address index.
|
|||
|
*
|
|||
|
* @param ami - [in] Address Manager index
|
|||
|
* @param pKeyNvId - [out] MASTER key NV ID
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrMasterKeyLookup( uint16 ami, uint16* pKeyNvId )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
ZDSecMgrMasterKeyData_t masterKeyData;
|
|||
|
|
|||
|
|
|||
|
for ( index = 0; index < ZDSECMGR_MASTERKEY_MAX ; index++ )
|
|||
|
{
|
|||
|
// Read entry index of the Master key table from NV
|
|||
|
osal_nv_read( (ZCD_NV_MASTER_KEY_DATA_START + index), 0,
|
|||
|
sizeof(ZDSecMgrMasterKeyData_t), &masterKeyData );
|
|||
|
|
|||
|
if ( masterKeyData.ami == ami )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*pKeyNvId = ZCD_NV_MASTER_KEY_DATA_START + index;
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset(&masterKeyData, 0x00, sizeof(ZDSecMgrMasterKeyData_t));
|
|||
|
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*pKeyNvId = SEC_NO_KEY_NV_ID;
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset(&masterKeyData, 0x00, sizeof(ZDSecMgrMasterKeyData_t));
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrMasterKeyStore
|
|||
|
*
|
|||
|
* @brief Store MASTER key for specified address index.
|
|||
|
*
|
|||
|
* @param ami - [in] Address Manager index
|
|||
|
* @param key - [in] valid key to store
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrMasterKeyStore( uint16 ami, uint8* key )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
ZDSecMgrMasterKeyData_t masterKeyData;
|
|||
|
|
|||
|
|
|||
|
for ( index = 0; index < ZDSECMGR_MASTERKEY_MAX ; index++ )
|
|||
|
{
|
|||
|
// Read entry index of the Master key table from NV
|
|||
|
osal_nv_read( (ZCD_NV_MASTER_KEY_DATA_START + index), 0,
|
|||
|
sizeof(ZDSecMgrMasterKeyData_t), &masterKeyData );
|
|||
|
|
|||
|
if ( masterKeyData.ami == INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
// store EXT address index
|
|||
|
masterKeyData.ami = ami;
|
|||
|
|
|||
|
if ( key != NULL )
|
|||
|
{
|
|||
|
osal_memcpy( masterKeyData.key, key, SEC_KEY_LEN );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
osal_memset( masterKeyData.key, 0, SEC_KEY_LEN );
|
|||
|
}
|
|||
|
|
|||
|
// set new values in NV
|
|||
|
osal_nv_write( (ZCD_NV_MASTER_KEY_DATA_START + index), 0,
|
|||
|
sizeof(ZDSecMgrMasterKeyData_t), &masterKeyData );
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( &masterKeyData, 0x00, sizeof(ZDSecMgrMasterKeyData_t) );
|
|||
|
|
|||
|
// return successful results
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( &masterKeyData, 0x00, sizeof(ZDSecMgrMasterKeyData_t) );
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryInit
|
|||
|
*
|
|||
|
* @brief Initialize entry sub module
|
|||
|
*
|
|||
|
* @param state - device initialization state
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrEntryInit(uint8 state)
|
|||
|
{
|
|||
|
if (ZDSecMgrEntries == NULL)
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
if ((ZDSecMgrEntries = osal_mem_alloc(sizeof(ZDSecMgrEntry_t) * ZDSECMGR_ENTRY_MAX)) == NULL)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (index = 0; index < ZDSECMGR_ENTRY_MAX; index++)
|
|||
|
{
|
|||
|
ZDSecMgrEntries[index].ami = INVALID_NODE_ADDR;
|
|||
|
|
|||
|
ZDSecMgrEntries[index].keyNvId = SEC_NO_KEY_NV_ID;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if defined NV_RESTORE
|
|||
|
if (state == ZDO_INITDEV_RESTORED_NETWORK_STATE)
|
|||
|
{
|
|||
|
ZDSecMgrRestoreFromNV();
|
|||
|
}
|
|||
|
#else
|
|||
|
(void)state;
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryLookup
|
|||
|
*
|
|||
|
* @brief Lookup entry index using specified NWK address.
|
|||
|
*
|
|||
|
* @param nwkAddr - [in] NWK address
|
|||
|
* @param entry - [out] valid entry
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryLookup( uint16 nwkAddr, ZDSecMgrEntry_t** entry )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
AddrMgrEntry_t addrMgrEntry;
|
|||
|
|
|||
|
// initialize results
|
|||
|
*entry = NULL;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
addrMgrEntry.user = ADDRMGR_USER_SECURITY;
|
|||
|
addrMgrEntry.nwkAddr = nwkAddr;
|
|||
|
|
|||
|
if ( AddrMgrEntryLookupNwk( &addrMgrEntry ) == TRUE )
|
|||
|
{
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( addrMgrEntry.index == ZDSecMgrEntries[index].ami )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*entry = &ZDSecMgrEntries[index];
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryLookupAMI
|
|||
|
*
|
|||
|
* @brief Lookup entry using specified address index
|
|||
|
*
|
|||
|
* @param ami - [in] Address Manager index
|
|||
|
* @param entry - [out] valid entry
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryLookupAMI( uint16 ami, ZDSecMgrEntry_t** entry )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// initialize results
|
|||
|
*entry = NULL;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami == ami )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*entry = &ZDSecMgrEntries[index];
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryLookupExt
|
|||
|
*
|
|||
|
* @brief Lookup entry index using specified EXT address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param entry - [out] valid entry
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryLookupExt( uint8* extAddr, ZDSecMgrEntry_t** entry )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
|
|||
|
// initialize results
|
|||
|
*entry = NULL;
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
|
|||
|
// lookup address index
|
|||
|
if ( ZDSecMgrExtAddrLookup( extAddr, &ami ) == ZSuccess )
|
|||
|
{
|
|||
|
status = ZDSecMgrEntryLookupAMI( ami, entry );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryLookupExtGetIndex
|
|||
|
*
|
|||
|
* @brief Lookup entry index using specified EXT address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param entryIndex - [out] valid index to the entry table
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryLookupExtGetIndex( uint8* extAddr, ZDSecMgrEntry_t** entry, uint16* entryIndex )
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// lookup address index
|
|||
|
if ( ZDSecMgrExtAddrLookup( extAddr, &ami ) == ZSuccess )
|
|||
|
{
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami == ami )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*entry = &ZDSecMgrEntries[index];
|
|||
|
*entryIndex = index;
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryLookupAMIGetIndex
|
|||
|
*
|
|||
|
* @brief Lookup entry using specified address index
|
|||
|
*
|
|||
|
* @param ami - [in] Address Manager index
|
|||
|
* @param entryIndex - [out] valid index to the entry table
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryLookupAMIGetIndex( uint16 ami, uint16* entryIndex )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami == ami )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
*entryIndex = index;
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryFree
|
|||
|
*
|
|||
|
* @brief Free entry.
|
|||
|
*
|
|||
|
* @param entry - [in] valid entry
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
void ZDSecMgrEntryFree( ZDSecMgrEntry_t* entry )
|
|||
|
{
|
|||
|
APSME_LinkKeyData_t *pApsLinkKey = NULL;
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
ZStatus_t status;
|
|||
|
uint16 entryIndex;
|
|||
|
|
|||
|
status = ZDSecMgrEntryLookupAMIGetIndex( entry->ami, &entryIndex );
|
|||
|
#endif
|
|||
|
|
|||
|
pApsLinkKey = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
if (pApsLinkKey != NULL)
|
|||
|
{
|
|||
|
osal_memset( pApsLinkKey, 0x00, sizeof(APSME_LinkKeyData_t) );
|
|||
|
|
|||
|
// Clear the APS Link key in NV
|
|||
|
osal_nv_write( entry->keyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey);
|
|||
|
|
|||
|
// set entry to invalid Key
|
|||
|
entry->keyNvId = SEC_NO_KEY_NV_ID;
|
|||
|
|
|||
|
osal_mem_free(pApsLinkKey);
|
|||
|
}
|
|||
|
|
|||
|
// marking the entry as INVALID_NODE_ADDR
|
|||
|
entry->ami = INVALID_NODE_ADDR;
|
|||
|
|
|||
|
// set to default value
|
|||
|
entry->authenticateOption = ZDSecMgr_Not_Authenticated;
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
ZDSecMgrUpdateNV(entryIndex);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEntryNew
|
|||
|
*
|
|||
|
* @brief Get a new entry.
|
|||
|
*
|
|||
|
* @param entry - [out] valid entry
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEntryNew( ZDSecMgrEntry_t** entry )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// initialize results
|
|||
|
*entry = NULL;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
// find available entry
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami == INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
// return successful result
|
|||
|
*entry = &ZDSecMgrEntries[index];
|
|||
|
|
|||
|
// Set the authentication option to default
|
|||
|
ZDSecMgrEntries[index].authenticateOption = ZDSecMgr_Not_Authenticated;
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlInit
|
|||
|
*
|
|||
|
* @brief Initialize control sub module
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrCtrlInit( void )
|
|||
|
{
|
|||
|
uint16 size;
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// allocate entry data
|
|||
|
size = (short)( sizeof(ZDSecMgrCtrl_t) * ZDSECMGR_CTRL_MAX );
|
|||
|
|
|||
|
ZDSecMgrCtrlData = osal_mem_alloc( size );
|
|||
|
|
|||
|
// initialize data
|
|||
|
if ( ZDSecMgrCtrlData != NULL )
|
|||
|
{
|
|||
|
for( index = 0; index < ZDSECMGR_CTRL_MAX; index++ )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlData[index].state = ZDSECMGR_CTRL_NONE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlRelease
|
|||
|
*
|
|||
|
* @brief Release control data.
|
|||
|
*
|
|||
|
* @param ctrl - [in] valid control data
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrCtrlRelease( ZDSecMgrCtrl_t* ctrl )
|
|||
|
{
|
|||
|
// should always be enough entry control data
|
|||
|
ctrl->state = ZDSECMGR_CTRL_NONE;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlLookup
|
|||
|
*
|
|||
|
* @brief Lookup control data.
|
|||
|
*
|
|||
|
* @param entry - [in] valid entry data
|
|||
|
* @param ctrl - [out] control data - NULL if not found
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrCtrlLookup( ZDSecMgrEntry_t* entry, ZDSecMgrCtrl_t** ctrl )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// initialize search results
|
|||
|
*ctrl = NULL;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrCtrlData != NULL )
|
|||
|
{
|
|||
|
for ( index = 0; index < ZDSECMGR_CTRL_MAX; index++ )
|
|||
|
{
|
|||
|
// make sure control data is in use
|
|||
|
if ( ZDSecMgrCtrlData[index].state != ZDSECMGR_CTRL_NONE )
|
|||
|
{
|
|||
|
// check for entry match
|
|||
|
if ( ZDSecMgrCtrlData[index].entry == entry )
|
|||
|
{
|
|||
|
// return this control data
|
|||
|
*ctrl = &ZDSecMgrCtrlData[index];
|
|||
|
|
|||
|
// break from loop
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlSet
|
|||
|
*
|
|||
|
* @brief Set control data.
|
|||
|
*
|
|||
|
* @param device - [in] valid device data
|
|||
|
* @param entry - [in] valid entry data
|
|||
|
* @param ctrl - [in] valid control data
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrCtrlSet( ZDSecMgrDevice_t* device,
|
|||
|
ZDSecMgrEntry_t* entry,
|
|||
|
ZDSecMgrCtrl_t* ctrl )
|
|||
|
{
|
|||
|
// set control date
|
|||
|
ctrl->parentAddr = device->parentAddr;
|
|||
|
ctrl->secure = device->secure;
|
|||
|
ctrl->entry = entry;
|
|||
|
ctrl->state = ZDSECMGR_CTRL_INIT;
|
|||
|
ctrl->cntr = 0;
|
|||
|
|
|||
|
// set device pointer
|
|||
|
device->ctrl = ctrl;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlAdd
|
|||
|
*
|
|||
|
* @brief Add control data.
|
|||
|
*
|
|||
|
* @param device - [in] valid device data
|
|||
|
* @param entry - [in] valid entry data
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrCtrlAdd( ZDSecMgrDevice_t* device, ZDSecMgrEntry_t* entry )
|
|||
|
{
|
|||
|
uint16 index;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrCtrlData != NULL )
|
|||
|
{
|
|||
|
// look for an empty slot
|
|||
|
for ( index = 0; index < ZDSECMGR_CTRL_MAX; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrCtrlData[index].state == ZDSECMGR_CTRL_NONE )
|
|||
|
{
|
|||
|
// return successful results
|
|||
|
ZDSecMgrCtrlSet( device, entry, &ZDSecMgrCtrlData[index] );
|
|||
|
|
|||
|
// break from loop
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlTerm
|
|||
|
*
|
|||
|
* @brief Terminate device control.
|
|||
|
*
|
|||
|
* @param entry - [in] valid entry data
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrCtrlTerm( ZDSecMgrEntry_t* entry )
|
|||
|
{
|
|||
|
ZDSecMgrCtrl_t* ctrl;
|
|||
|
|
|||
|
// remove device from control data
|
|||
|
ZDSecMgrCtrlLookup ( entry, &ctrl );
|
|||
|
|
|||
|
if ( ctrl != NULL )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlRelease ( ctrl );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrCtrlReset
|
|||
|
*
|
|||
|
* @brief Reset control data.
|
|||
|
*
|
|||
|
* @param device - [in] valid device data
|
|||
|
* @param entry - [in] valid entry data
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrCtrlReset( ZDSecMgrDevice_t* device, ZDSecMgrEntry_t* entry )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
ZDSecMgrCtrl_t* ctrl;
|
|||
|
|
|||
|
// initialize results
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
|
|||
|
// look for a match for the entry
|
|||
|
ZDSecMgrCtrlLookup( entry, &ctrl );
|
|||
|
|
|||
|
if ( ctrl != NULL )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlSet( device, entry, ctrl );
|
|||
|
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZDSecMgrCtrlAdd( device, entry );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrMasterKeyLoad
|
|||
|
*
|
|||
|
* @brief Load the MASTER key for device with specified EXT
|
|||
|
* address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address of device
|
|||
|
* @param key - [in] MASTER key shared with device
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrMasterKeyLoad( uint8* extAddr, uint8* key )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
uint16 keyNvId;
|
|||
|
|
|||
|
// set status based on policy
|
|||
|
status = ZDSecMgrExtAddrLookup( extAddr, &ami );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// get the address NV ID
|
|||
|
if ( ZDSecMgrMasterKeyLookup( ami, &keyNvId ) == ZSuccess )
|
|||
|
{
|
|||
|
// overwrite old key in NV
|
|||
|
osal_nv_write( keyNvId, osal_offsetof(ZDSecMgrMasterKeyData_t, key),
|
|||
|
SEC_KEY_LEN, key );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// store new key -- NULL will zero key
|
|||
|
status = ZDSecMgrMasterKeyStore( ami, key );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAppKeyGet
|
|||
|
*
|
|||
|
* @brief get an APP key - option APP(MASTER or LINK) key
|
|||
|
*
|
|||
|
* @param initNwkAddr - [in] NWK address of initiator device
|
|||
|
* @param initExtAddr - [in] EXT address of initiator device
|
|||
|
* @param partNwkAddr - [in] NWK address of partner device
|
|||
|
* @param partExtAddr - [in] EXT address of partner device
|
|||
|
* @param key - [out] APP(MASTER or LINK) key
|
|||
|
* @param keyType - [out] APP(MASTER or LINK) key type
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrAppKeyType = KEY_TYPE_APP_LINK; // Set the default key type
|
|||
|
// to KEY_TYPE_APP_LINK since
|
|||
|
// only specific requirement
|
|||
|
// right now comes from SE profile
|
|||
|
|
|||
|
ZStatus_t ZDSecMgrAppKeyGet( uint16 initNwkAddr,
|
|||
|
uint8* initExtAddr,
|
|||
|
uint16 partNwkAddr,
|
|||
|
uint8* partExtAddr,
|
|||
|
uint8** key,
|
|||
|
uint8* keyType )
|
|||
|
{
|
|||
|
// Intentionally unreferenced parameters
|
|||
|
(void)initNwkAddr;
|
|||
|
(void)initExtAddr;
|
|||
|
(void)partNwkAddr;
|
|||
|
(void)partExtAddr;
|
|||
|
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
// note:
|
|||
|
// should use a robust mechanism to generate keys, for example
|
|||
|
// combine EXT addresses and call a hash function
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
SSP_GetTrueRand( SEC_KEY_LEN, *key );
|
|||
|
|
|||
|
*keyType = ZDSecMgrAppKeyType;
|
|||
|
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAppKeyReq
|
|||
|
*
|
|||
|
* @brief Process request for APP key between two devices.
|
|||
|
*
|
|||
|
* @param device - [in] ZDO_RequestKeyInd_t, request info
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAppKeyReq( ZDO_RequestKeyInd_t* ind )
|
|||
|
{
|
|||
|
APSME_TransportKeyReq_t req;
|
|||
|
uint8 initExtAddr[Z_EXTADDR_LEN];
|
|||
|
uint16 partNwkAddr;
|
|||
|
uint8 key[SEC_KEY_LEN];
|
|||
|
|
|||
|
|
|||
|
// validate initiator and partner
|
|||
|
if ( ( APSME_LookupNwkAddr( ind->partExtAddr, &partNwkAddr ) == TRUE ) &&
|
|||
|
( APSME_LookupExtAddr( ind->srcAddr, initExtAddr ) == TRUE ) )
|
|||
|
{
|
|||
|
// point the key to some memory
|
|||
|
req.key = key;
|
|||
|
|
|||
|
// get an APP key - option APP (MASTER or LINK) key
|
|||
|
if ( ZDSecMgrAppKeyGet( ind->srcAddr,
|
|||
|
initExtAddr,
|
|||
|
partNwkAddr,
|
|||
|
ind->partExtAddr,
|
|||
|
&req.key,
|
|||
|
&req.keyType ) == ZSuccess )
|
|||
|
{
|
|||
|
// always secure
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
req.apsSecure = TRUE;
|
|||
|
req.tunnel = NULL;
|
|||
|
|
|||
|
// send key to initiator device
|
|||
|
req.dstAddr = ind->srcAddr;
|
|||
|
req.extAddr = ind->partExtAddr;
|
|||
|
req.initiator = TRUE;
|
|||
|
APSME_TransportKeyReq( &req );
|
|||
|
|
|||
|
// send key to partner device
|
|||
|
req.dstAddr = partNwkAddr;
|
|||
|
req.extAddr = initExtAddr;
|
|||
|
req.initiator = FALSE;
|
|||
|
|
|||
|
APSME_TransportKeyReq( &req );
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( key, 0x00, SEC_KEY_LEN);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEstablishKey
|
|||
|
*
|
|||
|
* @brief Start SKKE with device joining network.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrEstablishKey( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_EstablishKeyReq_t req;
|
|||
|
|
|||
|
|
|||
|
req.respExtAddr = device->extAddr;
|
|||
|
req.method = APSME_SKKE_METHOD;
|
|||
|
|
|||
|
if ( device->parentAddr == NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
req.dstAddr = device->nwkAddr;
|
|||
|
//devtag.0604.todo - remove obsolete
|
|||
|
req.apsSecure = FALSE;
|
|||
|
req.nwkSecure = FALSE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.dstAddr = device->parentAddr;
|
|||
|
//devtag.0604.todo - remove obsolete
|
|||
|
req.apsSecure = TRUE;
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
status = APSME_EstablishKeyReq( &req );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSendMasterKey
|
|||
|
*
|
|||
|
* @brief Send MASTER key to device joining network.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrSendMasterKey( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_TransportKeyReq_t req;
|
|||
|
uint16 keyNvId;
|
|||
|
uint8 masterKey[SEC_KEY_LEN];
|
|||
|
|
|||
|
|
|||
|
req.keyType = KEY_TYPE_TC_MASTER;
|
|||
|
req.extAddr = device->extAddr;
|
|||
|
req.tunnel = NULL;
|
|||
|
|
|||
|
if ( ZDSecMgrMasterKeyLookup( device->ctrl->entry->ami, &keyNvId ) == ZSuccess )
|
|||
|
{
|
|||
|
osal_nv_read( keyNvId, osal_offsetof(ZDSecMgrMasterKeyData_t, key),
|
|||
|
SEC_KEY_LEN, masterKey );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// in case read from NV fails
|
|||
|
osal_memset( masterKey, 0x00, SEC_KEY_LEN);
|
|||
|
}
|
|||
|
|
|||
|
req.key = masterKey;
|
|||
|
|
|||
|
//check if using secure hop to to parent
|
|||
|
if ( device->parentAddr != NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
//send to parent with security
|
|||
|
req.dstAddr = device->parentAddr;
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
req.apsSecure = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//direct with no security
|
|||
|
req.dstAddr = device->nwkAddr;
|
|||
|
req.nwkSecure = FALSE;
|
|||
|
req.apsSecure = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
status = APSME_TransportKeyReq( &req );
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( masterKey, 0x00, SEC_KEY_LEN);
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSendNwkKey
|
|||
|
*
|
|||
|
* @brief Send NWK key to device joining network.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrSendNwkKey( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_TransportKeyReq_t req;
|
|||
|
APSDE_FrameTunnel_t tunnel;
|
|||
|
nwkKeyDesc tmpKey;
|
|||
|
|
|||
|
req.dstAddr = device->nwkAddr;
|
|||
|
req.extAddr = device->extAddr;
|
|||
|
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
req.keyType = KEY_TYPE_NWK_HIGH;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.keyType = KEY_TYPE_NWK;
|
|||
|
}
|
|||
|
|
|||
|
// get the Active Key into a local variable
|
|||
|
if( NLME_ReadNwkKeyInfo( 0, sizeof(tmpKey), &tmpKey,
|
|||
|
ZCD_NV_NWK_ACTIVE_KEY_INFO ) != SUCCESS )
|
|||
|
{
|
|||
|
// set key data to all 0s if NV read fails
|
|||
|
osal_memset(&tmpKey, 0x00, sizeof(tmpKey));
|
|||
|
}
|
|||
|
|
|||
|
if ( (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH)
|
|||
|
|| (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD) )
|
|||
|
{
|
|||
|
// set values
|
|||
|
req.keySeqNum = tmpKey.keySeqNum;
|
|||
|
req.key = tmpKey.key;
|
|||
|
|
|||
|
//devtag.pro.security.todo - make sure that if there is no link key the NWK
|
|||
|
//key isn't used to secure the frame at the APS layer -- since the receiving
|
|||
|
//device may not have a NWK key yet
|
|||
|
req.apsSecure = TRUE;
|
|||
|
|
|||
|
// check if using secure hop to to parent
|
|||
|
if ( device->parentAddr == NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
req.nwkSecure = FALSE;
|
|||
|
req.tunnel = NULL;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
req.tunnel = &tunnel;
|
|||
|
req.tunnel->tna = device->parentAddr;
|
|||
|
req.tunnel->dea = device->extAddr;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// default values
|
|||
|
//devtag.0604.verify
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
req.apsSecure = FALSE;
|
|||
|
req.tunnel = NULL;
|
|||
|
|
|||
|
if ( device->parentAddr != NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
req.dstAddr = device->parentAddr;
|
|||
|
}
|
|||
|
|
|||
|
// special cases
|
|||
|
//devtag.0604.todo - modify to preconfig flag
|
|||
|
if ( device->secure == FALSE )
|
|||
|
{
|
|||
|
req.keySeqNum = tmpKey.keySeqNum;
|
|||
|
req.key = tmpKey.key;
|
|||
|
|
|||
|
// check if using secure hop to to parent
|
|||
|
if ( device->parentAddr == NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
req.nwkSecure = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.key = NULL;
|
|||
|
req.keySeqNum = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
status = APSME_TransportKeyReq( &req );
|
|||
|
|
|||
|
// clear copy of key in RAM before return
|
|||
|
osal_memset( &tmpKey, 0x00, sizeof(nwkKeyDesc) );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceEntryRemove
|
|||
|
*
|
|||
|
* @brief Remove device entry.
|
|||
|
*
|
|||
|
* @param entry - [in] valid entry
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrDeviceEntryRemove( ZDSecMgrEntry_t* entry )
|
|||
|
{
|
|||
|
// terminate device control
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlTerm( entry );
|
|||
|
}
|
|||
|
|
|||
|
// remove device from entry data
|
|||
|
ZDSecMgrEntryFree( entry );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceRemoveByExtAddr
|
|||
|
*
|
|||
|
* @brief Remove device entry by its ext address.
|
|||
|
*
|
|||
|
* @param pAddr - pointer to the extended address
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceRemoveByExtAddr( uint8 *pAddr )
|
|||
|
{
|
|||
|
ZDSecMgrEntry_t *pEntry;
|
|||
|
uint8 retValue;
|
|||
|
|
|||
|
retValue = (uint8)ZDSecMgrEntryLookupExt( pAddr, &pEntry );
|
|||
|
|
|||
|
if( retValue == ZSuccess )
|
|||
|
{
|
|||
|
ZDSecMgrDeviceEntryRemove( pEntry );
|
|||
|
}
|
|||
|
|
|||
|
return retValue;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceEntryAdd
|
|||
|
*
|
|||
|
* @brief Add entry.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
* @param ami - [in] Address Manager index
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
void ZDSecMgrAddrMgrUpdate( uint16 ami, uint16 nwkAddr )
|
|||
|
{
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
// get the ami data
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.index = ami;
|
|||
|
|
|||
|
AddrMgrEntryGet( &entry );
|
|||
|
|
|||
|
// check if NWK address is same
|
|||
|
if ( entry.nwkAddr != nwkAddr )
|
|||
|
{
|
|||
|
// update NWK address
|
|||
|
entry.nwkAddr = nwkAddr;
|
|||
|
|
|||
|
AddrMgrEntryUpdate( &entry );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ZStatus_t ZDSecMgrDeviceEntryAdd( ZDSecMgrDevice_t* device, uint16 ami )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
|
|||
|
// initialize as unknown until completion
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
|
|||
|
device->ctrl = NULL;
|
|||
|
|
|||
|
// make sure not already registered
|
|||
|
if ( ZDSecMgrEntryLookup( device->nwkAddr, &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
// verify that address index is same
|
|||
|
if ( entry->ami != ami )
|
|||
|
{
|
|||
|
// remove conflicting entry
|
|||
|
ZDSecMgrDeviceEntryRemove( entry );
|
|||
|
|
|||
|
if ( ZDSecMgrEntryLookupAMI( ami, &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
// update NWK address
|
|||
|
ZDSecMgrAddrMgrUpdate( ami, device->nwkAddr );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( ZDSecMgrEntryLookupAMI( ami, &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
// update NWK address
|
|||
|
ZDSecMgrAddrMgrUpdate( ami, device->nwkAddr );
|
|||
|
}
|
|||
|
|
|||
|
// check if a new entry needs to be created
|
|||
|
if ( entry == NULL )
|
|||
|
{
|
|||
|
// get new entry
|
|||
|
if ( ZDSecMgrEntryNew( &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
// reset entry lkd
|
|||
|
|
|||
|
// finish setting up entry
|
|||
|
entry->ami = ami;
|
|||
|
|
|||
|
// update NWK address
|
|||
|
ZDSecMgrAddrMgrUpdate( ami, device->nwkAddr );
|
|||
|
|
|||
|
// enter new device into device control
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
status = ZDSecMgrCtrlAdd( device, entry );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// reset entry lkd
|
|||
|
|
|||
|
// reset entry in entry control
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
status = ZDSecMgrCtrlReset( device, entry );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceCtrlHandler
|
|||
|
*
|
|||
|
* @brief Device control handler.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrDeviceCtrlHandler( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
uint8 state;
|
|||
|
uint8 cntr;
|
|||
|
|
|||
|
state = device->ctrl->state;
|
|||
|
cntr = ZDSECMGR_CTRL_BASE_CNTR;
|
|||
|
|
|||
|
switch ( state )
|
|||
|
{
|
|||
|
case ZDSECMGR_CTRL_TK_MASTER:
|
|||
|
if ( ZDSecMgrSendMasterKey( device ) == ZSuccess )
|
|||
|
{
|
|||
|
state = ZDSECMGR_CTRL_SKKE_INIT;
|
|||
|
cntr = ZDSECMGR_CTRL_SKKE_INIT_CNTR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ZDSECMGR_CTRL_SKKE_INIT:
|
|||
|
if ( ZDSecMgrEstablishKey( device ) == ZSuccess )
|
|||
|
{
|
|||
|
state = ZDSECMGR_CTRL_SKKE_WAIT;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ZDSECMGR_CTRL_SKKE_WAIT:
|
|||
|
// continue to wait for SKA control timeout
|
|||
|
break;
|
|||
|
|
|||
|
case ZDSECMGR_CTRL_TK_NWK:
|
|||
|
if ( ZDSecMgrSendNwkKey( device ) == ZSuccess )
|
|||
|
{
|
|||
|
state = ZDSECMGR_CTRL_NONE;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
state = ZDSECMGR_CTRL_NONE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if ( state != ZDSECMGR_CTRL_NONE )
|
|||
|
{
|
|||
|
device->ctrl->state = state;
|
|||
|
device->ctrl->cntr = cntr;
|
|||
|
|
|||
|
osal_start_timerEx(ZDAppTaskID, ZDO_SECMGR_EVENT, 100 );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ZDSecMgrCtrlRelease( device->ctrl );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceCtrlSetup
|
|||
|
*
|
|||
|
* @brief Setup device control.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
void ZDSecMgrDeviceCtrlSetup( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
if ( device->ctrl != NULL )
|
|||
|
{
|
|||
|
if ( device->secure == FALSE )
|
|||
|
{
|
|||
|
// send the master key data to the joining device
|
|||
|
device->ctrl->state = ZDSECMGR_CTRL_TK_MASTER;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// start SKKE
|
|||
|
device->ctrl->state = ZDSECMGR_CTRL_SKKE_INIT;
|
|||
|
}
|
|||
|
|
|||
|
ZDSecMgrDeviceCtrlHandler( device );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceCtrlUpdate
|
|||
|
*
|
|||
|
* @brief Update control data.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param state - [in] new control state
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrDeviceCtrlUpdate( uint8* extAddr, uint8 state )
|
|||
|
{
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
ZDSecMgrCtrl_t* ctrl;
|
|||
|
|
|||
|
// lookup device entry data
|
|||
|
(void)ZDSecMgrEntryLookupExt( extAddr, &entry );
|
|||
|
|
|||
|
if ( entry != NULL )
|
|||
|
{
|
|||
|
// lookup device control data
|
|||
|
ZDSecMgrCtrlLookup( entry, &ctrl );
|
|||
|
|
|||
|
// make sure control data is valid
|
|||
|
if ( ctrl != NULL )
|
|||
|
{
|
|||
|
// possible state transitions
|
|||
|
if ( ctrl->state == ZDSECMGR_CTRL_SKKE_WAIT )
|
|||
|
{
|
|||
|
if ( state == ZDSECMGR_CTRL_SKKE_DONE )
|
|||
|
{
|
|||
|
// send the network key
|
|||
|
ctrl->state = ZDSECMGR_CTRL_TK_NWK;
|
|||
|
ctrl->cntr = ZDSECMGR_CTRL_TK_NWK_CNTR;
|
|||
|
}
|
|||
|
else if ( state == ZDSECMGR_CTRL_SKKE_FAIL )
|
|||
|
{
|
|||
|
// force default timeout in order to cleanup control logic
|
|||
|
ctrl->state = ZDSECMGR_CTRL_SKKE_FAIL;
|
|||
|
ctrl->cntr = ZDSECMGR_CTRL_BASE_CNTR;
|
|||
|
}
|
|||
|
}
|
|||
|
// timer should be active
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void APSME_SKA_TimerExpired( uint8 initiator, uint8* partExtAddr );
|
|||
|
void APSME_SKA_TimerExpired( uint8 initiator, uint8* partExtAddr )
|
|||
|
{
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
if ( initiator == TRUE )
|
|||
|
{
|
|||
|
ZDSecMgrDeviceCtrlUpdate( partExtAddr, ZDSECMGR_CTRL_SKKE_FAIL );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceRemove
|
|||
|
*
|
|||
|
* @brief Remove device from network.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrDeviceRemove( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
APSME_RemoveDeviceReq_t remDevReq;
|
|||
|
NLME_LeaveReq_t leaveReq;
|
|||
|
associated_devices_t* assoc;
|
|||
|
|
|||
|
// check if parent, remove the device
|
|||
|
if ( device->parentAddr == NLME_GetShortAddr() )
|
|||
|
{
|
|||
|
// this is the parent of the device
|
|||
|
leaveReq.extAddr = device->extAddr;
|
|||
|
leaveReq.removeChildren = FALSE;
|
|||
|
leaveReq.rejoin = FALSE;
|
|||
|
|
|||
|
// find child association
|
|||
|
assoc = AssocGetWithExt( device->extAddr );
|
|||
|
|
|||
|
if ( ( assoc != NULL ) &&
|
|||
|
( assoc->nodeRelation >= CHILD_RFD ) &&
|
|||
|
( assoc->nodeRelation <= CHILD_FFD_RX_IDLE ) )
|
|||
|
{
|
|||
|
// check if associated device is authenticated
|
|||
|
if ( assoc->devStatus & DEV_SEC_AUTH_STATUS )
|
|||
|
{
|
|||
|
leaveReq.silent = FALSE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
leaveReq.silent = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
NLME_LeaveReq( &leaveReq );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// this is not the parent of the device
|
|||
|
remDevReq.parentAddr = device->parentAddr;
|
|||
|
remDevReq.childExtAddr = device->extAddr;
|
|||
|
|
|||
|
APSME_RemoveDeviceReq( &remDevReq );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceValidateSKKE
|
|||
|
*
|
|||
|
* @brief Decide whether device is allowed for SKKE.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateSKKE( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
uint16 keyNvId;
|
|||
|
|
|||
|
// get EXT address
|
|||
|
status = ZDSecMgrExtAddrLookup( device->extAddr, &ami );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// get MASTER key
|
|||
|
status = ZDSecMgrMasterKeyLookup( ami, &keyNvId );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
status = ZDSecMgrDeviceEntryAdd( device, ami );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceValidateRM (RESIDENTIAL MODE)
|
|||
|
*
|
|||
|
* @brief Decide whether device is allowed.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateRM( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
status = ZSuccess;
|
|||
|
|
|||
|
(void)device; // Intentionally unreferenced parameter
|
|||
|
|
|||
|
// For test purpose, turning off the zgSecurePermitJoin flag will force
|
|||
|
// the trust center to reject any newly joining devices by sending
|
|||
|
// Remove-device to the parents.
|
|||
|
if ( zgSecurePermitJoin == FALSE )
|
|||
|
{
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#if 0 // Taken out because the following functionality is only used for test
|
|||
|
// purpose. A more efficient (above) way is used. It can be put
|
|||
|
// back in if customers request for a white/black list feature.
|
|||
|
// ZDSecMgrStoredDeviceList[] is defined in ZDSecMgr.c
|
|||
|
|
|||
|
// The following code processes the device black list (stored device list)
|
|||
|
// If the joining device is not part of the forbidden device list
|
|||
|
// Return ZSuccess. Otherwise, return ZNwkUnknownDevice. The trust center
|
|||
|
// will send Remove-device and ban the device from joining.
|
|||
|
|
|||
|
uint8 index;
|
|||
|
uint8* restricted;
|
|||
|
|
|||
|
// Look through the stored device list - used for restricted devices
|
|||
|
for ( index = 0; index < ZDSECMGR_STORED_DEVICES; index++ )
|
|||
|
{
|
|||
|
restricted = ZDSecMgrStoredDeviceList[index];
|
|||
|
|
|||
|
if ( AddrMgrExtAddrEqual( restricted, device->extAddr ) == TRUE )
|
|||
|
{
|
|||
|
// return as unknown device in regards to validation
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
|
|||
|
// break from loop
|
|||
|
index = ZDSECMGR_STORED_DEVICES;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceValidateCM (COMMERCIAL MODE)
|
|||
|
*
|
|||
|
* @brief Decide whether device is allowed.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
//devtag.pro.security
|
|||
|
ZStatus_t ZDSecMgrDeviceValidateCM( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
uint8 key[SEC_KEY_LEN];
|
|||
|
|
|||
|
// implement EXT address and MASTER key policy here -- the total number of
|
|||
|
// Security Manager entries should never exceed the number of EXT addresses
|
|||
|
// and MASTER keys available
|
|||
|
|
|||
|
// set status based on policy
|
|||
|
//status = ZNwkUnknownDevice;
|
|||
|
|
|||
|
// set status based on policy
|
|||
|
status = ZSuccess; // ZNwkUnknownDevice;
|
|||
|
|
|||
|
// get key based on policy
|
|||
|
osal_memcpy( key, ZDSecMgrTCMasterKey, SEC_KEY_LEN);
|
|||
|
|
|||
|
// if policy, store new EXT address
|
|||
|
status = ZDSecMgrAddrStore( device->nwkAddr, device->extAddr, &ami );
|
|||
|
|
|||
|
// set the key
|
|||
|
ZDSecMgrMasterKeyLoad( device->extAddr, key );
|
|||
|
|
|||
|
// if EXT address and MASTER key available -- add device
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// add device to internal data - with control
|
|||
|
status = ZDSecMgrDeviceEntryAdd( device, ami );
|
|||
|
}
|
|||
|
|
|||
|
// remove copy of key in RAM
|
|||
|
osal_memset( key, 0x00, SEC_KEY_LEN );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceValidate
|
|||
|
*
|
|||
|
* @brief Decide whether device is allowed.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceValidate( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
|
|||
|
if ( ZDSecMgrPermitJoiningEnabled == TRUE )
|
|||
|
{
|
|||
|
// device may be joining with a secure flag but it is ultimately the Trust
|
|||
|
// Center that decides -- check if expected pre configured device --
|
|||
|
// override settings
|
|||
|
if ( zgPreConfigKeys == TRUE )
|
|||
|
{
|
|||
|
device->secure = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
device->secure = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
status = ZDSecMgrDeviceValidateCM( device );
|
|||
|
}
|
|||
|
else // ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_RESIDENTIAL )
|
|||
|
{
|
|||
|
status = ZDSecMgrDeviceValidateRM( device );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZNwkUnknownDevice;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceJoin
|
|||
|
*
|
|||
|
* @brief Try to join this device.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceJoin( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
|
|||
|
// attempt to validate device
|
|||
|
status = ZDSecMgrDeviceValidate( device );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
ZDSecMgrDeviceCtrlSetup( device );
|
|||
|
}
|
|||
|
else // ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_RESIDENTIAL )
|
|||
|
{
|
|||
|
// Add the device to the address manager
|
|||
|
ZDSecMgrAddrStore( device->nwkAddr, device->extAddr, &ami );
|
|||
|
//send the nwk key data to the joining device
|
|||
|
status = ZDSecMgrSendNwkKey( device );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// not allowed, remove the device
|
|||
|
ZDSecMgrDeviceRemove( device );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceJoinDirect
|
|||
|
*
|
|||
|
* @brief Try to join this device as a direct child.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceJoinDirect( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
status = ZDSecMgrDeviceJoin( device );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// set association status to authenticated
|
|||
|
ZDSecMgrAssocDeviceAuth( AssocGetWithShort( device->nwkAddr ) );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceJoinFwd
|
|||
|
*
|
|||
|
* @brief Forward join to Trust Center.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceJoinFwd( ZDSecMgrDevice_t* device )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_UpdateDeviceReq_t req;
|
|||
|
|
|||
|
// forward any joining device to the Trust Center -- the Trust Center will
|
|||
|
// decide if the device is allowed to join
|
|||
|
status = ZSuccess;
|
|||
|
|
|||
|
// forward authorization to the Trust Center
|
|||
|
req.dstAddr = APSME_TRUSTCENTER_NWKADDR;
|
|||
|
req.devAddr = device->nwkAddr;
|
|||
|
req.devExtAddr = device->extAddr;
|
|||
|
|
|||
|
// set security status, option for router to reject if policy set
|
|||
|
if ( (device->devStatus & DEV_HIGH_SEC_STATUS) )
|
|||
|
{
|
|||
|
if ( device->devStatus & DEV_REJOIN_STATUS )
|
|||
|
{
|
|||
|
if ( device->secure == TRUE )
|
|||
|
{
|
|||
|
req.status = APSME_UD_HIGH_SECURED_REJOIN;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.status = APSME_UD_HIGH_UNSECURED_REJOIN;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.status = APSME_UD_HIGH_UNSECURED_JOIN;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( device->devStatus & DEV_REJOIN_STATUS )
|
|||
|
{
|
|||
|
if ( device->secure == TRUE )
|
|||
|
{
|
|||
|
req.status = APSME_UD_STANDARD_SECURED_REJOIN;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.status = APSME_UD_STANDARD_UNSECURED_REJOIN;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.status = APSME_UD_STANDARD_UNSECURED_JOIN;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
req.apsSecure = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.apsSecure = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// send and APSME_UPDATE_DEVICE request to the trust center
|
|||
|
status = APSME_UpdateDeviceReq( &req );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrDeviceNew
|
|||
|
*
|
|||
|
* @brief Process a new device.
|
|||
|
*
|
|||
|
* @param device - [in] ZDSecMgrDevice_t, device info
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrDeviceNew( ZDSecMgrDevice_t* joiner )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
// try to join this device
|
|||
|
status = ZDSecMgrDeviceJoinDirect( joiner );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZDSecMgrDeviceJoinFwd( joiner );
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAssocDeviceAuth
|
|||
|
*
|
|||
|
* @brief Set associated device status to authenticated
|
|||
|
*
|
|||
|
* @param assoc - [in, out] associated_devices_t
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAssocDeviceAuth( associated_devices_t* assoc )
|
|||
|
{
|
|||
|
if ( assoc != NULL )
|
|||
|
{
|
|||
|
assoc->devStatus |= DEV_SEC_AUTH_STATUS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthInitiate
|
|||
|
*
|
|||
|
* @brief Initiate entity authentication
|
|||
|
*
|
|||
|
* @param responder - [in] responder EXT address
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAuthInitiate( uint8* responder )
|
|||
|
{
|
|||
|
APSME_AuthenticateReq_t req;
|
|||
|
|
|||
|
|
|||
|
// make sure NWK address is available
|
|||
|
if ( APSME_LookupNwkAddr( responder, &req.nwkAddr ) )
|
|||
|
{
|
|||
|
// set request fields
|
|||
|
req.extAddr = responder;
|
|||
|
req.action = APSME_EA_INITIATE;
|
|||
|
req.challenge = NULL;
|
|||
|
|
|||
|
// start EA processing
|
|||
|
APSME_AuthenticateReq( &req );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthNwkKey
|
|||
|
*
|
|||
|
* @brief Handle next step in authentication process
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAuthNwkKey()
|
|||
|
{
|
|||
|
if ( devState == DEV_END_DEVICE_UNAUTH )
|
|||
|
{
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
uint8 parent[Z_EXTADDR_LEN];
|
|||
|
|
|||
|
// get parent's EXT address
|
|||
|
NLME_GetCoordExtAddr( parent );
|
|||
|
|
|||
|
// begin entity authentication with parent
|
|||
|
ZDSecMgrAuthInitiate( parent );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// inform ZDO that device has been authenticated
|
|||
|
osal_set_event ( ZDAppTaskID, ZDO_DEVICE_AUTH );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* PUBLIC FUNCTIONS
|
|||
|
*/
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrInit
|
|||
|
*
|
|||
|
* @brief Initialize ZigBee Device Security Manager.
|
|||
|
*
|
|||
|
* @param state - device initialization state
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
#if ( ADDRMGR_CALLBACK_ENABLED == 1 )
|
|||
|
void ZDSecMgrAddrMgrCB( uint8 update, AddrMgrEntry_t* newEntry, AddrMgrEntry_t* oldEntry );
|
|||
|
void ZDSecMgrAddrMgrCB( uint8 update,
|
|||
|
AddrMgrEntry_t* newEntry,
|
|||
|
AddrMgrEntry_t* oldEntry )
|
|||
|
{
|
|||
|
(void)update;
|
|||
|
(void)newEntry;
|
|||
|
(void)oldEntry;
|
|||
|
}
|
|||
|
#endif // ( ADDRMGR_CALLBACK_ENABLED == 1 )
|
|||
|
|
|||
|
void ZDSecMgrInit(uint8 state)
|
|||
|
{
|
|||
|
if ( (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH)
|
|||
|
|| (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD) )
|
|||
|
{
|
|||
|
// initialize sub modules
|
|||
|
ZDSecMgrEntryInit(state);
|
|||
|
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlInit();
|
|||
|
}
|
|||
|
|
|||
|
// register with Address Manager
|
|||
|
#if ( ADDRMGR_CALLBACK_ENABLED == 1 )
|
|||
|
AddrMgrRegister( ADDRMGR_REG_SECURITY, ZDSecMgrAddrMgrCB );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
// configure SKA slot data
|
|||
|
APSME_SKA_SlotInit( ZDSECMGR_SKA_SLOT_MAX );
|
|||
|
}
|
|||
|
|
|||
|
if ( ZG_SECURE_ENABLED )
|
|||
|
{
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
// setup joining permissions
|
|||
|
ZDSecMgrPermitJoiningEnabled = TRUE;
|
|||
|
ZDSecMgrPermitJoiningTimed = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// configure security based on security mode and type of device
|
|||
|
ZDSecMgrConfig();
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrConfig
|
|||
|
*
|
|||
|
* @brief Configure ZigBee Device Security Manager.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrConfig( void )
|
|||
|
{
|
|||
|
if ( ZG_SECURE_ENABLED )
|
|||
|
{
|
|||
|
SSP_Init();
|
|||
|
|
|||
|
if ( (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH)
|
|||
|
|| (ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD) )
|
|||
|
{
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
// COMMERCIAL MODE - COORDINATOR DEVICE
|
|||
|
APSME_SecurityCM_CD();
|
|||
|
}
|
|||
|
else if ( ZSTACK_ROUTER_BUILD )
|
|||
|
{
|
|||
|
// COMMERCIAL MODE - ROUTER DEVICE
|
|||
|
APSME_SecurityCM_RD();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// COMMERCIAL MODE - END DEVICE
|
|||
|
APSME_SecurityCM_ED();
|
|||
|
}
|
|||
|
}
|
|||
|
else // ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_RESIDENTIAL )
|
|||
|
{
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
// RESIDENTIAL MODE - COORDINATOR DEVICE
|
|||
|
APSME_SecurityRM_CD();
|
|||
|
}
|
|||
|
else if ( ZSTACK_ROUTER_BUILD )
|
|||
|
{
|
|||
|
// RESIDENTIAL MODE - ROUTER DEVICE
|
|||
|
APSME_SecurityRM_RD();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// RESIDENTIAL MODE - END DEVICE
|
|||
|
APSME_SecurityRM_ED();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// NO SECURITY
|
|||
|
APSME_SecurityNM();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrPermitJoining
|
|||
|
*
|
|||
|
* @brief Process request to change joining permissions.
|
|||
|
*
|
|||
|
* @param duration - [in] timed duration for join in seconds
|
|||
|
* - 0x00 not allowed
|
|||
|
* - 0xFF allowed without timeout
|
|||
|
*
|
|||
|
* @return uint8 - success(TRUE:FALSE)
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrPermitJoining( uint8 duration )
|
|||
|
{
|
|||
|
uint8 accept;
|
|||
|
|
|||
|
ZDSecMgrPermitJoiningTimed = FALSE;
|
|||
|
|
|||
|
if ( duration > 0 )
|
|||
|
{
|
|||
|
ZDSecMgrPermitJoiningEnabled = TRUE;
|
|||
|
|
|||
|
if ( duration != 0xFF )
|
|||
|
{
|
|||
|
ZDSecMgrPermitJoiningTimed = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ZDSecMgrPermitJoiningEnabled = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
accept = TRUE;
|
|||
|
|
|||
|
return accept;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrPermitJoiningTimeout
|
|||
|
*
|
|||
|
* @brief Process permit joining timeout
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrPermitJoiningTimeout( void )
|
|||
|
{
|
|||
|
if ( ZDSecMgrPermitJoiningTimed == TRUE )
|
|||
|
{
|
|||
|
ZDSecMgrPermitJoiningEnabled = FALSE;
|
|||
|
ZDSecMgrPermitJoiningTimed = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrNewDeviceEvent
|
|||
|
*
|
|||
|
* @brief Process a the new device event, if found reset new device
|
|||
|
* event/timer.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return uint8 - found(TRUE:FALSE)
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrNewDeviceEvent( void )
|
|||
|
{
|
|||
|
uint8 found;
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
AddrMgrEntry_t addrEntry;
|
|||
|
associated_devices_t* assoc;
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
// initialize return results
|
|||
|
found = FALSE;
|
|||
|
|
|||
|
// look for device in the security init state
|
|||
|
assoc = AssocMatchDeviceStatus( DEV_SEC_INIT_STATUS );
|
|||
|
|
|||
|
if ( assoc != NULL )
|
|||
|
{
|
|||
|
// device found
|
|||
|
found = TRUE;
|
|||
|
|
|||
|
// check for preconfigured security
|
|||
|
if ( zgPreConfigKeys == TRUE )
|
|||
|
{
|
|||
|
// set association status to authenticated
|
|||
|
ZDSecMgrAssocDeviceAuth( assoc );
|
|||
|
}
|
|||
|
|
|||
|
// set up device info
|
|||
|
addrEntry.user = ADDRMGR_USER_DEFAULT;
|
|||
|
addrEntry.index = assoc->addrIdx;
|
|||
|
AddrMgrEntryGet( &addrEntry );
|
|||
|
|
|||
|
device.nwkAddr = assoc->shortAddr;
|
|||
|
device.extAddr = addrEntry.extAddr;
|
|||
|
device.parentAddr = NLME_GetShortAddr();
|
|||
|
device.secure = FALSE;
|
|||
|
device.devStatus = assoc->devStatus;
|
|||
|
|
|||
|
// process new device
|
|||
|
status = ZDSecMgrDeviceNew( &device );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
assoc->devStatus &= ~DEV_SEC_INIT_STATUS;
|
|||
|
}
|
|||
|
else if ( status == ZNwkUnknownDevice )
|
|||
|
{
|
|||
|
AssocRemove( addrEntry.extAddr );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return found;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEvent
|
|||
|
*
|
|||
|
* @brief Handle ZDO Security Manager event/timer(ZDO_SECMGR_EVENT).
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrEvent( void )
|
|||
|
{
|
|||
|
uint8 action;
|
|||
|
uint8 restart;
|
|||
|
uint16 index;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrCtrlData != NULL )
|
|||
|
{
|
|||
|
action = FALSE;
|
|||
|
restart = FALSE;
|
|||
|
|
|||
|
// update all the counters
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrCtrlData[index].state != ZDSECMGR_CTRL_NONE )
|
|||
|
{
|
|||
|
if ( ZDSecMgrCtrlData[index].cntr != 0 )
|
|||
|
{
|
|||
|
ZDSecMgrCtrlData[index].cntr--;
|
|||
|
}
|
|||
|
|
|||
|
if ( ( action == FALSE ) && ( ZDSecMgrCtrlData[index].cntr == 0 ) )
|
|||
|
{
|
|||
|
action = TRUE;
|
|||
|
|
|||
|
// update from control data
|
|||
|
device.parentAddr = ZDSecMgrCtrlData[index].parentAddr;
|
|||
|
device.secure = ZDSecMgrCtrlData[index].secure;
|
|||
|
device.ctrl = &ZDSecMgrCtrlData[index];
|
|||
|
|
|||
|
// set the user and address index
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.index = ZDSecMgrCtrlData[index].entry->ami;
|
|||
|
|
|||
|
// get the address data
|
|||
|
AddrMgrEntryGet( &entry );
|
|||
|
|
|||
|
// set device address data
|
|||
|
device.nwkAddr = entry.nwkAddr;
|
|||
|
device.extAddr = entry.extAddr;
|
|||
|
|
|||
|
// update from entry data
|
|||
|
ZDSecMgrDeviceCtrlHandler( &device );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
restart = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// check for timer restart
|
|||
|
if ( restart == TRUE )
|
|||
|
{
|
|||
|
osal_start_timerEx(ZDAppTaskID, ZDO_SECMGR_EVENT, 100 );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEstablishKeyCfm
|
|||
|
*
|
|||
|
* @brief Process the ZDO_EstablishKeyCfm_t message.
|
|||
|
*
|
|||
|
* @param cfm - [in] ZDO_EstablishKeyCfm_t confirmation
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrEstablishKeyCfm( ZDO_EstablishKeyCfm_t* cfm )
|
|||
|
{
|
|||
|
// send the NWK key
|
|||
|
if ( ( ZG_BUILD_COORDINATOR_TYPE ) && ( ZG_DEVICE_COORDINATOR_TYPE ) )
|
|||
|
{
|
|||
|
// update control for specified EXT address
|
|||
|
ZDSecMgrDeviceCtrlUpdate( cfm->partExtAddr, ZDSECMGR_CTRL_SKKE_DONE );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// this should be done when receiving the NWK key
|
|||
|
// if devState ==
|
|||
|
//if ( devState == DEV_END_DEVICE_UNAUTH )
|
|||
|
//osal_set_event( ZDAppTaskID, ZDO_DEVICE_AUTH );
|
|||
|
|
|||
|
// if not in joining state -- this should trigger an event for an
|
|||
|
// end point that requested SKKE
|
|||
|
// if ( devState == DEV_END_DEVICE )
|
|||
|
// devState == DEV_ROUTER;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrTCExtAddrCheck
|
|||
|
*
|
|||
|
* @brief Verifies if received ext. address matches TC ext. address.
|
|||
|
*
|
|||
|
* @param extAddr - Extended address to be verified.
|
|||
|
*
|
|||
|
* @return TRUE - extended address matches
|
|||
|
* FALSE - otherwise
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrTCExtAddrCheck( uint8* extAddr )
|
|||
|
{
|
|||
|
uint8 match;
|
|||
|
uint8 lookup[Z_EXTADDR_LEN];
|
|||
|
|
|||
|
match = FALSE;
|
|||
|
|
|||
|
if ( AddrMgrExtAddrLookup( APSME_TRUSTCENTER_NWKADDR, lookup ) )
|
|||
|
{
|
|||
|
match = AddrMgrExtAddrEqual( lookup, extAddr );
|
|||
|
}
|
|||
|
|
|||
|
return match;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrTCDataLoad
|
|||
|
*
|
|||
|
* @brief Stores the address of TC into address manager and stores the
|
|||
|
* preconfigured ZDSecMgrTCMasterKey to NV if zgPreConfigKeys
|
|||
|
* is set to TRUE.
|
|||
|
*
|
|||
|
* @param extAddr - Extended address to be verified.
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrTCDataLoad( uint8* extAddr )
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
uint16 keyNvId;
|
|||
|
uint8 masterKey[SEC_KEY_LEN];
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
// lookup using TC short address
|
|||
|
entry.user = ADDRMGR_USER_DEFAULT;
|
|||
|
entry.nwkAddr = zgTrustCenterAddr;
|
|||
|
|
|||
|
// Verify if TC address has been added to Address Manager
|
|||
|
if ( AddrMgrEntryLookupNwk( &entry ) != TRUE )
|
|||
|
{
|
|||
|
if ( ZDSecMgrAddrStore( zgTrustCenterAddr, extAddr, &ami ) == ZSuccess )
|
|||
|
{
|
|||
|
// if preconfigured load key
|
|||
|
if ( zgPreConfigKeys == TRUE )
|
|||
|
{
|
|||
|
if ( ZDSecMgrMasterKeyLookup( ami, &keyNvId ) != ZSuccess )
|
|||
|
{
|
|||
|
// temporary copy
|
|||
|
osal_memcpy( masterKey, ZDSecMgrTCMasterKey, SEC_KEY_LEN);
|
|||
|
|
|||
|
ZDSecMgrMasterKeyStore( ami, masterKey );
|
|||
|
|
|||
|
// remove copy of key in RAM
|
|||
|
osal_memset( masterKey, 0x00, SEC_KEY_LEN );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrEstablishKeyInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_EstablishKeyInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_EstablishKeyInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrEstablishKeyInd( ZDO_EstablishKeyInd_t* ind )
|
|||
|
{
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
APSME_EstablishKeyRsp_t rsp;
|
|||
|
|
|||
|
|
|||
|
// load Trust Center data if needed
|
|||
|
ZDSecMgrTCDataLoad( ind->initExtAddr );
|
|||
|
|
|||
|
if ( ZDSecMgrTCExtAddrCheck( ind->initExtAddr ) )
|
|||
|
{
|
|||
|
//IF (ind->srcAddr == APSME_TRUSTCENTER_NWKADDR)
|
|||
|
//OR
|
|||
|
//!ZDSecMgrTCAuthenticated
|
|||
|
//devtag.0604.critical
|
|||
|
//how is the parentAddr used here
|
|||
|
|
|||
|
// initial SKKE from Trust Center via parent
|
|||
|
device.nwkAddr = APSME_TRUSTCENTER_NWKADDR;
|
|||
|
device.parentAddr = ind->srcAddr;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Trust Center direct or E2E SKKE
|
|||
|
device.nwkAddr = ind->srcAddr;
|
|||
|
device.parentAddr = INVALID_NODE_ADDR;
|
|||
|
}
|
|||
|
|
|||
|
device.extAddr = ind->initExtAddr;
|
|||
|
//devtag.pro.security.0724.todo - verify usage
|
|||
|
device.secure = ind->nwkSecure;
|
|||
|
|
|||
|
// validate device for SKKE
|
|||
|
if ( ZDSecMgrDeviceValidateSKKE( &device ) == ZSuccess )
|
|||
|
{
|
|||
|
rsp.accept = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rsp.accept = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
rsp.dstAddr = ind->srcAddr;
|
|||
|
rsp.initExtAddr = &ind->initExtAddr[0];
|
|||
|
//devtag.0604.todo - remove obsolete
|
|||
|
rsp.apsSecure = ind->apsSecure;
|
|||
|
rsp.nwkSecure = ind->nwkSecure;
|
|||
|
|
|||
|
APSME_EstablishKeyRsp( &rsp );
|
|||
|
}
|
|||
|
|
|||
|
//devtag.pro.security
|
|||
|
#if 0
|
|||
|
void ZDSecMgrEstablishKeyInd( ZDO_EstablishKeyInd_t* ind )
|
|||
|
{
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
APSME_EstablishKeyRsp_t rsp;
|
|||
|
|
|||
|
|
|||
|
device.extAddr = ind->initExtAddr;
|
|||
|
device.secure = ind->secure;
|
|||
|
|
|||
|
if ( ind->secure == FALSE )
|
|||
|
{
|
|||
|
// SKKE from Trust Center is not secured between child and parent
|
|||
|
device.nwkAddr = APSME_TRUSTCENTER_NWKADDR;
|
|||
|
device.parentAddr = ind->srcAddr;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// SKKE from initiator should be secured
|
|||
|
device.nwkAddr = ind->srcAddr;
|
|||
|
device.parentAddr = INVALID_NODE_ADDR;
|
|||
|
}
|
|||
|
|
|||
|
rsp.dstAddr = ind->srcAddr;
|
|||
|
rsp.initExtAddr = &ind->initExtAddr[0];
|
|||
|
rsp.secure = ind->secure;
|
|||
|
|
|||
|
// validate device for SKKE
|
|||
|
if ( ZDSecMgrDeviceValidateSKKE( &device ) == ZSuccess )
|
|||
|
{
|
|||
|
rsp.accept = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
rsp.accept = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
APSME_EstablishKeyRsp( &rsp );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrTransportKeyInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_TransportKeyInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_TransportKeyInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrTransportKeyInd( ZDO_TransportKeyInd_t* ind )
|
|||
|
{
|
|||
|
uint8 index;
|
|||
|
uint8 zgPreConfigKey[SEC_KEY_LEN];
|
|||
|
|
|||
|
// load Trust Center data if needed
|
|||
|
ZDSecMgrTCDataLoad( ind->srcExtAddr );
|
|||
|
|
|||
|
if ( ind->keyType == KEY_TYPE_TC_MASTER )
|
|||
|
{
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
//ZDSecMgrTCMasterKey( ind );
|
|||
|
{
|
|||
|
if ( zgPreConfigKeys != TRUE )
|
|||
|
{
|
|||
|
// devtag.pro.security.todo - check if Trust Center address is configured and correct
|
|||
|
ZDSecMgrMasterKeyLoad( ind->srcExtAddr, ind->key );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// error condition - reject key
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( ( ind->keyType == KEY_TYPE_NWK ) ||
|
|||
|
( ind->keyType == 6 ) ||
|
|||
|
( ind->keyType == KEY_TYPE_NWK_HIGH ) )
|
|||
|
{
|
|||
|
// check for dummy NWK key (all zeros)
|
|||
|
for ( index = 0;
|
|||
|
( (index < SEC_KEY_LEN) && (ind->key[index] == 0) );
|
|||
|
index++ );
|
|||
|
|
|||
|
if ( index == SEC_KEY_LEN )
|
|||
|
{
|
|||
|
// load preconfigured key - once!!
|
|||
|
if ( !_NIB.nwkKeyLoaded )
|
|||
|
{
|
|||
|
ZDSecMgrReadKeyFromNv(ZCD_NV_PRECFGKEY, zgPreConfigKey);
|
|||
|
SSP_UpdateNwkKey( zgPreConfigKey, 0 );
|
|||
|
SSP_SwitchNwkKey( 0 );
|
|||
|
|
|||
|
// clear local copy of key
|
|||
|
osal_memset(zgPreConfigKey, 0x00, SEC_KEY_LEN);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
SSP_UpdateNwkKey( ind->key, ind->keySeqNum );
|
|||
|
if ( !_NIB.nwkKeyLoaded )
|
|||
|
{
|
|||
|
SSP_SwitchNwkKey( ind->keySeqNum );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// handle next step in authentication process
|
|||
|
ZDSecMgrAuthNwkKey();
|
|||
|
}
|
|||
|
else if ( ind->keyType == KEY_TYPE_TC_LINK )
|
|||
|
{
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
// This should not happen because TCLK should not be Tx
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( ind->keyType == KEY_TYPE_APP_MASTER )
|
|||
|
{
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
ZDSecMgrEntry_t* entryZD;
|
|||
|
|
|||
|
ZDSecMgrExtAddrLookup( ind->srcExtAddr, &ami );
|
|||
|
|
|||
|
if ( ind->initiator == TRUE )
|
|||
|
{
|
|||
|
// get the ami data
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.index = ami;
|
|||
|
AddrMgrEntryGet( &entry );
|
|||
|
|
|||
|
if ( entry.nwkAddr != INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
APSME_EstablishKeyReq_t req;
|
|||
|
ZDSecMgrMasterKeyLoad( ind->srcExtAddr, ind->key );
|
|||
|
|
|||
|
ZDSecMgrEntryLookupAMI( ami, &entryZD );
|
|||
|
|
|||
|
if ( entryZD == NULL )
|
|||
|
{
|
|||
|
// get new entry
|
|||
|
if ( ZDSecMgrEntryNew( &entryZD ) == ZSuccess )
|
|||
|
{
|
|||
|
// finish setting up entry
|
|||
|
entryZD->ami = ami;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
req.respExtAddr = ind->srcExtAddr;
|
|||
|
req.method = APSME_SKKE_METHOD;
|
|||
|
req.dstAddr = entry.nwkAddr;
|
|||
|
req.apsSecure = FALSE;
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
APSME_EstablishKeyReq( &req );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( ami == INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
// store new EXT address
|
|||
|
ZDSecMgrAddrStore( INVALID_NODE_ADDR, ind->srcExtAddr, &ami );
|
|||
|
}
|
|||
|
|
|||
|
ZDSecMgrMasterKeyLoad( ind->srcExtAddr, ind->key );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( ind->keyType == KEY_TYPE_APP_LINK )
|
|||
|
{
|
|||
|
if ( ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH ) ||
|
|||
|
( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD ) )
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
|
|||
|
// get the address index
|
|||
|
if ( ZDSecMgrExtAddrLookup( ind->srcExtAddr, &ami ) != ZSuccess )
|
|||
|
{
|
|||
|
// store new EXT address
|
|||
|
ZDSecMgrAddrStore( INVALID_NODE_ADDR, ind->srcExtAddr, &ami );
|
|||
|
ZDP_NwkAddrReq( ind->srcExtAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
|
|||
|
}
|
|||
|
|
|||
|
ZDSecMgrEntryLookupAMI( ami, &entry );
|
|||
|
|
|||
|
if ( entry == NULL )
|
|||
|
{
|
|||
|
// get new entry
|
|||
|
if ( ZDSecMgrEntryNew( &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
// finish setting up entry
|
|||
|
entry->ami = ami;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ZDSecMgrLinkKeySet( ind->srcExtAddr, ind->key );
|
|||
|
|
|||
|
#if defined NV_RESTORE
|
|||
|
ZDSecMgrWriteNV(); // Write the control record for the new established link key to NV.
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrUpdateDeviceInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_UpdateDeviceInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_UpdateDeviceInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrUpdateDeviceInd( ZDO_UpdateDeviceInd_t* ind )
|
|||
|
{
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
|
|||
|
device.nwkAddr = ind->devAddr;
|
|||
|
device.extAddr = ind->devExtAddr;
|
|||
|
device.parentAddr = ind->srcAddr;
|
|||
|
|
|||
|
//if ( ( ind->status == APSME_UD_SECURED_JOIN ) ||
|
|||
|
// ( ind->status == APSME_UD_UNSECURED_JOIN ) )
|
|||
|
//{
|
|||
|
// if ( ind->status == APSME_UD_SECURED_JOIN )
|
|||
|
// {
|
|||
|
// device.secure = TRUE;
|
|||
|
// }
|
|||
|
// else
|
|||
|
// {
|
|||
|
// device.secure = FALSE;
|
|||
|
// }
|
|||
|
|
|||
|
// try to join this device
|
|||
|
ZDSecMgrDeviceJoin( &device );
|
|||
|
//}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrRemoveDeviceInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_RemoveDeviceInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_RemoveDeviceInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrRemoveDeviceInd( ZDO_RemoveDeviceInd_t* ind )
|
|||
|
{
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
|
|||
|
// only accept from Trust Center
|
|||
|
if ( ind->srcAddr == APSME_TRUSTCENTER_NWKADDR )
|
|||
|
{
|
|||
|
// look up NWK address
|
|||
|
if ( APSME_LookupNwkAddr( ind->childExtAddr, &device.nwkAddr ) == TRUE )
|
|||
|
{
|
|||
|
device.parentAddr = NLME_GetShortAddr();
|
|||
|
device.extAddr = ind->childExtAddr;
|
|||
|
|
|||
|
// remove device
|
|||
|
ZDSecMgrDeviceRemove( &device );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrRequestKeyInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_RequestKeyInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_RequestKeyInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrRequestKeyInd( ZDO_RequestKeyInd_t* ind )
|
|||
|
{
|
|||
|
if ( ind->keyType == KEY_TYPE_NWK )
|
|||
|
{
|
|||
|
}
|
|||
|
else if ( ind->keyType == KEY_TYPE_APP_MASTER )
|
|||
|
{
|
|||
|
ZDSecMgrAppKeyReq( ind );
|
|||
|
}
|
|||
|
else if ( ind->keyType == KEY_TYPE_TC_LINK )
|
|||
|
{
|
|||
|
}
|
|||
|
//else ignore
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSwitchKeyInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_SwitchKeyInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_SwitchKeyInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrSwitchKeyInd( ZDO_SwitchKeyInd_t* ind )
|
|||
|
{
|
|||
|
SSP_SwitchNwkKey( ind->keySeqNum );
|
|||
|
|
|||
|
// Save if nv
|
|||
|
ZDApp_NVUpdate();
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthenticateInd
|
|||
|
*
|
|||
|
* @brief Process the ZDO_AuthenticateInd_t message.
|
|||
|
*
|
|||
|
* @param ind - [in] ZDO_AuthenticateInd_t indication
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAuthenticateInd( ZDO_AuthenticateInd_t* ind )
|
|||
|
{
|
|||
|
APSME_AuthenticateReq_t req;
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
|
|||
|
// update the address manager
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
// note:
|
|||
|
// required for EA processing, but ultimately EA logic could also use the
|
|||
|
// neighbor table to look up addresses -- also(IF using EA) the neighbor
|
|||
|
// table is supposed to have authentication states for neighbors
|
|||
|
//---------------------------------------------------------------------------
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.nwkAddr = ind->aps.initNwkAddr;
|
|||
|
AddrMgrExtAddrSet( entry.extAddr, ind->aps.initExtAddr );
|
|||
|
|
|||
|
if ( AddrMgrEntryUpdate( &entry ) == TRUE )
|
|||
|
{
|
|||
|
// set request fields
|
|||
|
req.nwkAddr = ind->aps.initNwkAddr;
|
|||
|
req.extAddr = ind->aps.initExtAddr;
|
|||
|
req.action = APSME_EA_ACCEPT;
|
|||
|
req.challenge = ind->aps.challenge;
|
|||
|
|
|||
|
// start EA processing
|
|||
|
APSME_AuthenticateReq( &req );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthenticateCfm
|
|||
|
*
|
|||
|
* @brief Process the ZDO_AuthenticateCfm_t message.
|
|||
|
*
|
|||
|
* @param cfm - [in] ZDO_AuthenticateCfm_t confirmation
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrAuthenticateCfm( ZDO_AuthenticateCfm_t* cfm )
|
|||
|
{
|
|||
|
if ( cfm->aps.status == ZSuccess )
|
|||
|
{
|
|||
|
if ( ( cfm->aps.initiator == TRUE ) && ( devState == DEV_END_DEVICE_UNAUTH ) )
|
|||
|
{
|
|||
|
// inform ZDO that device has been authenticated
|
|||
|
osal_set_event ( ZDAppTaskID, ZDO_DEVICE_AUTH );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if ( ZG_BUILD_COORDINATOR_TYPE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrUpdateNwkKey
|
|||
|
*
|
|||
|
* @brief Load a new NWK key and trigger a network wide update.
|
|||
|
*
|
|||
|
* @param key - [in] new NWK key
|
|||
|
* @param keySeqNum - [in] new NWK key sequence number
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrUpdateNwkKey( uint8* key, uint8 keySeqNum, uint16 dstAddr )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_TransportKeyReq_t req;
|
|||
|
|
|||
|
// initialize common elements of local variables
|
|||
|
if ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH )
|
|||
|
{
|
|||
|
req.keyType = KEY_TYPE_NWK_HIGH;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
req.keyType = KEY_TYPE_NWK;
|
|||
|
}
|
|||
|
|
|||
|
req.dstAddr = dstAddr;
|
|||
|
req.keySeqNum = keySeqNum;
|
|||
|
req.key = key;
|
|||
|
req.extAddr = NULL;
|
|||
|
req.nwkSecure = TRUE;
|
|||
|
req.apsSecure = TRUE;
|
|||
|
req.tunnel = NULL;
|
|||
|
|
|||
|
if (( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH ) ||
|
|||
|
( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD ))
|
|||
|
{
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
uint16 index;
|
|||
|
AddrMgrEntry_t addrEntry;
|
|||
|
|
|||
|
addrEntry.user = ADDRMGR_USER_SECURITY;
|
|||
|
|
|||
|
status = ZFailure;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
// find available entry
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami != INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
// return successful result
|
|||
|
entry = &ZDSecMgrEntries[index];
|
|||
|
|
|||
|
// get NWK address
|
|||
|
addrEntry.index = entry->ami;
|
|||
|
if ( AddrMgrEntryGet( &addrEntry ) == TRUE )
|
|||
|
{
|
|||
|
req.dstAddr = addrEntry.nwkAddr;
|
|||
|
req.extAddr = addrEntry.extAddr;
|
|||
|
status = APSME_TransportKeyReq( &req );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_RESIDENTIAL )
|
|||
|
{
|
|||
|
status = APSME_TransportKeyReq( &req );
|
|||
|
}
|
|||
|
|
|||
|
SSP_UpdateNwkKey( key, keySeqNum );
|
|||
|
|
|||
|
// Save if nv
|
|||
|
ZDApp_NVUpdate();
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
#endif // ( ZG_BUILD_COORDINATOR_TYPE )
|
|||
|
|
|||
|
#if ( ZG_BUILD_COORDINATOR_TYPE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSwitchNwkKey
|
|||
|
*
|
|||
|
* @brief Causes the NWK key to switch via a network wide command.
|
|||
|
*
|
|||
|
* @param keySeqNum - [in] new NWK key sequence number
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrSwitchNwkKey( uint8 keySeqNum, uint16 dstAddr )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_SwitchKeyReq_t req;
|
|||
|
|
|||
|
// initialize common elements of local variables
|
|||
|
req.dstAddr = dstAddr;
|
|||
|
req.keySeqNum = keySeqNum;
|
|||
|
|
|||
|
if (( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_PRO_HIGH ) ||
|
|||
|
( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_SE_STANDARD ))
|
|||
|
{
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
uint16 index;
|
|||
|
AddrMgrEntry_t addrEntry;
|
|||
|
|
|||
|
addrEntry.user = ADDRMGR_USER_SECURITY;
|
|||
|
|
|||
|
status = ZFailure;
|
|||
|
|
|||
|
// verify data is available
|
|||
|
if ( ZDSecMgrEntries != NULL )
|
|||
|
{
|
|||
|
// find available entry
|
|||
|
for ( index = 0; index < ZDSECMGR_ENTRY_MAX ; index++ )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami != INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
// return successful result
|
|||
|
entry = &ZDSecMgrEntries[index];
|
|||
|
|
|||
|
// get NWK address
|
|||
|
addrEntry.index = entry->ami;
|
|||
|
|
|||
|
if ( AddrMgrEntryGet( &addrEntry ) == TRUE )
|
|||
|
{
|
|||
|
req.dstAddr = addrEntry.nwkAddr;
|
|||
|
status = APSME_SwitchKeyReq( &req );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else // ( ZG_CHECK_SECURITY_MODE == ZG_SECURITY_RESIDENTIAL )
|
|||
|
{
|
|||
|
status = APSME_SwitchKeyReq( &req );
|
|||
|
}
|
|||
|
|
|||
|
SSP_SwitchNwkKey( keySeqNum );
|
|||
|
|
|||
|
// Save if nv
|
|||
|
ZDApp_NVUpdate();
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
#endif // ( ZG_BUILD_COORDINATOR_TYPE )
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrRequestAppKey
|
|||
|
*
|
|||
|
* @brief Request an application key with partner.
|
|||
|
*
|
|||
|
* @param partExtAddr - [in] partner extended address
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrRequestAppKey( uint8 *partExtAddr )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
APSME_RequestKeyReq_t req;
|
|||
|
|
|||
|
req.dstAddr = 0;
|
|||
|
req.keyType = KEY_TYPE_APP_MASTER;
|
|||
|
|
|||
|
req.partExtAddr = partExtAddr;
|
|||
|
status = APSME_RequestKeyReq( &req );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
#if ( ZG_BUILD_JOINING_TYPE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSetupPartner
|
|||
|
*
|
|||
|
* @brief Setup for application key partner.
|
|||
|
*
|
|||
|
* @param partNwkAddr - [in] partner network address
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrSetupPartner( uint16 partNwkAddr, uint8* partExtAddr )
|
|||
|
{
|
|||
|
AddrMgrEntry_t entry;
|
|||
|
ZStatus_t status;
|
|||
|
|
|||
|
status = ZFailure;
|
|||
|
|
|||
|
// update the address manager
|
|||
|
entry.user = ADDRMGR_USER_SECURITY;
|
|||
|
entry.nwkAddr = partNwkAddr;
|
|||
|
AddrMgrExtAddrSet( entry.extAddr, partExtAddr );
|
|||
|
|
|||
|
if ( AddrMgrEntryUpdate( &entry ) == TRUE )
|
|||
|
{
|
|||
|
status = ZSuccess;
|
|||
|
|
|||
|
// check for address discovery
|
|||
|
if ( partNwkAddr == INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
status = ZDP_NwkAddrReq( partExtAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
|
|||
|
}
|
|||
|
else if ( !AddrMgrExtAddrValid( partExtAddr ) )
|
|||
|
{
|
|||
|
status = ZDP_IEEEAddrReq( partNwkAddr, ZDP_ADDR_REQTYPE_SINGLE, 0, 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
#endif // ( ZG_BUILD_JOINING_TYPE )
|
|||
|
|
|||
|
#if ( ZG_BUILD_COORDINATOR_TYPE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAppKeyTypeSet
|
|||
|
*
|
|||
|
* @brief Set application key type.
|
|||
|
*
|
|||
|
* @param keyType - [in] application key type (KEY_TYPE_APP_MASTER@2 or
|
|||
|
* KEY_TYPE_APP_LINK@3
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAppKeyTypeSet( uint8 keyType )
|
|||
|
{
|
|||
|
if ( keyType == KEY_TYPE_APP_LINK )
|
|||
|
{
|
|||
|
ZDSecMgrAppKeyType = KEY_TYPE_APP_LINK;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ZDSecMgrAppKeyType = KEY_TYPE_APP_MASTER;
|
|||
|
}
|
|||
|
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* ZigBee Device Security Manager - Stub Implementations
|
|||
|
*/
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrMasterKeyGet (stubs APSME_MasterKeyGet)
|
|||
|
*
|
|||
|
* @brief Get MASTER key for specified EXT address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param pKeyNvId - [out] MASTER key NV ID
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrMasterKeyGet( uint8* extAddr, uint16* pKeyNvId )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
uint16 ami;
|
|||
|
|
|||
|
// lookup entry for specified EXT address
|
|||
|
status = ZDSecMgrExtAddrLookup( extAddr, &ami );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
ZDSecMgrMasterKeyLookup( ami, pKeyNvId );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*pKeyNvId = SEC_NO_KEY_NV_ID;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrLinkKeySet (stubs APSME_LinkKeySet)
|
|||
|
*
|
|||
|
* @brief Set <APSME_LinkKeyData_t> for specified NWK address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param data - [in] APSME_LinkKeyData_t
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrLinkKeySet( uint8* extAddr, uint8* key )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
APSME_LinkKeyData_t *pApsLinkKey = NULL;
|
|||
|
uint16 Index;
|
|||
|
|
|||
|
// lookup entry index for specified EXT address
|
|||
|
status = ZDSecMgrEntryLookupExtGetIndex( extAddr, &entry, &Index );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// point to NV item
|
|||
|
entry->keyNvId = ZCD_NV_APS_LINK_KEY_DATA_START + Index;
|
|||
|
|
|||
|
pApsLinkKey = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
if (pApsLinkKey != NULL)
|
|||
|
{
|
|||
|
// read the key form NV, keyNvId must be ZCD_NV_APS_LINK_KEY_DATA_START based
|
|||
|
osal_nv_read( entry->keyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey );
|
|||
|
|
|||
|
// set new values of the key
|
|||
|
osal_memcpy( pApsLinkKey->key, key, SEC_KEY_LEN );
|
|||
|
pApsLinkKey->rxFrmCntr = 0;
|
|||
|
pApsLinkKey->txFrmCntr = 0;
|
|||
|
|
|||
|
osal_nv_write( entry->keyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey );
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset(pApsLinkKey, 0x00, sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
osal_mem_free(pApsLinkKey);
|
|||
|
|
|||
|
// set initial values for counters in RAM
|
|||
|
ApsLinkKeyFrmCntr[entry->keyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].txFrmCntr = 0;
|
|||
|
ApsLinkKeyFrmCntr[entry->keyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].rxFrmCntr = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthenticationSet
|
|||
|
*
|
|||
|
* @brief Mark the specific device as authenticated or not
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param option - [in] authenticated or not
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAuthenticationSet( uint8* extAddr, ZDSecMgr_Authentication_Option option )
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
|
|||
|
|
|||
|
// lookup entry index for specified EXT address
|
|||
|
status = ZDSecMgrEntryLookupExt( extAddr, &entry );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
entry->authenticateOption = option;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAuthenticationCheck
|
|||
|
*
|
|||
|
* @brief Check if the specific device has been authenticated or not
|
|||
|
* For non-trust center device, always return TRUE
|
|||
|
*
|
|||
|
* @param shortAddr - [in] short address
|
|||
|
*
|
|||
|
* @return TRUE @ authenticated with CBKE
|
|||
|
* FALSE @ not authenticated
|
|||
|
*/
|
|||
|
|
|||
|
uint8 ZDSecMgrAuthenticationCheck( uint16 shortAddr )
|
|||
|
{
|
|||
|
#if defined (TC_LINKKEY_JOIN)
|
|||
|
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
uint8 extAddr[Z_EXTADDR_LEN];
|
|||
|
|
|||
|
// If the local device is not the trust center, always return TRUE
|
|||
|
if ( NLME_GetShortAddr() != zgTrustCenterAddr )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
// Otherwise, check the authentication option
|
|||
|
else if ( AddrMgrExtAddrLookup( shortAddr, extAddr ) )
|
|||
|
{
|
|||
|
// lookup entry index for specified EXT address
|
|||
|
if ( ZDSecMgrEntryLookupExt( extAddr, &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
if ( entry->authenticateOption != ZDSecMgr_Not_Authenticated )
|
|||
|
{
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
|
|||
|
#else
|
|||
|
(void)shortAddr; // Intentionally unreferenced parameter
|
|||
|
|
|||
|
// For non AMI/SE Profile, perform no check and always return TRUE.
|
|||
|
return TRUE;
|
|||
|
|
|||
|
#endif // TC_LINKKEY_JOIN
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrLinkKeyNVIdGet (stubs APSME_LinkKeyNVIdGet)
|
|||
|
*
|
|||
|
* @brief Get Key NV ID for specified NWK address.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
* @param keyNvId - [out] NV ID
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrLinkKeyNVIdGet(uint8* extAddr, uint16 *pKeyNvId)
|
|||
|
{
|
|||
|
ZStatus_t status;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
|
|||
|
// lookup entry index for specified NWK address
|
|||
|
status = ZDSecMgrEntryLookupExt( extAddr, &entry );
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
// return the index to the NV table
|
|||
|
*pKeyNvId = entry->keyNvId;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*pKeyNvId = SEC_NO_KEY_NV_ID;
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrIsLinkKeyValid (stubs APSME_IsLinkKeyValid)
|
|||
|
*
|
|||
|
* @brief Verifies if Link Key in NV has been set.
|
|||
|
*
|
|||
|
* @param extAddr - [in] EXT address
|
|||
|
*
|
|||
|
* @return TRUE - Link Key has been established
|
|||
|
* FALSE - Link Key in NV has default value.
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrIsLinkKeyValid(uint8* extAddr)
|
|||
|
{
|
|||
|
APSME_LinkKeyData_t *pKeyData;
|
|||
|
uint16 apsLinkKeyNvId;
|
|||
|
uint8 nullKey[SEC_KEY_LEN];
|
|||
|
uint8 status = FALSE;
|
|||
|
|
|||
|
// initialize default vealue to compare to
|
|||
|
osal_memset(nullKey, 0x00, SEC_KEY_LEN);
|
|||
|
|
|||
|
// check for APS link NV ID
|
|||
|
APSME_LinkKeyNVIdGet( extAddr, &apsLinkKeyNvId );
|
|||
|
|
|||
|
if (apsLinkKeyNvId != SEC_NO_KEY_NV_ID )
|
|||
|
{
|
|||
|
pKeyData = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
if (pKeyData != NULL)
|
|||
|
{
|
|||
|
// retrieve key from NV
|
|||
|
if ( osal_nv_read( apsLinkKeyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pKeyData) == ZSUCCESS)
|
|||
|
{
|
|||
|
// if stored key is different than default value, then a key has been established
|
|||
|
if (!osal_memcmp(pKeyData, nullKey, SEC_KEY_LEN))
|
|||
|
{
|
|||
|
status = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset(pKeyData, 0x00, sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
osal_mem_free(pKeyData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrKeyFwdToChild (stubs APSME_KeyFwdToChild)
|
|||
|
*
|
|||
|
* @brief Verify and process key transportation to child.
|
|||
|
*
|
|||
|
* @param ind - [in] APSME_TransportKeyInd_t
|
|||
|
*
|
|||
|
* @return uint8 - success(TRUE:FALSE)
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrKeyFwdToChild( APSME_TransportKeyInd_t* ind )
|
|||
|
{
|
|||
|
// verify from Trust Center
|
|||
|
if ( ind->srcAddr == APSME_TRUSTCENTER_NWKADDR )
|
|||
|
{
|
|||
|
// check for initial NWK key
|
|||
|
if ( ( ind->keyType == KEY_TYPE_NWK ) ||
|
|||
|
( ind->keyType == 6 ) ||
|
|||
|
( ind->keyType == KEY_TYPE_NWK_HIGH ) )
|
|||
|
{
|
|||
|
// set association status to authenticated
|
|||
|
ZDSecMgrAssocDeviceAuth( AssocGetWithExt( ind->dstExtAddr ) );
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAddLinkKey
|
|||
|
*
|
|||
|
* @brief Add the application link key to ZDSecMgr. Also mark the device
|
|||
|
* as authenticated in the authenticateOption. Note that this function
|
|||
|
* is hardwared to CBKE right now.
|
|||
|
*
|
|||
|
* @param shortAddr - short address of the partner device
|
|||
|
* @param extAddr - extended address of the partner device
|
|||
|
* @param key - link key
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAddLinkKey( uint16 shortAddr, uint8 *extAddr, uint8 *key)
|
|||
|
{
|
|||
|
uint16 ami;
|
|||
|
ZDSecMgrEntry_t* entry;
|
|||
|
|
|||
|
/* Store the device address in the addr manager */
|
|||
|
if( ZDSecMgrAddrStore( shortAddr, extAddr, &ami ) != ZSuccess )
|
|||
|
{
|
|||
|
/* Adding to Addr Manager fails */
|
|||
|
return ZFailure;
|
|||
|
}
|
|||
|
|
|||
|
/* Lookup entry using specified address index */
|
|||
|
ZDSecMgrEntryLookupAMI( ami, &entry );
|
|||
|
|
|||
|
// If no existing entry, create one
|
|||
|
if ( entry == NULL )
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntryNew( &entry ) == ZSuccess )
|
|||
|
{
|
|||
|
entry->ami = ami;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* Security Manager full */
|
|||
|
return ZBufferFull;
|
|||
|
}
|
|||
|
}
|
|||
|
// Write the link key
|
|||
|
APSME_LinkKeySet( extAddr, key );
|
|||
|
|
|||
|
#if defined (TC_LINKKEY_JOIN)
|
|||
|
// Mark the device as authenticated.
|
|||
|
ZDSecMgrAuthenticationSet( extAddr, ZDSecMgr_Authenticated_CBCK );
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined NV_RESTORE
|
|||
|
ZDSecMgrWriteNV(); // Write the new established link key to NV.
|
|||
|
#endif
|
|||
|
|
|||
|
return ZSuccess;
|
|||
|
}
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrInitNV
|
|||
|
*
|
|||
|
* @brief Initialize the SecMgr entry data in NV with all values set to 0
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return uint8 - <osal_nv_item_init> return codes
|
|||
|
*/
|
|||
|
uint8 ZDSecMgrInitNV(void)
|
|||
|
{
|
|||
|
|
|||
|
uint8 rtrn = osal_nv_item_init(ZCD_NV_APS_LINK_KEY_TABLE,
|
|||
|
(sizeof(nvDeviceListHdr_t) + (sizeof(ZDSecMgrEntry_t) * ZDSECMGR_ENTRY_MAX)), NULL);
|
|||
|
|
|||
|
// If the item does not already exist, set all values to 0
|
|||
|
if (rtrn != SUCCESS)
|
|||
|
{
|
|||
|
nvDeviceListHdr_t hdr;
|
|||
|
hdr.numRecs = 0;
|
|||
|
osal_nv_write(ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof(nvDeviceListHdr_t), &hdr);
|
|||
|
}
|
|||
|
|
|||
|
return rtrn;
|
|||
|
}
|
|||
|
#endif // NV_RESTORE
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDSecMgrWriteNV()
|
|||
|
*
|
|||
|
* @brief Save off the APS link key list to NV
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDSecMgrWriteNV( void )
|
|||
|
{
|
|||
|
uint16 i;
|
|||
|
nvDeviceListHdr_t hdr;
|
|||
|
|
|||
|
hdr.numRecs = 0;
|
|||
|
|
|||
|
if (ZDSecMgrEntries != NULL)
|
|||
|
{
|
|||
|
for ( i = 0; i < ZDSECMGR_ENTRY_MAX; i++ )
|
|||
|
{
|
|||
|
// Save off the record
|
|||
|
osal_nv_write( ZCD_NV_APS_LINK_KEY_TABLE,
|
|||
|
(uint16)((sizeof(nvDeviceListHdr_t)) + (i * sizeof(ZDSecMgrEntry_t))),
|
|||
|
sizeof(ZDSecMgrEntry_t), &ZDSecMgrEntries[i] );
|
|||
|
|
|||
|
if ( ZDSecMgrEntries[i].ami != INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
hdr.numRecs++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Save off the header
|
|||
|
osal_nv_write( ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof( nvDeviceListHdr_t ), &hdr );
|
|||
|
}
|
|||
|
#endif // NV_RESTORE
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrRestoreFromNV
|
|||
|
*
|
|||
|
* @brief Restore the APS Link Key entry data from NV. It does not restore
|
|||
|
* the key data itself as they remain in NV until they are used.
|
|||
|
* Only list data is restored.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return None.
|
|||
|
*/
|
|||
|
static void ZDSecMgrRestoreFromNV( void )
|
|||
|
{
|
|||
|
nvDeviceListHdr_t hdr;
|
|||
|
APSME_LinkKeyData_t *pApsLinkKey = NULL;
|
|||
|
|
|||
|
if ((osal_nv_read(ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof(nvDeviceListHdr_t), &hdr) == ZSUCCESS) &&
|
|||
|
((hdr.numRecs > 0) && (hdr.numRecs <= ZDSECMGR_ENTRY_MAX)))
|
|||
|
{
|
|||
|
uint8 x;
|
|||
|
|
|||
|
pApsLinkKey = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
for (x = 0; x < ZDSECMGR_ENTRY_MAX; x++)
|
|||
|
{
|
|||
|
if ( osal_nv_read( ZCD_NV_APS_LINK_KEY_TABLE,
|
|||
|
(uint16)(sizeof(nvDeviceListHdr_t) + (x * sizeof(ZDSecMgrEntry_t))),
|
|||
|
sizeof(ZDSecMgrEntry_t), &ZDSecMgrEntries[x] ) == SUCCESS )
|
|||
|
{
|
|||
|
// update data only for valid entries
|
|||
|
if ( ZDSecMgrEntries[x].ami != INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
if (pApsLinkKey != NULL)
|
|||
|
{
|
|||
|
// read the key form NV, keyNvId must be ZCD_NV_APS_LINK_KEY_DATA_START based
|
|||
|
osal_nv_read( ZDSecMgrEntries[x].keyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey );
|
|||
|
|
|||
|
// set new values for the counter
|
|||
|
pApsLinkKey->txFrmCntr += ( MAX_APS_FRAMECOUNTER_CHANGES + 1 );
|
|||
|
|
|||
|
// restore values for counters in RAM
|
|||
|
ApsLinkKeyFrmCntr[ZDSecMgrEntries[x].keyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].txFrmCntr =
|
|||
|
pApsLinkKey->txFrmCntr;
|
|||
|
|
|||
|
ApsLinkKeyFrmCntr[ZDSecMgrEntries[x].keyNvId - ZCD_NV_APS_LINK_KEY_DATA_START].rxFrmCntr =
|
|||
|
pApsLinkKey->rxFrmCntr;
|
|||
|
|
|||
|
osal_nv_write( ZDSecMgrEntries[x].keyNvId, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey );
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset(pApsLinkKey, 0x00, sizeof(APSME_LinkKeyData_t));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (pApsLinkKey != NULL)
|
|||
|
{
|
|||
|
osal_mem_free(pApsLinkKey);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // NV_RESTORE
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDSecMgrSetDefaultNV
|
|||
|
*
|
|||
|
* @brief Write the defaults to NV for Entry table and for APS key data table
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrSetDefaultNV( void )
|
|||
|
{
|
|||
|
uint16 i;
|
|||
|
nvDeviceListHdr_t hdr;
|
|||
|
ZDSecMgrEntry_t secMgrEntry;
|
|||
|
APSME_LinkKeyData_t *pApsLinkKey = NULL;
|
|||
|
|
|||
|
// Initialize the header
|
|||
|
hdr.numRecs = 0;
|
|||
|
|
|||
|
// clear the header
|
|||
|
osal_nv_write(ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof(nvDeviceListHdr_t), &hdr);
|
|||
|
|
|||
|
osal_memset( &secMgrEntry, 0x00, sizeof(ZDSecMgrEntry_t) );
|
|||
|
|
|||
|
for ( i = 0; i < ZDSECMGR_ENTRY_MAX; i++ )
|
|||
|
{
|
|||
|
// Clear the record
|
|||
|
osal_nv_write( ZCD_NV_APS_LINK_KEY_TABLE,
|
|||
|
(uint16)((sizeof(nvDeviceListHdr_t)) + (i * sizeof(ZDSecMgrEntry_t))),
|
|||
|
sizeof(ZDSecMgrEntry_t), &secMgrEntry );
|
|||
|
}
|
|||
|
|
|||
|
pApsLinkKey = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
if (pApsLinkKey != NULL)
|
|||
|
{
|
|||
|
osal_memset( pApsLinkKey, 0x00, sizeof(APSME_LinkKeyData_t) );
|
|||
|
|
|||
|
for ( i = 0; i < ZDSECMGR_ENTRY_MAX; i++ )
|
|||
|
{
|
|||
|
// Clear the record
|
|||
|
osal_nv_write( (ZCD_NV_APS_LINK_KEY_DATA_START + i), 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pApsLinkKey);
|
|||
|
}
|
|||
|
|
|||
|
osal_mem_free(pApsLinkKey);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDSecMgrUpdateNV()
|
|||
|
*
|
|||
|
* @brief Updates one entry of the APS link key table to NV
|
|||
|
*
|
|||
|
* @param index - to the entry in security manager table
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
static void ZDSecMgrUpdateNV( uint16 index )
|
|||
|
{
|
|||
|
nvDeviceListHdr_t hdr;
|
|||
|
|
|||
|
if (ZDSecMgrEntries != NULL)
|
|||
|
{
|
|||
|
// Save off the record
|
|||
|
osal_nv_write( ZCD_NV_APS_LINK_KEY_TABLE,
|
|||
|
(uint16)((sizeof(nvDeviceListHdr_t)) + (index * sizeof(ZDSecMgrEntry_t))),
|
|||
|
sizeof(ZDSecMgrEntry_t), &ZDSecMgrEntries[index] );
|
|||
|
}
|
|||
|
|
|||
|
if (osal_nv_read(ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof(nvDeviceListHdr_t), &hdr) == ZSUCCESS)
|
|||
|
{
|
|||
|
if ( ZDSecMgrEntries[index].ami == INVALID_NODE_ADDR )
|
|||
|
{
|
|||
|
if (hdr.numRecs > 0)
|
|||
|
{
|
|||
|
hdr.numRecs--;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
hdr.numRecs++;
|
|||
|
}
|
|||
|
|
|||
|
// Save off the header
|
|||
|
osal_nv_write( ZCD_NV_APS_LINK_KEY_TABLE, 0, sizeof( nvDeviceListHdr_t ), &hdr );
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // NV_RESTORE
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrAPSRemove
|
|||
|
*
|
|||
|
* @brief Remove device from network.
|
|||
|
*
|
|||
|
* @param nwkAddr - device's NWK address
|
|||
|
* @param extAddr - device's Extended address
|
|||
|
* @param parentAddr - parent's NWK address
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrAPSRemove( uint16 nwkAddr, uint8 *extAddr, uint16 parentAddr )
|
|||
|
{
|
|||
|
ZDSecMgrDevice_t device;
|
|||
|
|
|||
|
if ( ( nwkAddr == INVALID_NODE_ADDR ) ||
|
|||
|
( extAddr == NULL ) ||
|
|||
|
( parentAddr == INVALID_NODE_ADDR ) )
|
|||
|
{
|
|||
|
return ( ZFailure );
|
|||
|
}
|
|||
|
|
|||
|
device.nwkAddr = nwkAddr;
|
|||
|
device.extAddr = extAddr;
|
|||
|
device.parentAddr = parentAddr;
|
|||
|
|
|||
|
// remove device
|
|||
|
ZDSecMgrDeviceRemove( &device );
|
|||
|
|
|||
|
return ( ZSuccess );
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn APSME_TCLinkKeyInit
|
|||
|
*
|
|||
|
* @brief Initialize the NV table for preconfigured TC link key
|
|||
|
*
|
|||
|
* When zgUseDefaultTCL is set to TRUE, the default preconfig
|
|||
|
* Trust Center Link Key is written to NV. A single tclk is used
|
|||
|
* by all devices joining the network.
|
|||
|
*
|
|||
|
* @param setDefault - TRUE to set default values
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void APSME_TCLinkKeyInit(uint8 setDefault)
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
APSME_TCLinkKey_t tcLinkKey;
|
|||
|
uint8 rtrn;
|
|||
|
|
|||
|
// Initialize all NV items for preconfigured TCLK
|
|||
|
for( i = 0; i < ZDSECMGR_TC_DEVICE_MAX; i++ )
|
|||
|
{
|
|||
|
// Making sure data is cleared for every key all the time
|
|||
|
osal_memset( &tcLinkKey, 0x00, sizeof(APSME_TCLinkKey_t) );
|
|||
|
|
|||
|
// Initialize first element of the table with the default TCLK
|
|||
|
if((i == 0) && ( zgUseDefaultTCLK == TRUE ))
|
|||
|
{
|
|||
|
osal_memset( tcLinkKey.extAddr, 0xFF, Z_EXTADDR_LEN );
|
|||
|
osal_memcpy( tcLinkKey.key, defaultTCLinkKey, SEC_KEY_LEN);
|
|||
|
}
|
|||
|
|
|||
|
// If the item doesn't exist in NV memory, create and initialize
|
|||
|
// it with the default value passed in, either defaultTCLK or 0
|
|||
|
rtrn = osal_nv_item_init( (ZCD_NV_TCLK_TABLE_START + i),
|
|||
|
sizeof(APSME_TCLinkKey_t), &tcLinkKey);
|
|||
|
|
|||
|
if (rtrn == SUCCESS)
|
|||
|
{
|
|||
|
// set the Frame counters to 0 to existing keys in NV
|
|||
|
osal_nv_read( ( ZCD_NV_TCLK_TABLE_START + i), 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), &tcLinkKey );
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
if (setDefault == TRUE)
|
|||
|
{
|
|||
|
// clear the value stored in NV
|
|||
|
tcLinkKey.txFrmCntr = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// increase the value stored in NV
|
|||
|
tcLinkKey.txFrmCntr += ( MAX_TCLK_FRAMECOUNTER_CHANGES + 1 );
|
|||
|
}
|
|||
|
#else
|
|||
|
// Clear the counters if NV_RESTORE is not enabled and this NV item
|
|||
|
// already existed in the NV memory
|
|||
|
tcLinkKey.txFrmCntr = 0;
|
|||
|
tcLinkKey.rxFrmCntr = 0;
|
|||
|
#endif // NV_RESTORE
|
|||
|
|
|||
|
osal_nv_write( ( ZCD_NV_TCLK_TABLE_START + i), 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), &tcLinkKey );
|
|||
|
|
|||
|
// set initial values for counters in RAM
|
|||
|
TCLinkKeyFrmCntr[i].txFrmCntr = tcLinkKey.txFrmCntr;
|
|||
|
TCLinkKeyFrmCntr[i].rxFrmCntr = tcLinkKey.rxFrmCntr;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( &tcLinkKey, 0x00, sizeof(APSME_TCLinkKey_t) );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn APSME_TCLinkKeySync
|
|||
|
*
|
|||
|
* @brief Sync Trust Center LINK key data.
|
|||
|
*
|
|||
|
* @param srcAddr - [in] srcAddr
|
|||
|
* @param si - [in, out] SSP_Info_t
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t APSME_TCLinkKeySync( uint16 srcAddr, SSP_Info_t* si )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
ZStatus_t status = ZSecNoKey;
|
|||
|
APSME_TCLinkKey_t tcLinkKey;
|
|||
|
uint32 *tclkRxFrmCntr;
|
|||
|
|
|||
|
// Look up the IEEE address of the trust center if it's available
|
|||
|
if ( AddrMgrExtAddrValid( si->extAddr ) == FALSE )
|
|||
|
{
|
|||
|
APSME_LookupExtAddr( srcAddr, si->extAddr );
|
|||
|
}
|
|||
|
|
|||
|
// Look up the TC link key associated with the device
|
|||
|
// or the default TC link key (extAddr is all FFs), whichever is found
|
|||
|
for( i = 0; i < ZDSECMGR_TC_DEVICE_MAX; i++ )
|
|||
|
{
|
|||
|
// Read entry i of the TC link key table from NV
|
|||
|
osal_nv_read( (ZCD_NV_TCLK_TABLE_START + i), 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), &tcLinkKey );
|
|||
|
|
|||
|
if( AddrMgrExtAddrEqual(si->extAddr, tcLinkKey.extAddr) ||
|
|||
|
APSME_IsDefaultTCLK(tcLinkKey.extAddr))
|
|||
|
{
|
|||
|
tclkRxFrmCntr = &TCLinkKeyFrmCntr[i].rxFrmCntr;
|
|||
|
|
|||
|
// verify that the incoming frame counter is valid
|
|||
|
if ( si->frmCntr >= *tclkRxFrmCntr )
|
|||
|
{
|
|||
|
// set the keyNvId to use
|
|||
|
si->keyNvId = (ZCD_NV_TCLK_TABLE_START + i);
|
|||
|
|
|||
|
// update the rx frame counter
|
|||
|
*tclkRxFrmCntr = si->frmCntr + 1;
|
|||
|
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
status = ZSecOldFrmCount;
|
|||
|
}
|
|||
|
// break from the loop
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( &tcLinkKey, 0x00, sizeof(APSME_TCLinkKey_t) );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn APSME_TCLinkKeyLoad
|
|||
|
*
|
|||
|
* @brief Load Trust Center LINK key data.
|
|||
|
*
|
|||
|
* @param dstAddr - [in] dstAddr
|
|||
|
* @param si - [in, out] SSP_Info_t
|
|||
|
*
|
|||
|
* @return ZStatus_t
|
|||
|
*/
|
|||
|
ZStatus_t APSME_TCLinkKeyLoad( uint16 dstAddr, SSP_Info_t* si )
|
|||
|
{
|
|||
|
uint8 i;
|
|||
|
ZStatus_t status = ZSecNoKey;
|
|||
|
APSME_TCLinkKey_t tcLinkKey;
|
|||
|
AddrMgrEntry_t addrEntry;
|
|||
|
uint32 *tclkTxFrmCntr;
|
|||
|
uint8 extAddrFound;
|
|||
|
uint8 defaultTCLKIdx = ZDSECMGR_TC_DEVICE_MAX;
|
|||
|
|
|||
|
// Look up the ami of the srcAddr if available
|
|||
|
addrEntry.user = ADDRMGR_USER_DEFAULT;
|
|||
|
addrEntry.nwkAddr = dstAddr;
|
|||
|
|
|||
|
APSME_LookupExtAddr( dstAddr, si->extAddr );
|
|||
|
|
|||
|
extAddrFound = AddrMgrExtAddrValid( si->extAddr );
|
|||
|
|
|||
|
// Look up the TC link key associated with the device
|
|||
|
// or the master TC link key (ami = 0xFFFF), whichever is found
|
|||
|
for( i = 0; i < ZDSECMGR_TC_DEVICE_MAX; i++ )
|
|||
|
{
|
|||
|
// Read entry i of the TC link key table from NV
|
|||
|
osal_nv_read( (ZCD_NV_TCLK_TABLE_START + i), 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), &tcLinkKey );
|
|||
|
|
|||
|
if( extAddrFound && AddrMgrExtAddrEqual(si->extAddr, tcLinkKey.extAddr) )
|
|||
|
{
|
|||
|
status = ZSuccess;
|
|||
|
|
|||
|
break; // break from the loop
|
|||
|
}
|
|||
|
|
|||
|
if ( APSME_IsDefaultTCLK(tcLinkKey.extAddr) )
|
|||
|
{
|
|||
|
if ( !extAddrFound )
|
|||
|
{
|
|||
|
status = ZSuccess;
|
|||
|
|
|||
|
break; // break from the loop
|
|||
|
}
|
|||
|
|
|||
|
// Remember the default TCLK index
|
|||
|
defaultTCLKIdx = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( (status != ZSuccess) && (defaultTCLKIdx < ZDSECMGR_TC_DEVICE_MAX) )
|
|||
|
{
|
|||
|
// Exact match was not found; use the default TC Link Key
|
|||
|
i = defaultTCLKIdx;
|
|||
|
status = ZSuccess;
|
|||
|
}
|
|||
|
|
|||
|
if ( status == ZSuccess )
|
|||
|
{
|
|||
|
tclkTxFrmCntr = &TCLinkKeyFrmCntr[i].txFrmCntr;
|
|||
|
|
|||
|
// set the keyNvId to use
|
|||
|
si->keyNvId = (ZCD_NV_TCLK_TABLE_START + i);
|
|||
|
|
|||
|
// update link key related fields
|
|||
|
si->keyID = SEC_KEYID_LINK;
|
|||
|
si->frmCntr = *tclkTxFrmCntr;
|
|||
|
|
|||
|
// update outgoing frame counter
|
|||
|
(*tclkTxFrmCntr)++;
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
// write periodically to NV
|
|||
|
if ( !(*tclkTxFrmCntr % MAX_TCLK_FRAMECOUNTER_CHANGES) )
|
|||
|
{
|
|||
|
// set the flag to write key to NV
|
|||
|
TCLinkKeyFrmCntr[i].pendingFlag = TRUE;
|
|||
|
|
|||
|
// Notify the ZDApp that the frame counter has changed.
|
|||
|
osal_set_event( ZDAppTaskID, ZDO_TCLK_FRAMECOUNTER_CHANGE );
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
// If no TC link key found, remove the device from the address manager
|
|||
|
if ( (status != ZSuccess) && (AddrMgrEntryLookupNwk(&addrEntry) == TRUE) )
|
|||
|
{
|
|||
|
AddrMgrEntryRelease( &addrEntry );
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( &tcLinkKey, 0x00, sizeof(APSME_TCLinkKey_t) );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn APSME_IsDefaultTCLK
|
|||
|
*
|
|||
|
* @brief Return TRUE or FALSE based on the extended address. If the
|
|||
|
* input ext address is all FFs, it means the trust center link
|
|||
|
* assoiciated with the address is the default trust center link key
|
|||
|
*
|
|||
|
* @param extAddr - [in] extended address
|
|||
|
*
|
|||
|
* @return uint8 TRUE/FALSE
|
|||
|
*/
|
|||
|
uint8 APSME_IsDefaultTCLK( uint8 *extAddr )
|
|||
|
{
|
|||
|
uint8 i = 0;
|
|||
|
|
|||
|
if( extAddr == NULL )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
while( i++ < Z_EXTADDR_LEN )
|
|||
|
{
|
|||
|
if( *extAddr++ != 0xFF )
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrNwkKeyInit
|
|||
|
*
|
|||
|
* @brief Initialize the NV items for
|
|||
|
* ZCD_NV_NWKKEY,
|
|||
|
* ZCD_NV_NWK_ACTIVE_KEY_INFO and
|
|||
|
* ZCD_NV_NWK_ALTERN_KEY_INFO
|
|||
|
*
|
|||
|
* @param setDefault
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrNwkKeyInit(uint8 setDefault)
|
|||
|
{
|
|||
|
uint8 status;
|
|||
|
nwkKeyDesc nwkKey;
|
|||
|
|
|||
|
// Initialize NV items for NWK key, this structure contains the frame counter
|
|||
|
// and is only used when NV_RESTORE is enabled
|
|||
|
nwkActiveKeyItems keyItems;
|
|||
|
|
|||
|
osal_memset( &keyItems, 0, sizeof( nwkActiveKeyItems ) );
|
|||
|
|
|||
|
status = osal_nv_item_init( ZCD_NV_NWKKEY, sizeof(nwkActiveKeyItems), (void *)&keyItems );
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if ((status == SUCCESS) && (setDefault == TRUE))
|
|||
|
{
|
|||
|
// clear NV data to default values
|
|||
|
osal_nv_write( ZCD_NV_NWKKEY, 0, sizeof(nwkActiveKeyItems), &keyItems );
|
|||
|
}
|
|||
|
#else
|
|||
|
(void)setDefault; // to eliminate compiler warning
|
|||
|
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if (status == SUCCESS)
|
|||
|
{
|
|||
|
osal_nv_write( ZCD_NV_NWKKEY, 0, sizeof(nwkActiveKeyItems), &keyItems );
|
|||
|
}
|
|||
|
#endif // defined (NV_RESTORE)
|
|||
|
|
|||
|
// Initialize NV items for NWK Active and Alternate keys. These items are used
|
|||
|
// all the time, independently of NV_RESTORE being set or not
|
|||
|
osal_memset( &nwkKey, 0x00, sizeof(nwkKey) );
|
|||
|
|
|||
|
status = osal_nv_item_init( ZCD_NV_NWK_ACTIVE_KEY_INFO, sizeof(nwkKey), &nwkKey);
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if ((status == SUCCESS) && (setDefault == TRUE))
|
|||
|
{
|
|||
|
// clear NV data to default values
|
|||
|
osal_nv_write( ZCD_NV_NWK_ACTIVE_KEY_INFO, 0, sizeof(nwkKey), &nwkKey );
|
|||
|
}
|
|||
|
#else
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if (status == SUCCESS)
|
|||
|
{
|
|||
|
osal_nv_write( ZCD_NV_NWK_ACTIVE_KEY_INFO, 0, sizeof(nwkKey), &nwkKey );
|
|||
|
}
|
|||
|
#endif // defined (NV_RESTORE)
|
|||
|
|
|||
|
status = osal_nv_item_init( ZCD_NV_NWK_ALTERN_KEY_INFO, sizeof(nwkKey), &nwkKey );
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if ((status == SUCCESS) && (setDefault == TRUE))
|
|||
|
{
|
|||
|
// clear NV data to default values
|
|||
|
osal_nv_write( ZCD_NV_NWK_ALTERN_KEY_INFO, 0, sizeof(nwkKey), &nwkKey );
|
|||
|
}
|
|||
|
#else
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if (status == SUCCESS)
|
|||
|
{
|
|||
|
osal_nv_write( ZCD_NV_NWK_ALTERN_KEY_INFO, 0, sizeof(nwkKey), &nwkKey );
|
|||
|
}
|
|||
|
#endif // defined (NV_RESTORE)
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn ZDSecMgrReadKeyFromNv
|
|||
|
*
|
|||
|
* @brief Looks for a specific key in NV based on Index value
|
|||
|
*
|
|||
|
* @param keyNvId - Index of key to look in NV
|
|||
|
* valid values are:
|
|||
|
* ZCD_NV_NWK_ACTIVE_KEY_INFO
|
|||
|
* ZCD_NV_NWK_ALTERN_KEY_INFO
|
|||
|
* ZCD_NV_TCLK_TABLE_START + <offset_in_table>
|
|||
|
* ZCD_NV_APS_LINK_KEY_DATA_START + <offset_in_table>
|
|||
|
* ZCD_NV_MASTER_KEY_DATA_START + <offset_in_table>
|
|||
|
* ZCD_NV_PRECFGKEY
|
|||
|
*
|
|||
|
* @param *keyinfo - Data is read into this buffer.
|
|||
|
*
|
|||
|
* @return SUCCESS if NV data was copied to the keyinfo parameter .
|
|||
|
* Otherwise, NV_OPER_FAILED for failure.
|
|||
|
*/
|
|||
|
ZStatus_t ZDSecMgrReadKeyFromNv(uint16 keyNvId, void *keyinfo)
|
|||
|
{
|
|||
|
if ((keyNvId == ZCD_NV_NWK_ACTIVE_KEY_INFO) ||
|
|||
|
(keyNvId == ZCD_NV_NWK_ALTERN_KEY_INFO))
|
|||
|
{
|
|||
|
// get NWK active or alternate key from NV
|
|||
|
return (osal_nv_read(keyNvId,
|
|||
|
osal_offsetof(nwkKeyDesc, key),
|
|||
|
SEC_KEY_LEN,
|
|||
|
keyinfo));
|
|||
|
}
|
|||
|
else if ((keyNvId >= ZCD_NV_TCLK_TABLE_START) &&
|
|||
|
(keyNvId < (ZCD_NV_TCLK_TABLE_START + ZDSECMGR_TC_DEVICE_MAX)))
|
|||
|
{
|
|||
|
// Read entry keyNvId of the TC link key table from NV. keyNvId should be
|
|||
|
// ZCD_NV_TCLK_TABLE_START + <offset_in_table>
|
|||
|
return (osal_nv_read(keyNvId,
|
|||
|
osal_offsetof(APSME_TCLinkKey_t, key),
|
|||
|
SEC_KEY_LEN,
|
|||
|
keyinfo));
|
|||
|
}
|
|||
|
else if ((keyNvId >= ZCD_NV_APS_LINK_KEY_DATA_START) &&
|
|||
|
(keyNvId < (ZCD_NV_APS_LINK_KEY_DATA_START + ZDSECMGR_ENTRY_MAX)))
|
|||
|
{
|
|||
|
// Read entry keyNvId of the APS link key table from NV. keyNvId should be
|
|||
|
// ZCD_NV_APS_LINK_KEY_DATA_START + <offset_in_table>
|
|||
|
return (osal_nv_read(keyNvId,
|
|||
|
osal_offsetof(APSME_LinkKeyData_t, key),
|
|||
|
SEC_KEY_LEN,
|
|||
|
keyinfo));
|
|||
|
}
|
|||
|
else if ((keyNvId >= ZCD_NV_MASTER_KEY_DATA_START) &&
|
|||
|
(keyNvId < (ZCD_NV_MASTER_KEY_DATA_START + ZDSECMGR_MASTERKEY_MAX)))
|
|||
|
{
|
|||
|
// Read entry keyNvId of the MASTER key table from NV. keyNvId should be
|
|||
|
// ZCD_NV_MASTER_KEY_DATA_START + <offset_in_table>
|
|||
|
return (osal_nv_read(keyNvId,
|
|||
|
osal_offsetof(ZDSecMgrMasterKeyData_t, key),
|
|||
|
SEC_KEY_LEN,
|
|||
|
keyinfo));
|
|||
|
}
|
|||
|
else if (keyNvId == ZCD_NV_PRECFGKEY)
|
|||
|
{
|
|||
|
// Read entry keyNvId of the Preconfig key from NV.
|
|||
|
return (osal_nv_read(keyNvId,
|
|||
|
0,
|
|||
|
SEC_KEY_LEN,
|
|||
|
keyinfo));
|
|||
|
}
|
|||
|
|
|||
|
return NV_OPER_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrApsLinkKeyInit
|
|||
|
*
|
|||
|
* @brief Initialize the NV table for Application link keys
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrApsLinkKeyInit(void)
|
|||
|
{
|
|||
|
APSME_LinkKeyData_t pApsLinkKey;
|
|||
|
uint8 i;
|
|||
|
uint8 status;
|
|||
|
|
|||
|
// Initialize all NV items for APS link key, if not exist already.
|
|||
|
osal_memset( &pApsLinkKey, 0x00, sizeof(APSME_LinkKeyData_t) );
|
|||
|
|
|||
|
for( i = 0; i < ZDSECMGR_ENTRY_MAX; i++ )
|
|||
|
{
|
|||
|
status = osal_nv_item_init( (ZCD_NV_APS_LINK_KEY_DATA_START + i),
|
|||
|
sizeof(APSME_LinkKeyData_t), &pApsLinkKey );
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
(void)status; // to eliminate compiler warning
|
|||
|
#else
|
|||
|
// reset the values of NV items if NV_RESTORE is not enabled
|
|||
|
if (status == SUCCESS)
|
|||
|
{
|
|||
|
osal_nv_write( (ZCD_NV_APS_LINK_KEY_DATA_START + i), 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), &pApsLinkKey );
|
|||
|
|
|||
|
}
|
|||
|
#endif // defined (NV_RESTORE)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrInitNVKeyTables
|
|||
|
*
|
|||
|
* @brief Initialize the NV table for All keys: NWK, Master, TCLK and APS
|
|||
|
*
|
|||
|
* @param setDefault - TRUE to set default values
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrInitNVKeyTables(uint8 setDefault)
|
|||
|
{
|
|||
|
ZDSecMgrNwkKeyInit(setDefault);
|
|||
|
ZDSecMgrMasterKeyInit();
|
|||
|
ZDSecMgrApsLinkKeyInit();
|
|||
|
APSME_TCLinkKeyInit(setDefault);
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSaveApsLinkKey
|
|||
|
*
|
|||
|
* @brief Save APS Link Key to NV. It will loop through all the keys
|
|||
|
* to see which one to save.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrSaveApsLinkKey(void)
|
|||
|
{
|
|||
|
APSME_LinkKeyData_t *pKeyData = NULL;
|
|||
|
int i;
|
|||
|
|
|||
|
pKeyData = (APSME_LinkKeyData_t *)osal_mem_alloc(sizeof(APSME_LinkKeyData_t));
|
|||
|
|
|||
|
if (pKeyData != NULL)
|
|||
|
{
|
|||
|
// checks all pending flags to know which one to save
|
|||
|
for (i = 0; i < ZDSECMGR_ENTRY_MAX; i++)
|
|||
|
{
|
|||
|
if (ApsLinkKeyFrmCntr[i].pendingFlag == TRUE)
|
|||
|
{
|
|||
|
// retrieve key from NV
|
|||
|
if (osal_nv_read(ZCD_NV_APS_LINK_KEY_DATA_START + i, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pKeyData) == SUCCESS)
|
|||
|
{
|
|||
|
pKeyData->txFrmCntr = ApsLinkKeyFrmCntr[i].txFrmCntr;
|
|||
|
pKeyData->rxFrmCntr = ApsLinkKeyFrmCntr[i].rxFrmCntr;
|
|||
|
|
|||
|
// Write the APS link key back to the NV
|
|||
|
osal_nv_write(ZCD_NV_APS_LINK_KEY_DATA_START + i, 0,
|
|||
|
sizeof(APSME_LinkKeyData_t), pKeyData);
|
|||
|
|
|||
|
// clear the pending write flag
|
|||
|
ApsLinkKeyFrmCntr[i].pendingFlag = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( pKeyData, 0x00, sizeof(APSME_LinkKeyData_t) );
|
|||
|
|
|||
|
osal_mem_free(pKeyData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrSaveTCLinkKey
|
|||
|
*
|
|||
|
* @brief Save TC Link Key to NV. It will loop through all the keys
|
|||
|
* to see which one to save.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrSaveTCLinkKey(void)
|
|||
|
{
|
|||
|
APSME_TCLinkKey_t *pKeyData = NULL;
|
|||
|
uint16 i;
|
|||
|
|
|||
|
pKeyData = (APSME_TCLinkKey_t *)osal_mem_alloc(sizeof(APSME_TCLinkKey_t));
|
|||
|
|
|||
|
if (pKeyData != NULL)
|
|||
|
{
|
|||
|
for( i = 0; i < ZDSECMGR_TC_DEVICE_MAX; i++ )
|
|||
|
{
|
|||
|
if (TCLinkKeyFrmCntr[i].pendingFlag == TRUE)
|
|||
|
{
|
|||
|
if (osal_nv_read(ZCD_NV_TCLK_TABLE_START + i, 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), pKeyData) == SUCCESS)
|
|||
|
{
|
|||
|
pKeyData->txFrmCntr = TCLinkKeyFrmCntr[i].txFrmCntr;
|
|||
|
pKeyData->rxFrmCntr = TCLinkKeyFrmCntr[i].rxFrmCntr;
|
|||
|
|
|||
|
// Write the TC link key back to the NV
|
|||
|
osal_nv_write(ZCD_NV_TCLK_TABLE_START + i, 0,
|
|||
|
sizeof(APSME_TCLinkKey_t), pKeyData);
|
|||
|
|
|||
|
// clear the pending write flag
|
|||
|
TCLinkKeyFrmCntr[i].pendingFlag = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// clear copy of key in RAM
|
|||
|
osal_memset( pKeyData, 0x00, sizeof(APSME_TCLinkKey_t) );
|
|||
|
|
|||
|
osal_mem_free(pKeyData);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#if defined ( ZBA_FALLBACK_NWKKEY )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrFallbackNwkKey
|
|||
|
*
|
|||
|
* @brief Use the ZBA fallback network key.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrFallbackNwkKey( void )
|
|||
|
{
|
|||
|
if ( !_NIB.nwkKeyLoaded )
|
|||
|
{
|
|||
|
uint8 fallbackKey[SEC_KEY_LEN];
|
|||
|
|
|||
|
ZDSecMgrReadKeyFromNv( ZCD_NV_PRECFGKEY, fallbackKey );
|
|||
|
SSP_UpdateNwkKey( fallbackKey, 0);
|
|||
|
SSP_SwitchNwkKey( 0 );
|
|||
|
|
|||
|
// clear local copy of key
|
|||
|
osal_memset( fallbackKey, 0x00, SEC_KEY_LEN );
|
|||
|
|
|||
|
// handle next step in authentication process
|
|||
|
ZDSecMgrAuthNwkKey();
|
|||
|
}
|
|||
|
}
|
|||
|
#endif // defined ( ZBA_FALLBACK_NWKKEY )
|
|||
|
|
|||
|
#if defined ( NV_RESTORE )
|
|||
|
/******************************************************************************
|
|||
|
* @fn ZDSecMgrClearNVKeyValues
|
|||
|
*
|
|||
|
* @brief If NV_RESTORE is enabled and the status of the network needs
|
|||
|
* default values this fuction clears ZCD_NV_NWKKEY,
|
|||
|
* ZCD_NV_NWK_ACTIVE_KEY_INFO and ZCD_NV_NWK_ALTERN_KEY_INFO link
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void ZDSecMgrClearNVKeyValues(void)
|
|||
|
{
|
|||
|
nwkActiveKeyItems keyItems;
|
|||
|
nwkKeyDesc nwkKey;
|
|||
|
|
|||
|
osal_memset(&keyItems, 0x00, sizeof(nwkActiveKeyItems));
|
|||
|
|
|||
|
osal_nv_write(ZCD_NV_NWKKEY, 0, sizeof(nwkActiveKeyItems), &keyItems);
|
|||
|
|
|||
|
// Initialize NV items for NWK Active and Alternate keys.
|
|||
|
osal_memset( &nwkKey, 0x00, sizeof(nwkKeyDesc) );
|
|||
|
|
|||
|
osal_nv_write(ZCD_NV_NWK_ACTIVE_KEY_INFO, 0, sizeof(nwkKeyDesc), &nwkKey);
|
|||
|
|
|||
|
osal_nv_write(ZCD_NV_NWK_ALTERN_KEY_INFO, 0, sizeof(nwkKeyDesc), &nwkKey);
|
|||
|
}
|
|||
|
#endif // defined ( NV_RESTORE )
|
|||
|
|
|||
|
/******************************************************************************
|
|||
|
******************************************************************************/
|