1 /*
2 * PSA AEAD entry points
3 */
4 /*
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include "common.h"
22
23 #if defined(MBEDTLS_PSA_CRYPTO_C)
24
25 #include "psa_crypto_aead.h"
26 #include "psa_crypto_core.h"
27 #include "psa_crypto_cipher.h"
28
29 #include <string.h>
30 #include "mbedtls/platform.h"
31
32 #include "mbedtls/ccm.h"
33 #include "mbedtls/chachapoly.h"
34 #include "mbedtls/cipher.h"
35 #include "mbedtls/gcm.h"
36 #include "mbedtls/error.h"
37
psa_aead_setup(mbedtls_psa_aead_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)38 static psa_status_t psa_aead_setup(
39 mbedtls_psa_aead_operation_t *operation,
40 const psa_key_attributes_t *attributes,
41 const uint8_t *key_buffer,
42 size_t key_buffer_size,
43 psa_algorithm_t alg)
44 {
45 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
46 size_t key_bits;
47 const mbedtls_cipher_info_t *cipher_info;
48 mbedtls_cipher_id_t cipher_id;
49
50 (void) key_buffer_size;
51
52 key_bits = attributes->core.bits;
53
54 cipher_info = mbedtls_cipher_info_from_psa(alg,
55 attributes->core.type, key_bits,
56 &cipher_id);
57 if (cipher_info == NULL) {
58 return PSA_ERROR_NOT_SUPPORTED;
59 }
60
61 switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
62 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
63 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
64 operation->alg = PSA_ALG_CCM;
65 /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
66 * The call to mbedtls_ccm_encrypt_and_tag or
67 * mbedtls_ccm_auth_decrypt will validate the tag length. */
68 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
69 return PSA_ERROR_INVALID_ARGUMENT;
70 }
71
72 mbedtls_ccm_init(&operation->ctx.ccm);
73 status = mbedtls_to_psa_error(
74 mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
75 key_buffer, (unsigned int) key_bits));
76 if (status != PSA_SUCCESS) {
77 return status;
78 }
79 break;
80 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
81
82 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
83 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
84 operation->alg = PSA_ALG_GCM;
85 /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
86 * The call to mbedtls_gcm_crypt_and_tag or
87 * mbedtls_gcm_auth_decrypt will validate the tag length. */
88 if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
89 return PSA_ERROR_INVALID_ARGUMENT;
90 }
91
92 mbedtls_gcm_init(&operation->ctx.gcm);
93 status = mbedtls_to_psa_error(
94 mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
95 key_buffer, (unsigned int) key_bits));
96 if (status != PSA_SUCCESS) {
97 return status;
98 }
99 break;
100 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
101
102 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
103 case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
104 operation->alg = PSA_ALG_CHACHA20_POLY1305;
105 /* We only support the default tag length. */
106 if (alg != PSA_ALG_CHACHA20_POLY1305) {
107 return PSA_ERROR_NOT_SUPPORTED;
108 }
109
110 mbedtls_chachapoly_init(&operation->ctx.chachapoly);
111 status = mbedtls_to_psa_error(
112 mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
113 key_buffer));
114 if (status != PSA_SUCCESS) {
115 return status;
116 }
117 break;
118 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
119
120 default:
121 (void) status;
122 (void) key_buffer;
123 return PSA_ERROR_NOT_SUPPORTED;
124 }
125
126 operation->key_type = psa_get_key_type(attributes);
127
128 operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
129
130 return PSA_SUCCESS;
131 }
132
mbedtls_psa_aead_encrypt(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * nonce,size_t nonce_length,const uint8_t * additional_data,size_t additional_data_length,const uint8_t * plaintext,size_t plaintext_length,uint8_t * ciphertext,size_t ciphertext_size,size_t * ciphertext_length)133 psa_status_t mbedtls_psa_aead_encrypt(
134 const psa_key_attributes_t *attributes,
135 const uint8_t *key_buffer, size_t key_buffer_size,
136 psa_algorithm_t alg,
137 const uint8_t *nonce, size_t nonce_length,
138 const uint8_t *additional_data, size_t additional_data_length,
139 const uint8_t *plaintext, size_t plaintext_length,
140 uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
141 {
142 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
143 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
144 uint8_t *tag;
145
146 status = psa_aead_setup(&operation, attributes, key_buffer,
147 key_buffer_size, alg);
148
149 if (status != PSA_SUCCESS) {
150 goto exit;
151 }
152
153 /* For all currently supported modes, the tag is at the end of the
154 * ciphertext. */
155 if (ciphertext_size < (plaintext_length + operation.tag_length)) {
156 status = PSA_ERROR_BUFFER_TOO_SMALL;
157 goto exit;
158 }
159 tag = ciphertext + plaintext_length;
160
161 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
162 if (operation.alg == PSA_ALG_CCM) {
163 status = mbedtls_to_psa_error(
164 mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
165 plaintext_length,
166 nonce, nonce_length,
167 additional_data,
168 additional_data_length,
169 plaintext, ciphertext,
170 tag, operation.tag_length));
171 } else
172 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
173 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
174 if (operation.alg == PSA_ALG_GCM) {
175 status = mbedtls_to_psa_error(
176 mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
177 MBEDTLS_GCM_ENCRYPT,
178 plaintext_length,
179 nonce, nonce_length,
180 additional_data, additional_data_length,
181 plaintext, ciphertext,
182 operation.tag_length, tag));
183 } else
184 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
185 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
186 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
187 if (operation.tag_length != 16) {
188 status = PSA_ERROR_NOT_SUPPORTED;
189 goto exit;
190 }
191 status = mbedtls_to_psa_error(
192 mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
193 plaintext_length,
194 nonce,
195 additional_data,
196 additional_data_length,
197 plaintext,
198 ciphertext,
199 tag));
200 } else
201 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
202 {
203 (void) tag;
204 (void) nonce;
205 (void) nonce_length;
206 (void) additional_data;
207 (void) additional_data_length;
208 (void) plaintext;
209 return PSA_ERROR_NOT_SUPPORTED;
210 }
211
212 if (status == PSA_SUCCESS) {
213 *ciphertext_length = plaintext_length + operation.tag_length;
214 }
215
216 exit:
217 mbedtls_psa_aead_abort(&operation);
218
219 return status;
220 }
221
222 /* Locate the tag in a ciphertext buffer containing the encrypted data
223 * followed by the tag. Return the length of the part preceding the tag in
224 * *plaintext_length. This is the size of the plaintext in modes where
225 * the encrypted data has the same size as the plaintext, such as
226 * CCM and GCM. */
psa_aead_unpadded_locate_tag(size_t tag_length,const uint8_t * ciphertext,size_t ciphertext_length,size_t plaintext_size,const uint8_t ** p_tag)227 static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
228 const uint8_t *ciphertext,
229 size_t ciphertext_length,
230 size_t plaintext_size,
231 const uint8_t **p_tag)
232 {
233 size_t payload_length;
234 if (tag_length > ciphertext_length) {
235 return PSA_ERROR_INVALID_ARGUMENT;
236 }
237 payload_length = ciphertext_length - tag_length;
238 if (payload_length > plaintext_size) {
239 return PSA_ERROR_BUFFER_TOO_SMALL;
240 }
241 *p_tag = ciphertext + payload_length;
242 return PSA_SUCCESS;
243 }
244
mbedtls_psa_aead_decrypt(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * nonce,size_t nonce_length,const uint8_t * additional_data,size_t additional_data_length,const uint8_t * ciphertext,size_t ciphertext_length,uint8_t * plaintext,size_t plaintext_size,size_t * plaintext_length)245 psa_status_t mbedtls_psa_aead_decrypt(
246 const psa_key_attributes_t *attributes,
247 const uint8_t *key_buffer, size_t key_buffer_size,
248 psa_algorithm_t alg,
249 const uint8_t *nonce, size_t nonce_length,
250 const uint8_t *additional_data, size_t additional_data_length,
251 const uint8_t *ciphertext, size_t ciphertext_length,
252 uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
253 {
254 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
255 mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
256 const uint8_t *tag = NULL;
257
258 status = psa_aead_setup(&operation, attributes, key_buffer,
259 key_buffer_size, alg);
260
261 if (status != PSA_SUCCESS) {
262 goto exit;
263 }
264
265 status = psa_aead_unpadded_locate_tag(operation.tag_length,
266 ciphertext, ciphertext_length,
267 plaintext_size, &tag);
268 if (status != PSA_SUCCESS) {
269 goto exit;
270 }
271
272 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
273 if (operation.alg == PSA_ALG_CCM) {
274 status = mbedtls_to_psa_error(
275 mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
276 ciphertext_length - operation.tag_length,
277 nonce, nonce_length,
278 additional_data,
279 additional_data_length,
280 ciphertext, plaintext,
281 tag, operation.tag_length));
282 } else
283 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
284 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
285 if (operation.alg == PSA_ALG_GCM) {
286 status = mbedtls_to_psa_error(
287 mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
288 ciphertext_length - operation.tag_length,
289 nonce, nonce_length,
290 additional_data,
291 additional_data_length,
292 tag, operation.tag_length,
293 ciphertext, plaintext));
294 } else
295 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
296 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
297 if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
298 if (operation.tag_length != 16) {
299 status = PSA_ERROR_NOT_SUPPORTED;
300 goto exit;
301 }
302 status = mbedtls_to_psa_error(
303 mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
304 ciphertext_length - operation.tag_length,
305 nonce,
306 additional_data,
307 additional_data_length,
308 tag,
309 ciphertext,
310 plaintext));
311 } else
312 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
313 {
314 (void) nonce;
315 (void) nonce_length;
316 (void) additional_data;
317 (void) additional_data_length;
318 (void) plaintext;
319 return PSA_ERROR_NOT_SUPPORTED;
320 }
321
322 if (status == PSA_SUCCESS) {
323 *plaintext_length = ciphertext_length - operation.tag_length;
324 }
325
326 exit:
327 mbedtls_psa_aead_abort(&operation);
328
329 if (status == PSA_SUCCESS) {
330 *plaintext_length = ciphertext_length - operation.tag_length;
331 }
332 return status;
333 }
334
335 /* Set the key and algorithm for a multipart authenticated encryption
336 * operation. */
mbedtls_psa_aead_encrypt_setup(mbedtls_psa_aead_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)337 psa_status_t mbedtls_psa_aead_encrypt_setup(
338 mbedtls_psa_aead_operation_t *operation,
339 const psa_key_attributes_t *attributes,
340 const uint8_t *key_buffer,
341 size_t key_buffer_size,
342 psa_algorithm_t alg)
343 {
344 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
345
346 status = psa_aead_setup(operation, attributes, key_buffer,
347 key_buffer_size, alg);
348
349 if (status == PSA_SUCCESS) {
350 operation->is_encrypt = 1;
351 }
352
353 return status;
354 }
355
356 /* Set the key and algorithm for a multipart authenticated decryption
357 * operation. */
mbedtls_psa_aead_decrypt_setup(mbedtls_psa_aead_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)358 psa_status_t mbedtls_psa_aead_decrypt_setup(
359 mbedtls_psa_aead_operation_t *operation,
360 const psa_key_attributes_t *attributes,
361 const uint8_t *key_buffer,
362 size_t key_buffer_size,
363 psa_algorithm_t alg)
364 {
365 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
366
367 status = psa_aead_setup(operation, attributes, key_buffer,
368 key_buffer_size, alg);
369
370 if (status == PSA_SUCCESS) {
371 operation->is_encrypt = 0;
372 }
373
374 return status;
375 }
376
377 /* Set a nonce for the multipart AEAD operation*/
mbedtls_psa_aead_set_nonce(mbedtls_psa_aead_operation_t * operation,const uint8_t * nonce,size_t nonce_length)378 psa_status_t mbedtls_psa_aead_set_nonce(
379 mbedtls_psa_aead_operation_t *operation,
380 const uint8_t *nonce,
381 size_t nonce_length)
382 {
383 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
384
385 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
386 if (operation->alg == PSA_ALG_GCM) {
387 status = mbedtls_to_psa_error(
388 mbedtls_gcm_starts(&operation->ctx.gcm,
389 operation->is_encrypt ?
390 MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
391 nonce,
392 nonce_length));
393 } else
394 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
395 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
396 if (operation->alg == PSA_ALG_CCM) {
397 status = mbedtls_to_psa_error(
398 mbedtls_ccm_starts(&operation->ctx.ccm,
399 operation->is_encrypt ?
400 MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
401 nonce,
402 nonce_length));
403 } else
404 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
405 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
406 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
407 /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
408 * allocate a buffer in the operation, copy the nonce to it and pad
409 * it, so for now check the nonce is 12 bytes, as
410 * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
411 * passed in buffer. */
412 if (nonce_length != 12) {
413 return PSA_ERROR_INVALID_ARGUMENT;
414 }
415
416 status = mbedtls_to_psa_error(
417 mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
418 nonce,
419 operation->is_encrypt ?
420 MBEDTLS_CHACHAPOLY_ENCRYPT :
421 MBEDTLS_CHACHAPOLY_DECRYPT));
422 } else
423 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
424 {
425 (void) operation;
426 (void) nonce;
427 (void) nonce_length;
428
429 return PSA_ERROR_NOT_SUPPORTED;
430 }
431
432 return status;
433 }
434
435 /* Declare the lengths of the message and additional data for AEAD. */
mbedtls_psa_aead_set_lengths(mbedtls_psa_aead_operation_t * operation,size_t ad_length,size_t plaintext_length)436 psa_status_t mbedtls_psa_aead_set_lengths(
437 mbedtls_psa_aead_operation_t *operation,
438 size_t ad_length,
439 size_t plaintext_length)
440 {
441 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
442 if (operation->alg == PSA_ALG_CCM) {
443 return mbedtls_to_psa_error(
444 mbedtls_ccm_set_lengths(&operation->ctx.ccm,
445 ad_length,
446 plaintext_length,
447 operation->tag_length));
448
449 }
450 #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
451 (void) operation;
452 (void) ad_length;
453 (void) plaintext_length;
454 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
455
456 return PSA_SUCCESS;
457 }
458
459 /* Pass additional data to an active multipart AEAD operation. */
mbedtls_psa_aead_update_ad(mbedtls_psa_aead_operation_t * operation,const uint8_t * input,size_t input_length)460 psa_status_t mbedtls_psa_aead_update_ad(
461 mbedtls_psa_aead_operation_t *operation,
462 const uint8_t *input,
463 size_t input_length)
464 {
465 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
466
467 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
468 if (operation->alg == PSA_ALG_GCM) {
469 status = mbedtls_to_psa_error(
470 mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
471 } else
472 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
473 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
474 if (operation->alg == PSA_ALG_CCM) {
475 status = mbedtls_to_psa_error(
476 mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
477 } else
478 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
479 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
480 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
481 status = mbedtls_to_psa_error(
482 mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
483 input,
484 input_length));
485 } else
486 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
487 {
488 (void) operation;
489 (void) input;
490 (void) input_length;
491
492 return PSA_ERROR_NOT_SUPPORTED;
493 }
494
495 return status;
496 }
497
498 /* Encrypt or decrypt a message fragment in an active multipart AEAD
499 * operation.*/
mbedtls_psa_aead_update(mbedtls_psa_aead_operation_t * operation,const uint8_t * input,size_t input_length,uint8_t * output,size_t output_size,size_t * output_length)500 psa_status_t mbedtls_psa_aead_update(
501 mbedtls_psa_aead_operation_t *operation,
502 const uint8_t *input,
503 size_t input_length,
504 uint8_t *output,
505 size_t output_size,
506 size_t *output_length)
507 {
508 size_t update_output_length;
509 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
510
511 update_output_length = input_length;
512
513 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
514 if (operation->alg == PSA_ALG_GCM) {
515 status = mbedtls_to_psa_error(
516 mbedtls_gcm_update(&operation->ctx.gcm,
517 input, input_length,
518 output, output_size,
519 &update_output_length));
520 } else
521 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
522 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
523 if (operation->alg == PSA_ALG_CCM) {
524 if (output_size < input_length) {
525 return PSA_ERROR_BUFFER_TOO_SMALL;
526 }
527
528 status = mbedtls_to_psa_error(
529 mbedtls_ccm_update(&operation->ctx.ccm,
530 input, input_length,
531 output, output_size,
532 &update_output_length));
533 } else
534 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
535 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
536 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
537 if (output_size < input_length) {
538 return PSA_ERROR_BUFFER_TOO_SMALL;
539 }
540
541 status = mbedtls_to_psa_error(
542 mbedtls_chachapoly_update(&operation->ctx.chachapoly,
543 input_length,
544 input,
545 output));
546 } else
547 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
548 {
549 (void) operation;
550 (void) input;
551 (void) output;
552 (void) output_size;
553
554 return PSA_ERROR_NOT_SUPPORTED;
555 }
556
557 if (status == PSA_SUCCESS) {
558 *output_length = update_output_length;
559 }
560
561 return status;
562 }
563
564 /* Finish encrypting a message in a multipart AEAD operation. */
mbedtls_psa_aead_finish(mbedtls_psa_aead_operation_t * operation,uint8_t * ciphertext,size_t ciphertext_size,size_t * ciphertext_length,uint8_t * tag,size_t tag_size,size_t * tag_length)565 psa_status_t mbedtls_psa_aead_finish(
566 mbedtls_psa_aead_operation_t *operation,
567 uint8_t *ciphertext,
568 size_t ciphertext_size,
569 size_t *ciphertext_length,
570 uint8_t *tag,
571 size_t tag_size,
572 size_t *tag_length)
573 {
574 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
575 size_t finish_output_size = 0;
576
577 if (tag_size < operation->tag_length) {
578 return PSA_ERROR_BUFFER_TOO_SMALL;
579 }
580
581 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
582 if (operation->alg == PSA_ALG_GCM) {
583 status = mbedtls_to_psa_error(
584 mbedtls_gcm_finish(&operation->ctx.gcm,
585 ciphertext, ciphertext_size, ciphertext_length,
586 tag, operation->tag_length));
587 } else
588 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
589 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
590 if (operation->alg == PSA_ALG_CCM) {
591 /* tag must be big enough to store a tag of size passed into set
592 * lengths. */
593 if (tag_size < operation->tag_length) {
594 return PSA_ERROR_BUFFER_TOO_SMALL;
595 }
596
597 status = mbedtls_to_psa_error(
598 mbedtls_ccm_finish(&operation->ctx.ccm,
599 tag, operation->tag_length));
600 } else
601 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
602 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
603 if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
604 /* Belt and braces. Although the above tag_size check should have
605 * already done this, if we later start supporting smaller tag sizes
606 * for chachapoly, then passing a tag buffer smaller than 16 into here
607 * could cause a buffer overflow, so better safe than sorry. */
608 if (tag_size < 16) {
609 return PSA_ERROR_BUFFER_TOO_SMALL;
610 }
611
612 status = mbedtls_to_psa_error(
613 mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
614 tag));
615 } else
616 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
617 {
618 (void) ciphertext;
619 (void) ciphertext_size;
620 (void) ciphertext_length;
621 (void) tag;
622 (void) tag_size;
623 (void) tag_length;
624
625 return PSA_ERROR_NOT_SUPPORTED;
626 }
627
628 if (status == PSA_SUCCESS) {
629 /* This will be zero for all supported algorithms currently, but left
630 * here for future support. */
631 *ciphertext_length = finish_output_size;
632 *tag_length = operation->tag_length;
633 }
634
635 return status;
636 }
637
638 /* Abort an AEAD operation */
mbedtls_psa_aead_abort(mbedtls_psa_aead_operation_t * operation)639 psa_status_t mbedtls_psa_aead_abort(
640 mbedtls_psa_aead_operation_t *operation)
641 {
642 switch (operation->alg) {
643 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
644 case PSA_ALG_CCM:
645 mbedtls_ccm_free(&operation->ctx.ccm);
646 break;
647 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
648 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
649 case PSA_ALG_GCM:
650 mbedtls_gcm_free(&operation->ctx.gcm);
651 break;
652 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
653 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
654 case PSA_ALG_CHACHA20_POLY1305:
655 mbedtls_chachapoly_free(&operation->ctx.chachapoly);
656 break;
657 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
658 }
659
660 operation->is_encrypt = 0;
661
662 return PSA_SUCCESS;
663 }
664
665 #endif /* MBEDTLS_PSA_CRYPTO_C */
666