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:
Validate input size: Ensures ciphertext length is at least one AES block size to contain the IV.
Extract IV: Reads the IV from the first AES block-sized bytes of ciphertext.
Retrieve AES key: Obtains the key handle using
generate_aes_key().Allocate decrypt operation: Creates AES-CTR decryption operation via
TEE_AllocateOperation().Set operation key: Assigns the AES key to the operation.
Initialize cipher: Initializes the operation with extracted IV.
Decrypt ciphertext: Processes ciphertext (excluding IV) using
TEE_CipherUpdate().Update output length: Sets plaintext length to decrypted data size.
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}