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