//*****************************************************************************
//
// Perform a basic GHASH operation with the hashsubkey and IV.  This is
// used to get Y0 when the IV is not 96 bits.  To use this GCM mode, the
// operation direction must not be set and the counter should be disabled.
//
//*****************************************************************************
void
AESGHASH(uint32_t ui32Keysize, uint32_t *pui32HashSubkey, uint32_t *pui32IV,
         uint32_t ui32IVLength, uint32_t *pui32Result)
{
    uint32_t ui32Count;

    //
    // Perform a soft reset.
    //
    ROM_AESReset(AES_BASE);

    //
    // Configure the AES module.
    //
    ROM_AESConfigSet(AES_BASE, (ui32Keysize | AES_CFG_MODE_GCM_HLY0ZERO));

    //
    // Set the hash subkey.
    //
    ROM_AESKey2Set(AES_BASE, pui32HashSubkey, ui32Keysize);

    //
    // Write the lengths
    //
    ROM_AESLengthSet(AES_BASE, (uint64_t)ui32IVLength);
    ROM_AESAuthLengthSet(AES_BASE, 0);

    //
    // Write the data.
    //
    for(ui32Count = 0; ui32Count < ui32IVLength; ui32Count += 16)
    {
        //
        // Write the data registers.
        //
        ROM_AESDataWrite(AES_BASE, pui32IV + (ui32Count / 4));
    }

    //
    // Read the hash tag value.
    //
    AESTagRead(AES_BASE, pui32Result);
}
Example #2
0
//*****************************************************************************
//
// Perform an CCM decryption operation.
// 
//*****************************************************************************
bool
AES128CCMDecrypt(uint32_t *pui32Key, uint32_t *pui32Src, uint32_t *pui32Dst,
                 uint32_t ui32DataLength, uint32_t *pui32Nonce, 
                 uint32_t ui32NonceLength, uint32_t *pui32AuthData, 
                 uint32_t ui32AuthDataLength, uint32_t *pui32Tag, 
                 uint32_t ui32TagLength, bool bUseDMA)
{
    uint32_t pui32IV[4], ui32Idx;
    uint32_t ui32M, ui32L;
    uint8_t *pui8Nonce, *pui8IV;

    //
    // Determine the value of M.  It is determined using 
    // the tag length.
    //
    if(ui32TagLength == 4)
    {
        ui32M = AES_CFG_CCM_M_4;
    }
    else if(ui32TagLength == 6)
    {
        ui32M = AES_CFG_CCM_M_6;
    }
    else if(ui32TagLength == 8)
    {
        ui32M = AES_CFG_CCM_M_8;
    }
    else if(ui32TagLength == 10)
    {
        ui32M = AES_CFG_CCM_M_10;
    }
    else if(ui32TagLength == 12)
    {
        ui32M = AES_CFG_CCM_M_12;
    }
    else if(ui32TagLength == 14)
    {
        ui32M = AES_CFG_CCM_M_14;
    }
    else if(ui32TagLength == 16)
    {
        ui32M = AES_CFG_CCM_M_16;
    }
    else
    {
        UARTprintf("Unexpected tag length.\n");
        return(false);
    }

    //
    // Determine the value of L. This is determined by using
    // the value of q from the NIST document:  n + q = 15
    //
    if(ui32NonceLength == 7)
    {   
        ui32L = AES_CFG_CCM_L_8;
    }
    else if(ui32NonceLength == 8)
    {   
        ui32L = AES_CFG_CCM_L_7;
    }
    else if(ui32NonceLength == 9)
    {   
        ui32L = AES_CFG_CCM_L_6;
    }
    else if(ui32NonceLength == 10)
    {   
        ui32L = AES_CFG_CCM_L_5;
    }
    else if(ui32NonceLength == 11)
    {
        ui32L = AES_CFG_CCM_L_4;
    }
    else if(ui32NonceLength == 12)
    {
        ui32L = AES_CFG_CCM_L_3;
    }
    else if(ui32NonceLength == 13)
    {
        ui32L = AES_CFG_CCM_L_2;
    }
    else if(ui32NonceLength == 14)
    {
        ui32L = AES_CFG_CCM_L_1;
    }
    else
    {
        UARTprintf("Unexpected nonce length.\n");
        return(false);
    }

    //
    // 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));

    //
    // Configure the AES module.
    //
    ROM_AESConfigSet(AES_BASE, (AES_CFG_KEY_SIZE_128BIT | AES_CFG_DIR_DECRYPT |
                                AES_CFG_CTR_WIDTH_128 |
                                AES_CFG_MODE_CCM | ui32L | ui32M));

    //
    // Determine the value to be written in the initial value registers.  It is 
    // the concatenation of 5 bits of zero, 3 bits of L, nonce, and the counter
    // value.  First, clear the contents of the IV.
    //
    for(ui32Idx = 0; ui32Idx < 4; ui32Idx++)
    {
        pui32IV[ui32Idx] = 0;
    }

    //
    // Now find the binary value of L.
    //
    if(ui32L == AES_CFG_CCM_L_8)
    {
        pui32IV[0] = 0x7;
    }
    else if(ui32L == AES_CFG_CCM_L_7)
    {
        pui32IV[0] = 0x6;
    }
    else if(ui32L == AES_CFG_CCM_L_6)
    {
        pui32IV[0] = 0x5;
    }
    else if(ui32L == AES_CFG_CCM_L_5)
    {
        pui32IV[0] = 0x4;
    }
    else if(ui32L == AES_CFG_CCM_L_4)
    {
        pui32IV[0] = 0x3;
    }
    else if(ui32L == AES_CFG_CCM_L_3)
    {
        pui32IV[0] = 0x2;
    }
    else if(ui32L == AES_CFG_CCM_L_2)
    {
        pui32IV[0] = 0x1;
    }

    //
    // Finally copy the contents of the nonce into the IV.  Convert
    // the pointers to simplify the copying.
    //
    pui8Nonce = (uint8_t *)pui32Nonce; 
    pui8IV = (uint8_t *)pui32IV;
    for(ui32Idx = 0; ui32Idx < ui32NonceLength; ui32Idx++)
    {
        pui8IV[ui32Idx + 1] = pui8Nonce[ui32Idx];
    }

    //
    // Write the initial value.
    //
    ROM_AESIVSet(AES_BASE, pui32IV);

    //
    // Write the key.
    //
    ROM_AESKey1Set(AES_BASE, pui32Key, AES_CFG_KEY_SIZE_128BIT);
    
    //
    // 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));

        //
        // 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 *)pui32AuthData,
                                   (void *)(AES_BASE + AES_O_DATA_IN_0),
                                   LengthRoundUp(ui32AuthDataLength) / 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(ui32DataLength) / 4);
        UARTprintf("Data out DMA request enabled.\n");

        //
        // Write the length registers.
        //
        ROM_AESLengthSet(AES_BASE, (uint64_t)ui32DataLength);

        //
        // Write the auth length registers to start the process.
        //
        ROM_AESAuthLengthSet(AES_BASE, ui32AuthDataLength);
        
        //
        // 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.
        // 
        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);

        //
        // Wait for the data in DMA done interrupt.
        //
        while(!g_bDataInDMADoneIntFlag)
        {
        }

        //
        // 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(ui32DataLength) / 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 the tag out.
        //
        ROM_AESTagRead(AES_BASE, pui32Tag);
    }
    else
    {
        //
        // Perform the decryption.
        //
        ROM_AESDataProcessAuth(AES_BASE, pui32Src, pui32Dst, ui32DataLength,
                               pui32AuthData, ui32AuthDataLength, pui32Tag);
    }
    return(true);
}
//*****************************************************************************
//
// 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);
}