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.

CC3235SF: CryptoCC32XX_encrypt fails with -1, g_bAESReadyFlag is never set

Part Number: CC3235SF
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello!
I'm trying to encrypt data using the crypto module, here is a simple example I'm using to test it out.

// Initialize the crypto-drivers
CryptoCC32XX_init();
CryptoCC32XX_Handle handle = NULL;

handle = CryptoCC32XX_open(0, CryptoCC32XX_AES | CryptoCC32XX_DES | CryptoCC32XX_HMAC);

if (!handle) {
   Display_printf(dispHandle, 0, 0, "CryptoCC32XX did not open");
}
else
{
    //Space for input and data
    unsigned char   plainData[16]   = "whatsoever123456";
    unsigned int    plainDataLen    = sizeof(plainData);
    unsigned char   cipherData[16]  = {0};
    unsigned int    cipherDataLen   = 0;
    
    // 32 byte key (256bits)
    uint8_t key[32] = {
       0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
       0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
       0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
       0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
    };
    
    //12 byte nonce + 4 bytes counter (for AES_CTR)
    uint8_t nonce[16] = {
        0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
        0xF8, 0xF9, 0xFA, 0xFB, 0x00, 0x00, 0x00, 0x00,
    };
    
    CryptoCC32XX_EncryptParams aesParams;
    aesParams.aes.keySize   = CryptoCC32XX_AES_KEY_SIZE_256BIT;
    aesParams.aes.pKey      = &key[0];
    aesParams.aes.pIV       = (void *)&nonce[0];
    
    int32_t status = CryptoCC32XX_encrypt(handle, CryptoCC32XX_AES_CTR , plainData, plainDataLen, cipherData , &cipherDataLen , &aesParams);
    Display_printf(dispHandle, 0, 0, "Encrypting Data: status = %d", status);
    
}


The  "CryptoCC32XX_encrypt()" returns -1, and when I step into the function, it correctly calls "CryptoCC32XX_aesProcess()".
But then it gets to this part

    int32_t count = CryptoCC32XX_CONTEXT_READY_MAX_COUNTER;
    /*
    Step1:  Enable Interrupts
    Step2:  Wait for Context Ready Interrupt
    Step3:  Set the Configuration Parameters (Direction,AES Mode and Key Size)
    Step4:  Set the Initialization Vector
    Step5:  Write Key
    Step6:  Start the Crypt Process
    */

    /* Clear the flag. */
    g_bAESReadyFlag = false;

    /* Enable all interrupts. */
    MAP_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, the flag will be set in the Interrupt handler. */
    while((!g_bAESReadyFlag) && (count > 0))
    {
        count --;
    }
    if (count == 0)
    {
        return CryptoCC32XX_STATUS_ERROR;
    }


where the counter always goes to 0, which returns "CryptoCC32XX_STATUS_ERROR" (the -1 value).
So, the "g_bAESReadyFlag" is never set to true within the 1000 tries.

And it looks like it should be set in "CryptoCC32XX_aesIntHandler()" here
void CryptoCC32XX_aesIntHandler(void)
{
    uint32_t uiIntStatus;

    /* Read the AES masked interrupt status. */
    uiIntStatus = MAP_AESIntStatus(AES_BASE, true);

    /* Set Different flags depending on the interrupt source. */
    if(uiIntStatus & AES_INT_CONTEXT_IN)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_IN);
        g_bAESReadyFlag = true;
    }
    if(uiIntStatus & AES_INT_DATA_IN)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_DATA_IN);
    }
    if(uiIntStatus & AES_INT_CONTEXT_OUT)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_CONTEXT_OUT);
    }
    if(uiIntStatus & AES_INT_DATA_OUT)
    {
        MAP_AESIntDisable(AES_BASE, AES_INT_DATA_OUT);
    }
}


if the "AES_INT_CONTEXT_IN" flag is set. (Although it looks like it disables the flag where "g_bAESReadyFlag" is set to true.)

From here on it is a little bit harder to follow, but my best guess is that

//This is a macro
MAP_AESIntEnable(AES_BASE, AES_INT_CONTEXT_IN | AES_INT_CONTEXT_OUT | AES_INT_DATA_IN | AES_INT_DATA_OUT);

//... which expands to
AESIntEnable(AES_BASE, AES_INT_CONTEXT_IN | AES_INT_CONTEXT_OUT | AES_INT_DATA_IN | AES_INT_DATA_OUT);


//The function looks for these flags and sets them (using some magic) if the type is AES.
    AES_INT_CONTEXT_IN
    AES_INT_CONTEXT_OUT
    AES_INT_DATA_IN
    AES_INT_DATA_OUT
    AES_INT_DMA_CONTEXT_IN
    AES_INT_DMA_CONTEXT_OUT
    AES_INT_DMA_DATA_IN
    AES_INT_DMA_DATA_OUT


So, from all I can see. It should really be working. Please tell me if I'm missing something, or if I have misunderstood things.
Thanks in advance for the help!

Kind regards
David

  • It looks like the issue has to do with the debugging tools, because if I restart the device when it is giving this error, then it starts working again.

    Although I have no idea why it stops working, might have to do with putting breakpoints in bad locations, and waiting for a while.
    Which might cause some unfortunate timeout, causing this issue. (Just a guess)

    However, my example above will produce the wrong decrypted data. Since the counter inside the nonce will be incremented for each
    use of CryptoCC32XX_encrypt and CryptoCC32XX_decrypt. Meaning, the nonce during encryption will not match the nonce during decryption.

    The solution is to use separate aesParams for encryption and decryption. (Makes sense since these could be on different devices)
    And the functions will change the nonce, so use 2 instances of that as well, IMPORTANT.

    Here is a working example. (Remember to use  #include <ti/drivers/crypto/CryptoCC32XX.h>  and to add a crypto instance in sysconfig as well)

    // Initialize the crypto-drivers
    CryptoCC32XX_init();
    CryptoCC32XX_Handle handle = NULL;
    handle = CryptoCC32XX_open(0, CryptoCC32XX_AES | CryptoCC32XX_HMAC);
    
    if (!handle) {
    Display_printf(dispHandle, 0, 0, "CryptoCC32XX did not open");
    }
    
    else
    {
        //Test data
        unsigned char   plainData[16] = "whatsoever123456";
        unsigned char   cipherData[16] = {0};
        unsigned char   decryptData[16] = {0};
    
        unsigned int    plainDataLen = sizeof(plainData);
        unsigned int    cipherDataLen = sizeof(plainData);
        unsigned int    decryptDataLen = sizeof(plainData);
        
        //Meta data for Encryption
        uint8_t key[32] = {
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
        };
    
        uint8_t nonceEnc[16] = {
            0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
            0xF8, 0xF9, 0xFA, 0xFB, 0x00, 0x00, 0x00, 0x00,
        };
    
        uint8_t nonceDec[16] = {
            0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
            0xF8, 0xF9, 0xFA, 0xFB, 0x00, 0x00, 0x00, 0x00,
        };
        
        
        // Encryption setup
        CryptoCC32XX_EncryptParams aesParamsEnc;
        memset(&aesParamsEnc, 0, sizeof(aesParamsEnc));
    
        aesParamsEnc.aes.keySize = CryptoCC32XX_AES_KEY_SIZE_256BIT;
        aesParamsEnc.aes.pKey = key;
        aesParamsEnc.aes.pIV = nonceEnc;  // Original nonce
        
        //Encrypt
        int32_t status = CryptoCC32XX_encrypt(handle, CryptoCC32XX_AES_CTR , plainData, plainDataLen, cipherData , &cipherDataLen , &aesParamsEnc);
        Display_printf(dispHandle, 0, 0, "Encrypting Data: status = %d", status);
        
        
        // Decryption setup
        CryptoCC32XX_EncryptParams aesParamsDec;
        memset(&aesParamsDec, 0, sizeof(aesParamsDec));
    
        aesParamsDec.aes.keySize = CryptoCC32XX_AES_KEY_SIZE_256BIT;
        aesParamsDec.aes.pKey = key;
        aesParamsDec.aes.pIV = nonceDec;  // Same original nonce
        
        //Decrypt
        status = CryptoCC32XX_decrypt(handle, CryptoCC32XX_AES_CTR, cipherData, cipherDataLen, decryptData, &decryptDataLen, &aesParamsDec);
        Display_printf(dispHandle, 0, 0, "Decrypting Data: status = %d", status);
        
    }

  • Not sure if I should start a new question or continue here, but it is related to testing out these functions so I'll keep going.

    When adding SHA256-verification to the example, I get a strange behavior which I hope you can explain. Here is the code

        //Put this at the end within the if-else block
        
        //Settings for HMAC-tag
        CryptoCC32XX_HmacParams hmacParams;
        CryptoCC32XX_HmacParams_init(&hmacParams);
        hmacParams.pKey = key;
        hmacParams.moreData = 0;
        
        //Generate tag
        uint8_t tag0[32] ={0};  // Full SHA-256 tag
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag0, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag0, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature: status = %d", status);


    This fails, returning -3 (CryptoCC32XX_STATUS_ERROR_VERIFY). However... after some further testing, it only fails
    under certain circumstances, and in some strange ways. Here is a summary of a few test cases.
        //Put this at the end within the if-else block
        
        //Settings for HMAC-tag
        CryptoCC32XX_HmacParams hmacParams;
        CryptoCC32XX_HmacParams_init(&hmacParams);
        hmacParams.pKey = key;
        hmacParams.moreData = 0;
        
        
        
        //Generate tag  (original pointer)
        uint8_t tag00[32] ={0};  // Full SHA-256 tag
        uint8_t tag01[32] ={0};  // Full SHA-256 tag
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag00, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag  (original, copy)          #Fails  (Wrong content in the tag???)
        memcpy(tag01, tag00, 32);
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag01, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature01: status = %d", status);
        
        //Verify tag  (original)                #Fails  (Wrong content in the tag???)
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag00, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature00: status = %d", status);
        
        
        
        //Generate tag  (new pointer)
        uint8_t tag10[32] ={0};  // Full SHA-256 tag
        uint8_t tag11[32] ={0};  // Full SHA-256 tag
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag10, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag  (new pointer, copy)       #Succeeds
        memcpy(tag11, tag10, 32);
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag11, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature11: status = %d", status);
        
        //Verify tag  (new pointer)             #Succeeds
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag10, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature10: status = %d", status);
        
        
        
        //Generate tag  (same pointer)
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag10, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag  (same pointer, copy)      #Succeeds
        memcpy(tag11, tag10, 32);
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag11, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature11: status = %d", status);
        
        //Verify tag  (same pointer)            #Succeeds
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag10, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature10: status = %d", status);
        
        
        
        //Generate tag  (reuse original)
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag00, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag  (original, copy)          #Fails  (The pointer becomes unusable after the first fail???)
        memcpy(tag01, tag00, 32);
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag11, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature11: status = %d", status);
        
        //Verify tag  (reuse original)          #Fails  (The pointer becomes unusable after the first fail???)
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag10, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature10: status = %d", status);


    As you can see from the comments, the first pointer becomes unusable after the first fail, and the first value is wrong.
    But the second time it is used (with a new pointer), then it works fine.

    Signing Data: status = 0
    Verifying Signature01: status = -3
    Verifying Signature00: status = -3
    Signing Data: status = 0
    Verifying Signature11: status = 0
    Verifying Signature10: status = 0
    Signing Data: status = 0
    Verifying Signature11: status = 0
    Verifying Signature10: status = 0
    Signing Data: status = 0
    Verifying Signature01: status = -3
    Verifying Signature00: status = -3
    


    Unclear why this happens.

  • So, to fix this second issue, you need to sign a "dummy" tag to initialize something deep in the background.

        // Dummy HMAC to initialize internal state
        uint8_t dummyTag[32] = {0};
        uint8_t dummyData[1] = {0};
        CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, dummyData, 1, dummyTag, &hmacParams);


    This dummy should then be discarded before signing the real data. I believe you only need to do this once, at startup,
    but I am not sure about that. (Note: I tried putting the dummy inside "{}" to not take up resources, but then it failed.) 

    Here is the full working example
    // Initialize the crypto-drivers
    CryptoCC32XX_init();
    CryptoCC32XX_Handle handle = NULL;
    handle = CryptoCC32XX_open(0, CryptoCC32XX_AES | CryptoCC32XX_HMAC);
    
    if (!handle) {
    Display_printf(dispHandle, 0, 0, "CryptoCC32XX did not open");
    }
    
    else
    {
        //Test data
        unsigned char   plainData[16] = "whatsoever123456";
        unsigned char   cipherData[16] = {0};
        unsigned char   decryptData[16] = {0};
    
        unsigned int    plainDataLen = sizeof(plainData);
        unsigned int    cipherDataLen = sizeof(plainData);
        unsigned int    decryptDataLen = sizeof(plainData);
        
        //Meta data for Encryption
        uint8_t key[32] = {
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
           0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
        };
    
        uint8_t nonceEnc[16] = {
            0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
            0xF8, 0xF9, 0xFA, 0xFB, 0x00, 0x00, 0x00, 0x00,
        };
    
        uint8_t nonceDec[16] = {
            0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
            0xF8, 0xF9, 0xFA, 0xFB, 0x00, 0x00, 0x00, 0x00,
        };
        
        
        
        // Encryption setup
        CryptoCC32XX_EncryptParams aesParamsEnc;
        memset(&aesParamsEnc, 0, sizeof(aesParamsEnc));
    
        aesParamsEnc.aes.keySize = CryptoCC32XX_AES_KEY_SIZE_256BIT;
        aesParamsEnc.aes.pKey = key;
        aesParamsEnc.aes.pIV = nonceEnc;  // Original nonce
        
        //Encrypt
        int32_t status = CryptoCC32XX_encrypt(handle, CryptoCC32XX_AES_CTR , plainData, plainDataLen, cipherData , &cipherDataLen , &aesParamsEnc);
        Display_printf(dispHandle, 0, 0, "Encrypting Data: status = %d", status);
        
        
        // Decryption setup
        CryptoCC32XX_EncryptParams aesParamsDec;
        memset(&aesParamsDec, 0, sizeof(aesParamsDec));
    
        aesParamsDec.aes.keySize = CryptoCC32XX_AES_KEY_SIZE_256BIT;
        aesParamsDec.aes.pKey = key;
        aesParamsDec.aes.pIV = nonceDec;  // Same original nonce
        
        //Decrypt
        status = CryptoCC32XX_decrypt(handle, CryptoCC32XX_AES_CTR, cipherData, cipherDataLen, decryptData, &decryptDataLen, &aesParamsDec);
        Display_printf(dispHandle, 0, 0, "Decrypting Data: status = %d", status);
        
        
        
        //Settings for HMAC-tag
        CryptoCC32XX_HmacParams hmacParams;
        CryptoCC32XX_HmacParams_init(&hmacParams);
        hmacParams.pKey = key;
        hmacParams.moreData = 0;
        
        // Dummy HMAC to initialize internal state
        uint8_t dummyTag[32] = {0};
        uint8_t dummyData[1] = {0};
        CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, dummyData, 1, dummyTag, &hmacParams);
        
        //Generate tag
        uint8_t tag0[32] ={0};  // Full SHA-256 tag
        status = CryptoCC32XX_sign(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag0, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Signing Data: status = %d", status);
    
        //Verify tag
        status = CryptoCC32XX_verify(handle, CryptoCC32XX_HMAC_SHA256, plainData, plainDataLen, tag0, &hmacParams);
        Display_printf(dispHandle, 0, 0, "Verifying Signature: status = %d", status);
        
        
    }


    Here is the log, confirming the results.
    Encrypting Data: status = 0
    Decrypting Data: status = 0
    Signing Data: status = 0
    Verifying Signature: status = 0


    Hope this helps someone!