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