@@ -128,6 +128,7 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
128128 constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH (PSA_KEY_TYPE_AES);
129129 size_t block_aligned_length = (plaintext_length / kBlockSize ) * kBlockSize ;
130130 size_t partial_block_length = plaintext_length % kBlockSize ;
131+ size_t ciphertext_length = 0 ;
131132
132133 // Make sure the calculated block_aligned_length is compliant with PSA's output size requirements.
133134 VerifyOrReturnError (block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, block_aligned_length),
@@ -137,37 +138,45 @@ CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, c
137138 {
138139 status = psa_aead_update (&operation, plaintext, block_aligned_length, ciphertext, block_aligned_length, &out_length);
139140 VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
140-
141- ciphertext += out_length;
141+ VerifyOrReturnError (out_length <= block_aligned_length, CHIP_ERROR_INTERNAL);
142+ ciphertext_length += out_length;
142143 }
143144
144145 if (partial_block_length > 0 )
145146 {
146- uint8_t temp_buffer [kBlockSize ];
147+ uint8_t temp [kBlockSize ] = { 0 } ;
147148 size_t rounded_up_length = PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, partial_block_length);
148149
149- VerifyOrReturnError (rounded_up_length <= sizeof (temp_buffer ), CHIP_ERROR_BUFFER_TOO_SMALL );
150+ VerifyOrReturnError (rounded_up_length <= sizeof (temp ), CHIP_ERROR_INTERNAL );
150151
151152 out_length = 0 ;
152- status = psa_aead_update (&operation, plaintext + block_aligned_length, partial_block_length, &temp_buffer[ 0 ] ,
153- rounded_up_length, &out_length);
153+ status = psa_aead_update (&operation, plaintext + block_aligned_length, partial_block_length, temp, rounded_up_length ,
154+ &out_length);
154155 VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
155156
156- VerifyOrReturnError (partial_block_length == out_length, CHIP_ERROR_INTERNAL);
157- memcpy (ciphertext, temp_buffer, partial_block_length);
158-
159- ciphertext += out_length;
157+ VerifyOrReturnError (ciphertext_length + out_length <= plaintext_length , CHIP_ERROR_INTERNAL);
158+ // Add the encrypted output, if any
159+ memcpy (&ciphertext[ciphertext_length], temp, out_length);
160+ ciphertext_length += out_length;
160161 }
161162
162163 if (plaintext_length != 0 )
163164 {
164- out_length = 0 ;
165- tag_out_length = 0 ;
165+ uint8_t temp[kBlockSize ] = { 0 };
166166
167- status = psa_aead_finish (&operation, ciphertext, PSA_AEAD_FINISH_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm), &out_length, tag,
168- tag_length, &tag_out_length );
169- }
167+ // The finish output should fit in the temp buffer
168+ size_t max_finish = PSA_AEAD_FINISH_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm );
169+ VerifyOrReturnError (max_finish <= sizeof (temp), CHIP_ERROR_BUFFER_TOO_SMALL);
170170
171+ // The finish may return the last part of the ciphertext
172+ status = psa_aead_finish (&operation, temp, max_finish, &out_length, tag, tag_length, &tag_out_length);
173+ VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
174+ // For CCM encryption, the ciphertext and plaintext length are equal
175+ VerifyOrReturnError ((ciphertext_length + out_length) == plaintext_length, CHIP_ERROR_INTERNAL);
176+ // Add the encrypted output, if any
177+ memcpy (&ciphertext[ciphertext_length], temp, out_length);
178+ ciphertext_length += out_length;
179+ }
171180 else
172181 {
173182 out_length = 0 ;
@@ -242,6 +251,8 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
242251 constexpr uint8_t kBlockSize = PSA_BLOCK_CIPHER_BLOCK_LENGTH (PSA_KEY_TYPE_AES);
243252 size_t block_aligned_length = (ciphertext_length / kBlockSize ) * kBlockSize ;
244253 size_t partial_block_length = ciphertext_length % kBlockSize ;
254+ size_t plaintext_length = 0 ;
255+ uint8_t temp[kBlockSize ] = { 0 };
245256
246257 // Make sure the calculated block_aligned_length is compliant with PSA's output size requirements.
247258 VerifyOrReturnError (block_aligned_length == PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, block_aligned_length),
@@ -251,33 +262,42 @@ CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length,
251262 {
252263 status = psa_aead_update (&operation, ciphertext, block_aligned_length, plaintext, block_aligned_length, &out_length);
253264 VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
254-
255- plaintext += out_length;
265+ VerifyOrReturnError (out_length <= block_aligned_length, CHIP_ERROR_INTERNAL);
266+ plaintext_length += out_length;
256267 }
257268
258269 if (partial_block_length > 0 )
259270 {
260- uint8_t temp_buffer[kBlockSize ];
261271 size_t rounded_up_length = PSA_AEAD_UPDATE_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm, partial_block_length);
262-
263- VerifyOrReturnError (rounded_up_length <= sizeof (temp_buffer), CHIP_ERROR_BUFFER_TOO_SMALL);
272+ VerifyOrReturnError (rounded_up_length <= sizeof (temp), CHIP_ERROR_BUFFER_TOO_SMALL);
264273
265274 out_length = 0 ;
266- status = psa_aead_update (&operation, ciphertext + block_aligned_length, partial_block_length, &temp_buffer[ 0 ] ,
267- rounded_up_length, &out_length);
275+ status = psa_aead_update (&operation, ciphertext + block_aligned_length, partial_block_length, temp, rounded_up_length ,
276+ &out_length);
268277 VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
269278
270- VerifyOrReturnError (partial_block_length == out_length, CHIP_ERROR_INTERNAL);
271- memcpy (plaintext, &temp_buffer[ 0 ], partial_block_length);
272-
273- plaintext += out_length;
279+ VerifyOrReturnError (plaintext_length + out_length <= ciphertext_length , CHIP_ERROR_INTERNAL);
280+ // Add the decrypted output, if any
281+ memcpy (&plaintext[plaintext_length], temp, out_length);
282+ plaintext_length += out_length;
274283 }
275284
285+ // The finish output should fit in the temp buffer
286+ size_t max_verify = PSA_AEAD_VERIFY_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm);
287+ VerifyOrReturnError (max_verify <= sizeof (temp), CHIP_ERROR_BUFFER_TOO_SMALL);
288+
276289 if (ciphertext_length != 0 )
277290 {
278291 out_length = 0 ;
279- status = psa_aead_verify (&operation, plaintext, PSA_AEAD_VERIFY_OUTPUT_SIZE (PSA_KEY_TYPE_AES, algorithm), &out_length, tag,
280- tag_length);
292+ memset (temp, 0 , sizeof (temp));
293+
294+ status = psa_aead_verify (&operation, temp, max_verify, &out_length, tag, tag_length);
295+ VerifyOrReturnError (status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
296+ // For CCM decryption, the ciphertext and plaintext length are equal
297+ VerifyOrReturnError ((plaintext_length + out_length) == ciphertext_length, CHIP_ERROR_INTERNAL);
298+ // Add the decrypted output, if any
299+ memcpy (&plaintext[plaintext_length], temp, out_length);
300+ plaintext_length += out_length;
281301 }
282302 else
283303 {
0 commit comments