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     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 
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)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. */
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)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 
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)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. */
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)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. */
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)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*/
mbedtls_psa_aead_set_nonce(mbedtls_psa_aead_operation_t * operation,const uint8_t * nonce,size_t nonce_length)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. */
mbedtls_psa_aead_set_lengths(mbedtls_psa_aead_operation_t * operation,size_t ad_length,size_t plaintext_length)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. */
mbedtls_psa_aead_update_ad(mbedtls_psa_aead_operation_t * operation,const uint8_t * input,size_t input_length)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.*/
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)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. */
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)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 */
mbedtls_psa_aead_abort(mbedtls_psa_aead_operation_t * 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 */
650