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