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