Other Parts Discussed in Thread: MSPM0G3519
Hi TI Team,
I am validating AES CMAC generation using the AESADV hardware accelerator on MSPM0G3519.
For 16-byte and 32-byte messages, the CMAC output from firmware matches perfectly with the NIST SP800-38B test vectors.
However, for a 40-byte message (non-multiple of 16), the CMAC output from firmware does not match the expected value.
Below are my detailed observations and test setup.
AES Key : 2b7e151628aed2a6abf7158809cf4f3c
AES-ECB(Zero) L : 7df76b0c1ab899b33e42f047b91b546f
Derived K1 : fbeed618357133667c85e08f7236a8de
Derived K2 : f7ddac306ae266ccf90bc11ee46d513b
Message (40 bytes):
6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c
9eb76fac45af8e5130c81c46a35ce411
Partial (un-padded) last 8 bytes : 30c81c46a35ce411
Padded block (before XOR K2) : 30c81c46a35ce4118000000000000000
K2 : f7ddac306ae266ccf90bc11ee46d513b
Final block (padded ^ K2) : c715b076c9be82dd790bc11ee46d513b
Expected CMAC (NIST SP800-38B):
dfa66747de9ae63030ca32611497c827
Firmware CMAC (Observed):
465AF15ED86DBF7223C13C77682B884D
Keys are loaded using:
DL_AESADV_setKeySize(AESADV, DL_AESADV_KEY_SIZE_128);
DL_AESADV_setKey(AESADV, (uint32_t *)aes_key);
Firmware Function Used
void generate_cmac(uint8_t *msg, uint32_t msgLen, uint8_t *tagOut)
{
__attribute__((aligned(4))) uint8_t lastBlock[16] = {0};
if ((msg == NULL_PTR) || (tagOut == NULL_PTR) || (msgLen == 0U))
return;
DL_AESADV_Config config = {
.mode = DL_AESADV_MODE_CMAC,
.direction = DL_AESADV_DIR_ENCRYPT,
.k1 = rub_output_subkey1,
.k2 = rub_output_subkey2,
.lowerCryptoLength = msgLen,
.upperCryptoLength = 0U,
.aadLength = 0U,
.iv = NULL,
.nonce = NULL
};
DL_AESADV_initCMAC(AESADV, &config);
uint32_t fullBlocks = msgLen / 16U;
uint32_t remBytes = msgLen % 16U;
for (uint32_t i = 0; i < fullBlocks; i++)
{
while (!DL_AESADV_isInputReady(AESADV)) {;}
DL_AESADV_STATUS st = DL_AESADV_loadInputData(AESADV, msg + (i * 16U));
if (st != DL_AESADV_STATUS_SUCCESS) { __BKPT(0); return; }
}
if (remBytes > 0U)
{
memcpy(lastBlock, msg + (fullBlocks * 16U), remBytes);
lastBlock[remBytes] = 0x80;
for (int i = 0; i < 16; i++)
lastBlock[i] ^= rub_output_subkey2[i];
while (!DL_AESADV_isInputReady(AESADV)) {;}
DL_AESADV_loadInputDataAligned(AESADV, (uint32_t *)lastBlock);
}
while (!DL_AESADV_isSavedOutputContextReady(AESADV)) {;}
DL_AESADV_STATUS st = DL_AESADV_readTAG(AESADV, tagOut);
if (st != DL_AESADV_STATUS_SUCCESS) { __BKPT(0); return; }
memset(lastBlock, 0, sizeof(lastBlock));
}
Clarifications Requested
Could you please confirm the following points:
-
Does
DL_AESADV_MODE_CMACautomatically handle padding and subkey (K1/K2) XOR internally,
or should firmware manually apply the XOR and padding before callingDL_AESADV_loadInputDataAligned()? -
Does AESADV support CMAC generation for non-multiple-of-16 message lengths (like 7 or 40 bytes)?
I observed that whenmsgLenis not a multiple of 16, the CMAC is incorrect.
Also, passing 0 bytes as length results in no valid output. -
Is it expected that only multiples of 16 bytes are supported for CMAC operation?
If not, are there additional configuration steps to enable partial-block processing?
Best regards,
Kasirajan C
