This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359: AES-GCM Algorithm on SITARA AM3359 not working properly

Part Number: AM3359

Hi,

I implemented the AES-GCM decryption algorithm in the AM3359 following the AM335x ARM Cortex-A8 Cyptographic Addendum "Technical Reference Manual", and the example given in tivaware_c_series_2_1_4_178/examples/boards/dk-tm4c129x/aes_gcm_decrypt.

Im running the tests given in the aes_gcm_decrypt.c file, but NOT using DMA. The decryption seems to work fine, but the calculation of the tag only works once after switching the Sitara OFF and ON. Every second run of the AESTagRead function returns a wrong value.

Here is the AESTagRead function:

void
AESTagRead(uint32_t ui32Base, uint32_t *pui32TagData)
{
    //
    // Check the arguments.
    //
    ASSERT(ui32Base == AES_BASE);

    //
    // Wait for the output context to be ready.
    //
    while((AES_CTRL_SVCTXTRDY & (HWREG(ui32Base + AES_O_CTRL))) == 0)
    {
    }

    //
    // Read the tag data.
    //
    pui32TagData[0] = HWREG((ui32Base + AES_O_TAG_OUT_0));
    pui32TagData[1] = HWREG((ui32Base + AES_O_TAG_OUT_1));
    pui32TagData[2] = HWREG((ui32Base + AES_O_TAG_OUT_2));
    pui32TagData[3] = HWREG((ui32Base + AES_O_TAG_OUT_3));
}
 

Do you have any idea what could be the reason that the tag is only calculated correctly one time after startup of the hardware? Regards

  • Hello,

    the example given in tivaware_c_series_2_1_4_178/examples/boards/dk-tm4c129x/aes_gcm_decrypt.

    Will you share some details on the referenced SW package?
    Best,
    -Hong

  • Hello Hong,

    here is some of the code:

    the testvectors:

    //*****************************************************************************
    //
    // Test Cases from NIST GCM Revised Spec.
    //
    //*****************************************************************************
    tAESGCMTestVector g_psAESGCMTestVectors[] =
    {
        //
        // Test Case #1
        // This is a special case that cannot use the GCM mode because the
        // data and AAD lengths are both zero.  The work around is to perform
        // an ECB encryption on Y0.
        //
        {
            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
            12,
            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
            0,
            { 0 },
            0,
            { 0 },
            { 0 },
            { 0xcefce258, 0x61307efa, 0x571d7f36, 0x5a45e7a4 }
        },
    
        //
        // Test Case #2
        // This is the first test in which the AAD length is zero.
        //
        {
            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
            12,
            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
            16,
            { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
            0,
            { 0 },
            { 0xceda8803, 0x92a3b660, 0xb9c228f3, 0x78feb271 },
            { 0xd4476eab, 0xbd13ec2c, 0xb2673af5, 0xdfbd5712 }
        },
    
        //
        // Test Case #3
        //
        {
            { 0x92e9fffe, 0x1c736586, 0x948f6a6d, 0x08833067 },
            12,
            { 0xbebafeca, 0xaddbcefa, 0x88f8cade, 0x00000000 },
            64,
            { 0x253231d9, 0xe50684f8, 0xc50959a5, 0x9a26f5af,
              0x53a9a786, 0xdaf73415, 0x3d304c2e, 0x728a318a,
              0x950c3c1c, 0x53096895, 0x240ecf2f, 0x25b5a649,
              0xf5ed6ab1, 0x57e60daa, 0x397b63ba, 0x55d2af1a },
            0,
            { 0 },
            { 0xc21e8342, 0x24747721, 0xb721724b, 0x9cd4d084,
              0x2f21aae3, 0xe0a4022c, 0x237ec135, 0x2ea1ac29,
              0xb214d521, 0x1c936654, 0x5a6a8f7d, 0x05aa84ac,
              0x390ba31b, 0x97ac0a6a, 0x91e0583d, 0x85593f47 },
            { 0xf32a5c4d, 0xa664cd27, 0xbd5af32c, 0xb4faa62b }
        },
    
        //
        // Test Case #4
        // When the data lengths do not align with the block
        // boundary, we need to pad with zeros to ensure unknown
        // data is not copied with uDMA.
        //
        {
            { 0x92e9fffe, 0x1c736586, 0x948f6a6d, 0x08833067 },
            12,
            { 0xbebafeca, 0xaddbcefa, 0x88f8cade, 0x00000000 },
            60,
            { 0x253231d9, 0xe50684f8, 0xc50959a5, 0x9a26f5af,
              0x53a9a786, 0xdaf73415, 0x3d304c2e, 0x728a318a,
              0x950c3c1c, 0x53096895, 0x240ecf2f, 0x25b5a649,
              0xf5ed6ab1, 0x57e60daa, 0x397b63ba, 0x00000000 },
            20,
            { 0xcefaedfe, 0xefbeadde, 0xcefaedfe, 0xefbeadde,
              0xd2daadab, 0x00000000, 0x00000000, 0x00000000 },
            { 0xc21e8342, 0x24747721, 0xb721724b, 0x9cd4d084,
              0x2f21aae3, 0xe0a4022c, 0x237ec135, 0x2ea1ac29,
              0xb214d521, 0x1c936654, 0x5a6a8f7d, 0x05aa84ac,
              0x390ba31b, 0x97ac0a6a, 0x91e0583d, 0x00000000 },
            { 0xbc4fc95b, 0xdba52132, 0x5ae9fa94, 0x471a12e7 }
        },
    
        //
        // Test Case #5
        // This is the first case in which IV is less than
        // 96 bits.
        //
        {
            { 0x92e9fffe, 0x1c736586, 0x948f6a6d, 0x08833067 },
            8,
            { 0xbebafeca, 0xaddbcefa, 0x00000000, 0x00000000 },
            60,
            { 0x253231d9, 0xe50684f8, 0xc50959a5, 0x9a26f5af,
              0x53a9a786, 0xdaf73415, 0x3d304c2e, 0x728a318a,
              0x950c3c1c, 0x53096895, 0x240ecf2f, 0x25b5a649,
              0xf5ed6ab1, 0x57e60daa, 0x397b63ba, 0x00000000 },
            20,
            { 0xcefaedfe, 0xefbeadde, 0xcefaedfe, 0xefbeadde,
              0xd2daadab, 0x00000000, 0x00000000, 0x00000000 },
            { 0x4c3b3561, 0x4a930628, 0x1ff57f77, 0x55472aa2,
              0x712a9b69, 0xf8c6cd4f, 0xf9e56637, 0x23746c7b,
              0x00698073, 0xb2249fe4, 0x4475092b, 0x426b89d4,
              0xe1b58949, 0x070faceb, 0x98453fc2, 0x00000000 },
            { 0xe7d21236, 0x85073b9e, 0x4ae11b56, 0xcbfca2ac }
        },
    
        //
        // Test Case #6
        // This is the first case in which IV is more than
        // 96 bits.
        //
        {
            { 0x92e9fffe, 0x1c736586, 0x948f6a6d, 0x08833067 },
            60,
            { 0x5d221393, 0xe50684f8, 0x5a9c9055, 0xaa6952ff,
              0x38957a6a, 0xa17d4f53, 0xd203c3e4, 0x28a718a3,
              0x51c9c0c3, 0x39958056, 0x42e2f0fc, 0x54526b9a,
              0xf5dbae16, 0x576adea0, 0x9bb337a6, 0x00000000 },
            60,
            { 0x253231d9, 0xe50684f8, 0xc50959a5, 0x9a26f5af,
              0x53a9a786, 0xdaf73415, 0x3d304c2e, 0x728a318a,
              0x950c3c1c, 0x53096895, 0x240ecf2f, 0x25b5a649,
              0xf5ed6ab1, 0x57e60daa, 0x397b63ba, 0x00000000 },
            20,
            { 0xcefaedfe, 0xefbeadde, 0xcefaedfe, 0xefbeadde,
              0xd2daadab },
            { 0x9849e28c, 0xb6155662, 0xac33a003, 0x94b83fa1,
              0xa51291be, 0xa811a2c3, 0x3c2a26ba, 0xa72c7eca,
              0xa4a9e401, 0x903ca4fb, 0x81b2dccc, 0x6f7c8cd4,
              0xd27528d6, 0x0317a4ac, 0xe5ae344c, 0x00000000 },
            { 0xaec59c61, 0xfa0bfeff, 0x3cf42a46, 0x50d09916 }
        }
    };

    And here the gcm decryption

    //*****************************************************************************
    //
    // Perform an GCM decryption operation.
    //
    //*****************************************************************************
    bool
    AESGCMDecrypt(uint32_t ui32Keysize, uint32_t *pui32Src, uint32_t *pui32Dst,
                  uint32_t ui32Length, uint32_t *pui32Key, uint32_t *pui32IV,
                  uint32_t *pui32AAD, uint32_t ui32AADLength, uint32_t *pui32Tag,
                  bool bUseDMA)
    {
        //
        // Perform a soft reset.
        //
        ROM_AESReset(AES_BASE);
    
        //
        // Clear the interrupt flags.
        //
        g_bContextInIntFlag = false;
        g_bDataInIntFlag = false;
        g_bContextOutIntFlag = false;
        g_bDataOutIntFlag = false;
        g_bContextInDMADoneIntFlag = false;
        g_bDataInDMADoneIntFlag = false;
        g_bContextOutDMADoneIntFlag = false;
        g_bDataOutDMADoneIntFlag = false;
    
        //
        // Enable all interrupts.
        //
        ROM_AESIntEnable(AES_BASE, (AES_INT_CONTEXT_IN | AES_INT_CONTEXT_OUT |
                                    AES_INT_DATA_IN | AES_INT_DATA_OUT));
    
        //
        // Wait for the context in flag.
        //
        while(!g_bContextInIntFlag)
        {
        }
    
        //
        // Configure the AES module.
        //
        ROM_AESConfigSet(AES_BASE, (ui32Keysize | AES_CFG_DIR_DECRYPT |
                                    AES_CFG_MODE_GCM_HY0CALC));
    
        //
        // Write the initialization value
        //
        ROM_AESIVSet(AES_BASE, pui32IV);
    
        //
        // Write the keys.
        //
        ROM_AESKey1Set(AES_BASE, pui32Key, ui32Keysize);
    
        //
        // Depending on the argument, perform the decryption
        // with or without uDMA.
        //
        if(bUseDMA)
        {
            //
            // Enable DMA interrupts.
            //
            ROM_AESIntEnable(AES_BASE, (AES_INT_DMA_CONTEXT_IN |
                                        AES_INT_DMA_DATA_IN |
                                        AES_INT_DMA_CONTEXT_OUT |
                                        AES_INT_DMA_DATA_OUT));
    
            if(ui32AADLength != 0)
            {
                //
                // Setup the DMA module to copy auth data in.
                //
                ROM_uDMAChannelAssign(UDMA_CH14_AES0DIN);
                ROM_uDMAChannelAttributeDisable(UDMA_CH14_AES0DIN,
                                                UDMA_ATTR_ALTSELECT |
                                                UDMA_ATTR_USEBURST |
                                                UDMA_ATTR_HIGH_PRIORITY |
                                                UDMA_ATTR_REQMASK);
                ROM_uDMAChannelControlSet(UDMA_CH14_AES0DIN | UDMA_PRI_SELECT,
                                          UDMA_SIZE_32 | UDMA_SRC_INC_32 |
                                          UDMA_DST_INC_NONE | UDMA_ARB_4 |
                                          UDMA_DST_PROT_PRIV);
                ROM_uDMAChannelTransferSet(UDMA_CH14_AES0DIN | UDMA_PRI_SELECT,
                                           UDMA_MODE_BASIC, (void *)pui32AAD,
                                           (void *)(AES_BASE + AES_O_DATA_IN_0),
                                           LengthRoundUp(ui32AADLength) / 4);
                UARTprintf("Data in DMA request enabled.\n");
            }
    
            //
            // Setup the DMA module to copy the data out.
            //
            ROM_uDMAChannelAssign(UDMA_CH15_AES0DOUT);
            ROM_uDMAChannelAttributeDisable(UDMA_CH15_AES0DOUT,
                                            UDMA_ATTR_ALTSELECT |
                                            UDMA_ATTR_USEBURST |
                                            UDMA_ATTR_HIGH_PRIORITY |
                                            UDMA_ATTR_REQMASK);
            ROM_uDMAChannelControlSet(UDMA_CH15_AES0DOUT | UDMA_PRI_SELECT,
                                      UDMA_SIZE_32 | UDMA_SRC_INC_NONE |
                                      UDMA_DST_INC_32 | UDMA_ARB_4 |
                                      UDMA_SRC_PROT_PRIV);
            ROM_uDMAChannelTransferSet(UDMA_CH15_AES0DOUT | UDMA_PRI_SELECT,
                                       UDMA_MODE_BASIC,
                                       (void *)(AES_BASE + AES_O_DATA_IN_0),
                                       (void *)pui32Dst,
                                       LengthRoundUp(ui32Length) / 4);
            UARTprintf("Data out DMA request enabled.\n");
    
            //
            // Write the plaintext length
            //
            ROM_AESLengthSet(AES_BASE, (uint64_t)ui32Length);
    
            //
            // Write the auth length registers to start the process.
            //
            ROM_AESAuthLengthSet(AES_BASE, ui32AADLength);
            
            //
            // Enable the DMA channels to start the transfers.  This must be done after
            // writing the length to prevent data from copying before the context is 
            // truly ready.
            // 
            if(ui32AADLength != 0)
            {
                ROM_uDMAChannelEnable(UDMA_CH14_AES0DIN);
            }
            ROM_uDMAChannelEnable(UDMA_CH15_AES0DOUT);
    
            //
            // Enable DMA requests
            //
            ROM_AESDMAEnable(AES_BASE, AES_DMA_DATA_IN | AES_DMA_DATA_OUT);
    
            if(ui32AADLength != 0)
            {
                //
                // Wait for the data in DMA done interrupt.
                //
                while(!g_bDataInDMADoneIntFlag)
                {
                }
            }
    
            if(ui32Length != 0)
            {
                //
                // Setup the uDMA to copy the plaintext data.
                //
                ROM_uDMAChannelAssign(UDMA_CH14_AES0DIN);
                ROM_uDMAChannelAttributeDisable(UDMA_CH14_AES0DIN,
                                                UDMA_ATTR_ALTSELECT |
                                                UDMA_ATTR_USEBURST |
                                                UDMA_ATTR_HIGH_PRIORITY |
                                                UDMA_ATTR_REQMASK);
                ROM_uDMAChannelControlSet(UDMA_CH14_AES0DIN | UDMA_PRI_SELECT,
                                          UDMA_SIZE_32 | UDMA_SRC_INC_32 |
                                          UDMA_DST_INC_NONE | UDMA_ARB_4 |
                                          UDMA_DST_PROT_PRIV);
                ROM_uDMAChannelTransferSet(UDMA_CH14_AES0DIN | UDMA_PRI_SELECT,
                                           UDMA_MODE_BASIC, (void *)pui32Src,
                                           (void *)(AES_BASE + AES_O_DATA_IN_0),
                                           LengthRoundUp(ui32Length) / 4);
                ROM_uDMAChannelEnable(UDMA_CH14_AES0DIN);
                UARTprintf("Data in DMA request enabled.\n");
    
                //
                // Wait for the data out DMA done interrupt.
                //
                while(!g_bDataOutDMADoneIntFlag)
                {
                }
            }
    
            //
            // Read out the tag.
            //
            AESTagRead(AES_BASE, pui32Tag);
        }
        else
        {
            //
            // Perform the decryption.
            //
            ROM_AESDataProcessAuth(AES_BASE, pui32Src, pui32Dst, ui32Length,
                                   pui32AAD, ui32AADLength, pui32Tag);
        }
    
        return(true);
    }

    I used the AESGCMDecrypt() function without DMA.

    Here is a link to the tivaware:
    SW-TM4C Software development kit (SDK) | TI.com

    Regards

    Timo

  • Hello Timo,
    Here're some pointers for your reference:

    1/. AM335x Crypto TRM
    2.4 AES Module Programming Guide

    2/. Linux SDK kernel crypto driver
    - online kernel crypto driver guide
    software-dl.ti.com/.../Crypto.html
    - kernel AES driver
    git.ti.com/.../omap-aes.c
    git.ti.com/.../omap-aes-gcm.c

    Best,
    -Hong