2828#include < lib/support/BufferWriter.h>
2929#include < lib/support/BytesToHex.h>
3030#include < lib/support/CHIPArgParser.hpp>
31+ #include < lib/support/CHIPMem.h>
3132#include < lib/support/CodeUtils.h>
3233#include < lib/support/SafeInt.h>
3334#include < lib/support/SafePointerCast.h>
@@ -71,45 +72,28 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
7172
7273 const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG (PSA_ALG_CCM, tag_length);
7374 psa_status_t status = PSA_SUCCESS;
74- psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
75- size_t out_length;
76- size_t tag_out_length;
75+ size_t ciphertext_length = 0 ;
7776
78- status = psa_aead_encrypt_setup (&operation, key.As <psa_key_id_t >(), algorithm);
79- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
77+ // The PSA single-part API appends the tag to the ciphertext output buffer.
78+ // So we need to allocate a temporary buffer to hold ciphertext + tag, then split them.
79+ size_t total_output_size = plaintext_length + tag_length;
80+ uint8_t * temp_output = static_cast <uint8_t *>(chip::Platform::MemoryAlloc (total_output_size));
81+ VerifyOrReturnError (temp_output != nullptr , CHIP_ERROR_NO_MEMORY);
8082
81- status = psa_aead_set_lengths (&operation, aad_length, plaintext_length);
82- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL );
83+ status = psa_aead_encrypt (key. As < psa_key_id_t >(), algorithm, nonce, nonce_length, aad, aad_length, plaintext, plaintext_length,
84+ temp_output, total_output_size, &ciphertext_length );
8385
84- status = psa_aead_set_nonce (&operation, nonce, nonce_length);
85- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
86-
87- if (aad_length != 0 )
88- {
89- status = psa_aead_update_ad (&operation, aad, aad_length);
90- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
91- }
92- else
86+ if (status == PSA_SUCCESS && ciphertext_length == total_output_size)
9387 {
94- ChipLogDetail (Crypto, " AES_CCM_encrypt: Using aad == null path" );
95- }
96-
97- if (plaintext_length != 0 )
98- {
99- status = psa_aead_update (&operation, plaintext, plaintext_length, ciphertext,
100- PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, plaintext_length), &out_length);
101- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
102-
103- ciphertext += out_length;
104-
105- status = psa_aead_finish (&operation, ciphertext, PSA_AEAD_FINISH_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm), &out_length, tag,
106- tag_length, &tag_out_length);
107- }
108- else
109- {
110- status = psa_aead_finish (&operation, nullptr , 0 , &out_length, tag, tag_length, &tag_out_length);
88+ // Copy ciphertext and tag to their respective output buffers
89+ if (plaintext_length > 0 )
90+ {
91+ memcpy (ciphertext, temp_output, plaintext_length);
92+ }
93+ memcpy (tag, temp_output + plaintext_length, tag_length);
11194 }
112- VerifyOrReturnError (status == PSA_SUCCESS && tag_length == tag_out_length, CHIP_ERROR_INTERNAL);
95+ chip::Platform::MemoryFree (temp_output);
96+ VerifyOrReturnError (status == PSA_SUCCESS && ciphertext_length == total_output_size, CHIP_ERROR_INTERNAL);
11397
11498 return CHIP_NO_ERROR;
11599}
@@ -125,45 +109,26 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
125109
126110 const psa_algorithm_t algorithm = PSA_ALG_AEAD_WITH_SHORTENED_TAG (PSA_ALG_CCM, tag_length);
127111 psa_status_t status = PSA_SUCCESS;
128- psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
129- size_t outLength;
130-
131- status = psa_aead_decrypt_setup (&operation, key.As <psa_key_id_t >(), algorithm);
132- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
133-
134- status = psa_aead_set_lengths (&operation, aad_length, ciphertext_length);
135- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
112+ size_t plaintext_length = 0 ;
136113
137- status = psa_aead_set_nonce (&operation, nonce, nonce_length);
138- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
114+ // The PSA single-part API expects the tag to be appended to the ciphertext input buffer.
115+ // So we need to allocate a temporary buffer to hold ciphertext + tag.
116+ size_t total_input_size = ciphertext_length + tag_length;
117+ uint8_t * temp_input = static_cast <uint8_t *>(chip::Platform::MemoryAlloc (total_input_size));
118+ VerifyOrReturnError (temp_input != nullptr , CHIP_ERROR_NO_MEMORY);
139119
140- if (aad_length != 0 )
141- {
142- status = psa_aead_update_ad (&operation, aad, aad_length);
143- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
144- }
145- else
120+ if (ciphertext_length > 0 )
146121 {
147- ChipLogDetail (Crypto, " AES_CCM_decrypt: Using aad == null path " );
122+ memcpy (temp_input, ciphertext, ciphertext_length );
148123 }
124+ memcpy (temp_input + ciphertext_length, tag, tag_length);
149125
150- if (ciphertext_length != 0 )
151- {
152- status = psa_aead_update (&operation, ciphertext, ciphertext_length, plaintext,
153- PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, ciphertext_length), &outLength);
154- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
155-
156- plaintext += outLength;
126+ status = psa_aead_decrypt (key.As <psa_key_id_t >(), algorithm, nonce, nonce_length, aad, aad_length, temp_input, total_input_size,
127+ plaintext, ciphertext_length, &plaintext_length);
157128
158- status = psa_aead_verify (&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm), &outLength, tag,
159- tag_length);
160- }
161- else
162- {
163- status = psa_aead_verify (&operation, nullptr , 0 , &outLength, tag, tag_length);
164- }
165-
166- VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
129+ chip::Platform::MemoryFree (temp_input);
130+ VerifyOrReturnError (status == PSA_SUCCESS && plaintext_length == ciphertext_length,
131+ (status == PSA_ERROR_INVALID_SIGNATURE) ? CHIP_ERROR_INVALID_SIGNATURE : CHIP_ERROR_INTERNAL);
167132
168133 return CHIP_NO_ERROR;
169134}
0 commit comments