Decryption using CTR Mode

This section describes decrypting AES-CTR encrypted data within the TEE.

  • Purpose: Decrypts ciphertext encrypted by AES-CTR, retrieving plaintext.

  • Process Overview:

    1. Validate input size: Ensures ciphertext length is at least one AES block size to contain the IV.

    2. Extract IV: Reads the IV from the first AES block-sized bytes of ciphertext.

    3. Retrieve AES key: Obtains the key handle using generate_aes_key().

    4. Allocate decrypt operation: Creates AES-CTR decryption operation via TEE_AllocateOperation().

    5. Set operation key: Assigns the AES key to the operation.

    6. Initialize cipher: Initializes the operation with extracted IV.

    7. Decrypt ciphertext: Processes ciphertext (excluding IV) using TEE_CipherUpdate().

    8. Update output length: Sets plaintext length to decrypted data size.

    9. Cleanup: Frees operation and key handles, zeroes IV buffer.

  • Notes:

    • The FIRST block of ciphertext contains the IV, which is critical for decryption.

    • Output buffer must be large enough to hold decrypted data.

 1TEE_Result decrypt_aes_data(const uint8_t *ciphertext, size_t ciphertext_len, char *plaintext, size_t *plaintext_len)
 2{
 3    TEE_Result res;
 4    TEE_ObjectHandle key_handle = TEE_HANDLE_NULL;
 5    TEE_OperationHandle operation = TEE_HANDLE_NULL;
 6    uint8_t iv[AES_BLOCK_SIZE] = {0};
 7    uint32_t dec_len = 0;
 8
 9    /* Check if the output buffer is large enough */
10    if (ciphertext_len < AES_BLOCK_SIZE)
11    {
12        EMSG("Output buffer is too small, expected size: %u bytes", AES_BLOCK_SIZE);
13        return TEE_ERROR_SHORT_BUFFER;
14    }
15
16    /* Extract IV from the start of ciphertext */
17    memcpy(iv, ciphertext, AES_BLOCK_SIZE);
18
19    /* Retrieve the AES key from persistent storage */
20    res = generate_aes_key(&key_handle);
21    if (res != TEE_SUCCESS)
22    {
23        EMSG("Failed to retrieve AES key, res=0x%08x", res);
24        goto exit;
25    }
26
27    /* Allocate decrypt operation */
28    res = TEE_AllocateOperation(&operation, TEE_ALG_AES_CTR, TEE_MODE_DECRYPT, AES_KEY_SIZE);
29    if (res != TEE_SUCCESS)
30    {
31        EMSG("Failed to allocate operation, res=0x%08x", res);
32        goto exit;
33    }
34
35    res = TEE_SetOperationKey(operation, key_handle);
36    if (res != TEE_SUCCESS)
37    {
38        EMSG("Failed to set operation key, res=0x%08x", res);
39        goto exit;
40    }
41
42    /* Initialize cipher with IV */
43    TEE_CipherInit(operation, iv, AES_BLOCK_SIZE);
44
45    /* Decrypt ciphertext (excluding the IV) */
46    dec_len = (uint32_t)(*plaintext_len);
47    size_t input_len = ciphertext_len - AES_BLOCK_SIZE;
48
49    res = TEE_CipherUpdate(operation, ciphertext + AES_BLOCK_SIZE, input_len, plaintext, &dec_len);
50    if (res != TEE_SUCCESS)
51    {
52        EMSG("Failed to decrypt data, res=0x%08x", res);
53        goto exit;
54    }
55
56    *plaintext_len = dec_len;
57
58exit:
59    if (operation != TEE_HANDLE_NULL)
60        TEE_FreeOperation(operation);
61    if (key_handle != TEE_HANDLE_NULL)
62        TEE_CloseObject(key_handle);
63    TEE_MemFill(iv, 0, sizeof(iv));
64
65    return res;
66}