Jump to main content

# 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;
            }
        }
    }

Rev: E