/********************************************************************* * Function: CIPHER_STATUS PHYCipher(INPUT CIPHER_MODE CipherMode, INPUT SECURITY_INPUT SecurityInput, OUTPUT BYTE *OutData, OUTPUT BYTE *OutDataLen) * * PreCondition: Called by DataEncrypt or DataDecrypt * * Input: CIPHER_MODE CipherMode - Either MODE_ENCRYPTION or MODE_DECRYPTION * SECURITY_INPUT SecurityInput - Cipher operation input. Filled by DataEncryption or DataDecryption * * Output: BYTE *OutData - Encrypted or decrypted data, including MIC * BYTE *OutDataLen - Data length after cipher operation, including MIC bytes * CIPHER_STATUS - Cipher operation result * * Side Effects: Input data get encrypted or decrypted and put into output buffer * * Overview: This is the function that invoke the hardware cipher to do encryption and decryption ********************************************************************/ CIPHER_STATUS PHYCipher(INPUT CIPHER_MODE CipherMode, INPUT SECURITY_INPUT SecurityInput, OUTPUT BYTE *OutData, OUTPUT BYTE *OutDataLen) { BYTE CipherRetry = CIPHER_RETRY; BYTE i; WORD loc; // make sure that we are not in the process of sending out a packet loc = 0; while( !TxStat.finished ) { loc++; if( loc > 0xfff ) { PHY_RESETn = 0; MACEnable(); TxStat.finished = 1; } #if defined(__C30__) if(RF_INT_PIN == 0) { RFIF = 1; } #else if( PORTBbits.RB0 == 0 ) { INTCONbits.INT0IF = 1; } #endif Nop(); } CipherOperationStart: // step 1, set the normal FIFO // step 1a, fill the length of the header if( SecurityInput.cipherMode > 0x04 ) { PHYSetLongRAMAddr(0x000, SecurityInput.HeaderLen+SecurityInput.TextLen+14); } else { PHYSetLongRAMAddr(0x000, SecurityInput.HeaderLen+14); } // step 1b, fill the length of the packet if( CipherMode == MODE_ENCRYPTION ) { PHYSetLongRAMAddr(0x001, SecurityInput.TextLen+SecurityInput.HeaderLen+14); } else { PHYSetLongRAMAddr(0x001, SecurityInput.TextLen+SecurityInput.HeaderLen+16);// two additional bytes FCS } // step 1c, fill the header loc = 0x002; for(i = 0; i < SecurityInput.HeaderLen; i++) { PHYSetLongRAMAddr(loc++, SecurityInput.Header[i]); } // step 1d, fill the auxilary header PHYSetLongRAMAddr(loc++, SecurityInput.SecurityControl.Val | nwkSecurityLevel); for(i = 0; i < 4; i++) { PHYSetLongRAMAddr(loc++, SecurityInput.FrameCounter.v[i]); } for(i = 0; i < 8; i++) { PHYSetLongRAMAddr(loc++, SecurityInput.SourceAddress->v[i]); } PHYSetLongRAMAddr(loc++, SecurityInput.KeySeq); // step 1e, fill the data to be encrypted or decrypted for(i = 0; i < SecurityInput.TextLen; i++) { PHYSetLongRAMAddr(loc++, SecurityInput.InputText[i]); } // step 2, set nounce SetNonce(SecurityInput.SourceAddress, &(SecurityInput.FrameCounter), SecurityInput.SecurityControl); // step 3, set TXNFIFO security key loc = 0x280; for(i = 0; i < 16; i++) { PHYSetLongRAMAddr(loc++, SecurityInput.SecurityKey[i]); } // step 4, set cipher mode either encryption or decryption if( CipherMode == MODE_ENCRYPTION ) { PHYSetShortRAMAddr(SECCR2, 0x40); } else { PHYSetShortRAMAddr(SECCR2, 0x80); } // step 5, fill the encryption mode PHYSetShortRAMAddr(SECCR0, SecurityInput.cipherMode); TxStat.cipher = 1; // step 6, trigger PHYSetShortRAMAddr(TXNMTRIG, 0x03); i = 0; while( TxStat.cipher ) { #if defined(__C30__) if(RF_INT_PIN == 0) { RFIF = 1; } #else if( PORTBbits.RB0 == 0 ) { INTCONbits.INT0IF = 1; } #endif i++; #if 1 // in rare condition, the hardware cipher will stall. Handle such condition // here if(i > 0x1f) { // in certain rare cases, the RX and Upper Cipher will block each other // in case that happens, reset the RF chip to avoid total disfunction ConsolePutROMString((ROM char*)"X"); PHYTasksPending.Val = 0; PHY_RESETn = 0; MACEnable(); break; } #endif } //PHYSetShortRAMAddr(0x0d, 0x01); // if MIC is generated, check MIC here if( (CipherMode == MODE_DECRYPTION) && (SecurityInput.cipherMode != 0x01)) { BYTE MIC_check = PHYGetShortRAMAddr(0x30); if( MIC_check & 0x40 ) { PHYSetShortRAMAddr(0x30, 0x40); // there is a small chance that the hardware cipher will not // decrypt for the first time, retry to solve this problem. // details documented in errata if( CipherRetry ) { CipherRetry--; for(loc = 0; loc < 0x255; loc++); goto CipherOperationStart; } PHY_RESETn = 0; MACEnable(); ConsolePutROMString((ROM char *)"MIC error"); return CIPHER_MIC_ERROR; } } if( TxStat.success ) { // get output data length *OutDataLen = PHYGetLongRAMAddr(0x001) - SecurityInput.HeaderLen - 14; // get the index of data encrypted or decrypted loc = 0x002 + SecurityInput.HeaderLen + 14; // if this is a decryption operation, get rid of the useless MIC and two bytes of FCS if( CipherMode == MODE_DECRYPTION ) { switch( SecurityInput.cipherMode ) { case 0x02: case 0x05: *OutDataLen -= 18; break; case 0x03: case 0x06: *OutDataLen -= 10; break; case 0x04: case 0x07: *OutDataLen -= 6; break; case 0x01: *OutDataLen-= 2; break; } } // copy the output data for(i = 0; i < *OutDataLen; i++) { OutData[i] = PHYGetLongRAMAddr(loc++); } return CIPHER_SUCCESS; } return CIPHER_ERROR; }
BYTE NVMInit( void ) { BYTE *memBlock; BYTE result = 0; WORD NodeDescriptorValiditykey; WORD validitykey; SPIUnselectEEPROM(); CLRWDT(); #if defined(I_SUPPORT_BINDINGS) result |= NVMalloc( sizeof(WORD), &bindingValidityKey ); result |= NVMalloc( sizeof(BINDING_RECORD) * MAX_BINDINGS, &apsBindingTable ); result |= NVMalloc( BINDING_USAGE_MAP_SIZE, &bindingTableUsageMap ); result |= NVMalloc( BINDING_USAGE_MAP_SIZE, &bindingTableSourceNodeMap ); #endif #if defined(USE_EXTERNAL_NVM) && defined(STORE_MAC_EXTERNAL) result |= NVMalloc( sizeof(WORD), &macLongAddrValidityKey ); result |= NVMalloc( sizeof(LONG_ADDR), &macLongAddrEE ); GetMACAddressValidityKey(&validitykey); if (validitykey != MAC_ADDRESS_VALID) { PutMACAddress(macLongAddrByte); MACEnable(); } #endif #if defined(I_SUPPORT_GROUP_ADDRESSING) result |= NVMalloc( sizeof(APS_GROUP_RECORD) * MAX_GROUP, &apsGroupAddressTable); #endif result |= NVMalloc( sizeof(NEIGHBOR_TABLE_INFO), &neighborTableInfo ); result |= NVMalloc( sizeof(NEIGHBOR_RECORD) * MAX_NEIGHBORS, &neighborTable ); #if defined(I_SUPPORT_ROUTING) && !defined(USE_TREE_ROUTING_ONLY) result |= NVMalloc( sizeof(ROUTING_ENTRY) * ROUTING_TABLE_SIZE, &routingTable ); #endif result |= NVMalloc( sizeof(WORD), &nodeDescriptorValidityKey); result |= NVMalloc( sizeof(NODE_DESCRIPTOR), &configNodeDescriptor ); result |= NVMalloc( sizeof(NODE_POWER_DESCRIPTOR), &configPowerDescriptor ); // NOTE - the simple descriptor for the ZDO has been removed in later specs, so the "+1" will go away. result |= NVMalloc( sizeof(NODE_SIMPLE_DESCRIPTOR) * (NUM_USER_ENDPOINTS+1), &configSimpleDescriptors ); result |= NVMalloc(sizeof(PERSISTENCE_PIB), &persistencePIB); #if MAX_APS_ADDRESSES > 0 result |= NVMalloc( sizeof(WORD), &apsAddressMapValidityKey ); result |= NVMalloc( sizeof(APS_ADDRESS_MAP) * MAX_APS_ADDRESSES, &apsAddressMap ); #endif #if defined(I_SUPPORT_SECURITY) result |= NVMalloc( sizeof(BYTE), &nwkActiveKeyNumber ); result |= NVMalloc( sizeof(NETWORK_KEY_INFO) * NUM_NWK_KEYS, &networkKeyInfo ); /* location for outgoing nwk frame counters */ result |= NVMalloc(( sizeof(DWORD_VAL)*2), &outgoingFrameCounterIndex); #endif #if I_SUPPORT_LINK_KEY == 1 result |= NVMalloc( sizeof(APS_KEY_PAIR_DESCRIPTOR) * MAX_APPLICATION_LINK_KEY_SUPPORTED, &appLinkKeyTable ); #endif #if I_SUPPORT_LINK_KEY == 1 #if I_SUPPORT_MULTIPLE_TC_LINK_KEY == 1 result |= NVMalloc( sizeof(TC_LINK_KEY_TABLE) * MAX_TC_LINK_KEY_SUPPORTED, &TCLinkKeyTable ); #endif #endif #if defined(I_SUPPORT_COMMISSIONING) result |= NVMalloc( sizeof(BYTE), &activeSASIndex ); result |= NVMalloc( sizeof(STARTUP_ATTRIBUTE_SET), &default_SAS ); result |= NVMalloc( (sizeof(STARTUP_ATTRIBUTE_SET) * 2), &Commissioned_SAS ); #endif #if defined(I_SUPPORT_SECURITY) result |= NVMalloc(( sizeof(DWORD_VAL)*2), &outgoingFrameCounterIndex); #endif if (!result) { #ifdef ENABLE_DEBUG ConsolePutROMString((ROM char * const)"Initializing EE...\r\n"); #endif #ifdef I_SUPPORT_COMMISSIONING BYTE index; #endif // If the MAC Address is stored externally, then the user is responsible // for programming it. They may choose to preprogram the EEPROM, or program // it based on other input. It should be programmed with the PutMACAddress() macro. /* // Initialize the trust center address //below is code is comment #if defined(I_SUPPORT_SECURITY) && (defined(I_AM_COORDINATOR) || defined(I_AM_TRUST_CENTER)) if ((memBlock = SRAMalloc( 8 )) == NULL) { result = 1; } else { int i = 0; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[0]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[1]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[2]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[3]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[4]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[5]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[6]; memBlock[i++] = current_SAS.spas.TrustCenterAddress.v[7]; NVMWrite( trustCenterLongAddr, memBlock, 8 ); SRAMfree( memBlock ); } #endif*/ GetNodeDescriptorValidity(&NodeDescriptorValiditykey); if (NodeDescriptorValiditykey != NODE_DESCRIPTOR_VALID) { // Initialize the descriptors using the ROM copy. if ((memBlock = SRAMalloc( sizeof(NODE_DESCRIPTOR) )) == NULL) { result = 1; } else { memcpy( memBlock, (void *)&Config_Node_Descriptor, sizeof(NODE_DESCRIPTOR) ); NVMWrite( configNodeDescriptor, memBlock, sizeof(NODE_DESCRIPTOR) ); SRAMfree( memBlock ); NodeDescriptorValiditykey = NODE_DESCRIPTOR_VALID; PutNodeDescriptorValidity(&NodeDescriptorValiditykey); } } if ((memBlock = SRAMalloc( sizeof(NODE_POWER_DESCRIPTOR) )) == NULL) { result = 1; } else { memcpy( memBlock, (void *)&Config_Power_Descriptor, sizeof(NODE_POWER_DESCRIPTOR) ); NVMWrite( configPowerDescriptor, memBlock, sizeof(NODE_POWER_DESCRIPTOR) ); SRAMfree( memBlock ); } if ((memBlock = SRAMalloc( sizeof(NODE_SIMPLE_DESCRIPTOR) )) == NULL) { result = 1; } else { // NOTE - Currently, a simple descriptor is needed for the ZDO endpoint. When this requirement // goes away, take off the "+1". int i; for (i=0; i<NUM_USER_ENDPOINTS+1; i++) { if(NOW_I_AM_A_ROUTER()) memcpypgm2ram( memBlock, (void *)Config_Simple_Descriptors_MTR + i * sizeof(NODE_SIMPLE_DESCRIPTOR), sizeof(NODE_SIMPLE_DESCRIPTOR) ); else if (NOW_I_AM_A_CORDINATOR()) memcpypgm2ram( memBlock, (void *)Config_Simple_Descriptors_ESP + i * sizeof(NODE_SIMPLE_DESCRIPTOR), sizeof(NODE_SIMPLE_DESCRIPTOR) ); //memcpypgm2ram( memBlock, (void *)Config_Simple_Descriptors + i * sizeof(NODE_SIMPLE_DESCRIPTOR), sizeof(NODE_SIMPLE_DESCRIPTOR) ); NVMWrite( configSimpleDescriptors + (WORD)i * (WORD)sizeof(NODE_SIMPLE_DESCRIPTOR), memBlock, sizeof(NODE_SIMPLE_DESCRIPTOR) ); } SRAMfree( memBlock ); } #ifdef I_SUPPORT_COMMISSIONING GetSAS(¤t_SAS,default_SAS); if( MSDCL_Commission.ValidCleanStartUp == MSDCL_COMMISSION_DATA_VALID) { memcpy(¤t_SAS.spas.ExtendedPANId.v[0], &MSDCL_Commission.ExtendedPANId[0], sizeof(MSDCL_Commission.ExtendedPANId) ); current_SAS.spas.PreconfiguredLinkKey[15]= MSDCL_Commission.LinkKey[15]; current_SAS.spas.PreconfiguredLinkKey[14]= MSDCL_Commission.LinkKey[14]; current_SAS.spas.PreconfiguredLinkKey[13]= MSDCL_Commission.LinkKey[13]; current_SAS.spas.PreconfiguredLinkKey[12]= MSDCL_Commission.LinkKey[12]; current_SAS.spas.PreconfiguredLinkKey[11]= MSDCL_Commission.LinkKey[11]; current_SAS.spas.PreconfiguredLinkKey[10]= MSDCL_Commission.LinkKey[10]; current_SAS.spas.PreconfiguredLinkKey[9]= MSDCL_Commission.LinkKey[9]; current_SAS.spas.PreconfiguredLinkKey[8]= MSDCL_Commission.LinkKey[8]; current_SAS.spas.PreconfiguredLinkKey[7]= MSDCL_Commission.LinkKey[7]; current_SAS.spas.PreconfiguredLinkKey[6]= MSDCL_Commission.LinkKey[6]; current_SAS.spas.PreconfiguredLinkKey[5]= MSDCL_Commission.LinkKey[5]; current_SAS.spas.PreconfiguredLinkKey[4]= MSDCL_Commission.LinkKey[4]; current_SAS.spas.PreconfiguredLinkKey[3]= MSDCL_Commission.LinkKey[3]; current_SAS.spas.PreconfiguredLinkKey[2]= MSDCL_Commission.LinkKey[2]; current_SAS.spas.PreconfiguredLinkKey[1]= MSDCL_Commission.LinkKey[1]; current_SAS.spas.PreconfiguredLinkKey[0]= MSDCL_Commission.LinkKey[0]; current_SAS.spas.ChannelMask.Val = MSDCL_Commission.ChannelMask.Val & 0x07FFF800UL; current_SAS.spas.StartupControl = MSDCL_Commission.StartupStatus; //PutNeighborTableInfo(); //MSDCL_Commission.DoCleanStartUp = 0; //NVMWrite( MSDCL_Commission_Locations, (BYTE*)&MSDCL_Commission, sizeof(MSDCL_Commission) ); } if(current_SAS.validitykey != SAS_TABLE_VALID) { Initdefault_SAS(); index = 0xFF; PutActiveSASIndex(&index); } #endif } CLRWDT(); return result; }