quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

psa_crypto_aead.c (22806B)


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