3.1.2 Using the Library
ICM can be configured to cover different purposes:
- Digest mode: Get the Hash values according to the region configurations
- Compare mode: Compare the Hash value previously calculated with the new Hash value obtained from the same memory region
- Monitor mode: The ICM passes through the Main List once to calculate the message digest of the monitored area and begins monitoring
Digest mode
/* Hash area */ uint32_t outputSHA[0x20] __ALIGNED(128); /* Memory region0 area */ volatile uint32_t appData[16] = { 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678 }; void SYS_Initialize ( void* data ) { (...) ICM_Initialize(); (...) } static void lAppHashCompletedCallback(ICM_REGION_ID regionId) { if (regionId == ICM_REGION_0) { appData.hashCompleted = true; } } void APP_Initialize ( void ) { appData.state = APP_STATE_CONFIGURE_ICM; appData.hashCompleted = false; (void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA)); } void APP_Tasks ( void ) { switch ( appData.state ) { case APP_STATE_CONFIGURE_ICM: { ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appData, sizeof(appData)); ICM_SetHashAreaAddress((uint32_t)outputSHA); // Set ICM callbacks (Hash Completed)) ICM_CallbackRegister(ICM_INTERRUPT_RHC, lAppHashCompletedCallback); ICM_EnableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0); // Compute de Hash values ICM_Enable(); appData.state = APP_STATE_WAIT_DIGEST; break; } case APP_STATE_WAIT_DIGEST: { if (appData.hashCompleted == true) { ICM_Disable(); } break; } default: { /* TODO: Handle error in application's state machine. */ break; } } }
Compare mode
/* Hash area */ uint32_t outputSHA[0x20] __ALIGNED(128); /* Memory region0 area */ volatile uint32_t appMessageSHA0[16] = { 0x80636261, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x18000000 }; /* Memory region1 main list area, * string "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" */ volatile uint32_t appMessageSHA1[16] = { 0x64636261, 0x65646362, 0x66656463, 0x67666564, 0x68676665, 0x69686766, 0x6a696867, 0x6b6a6968, 0x6c6b6a69, 0x6d6c6b6a, 0x6e6d6c6b, 0x6f6e6d6c, 0x706f6e6d, 0x71706f6e, 0x00000080, 0x00000000 }; /* Memory region1 secondary list area */ volatile uint32_t appMessageSHA1Sec[16] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0010000 }; void SYS_Initialize ( void* data ) { (...) ICM_Initialize(); (...) } static void lAppHashCompletedCallback(ICM_REGION_ID regionId) { if (regionId == ICM_REGION_0) { appData.hashCompleted = true; } } static void _appDigestMismatchCallback(ICM_REGION_ID regionId) { if (regionId == ICM_REGION_0) { printf("...ICM_REGION_0 is modified\r\n"); appData.data0Changed = true; } else if (regionId == ICM_REGION_1) { printf("...ICM_REGION_1 is modified\r\n"); appData.data1Changed = true; } } void APP_Initialize ( void ) { appData.state = APP_STATE_CONFIGURE_ICM; appData.hashCompleted = false; appData.data0Changed = false; appData.data1Changed = false; (void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA)); } void APP_Tasks ( void ) { switch ( appData.state ) { case APP_STATE_CONFIGURE_ICM: { ICM_SECONDARY_LIST icmSecList; ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appMessageSHA0, sizeof(appMessageSHA0)); ICM_SetRegionDescriptorData(ICM_REGION_1, (uint32_t *)appMessageSHA1, sizeof(appMessageSHA1)); ICM_SetHashAreaAddress((uint32_t)outputSHA); // Configure Secondary List of the region 1 appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_1); appData.pRegionDescriptor->secondaryList = &icmSecList; icmSecList.startAddress = (uint32_t)appMessageSHA1Sec; icmSecList.transferSize = ICM_GetTransferSize(sizeof(appMessageSHA1Sec)); icmSecList.nextAddress = 0; // Compute de Hash values ICM_Enable(); appData.state = APP_STATE_WAIT_DIGEST; break; } case APP_STATE_WAIT_DIGEST: { if (appData.hashCompleted == true) { appData.state = APP_STATE_MODIFY_REGION0_DATA; } break; } case APP_STATE_MODIFY_REGION0_DATA: { // Set Compare mode appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_0); appData.pRegionDescriptor->config.bitfield.compareMode = 1; appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_1); appData.pRegionDescriptor->config.bitfield.compareMode = 1; // Set ICM callbacks ICM_CallbackRegister(ICM_INTERRUPT_RDM, _appDigestMismatchCallback); ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_0); ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_1); printf("Change Data in Region 0\r\n"); appMessageSHA0[2] = 1; ICM_Enable(); appData.state = APP_STATE_WAIT_REGION0_MISMATCH; break; } case APP_STATE_WAIT_REGION0_MISMATCH: { if (appData.data0Changed == true) { appData.data0Changed = false; printf("...appMessageSHA0 content has been modified\r\n\r\n"); // restore data content appMessageSHA0[2] = 0; appData.state = APP_STATE_MODIFY_REGION1_DATA; } break; } case APP_STATE_MODIFY_REGION1_DATA: { printf("Change Data in Region 1\r\n"); appMessageSHA1[5] = 0xAA5555AA; ICM_Enable(); appData.state = APP_STATE_WAIT_REGION1_MISMATCH; break; } case APP_STATE_WAIT_REGION1_MISMATCH: { if (appData.data1Changed == true) { appData.data1Changed = false; printf("...appMessageSHA1 content has been modified\r\n\r\n"); // restore data content appMessageSHA1[5] = 0x69686766; appData.state = APP_STATE_MODIFY_REGION1SEC_DATA; } break; } case APP_STATE_MODIFY_REGION1SEC_DATA: { printf("Change Data in Region 1 - secondary list\r\n"); appMessageSHA1Sec[5] = 0xAA5555AA; ICM_Enable(); appData.state = APP_STATE_WAIT_REGION1SEC_MISMATCH; break; } case APP_STATE_WAIT_REGION1SEC_MISMATCH: { if (appData.data1Changed == true) { appData.data1Changed = false; printf("...appMessageSHA1Sec content has been modified\r\n\r\n"); appData.state = APP_STATE_IDLE; } break; } case APP_STATE_IDLE: default: { /* TODO: Handle error in application's state machine. */ break; } } }
Monitor mode
/* Hash area */ uint32_t outputSHA[0x20] __ALIGNED(128); /* Memory region0 area */ volatile uint32_t appMonitoredData[16] = { 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678 }; void SYS_Initialize ( void* data ) { (...) ICM_Initialize(); (...) } static void lAppHashCompletedCallback(ICM_REGION_ID regionId) { if (regionId == ICM_REGION_0) { appData.hashCompleted = true; } } static void lAppDigestMismatchCallback(ICM_REGION_ID regionId) { if (regionId == ICM_REGION_0) { appData.dataChanged = true; } } void lAppTimerCallback ( uintptr_t context ) { appData.timerExpired = true; } void APP_Initialize ( void ) { appData.state = APP_STATE_CONFIGURE_ICM; appData.hashCompleted = false; appData.dataChanged = false; appData.timerExpired = false; (void *)memset((uint8_t *)outputSHA, 0, sizeof(outputSHA)); } void APP_Tasks ( void ) { switch ( appData.state ) { case APP_STATE_CONFIGURE_ICM: { ICM_SetRegionDescriptorData(ICM_REGION_0, (uint32_t *)appData, sizeof(appData)); ICM_SetHashAreaAddress((uint32_t)outputSHA); // Set ICM callbacks (Hash Completed)) ICM_CallbackRegister(ICM_INTERRUPT_RHC, lAppHashCompletedCallback); ICM_EnableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0); // Compute de Hash values ICM_Enable(); appData.state = APP_STATE_WAIT_DIGEST; break; } case APP_STATE_WAIT_DIGEST: { if (appData.hashCompleted == true) { ICM_Disable(); // Disable ICM callbacks (Hash Completed)) ICM_CallbackRegister(ICM_INTERRUPT_RHC, NULL); ICM_DisableInterrupt(ICM_INTERRUPT_RHC, ICM_REGION_0); // Set ICM Monitor Mode appData.pRegionDescriptor = ICM_GetRegionDescriptor(ICM_REGION_0); appData.pRegionDescriptor->config.bitfield.compareMode = 1; appData.pRegionDescriptor->config.bitfield.wrap = 1; appData.pRegionDescriptor->config.bitfield.endMonitor = 0; appData.pRegionDescriptor->config.bitfield.mismatchIntDis = 0; // Set ICM callbacks (Digest mismatch) ICM_CallbackRegister(ICM_INTERRUPT_RDM, lAppDigestMismatchCallback); ICM_EnableInterrupt(ICM_INTERRUPT_RDM, ICM_REGION_0); ICM_SetMonitorMode(true, 15); ICM_EnableRegionMonitor(ICM_REGION_0); ICM_Enable(); // Launch Periodic Timer to Modify data appData.timer = SYS_TIME_CallbackRegisterMS(lAppTimerCallback, 0, APP_TIME_TO_CHANGE_DATA, SYS_TIME_SINGLE); appData.state = APP_STATE_MODIFY_REGION0_DATA; } break; } case APP_STATE_MODIFY_REGION0_DATA: { if (appData.timerExpired == true) { appData.timerExpired = false; appMonitoredData[2] = 1; appData.state = APP_STATE_WAIT_REGION0_MISMATCH; } break; } case APP_STATE_WAIT_REGION0_MISMATCH: { if (appData.dataChanged == true) { appData.dataChanged = false; // restore data content appMonitoredData[2] = 0x12345678; appData.state = APP_STATE_IDLE; } break; } case APP_STATE_IDLE: default: { /* TODO: Handle error in application's state machine. */ break; } } }
