static void aesCrypt(uint8 skipCnt, uint8 *pBuf) { // A0: L-encoding of L-1 = 2-1 = 1; starting 2-byte CTR at 1. uint8 ivNonce[KEY_BLENGTH] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ENCCS = CTR | AES_LOAD_IV | 0x01; // 'while ((ENCCS & BV(3)) == 0)' was seen to hang without #pragma optimize=none. // So proactively adding this wait after every 'ENCCS = ' which empirically seems to work. ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; for (uint8 idx = 0; idx < KEY_BLENGTH; idx++) { ENCDI = ivNonce[idx]; } while ((ENCCS & BV(3)) == 0); for (uint8 cnt = 0; cnt < (SBL_RW_BUF_LEN / KEY_BLENGTH); cnt++) { if (skipCnt == 0) { ENCCS = CTR | AES_ENCRYPT | 0x01; // 'while ((ENCCS & BV(3)) == 0)' was seen to hang without #pragma optimize=none. // So proactively adding this wait after every 'ENCCS = ' which empirically seems to work. ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; for (uint8 blk = 0; blk < 4; blk++) { for (uint8 idx = 0; idx < 4; idx++) { ENCDI = pBuf[idx]; } HAL_AES_DELAY(); // Delay required for non-DMA AES as RDY bit only goes hi after read out. for (uint8 idx = 0; idx < 4; idx++) { pBuf[idx] = ENCDO; } pBuf += 4; } } else { skipCnt--; pBuf += KEY_BLENGTH; } } }
/****************************************************************************** * @fn AesStartBlock * * @brief Write and read a block to and from the AES engine * * input parameters * * @param out - Pointer to result to be read. * in - pointer to data to be written. * * @return None */ void AesStartBlock( uint8 *out, uint8 *in ) { uint8 i; /* Kick it off */ AES_START(); /* Copy data to encryption input register */ for (i = 0; i < STATE_BLENGTH; i++) { ENCDI = *in++; } /* Delay is required for non-DMA AES */ HAL_AES_DELAY(); /* Copy encryption output register to out */ for (i = 0; i < STATE_BLENGTH; i++) { *out++ = ENCDO; } }
/****************************************************************************** * @fn AesStartShortBlock * * @brief Write and read a block to and from the AES engine. When using CFB, * OFB, and CTR mode, the 128 bits blocks are divided into four 32 bit * blocks. * * input parameters * * @param out - Pointer to result to be read. * in - pointer to data to be written. * * @return None */ void AesStartShortBlock( uint8 *out, uint8 *in ) { uint8 i, j; AES_START(); for (i = 0; i < 4; i++) { /* Copy in block to encryption input register */ for (j = 0; j < 4; j++) { ENCDI = *in++; } /* Delay is required for non-DMA AES */ HAL_AES_DELAY(); /* Copy encryptioon output register to out block */ for (j = 0; j < 4; j++) { *out++ = ENCDO; } } }
/************************************************************************************************** * @fn aesSignature * * @brief Run the AES CRC-MAC calculation over the RC image according to the * AES Control Block parameters and update the control block accordingly. * * input parameters * * None. * * output parameters * * @param pBuf - Pointer to the KEY_BLENGTH-byte buffer to hold the signature calculated. * * @return TRUE or FALSE whether the AES signature could be calculated. */ static uint8 aesSignature(void *pBuf) { aesInitSig(); #if defined AES_TEST_VECS uint8 testInput[48] = { 0x00, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(pageBuf+HAL_FLASH_PAGE_SIZE-48, testInput, 48); uint8 idx = 0; for (uint8 loop = 0; loop < 2; loop++) { ENCCS |= 0x01; for (uint8 cnt = 0; cnt < KEY_BLENGTH; cnt++) { ENCDI = testInput[idx++]; } while ((ENCCS & BV(3)) == 0); } #else const uint8 lastPg = imgHdr.len / SBL_PAGE_LEN + SBL_PAGE_BEG - 1; for (uint8 pg = SBL_PAGE_BEG; pg <= lastPg; pg++) { HalFlashRead(pg, 0, pageBuf, HAL_FLASH_PAGE_SIZE); for (uint16 oset = 0; oset < HAL_FLASH_PAGE_SIZE; ) { if ((pg == SBL_PAGE_BEG) && (oset == sizeof(img_hdr_t))) { oset += KEY_BLENGTH; // Must not include the signature bytes in the signature calculation. } else if ((pg == lastPg) && (oset == (HAL_FLASH_PAGE_SIZE - KEY_BLENGTH))) { break; // Need to change mode to CBC-MAC for the last block. } ENCCS |= 0x01; for (uint8 cnt = 0; cnt < KEY_BLENGTH; cnt++) { ENCDI = pageBuf[oset++]; } while ((ENCCS & BV(3)) == 0); } } #endif ENCCS = CBC | AES_ENCRYPT | 0x01; // Switch to CBC mode for the last block. // 'while ((ENCCS & BV(3)) == 0)' was seen to hang without #pragma optimize=none. // So proactively adding this wait after every 'ENCCS = ' which empirically seems to work. ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; for (uint16 oset = (HAL_FLASH_PAGE_SIZE - KEY_BLENGTH); oset < HAL_FLASH_PAGE_SIZE; oset++) { ENCDI = pageBuf[oset]; } HAL_AES_DELAY(); // Delay required for non-DMA AES as RDY bit only goes hi after read out below. // CBC-MAC generates output on the last block. for (uint8 cnt = 0, *pSig = (uint8 *)pBuf; cnt < KEY_BLENGTH; cnt++) { *pSig++ = ENCDO; } return TRUE; }
/************************************************************************************************** * @fn aesSignature * * @brief Run the AES CRC-MAC calculation over the image specified according to the * AES Control Block parameters and update the control block accordingly. * * input parameters * * @param imgSel - Image select: 0 for Image-A and 1 for Image-B. * @param aesHdr - Pointer to the aes_hdr_t info to use for the signature calculation. * * output parameters * * @param aesHdr - Pointer to the aes_hdr_t info with the signature calculated. * * @return TRUE or FALSE whether the AES signature calculated matches the one in the header. */ static uint8 aesSignature(uint8 imgSel, aes_hdr_t *aesHdr) { uint8 sigBuf[KEY_BLENGTH]; aesInitSig(aesHdr); uint8 pgEnd = ImgPageBeg[imgSel] + aesHdr->spare[3] - 1; if (imgSel == 0) { pgEnd += ImgPageLen[1]; } for (uint8 pgNum = ImgPageBeg[imgSel]; pgNum <= pgEnd; ) { BEM_NVM_GET(pgNum, pageBuf, HAL_FLASH_PAGE_SIZE); for (uint16 oset = 0; oset < HAL_FLASH_PAGE_SIZE; ) { if ((pgNum == ImgPageBeg[imgSel]) && (oset == sizeof(img_hdr_t))) { oset += KEY_BLENGTH; // Must not include the signature bytes in the signature calculation. } else if ((pgNum == pgEnd) && (oset == (HAL_FLASH_PAGE_SIZE - KEY_BLENGTH))) { break; // Need to change mode to CBC-MAC for the last block. } ENCCS |= 0x01; for (uint8 cnt = 0; cnt < KEY_BLENGTH; cnt++) { ENCDI = pageBuf[oset++]; } while ((ENCCS & BV(3)) == 0); } pgNum++; if ((imgSel == 0) && (pgNum == ImgPageBeg[1])) { pgNum += ImgPageLen[1]; } } ENCCS = CBC | AES_ENCRYPT | 0x01; // Switch to CBC mode for the last block. // 'while ((ENCCS & BV(3)) == 0)' was seen to hang without #pragma optimize=none. // So proactively adding this wait after every 'ENCCS = ' which empirically seems to work. ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; ASM_NOP; for (uint16 oset = (HAL_FLASH_PAGE_SIZE - KEY_BLENGTH); oset < HAL_FLASH_PAGE_SIZE; oset++) { ENCDI = pageBuf[oset]; } HAL_AES_DELAY(); // Delay required for non-DMA AES as RDY bit only goes hi after read out below. // CBC-MAC generates output on the last block. for (uint8 cnt = 0; cnt < KEY_BLENGTH; cnt++) { sigBuf[cnt] = ENCDO; } return ((memcmp(sigBuf, aesHdr->signature, KEY_BLENGTH) == 0) ? TRUE : FALSE); }