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