blob: 47b0e7b3e2cda0d55b5f1693eaf53ad9babf80b8 [file] [log] [blame]
Ronald Cron7ceee8d2021-03-17 16:55:43 +01001/*
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
Paul Elliottadb8b162021-04-20 16:06:57 +010023
Ronald Cron7ceee8d2021-03-17 16:55:43 +010024#if defined(MBEDTLS_PSA_CRYPTO_C)
25
26#include "psa_crypto_aead.h"
Ronald Cron46f91782021-03-17 08:16:34 +010027#include "psa_crypto_core.h"
28
Paul Elliottadb8b162021-04-20 16:06:57 +010029#include <string.h>
30#include "mbedtls/platform.h"
31#if !defined(MBEDTLS_PLATFORM_C)
32#define mbedtls_calloc calloc
33#define mbedtls_free free
34#endif
35
Ronald Cron46f91782021-03-17 08:16:34 +010036#include "mbedtls/ccm.h"
37#include "mbedtls/chachapoly.h"
38#include "mbedtls/cipher.h"
39#include "mbedtls/gcm.h"
Paul Elliottadb8b162021-04-20 16:06:57 +010040#include "mbedtls/error.h"
Ronald Cron46f91782021-03-17 08:16:34 +010041
Paul Elliottadb8b162021-04-20 16:06:57 +010042/* Constant-time buffer comparison. This is duplication of code from
43 * psa_crypto.c, but has nowhere private I can put it for the minute. Really
44 belongs in the constant time module, when that gets implemented */
45static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
Ronald Cron46f91782021-03-17 08:16:34 +010046{
Paul Elliottadb8b162021-04-20 16:06:57 +010047 size_t i;
48 unsigned char diff = 0;
49
50 for( i = 0; i < n; i++ )
51 diff |= a[i] ^ b[i];
52
53 return( diff );
Ronald Cron46f91782021-03-17 08:16:34 +010054}
55
Paul Elliottadb8b162021-04-20 16:06:57 +010056
Ronald Cron46f91782021-03-17 08:16:34 +010057static psa_status_t psa_aead_setup(
Paul Elliott07a30c42021-04-20 14:13:23 +010058 psa_aead_operation_t *operation,
Ronald Cron46f91782021-03-17 08:16:34 +010059 const psa_key_attributes_t *attributes,
60 const uint8_t *key_buffer,
61 psa_algorithm_t alg )
62{
63 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
64 size_t key_bits;
Ronald Cronecbc0682021-03-26 13:25:17 +010065 const mbedtls_cipher_info_t *cipher_info;
Ronald Cron46f91782021-03-17 08:16:34 +010066 mbedtls_cipher_id_t cipher_id;
Ronald Cronecbc0682021-03-26 13:25:17 +010067 size_t full_tag_length = 0;
Ronald Cron46f91782021-03-17 08:16:34 +010068
Paul Elliottadb8b162021-04-20 16:06:57 +010069 if( operation->key_set || operation->nonce_set ||
70 operation->ad_started || operation->body_started )
71 {
72 return( PSA_ERROR_BAD_STATE );
73 }
74
Ronald Cron46f91782021-03-17 08:16:34 +010075 key_bits = attributes->core.bits;
76
Ronald Cronecbc0682021-03-26 13:25:17 +010077 cipher_info = mbedtls_cipher_info_from_psa( alg,
78 attributes->core.type, key_bits,
79 &cipher_id );
80 if( cipher_info == NULL )
Ronald Cron46f91782021-03-17 08:16:34 +010081 return( PSA_ERROR_NOT_SUPPORTED );
82
83 switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) )
84 {
85#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
86 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +010087 operation->alg = PSA_ALG_CCM;
Ronald Cronecbc0682021-03-26 13:25:17 +010088 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +010089 /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
90 * The call to mbedtls_ccm_encrypt_and_tag or
91 * mbedtls_ccm_auth_decrypt will validate the tag length. */
92 if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
93 return( PSA_ERROR_INVALID_ARGUMENT );
94
95 mbedtls_ccm_init( &operation->ctx.ccm );
96 status = mbedtls_to_psa_error(
97 mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
98 key_buffer, (unsigned int) key_bits ) );
99 if( status != PSA_SUCCESS )
100 return( status );
101 break;
102#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
103
104#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
105 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +0100106 operation->alg = PSA_ALG_GCM;
Ronald Cronecbc0682021-03-26 13:25:17 +0100107 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +0100108 /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
109 * The call to mbedtls_gcm_crypt_and_tag or
110 * mbedtls_gcm_auth_decrypt will validate the tag length. */
111 if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 )
112 return( PSA_ERROR_INVALID_ARGUMENT );
113
114 mbedtls_gcm_init( &operation->ctx.gcm );
115 status = mbedtls_to_psa_error(
116 mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
117 key_buffer, (unsigned int) key_bits ) );
118 if( status != PSA_SUCCESS )
119 return( status );
120 break;
121#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
122
123#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
124 case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
Paul Elliott07a30c42021-04-20 14:13:23 +0100125 operation->alg = PSA_ALG_CHACHA20_POLY1305;
Ronald Cronecbc0682021-03-26 13:25:17 +0100126 full_tag_length = 16;
Ronald Cron46f91782021-03-17 08:16:34 +0100127 /* We only support the default tag length. */
128 if( alg != PSA_ALG_CHACHA20_POLY1305 )
129 return( PSA_ERROR_NOT_SUPPORTED );
130
131 mbedtls_chachapoly_init( &operation->ctx.chachapoly );
132 status = mbedtls_to_psa_error(
133 mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
134 key_buffer ) );
135 if( status != PSA_SUCCESS )
136 return( status );
137 break;
138#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
139
140 default:
141 return( PSA_ERROR_NOT_SUPPORTED );
142 }
143
Bence Szépkútiec174e22021-03-19 18:46:15 +0100144 if( PSA_AEAD_TAG_LENGTH( attributes->core.type,
145 key_bits, alg )
146 > full_tag_length )
Ronald Cron46f91782021-03-17 08:16:34 +0100147 return( PSA_ERROR_INVALID_ARGUMENT );
148
Bence Szépkútiec174e22021-03-19 18:46:15 +0100149 operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
150 key_bits,
151 alg );
Ronald Cron46f91782021-03-17 08:16:34 +0100152
Paul Elliottadb8b162021-04-20 16:06:57 +0100153 operation->key_set = 1;
154
Ronald Cron46f91782021-03-17 08:16:34 +0100155 return( PSA_SUCCESS );
156}
157
158psa_status_t mbedtls_psa_aead_encrypt(
159 const psa_key_attributes_t *attributes,
160 const uint8_t *key_buffer, size_t key_buffer_size,
161 psa_algorithm_t alg,
162 const uint8_t *nonce, size_t nonce_length,
163 const uint8_t *additional_data, size_t additional_data_length,
164 const uint8_t *plaintext, size_t plaintext_length,
165 uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
166{
167 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliott07a30c42021-04-20 14:13:23 +0100168 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100169 uint8_t *tag;
170 (void) key_buffer_size;
171
172 status = psa_aead_setup( &operation, attributes, key_buffer, alg );
173 if( status != PSA_SUCCESS )
174 goto exit;
175
176 /* For all currently supported modes, the tag is at the end of the
177 * ciphertext. */
178 if( ciphertext_size < ( plaintext_length + operation.tag_length ) )
179 {
180 status = PSA_ERROR_BUFFER_TOO_SMALL;
181 goto exit;
182 }
183 tag = ciphertext + plaintext_length;
184
Ronald Cron46f91782021-03-17 08:16:34 +0100185#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100186 if( operation.alg == PSA_ALG_CCM )
Ronald Cron46f91782021-03-17 08:16:34 +0100187 {
188 status = mbedtls_to_psa_error(
189 mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
190 plaintext_length,
191 nonce, nonce_length,
192 additional_data,
193 additional_data_length,
194 plaintext, ciphertext,
195 tag, operation.tag_length ) );
196 }
197 else
198#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200199#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100200 if( operation.alg == PSA_ALG_GCM )
Ronald Cron810eb162021-04-06 09:01:39 +0200201 {
202 status = mbedtls_to_psa_error(
203 mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
204 MBEDTLS_GCM_ENCRYPT,
205 plaintext_length,
206 nonce, nonce_length,
207 additional_data, additional_data_length,
208 plaintext, ciphertext,
209 operation.tag_length, tag ) );
210 }
211 else
212#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100213#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott07a30c42021-04-20 14:13:23 +0100214 if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
Ronald Cron46f91782021-03-17 08:16:34 +0100215 {
216 if( nonce_length != 12 || operation.tag_length != 16 )
217 {
218 status = PSA_ERROR_NOT_SUPPORTED;
219 goto exit;
220 }
221 status = mbedtls_to_psa_error(
222 mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly,
223 plaintext_length,
224 nonce,
225 additional_data,
226 additional_data_length,
227 plaintext,
228 ciphertext,
229 tag ) );
230 }
231 else
232#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
233 {
234 (void) tag;
235 return( PSA_ERROR_NOT_SUPPORTED );
236 }
237
238 if( status == PSA_SUCCESS )
239 *ciphertext_length = plaintext_length + operation.tag_length;
240
241exit:
Paul Elliottadb8b162021-04-20 16:06:57 +0100242 mbedtls_psa_aead_abort( &operation );
Ronald Cron46f91782021-03-17 08:16:34 +0100243
244 return( status );
245}
246
247/* Locate the tag in a ciphertext buffer containing the encrypted data
248 * followed by the tag. Return the length of the part preceding the tag in
249 * *plaintext_length. This is the size of the plaintext in modes where
250 * the encrypted data has the same size as the plaintext, such as
251 * CCM and GCM. */
252static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length,
253 const uint8_t *ciphertext,
254 size_t ciphertext_length,
255 size_t plaintext_size,
256 const uint8_t **p_tag )
257{
258 size_t payload_length;
259 if( tag_length > ciphertext_length )
260 return( PSA_ERROR_INVALID_ARGUMENT );
261 payload_length = ciphertext_length - tag_length;
262 if( payload_length > plaintext_size )
263 return( PSA_ERROR_BUFFER_TOO_SMALL );
264 *p_tag = ciphertext + payload_length;
265 return( PSA_SUCCESS );
266}
267
268psa_status_t mbedtls_psa_aead_decrypt(
269 const psa_key_attributes_t *attributes,
270 const uint8_t *key_buffer, size_t key_buffer_size,
271 psa_algorithm_t alg,
272 const uint8_t *nonce, size_t nonce_length,
273 const uint8_t *additional_data, size_t additional_data_length,
274 const uint8_t *ciphertext, size_t ciphertext_length,
275 uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
276{
277 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
Paul Elliott07a30c42021-04-20 14:13:23 +0100278 psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
Ronald Cron46f91782021-03-17 08:16:34 +0100279 const uint8_t *tag = NULL;
280 (void) key_buffer_size;
281
282 status = psa_aead_setup( &operation, attributes, key_buffer, alg );
283 if( status != PSA_SUCCESS )
284 goto exit;
285
286 status = psa_aead_unpadded_locate_tag( operation.tag_length,
287 ciphertext, ciphertext_length,
288 plaintext_size, &tag );
289 if( status != PSA_SUCCESS )
290 goto exit;
291
Ronald Cron46f91782021-03-17 08:16:34 +0100292#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100293 if( operation.alg == PSA_ALG_CCM )
Ronald Cron46f91782021-03-17 08:16:34 +0100294 {
295 status = mbedtls_to_psa_error(
296 mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
297 ciphertext_length - operation.tag_length,
298 nonce, nonce_length,
299 additional_data,
300 additional_data_length,
301 ciphertext, plaintext,
302 tag, operation.tag_length ) );
303 }
304 else
305#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
Ronald Cron810eb162021-04-06 09:01:39 +0200306#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
Paul Elliott07a30c42021-04-20 14:13:23 +0100307 if( operation.alg == PSA_ALG_GCM )
Ronald Cron810eb162021-04-06 09:01:39 +0200308 {
309 status = mbedtls_to_psa_error(
310 mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
311 ciphertext_length - operation.tag_length,
312 nonce, nonce_length,
313 additional_data,
314 additional_data_length,
315 tag, operation.tag_length,
316 ciphertext, plaintext ) );
317 }
318 else
319#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
Ronald Cron46f91782021-03-17 08:16:34 +0100320#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
Paul Elliott07a30c42021-04-20 14:13:23 +0100321 if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
Ronald Cron46f91782021-03-17 08:16:34 +0100322 {
323 if( nonce_length != 12 || operation.tag_length != 16 )
324 {
325 status = PSA_ERROR_NOT_SUPPORTED;
326 goto exit;
327 }
328 status = mbedtls_to_psa_error(
329 mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly,
330 ciphertext_length - operation.tag_length,
331 nonce,
332 additional_data,
333 additional_data_length,
334 tag,
335 ciphertext,
336 plaintext ) );
337 }
338 else
339#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
340 {
341 return( PSA_ERROR_NOT_SUPPORTED );
342 }
343
344 if( status == PSA_SUCCESS )
345 *plaintext_length = ciphertext_length - operation.tag_length;
346
347exit:
Paul Elliottadb8b162021-04-20 16:06:57 +0100348 mbedtls_psa_aead_abort( &operation );
Ronald Cron46f91782021-03-17 08:16:34 +0100349
350 if( status == PSA_SUCCESS )
351 *plaintext_length = ciphertext_length - operation.tag_length;
352 return( status );
353}
Ronald Cron7ceee8d2021-03-17 16:55:43 +0100354
Paul Elliottadb8b162021-04-20 16:06:57 +0100355/* Set the key and algorithm for a multipart authenticated encryption
356 * operation. */
357psa_status_t mbedtls_psa_aead_encrypt_setup( psa_aead_operation_t *operation,
358 const psa_key_attributes_t *attributes,
359 const uint8_t *key_buffer, size_t key_buffer_size,
360 psa_algorithm_t alg )
361{
362 psa_status_t status;
363
364 (void) key_buffer_size;
365
366 status = psa_aead_setup( operation, attributes, key_buffer, alg );
367
368 if( status == PSA_SUCCESS )
369 {
370 operation->is_encrypt = 1;
371 }
372
373 return ( status );
374}
375
376/* Set the key and algorithm for a multipart authenticated decryption
377 * operation. */
378psa_status_t mbedtls_psa_aead_decrypt_setup( psa_aead_operation_t *operation,
379 const psa_key_attributes_t *attributes,
380 const uint8_t *key_buffer, size_t key_buffer_size,
381 psa_algorithm_t alg )
382{
383 psa_status_t status;
384
385 (void) key_buffer_size;
386
387 status = psa_aead_setup( operation, attributes, key_buffer, alg );
388
389 if( status == PSA_SUCCESS )
390 {
391 operation->is_encrypt = 0;
392 }
393
394 return ( status );
395}
396
397/* Generate a random nonce / IV for multipart AEAD operation */
398psa_status_t mbedtls_psa_aead_generate_nonce( psa_aead_operation_t *operation,
399 uint8_t *nonce,
400 size_t nonce_size,
401 size_t *nonce_length )
402{
403 psa_status_t status;
404 size_t required_nonce_size = nonce_size;
405
406 if( !operation->key_set || operation->nonce_set ||
407 operation->ad_started || operation->body_started )
408 {
409 return( PSA_ERROR_BAD_STATE );
410 }
411
412 required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, operation->alg);
413
414 if( nonce_size == 0 || nonce_size < required_nonce_size )
415 {
416 return( PSA_ERROR_BUFFER_TOO_SMALL );
417 }
418
419 status = psa_generate_random( nonce, required_nonce_size );
420
421 if( status != PSA_SUCCESS )
422 {
423 return status;
424 }
425
426 status = mbedtls_psa_aead_set_nonce( operation, nonce, required_nonce_size );
427
428 if( status == PSA_SUCCESS )
429 {
430 *nonce_length = required_nonce_size;
431 }
432
433 return status;
434}
435
436/* Set a nonce for the multipart AEAD operation*/
437psa_status_t mbedtls_psa_aead_set_nonce( psa_aead_operation_t *operation,
438 const uint8_t *nonce,
439 size_t nonce_length )
440{
441 psa_status_t status;
442
443 if( !operation->key_set || operation->nonce_set ||
444 operation->ad_started || operation->body_started )
445 {
446 return( PSA_ERROR_BAD_STATE );
447 }
448
449 /* Restricting to a nominal safe length for nonces even though some
450 algorithms can handle longer nonces, but not without collision */
451 if( nonce_length > PSA_AEAD_NONCE_MAX_SIZE )
452 {
453 return( PSA_ERROR_INVALID_ARGUMENT );
454 }
455
456 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
457 if( operation->alg == PSA_ALG_GCM )
458 {
459 /* GCM sets nonce once additional data has been supplied */
460 memcpy(operation->nonce, nonce, nonce_length);
461
462 /* We know that nonce size cannot exceed the uint8_t size */
463 operation->nonce_length = ( uint8_t ) nonce_length;
464 status = PSA_SUCCESS;
465 }
466 else
467#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
468#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
469 if( operation->alg == PSA_ALG_CCM )
470 {
471 /* Multipart CCM not supported as yet, so CCM is basically operating
472 in oneshot mode. Store the nonce as we need this later */
473 memcpy(operation->nonce, nonce, nonce_length);
474
475 /* We know that nonce size cannot exceed the uint8_t size */
476 operation->nonce_length = ( uint8_t ) nonce_length;
477 status = PSA_SUCCESS;
478 }
479 else
480#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
481#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
482 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
483 {
484 if( nonce_length != 12 && nonce_length != 8)
485 {
486 return( PSA_ERROR_INVALID_ARGUMENT );
487 }
488
489 status = mbedtls_to_psa_error(mbedtls_chachapoly_starts( &operation->ctx.chachapoly,
490 nonce,
491 operation->is_encrypt ?
492 MBEDTLS_CHACHAPOLY_ENCRYPT :
493 MBEDTLS_CHACHAPOLY_DECRYPT ) );
494 }
495 else
496#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
497 {
498 ( void ) nonce;
499 ( void ) nonce_length;
500
501 return ( PSA_ERROR_NOT_SUPPORTED );
502 }
503
504 if( status == PSA_SUCCESS )
505 {
506 operation->nonce_set = 1;
507 }
508
509 return( status );
510}
511 /* Declare the lengths of the message and additional data for AEAD. */
512psa_status_t mbedtls_psa_aead_set_lengths( psa_aead_operation_t *operation,
513 size_t ad_length,
514 size_t plaintext_length )
515{
516
517 if( !operation->key_set || operation->lengths_set )
518 {
519 return( PSA_ERROR_BAD_STATE );
520 }
521
522#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
523 if( operation->alg == PSA_ALG_GCM )
524 {
525#if SIZE_MAX > UINT32_MAX
526 if( ( (uint64_t) ad_length ) >> 61 != 0 ||
527 ( (uint64_t) plaintext_length ) > 0xFFFFFFFE0ull )
528 {
529 return ( PSA_ERROR_INVALID_ARGUMENT );
530 }
531#endif
532 }
533 else
534#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
535#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
536 if( operation->alg == PSA_ALG_CCM )
537 {
538 if( ad_length > 0xFF00 )
539 {
540 return ( PSA_ERROR_INVALID_ARGUMENT );
541 }
542 }
543 else
544#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
545#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
546 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
547 {
548 /* No length restrictions for ChaChaPoly. */
549 }
550 else
551#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
552 {
553 ( void ) ad_length;
554 ( void ) plaintext_length;
555
556 return ( PSA_ERROR_NOT_SUPPORTED );
557 }
558
559 operation->ad_remaining = ad_length;
560 operation->body_remaining = plaintext_length;
561 operation->lengths_set = 1;
562
563 return ( PSA_SUCCESS );
564}
565
566/* Pass additional data to an active multipart AEAD operation. */
567psa_status_t mbedtls_psa_aead_update_ad( psa_aead_operation_t *operation,
568 const uint8_t *input,
569 size_t input_length )
570{
571 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
572
573 if( !operation->nonce_set || !operation->key_set )
574 {
575 return( PSA_ERROR_BAD_STATE );
576 }
577
578 if( operation->lengths_set )
579 {
580 if ( operation->ad_remaining < input_length )
581 {
582 return( PSA_ERROR_INVALID_ARGUMENT );
583 }
584
585 operation->ad_remaining -= input_length;
586 }
587
588#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
589 if( operation->alg == PSA_ALG_GCM )
590 {
591 if( !operation->lengths_set || operation->ad_started )
592 {
593 return( PSA_ERROR_BAD_STATE );
594 }
595
596 /* GCM currently requires all the additional data to be passed in in
597 * one contigious buffer, so until that is re-done, we have to enforce
598 * this, as we cannot allocate a buffer to collate multiple calls into.
599 */
600 if( input_length != operation->ad_remaining )
601 {
602 return ( PSA_ERROR_INVALID_ARGUMENT );
603 }
604
605 status = mbedtls_to_psa_error( mbedtls_gcm_starts( &operation->ctx.gcm,
606 operation->is_encrypt ?
607 MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
608 operation->nonce,
609 operation->nonce_length,
610 input,
611 input_length ) );
612
613 }
614 else
615#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
616#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
617 if( operation->alg == PSA_ALG_CCM )
618 {
619 /* CCM requires all additional data to be passed in in one go at the
620 minute, as we are basically operating in oneshot mode. */
621 if( !operation->lengths_set || operation->ad_started )
622 {
623 return( PSA_ERROR_BAD_STATE );
624 }
625
626 /* Save the additional data for later, this will be passed in
627 when we have the body. */
628 operation->ad_buffer = ( uint8_t * ) mbedtls_calloc(1, input_length );
629
630 if( operation->ad_buffer )
631 {
632 memcpy( operation->ad_buffer, input, input_length );
633 operation->ad_length = input_length;
634 }
635 else
636 {
637 return ( PSA_ERROR_INSUFFICIENT_MEMORY );
638 }
639 }
640 else
641#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
642#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
643 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
644 {
645 status = mbedtls_to_psa_error( mbedtls_chachapoly_update_aad( &operation->ctx.chachapoly,
646 input,
647 input_length ) );
648 }
649 else
650#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
651 {
652 (void) input;
653 (void) input_length;
654
655 return ( PSA_ERROR_NOT_SUPPORTED );
656 }
657
658 if( status == PSA_SUCCESS )
659 {
660 operation->ad_started = 1;
661 }
662
663 return ( status );
664}
665
666/* Encrypt or decrypt a message fragment in an active multipart AEAD
667 * operation.*/
668psa_status_t mbedtls_psa_aead_update( psa_aead_operation_t *operation,
669 const uint8_t *input,
670 size_t input_length,
671 uint8_t *output,
672 size_t output_size,
673 size_t *output_length )
674{
675 size_t update_output_size;
676 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
677
678 if( !operation->nonce_set || !operation->key_set || !operation->ad_started )
679 {
680 return( PSA_ERROR_BAD_STATE );
681 }
682
683 update_output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(operation->key_type,
684 operation->alg, input_length);
685
686 if(update_output_size > output_size )
687 {
688 return ( PSA_ERROR_BUFFER_TOO_SMALL );
689 }
690
691 if( operation->lengths_set)
692 {
693 /* Additional data length was supplied, but not all the additional
694 data was supplied.*/
695 if( operation->ad_remaining != 0 )
696 {
697 return ( PSA_ERROR_INVALID_ARGUMENT );
698 }
699
700 /* Too much data provided. */
701 if( operation->body_remaining < input_length )
702 {
703 return ( PSA_ERROR_INVALID_ARGUMENT );
704 }
705
706 operation->body_remaining -= input_length;
707 }
708
709#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
710 if( operation->alg == PSA_ALG_GCM )
711 {
712 /* For the time being set the requirement that all of the body data
713 * must be passed in in one update, rather than deal with the complexity
714 * of non block size aligned updates. This will be fixed in 3.0 when
715 we can change the signature of the GCM multipart functions */
716 if( !operation->lengths_set || operation->body_remaining != 0 )
717 {
718 return( PSA_ERROR_BAD_STATE );
719 }
720
721 if( operation->ad_started )
722 {
723 return( PSA_ERROR_BAD_STATE );
724 }
725
726 status = mbedtls_to_psa_error( mbedtls_gcm_update( &operation->ctx.gcm,
727 input_length,
728 input,
729 output ) );
730 }
731 else
732#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
733#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
734 if( operation->alg == PSA_ALG_CCM )
735 {
736 /* CCM dooes not support multipart yet, so all the input has to be
737 passed in in one go. Store the data for the final step.*/
738 if( operation->ad_started )
739 {
740 return( PSA_ERROR_BAD_STATE );
741 }
742
743 /* Save the additional data for later, this will be passed in
744 when we have the body. */
745 operation->data_buffer = ( uint8_t * ) mbedtls_calloc(1, input_length );
746
747 if( operation->data_buffer )
748 {
749 memcpy( operation->data_buffer, input, input_length );
750 operation->data_length = input_length;
751 }
752 else
753 {
754 return ( PSA_ERROR_INSUFFICIENT_MEMORY );
755 }
756
757 }
758 else
759#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
760#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
761 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
762 {
763 status = mbedtls_to_psa_error( mbedtls_chachapoly_update( &operation->ctx.chachapoly,
764 input_length,
765 input,
766 output ) );
767 }
768 else
769#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
770 {
771 (void) input;
772 (void) input_length;
773
774 return ( PSA_ERROR_NOT_SUPPORTED );
775 }
776
777 if( status == PSA_SUCCESS )
778 {
779 *output_length = update_output_size;
780 operation->body_started = 1;
781 }
782
783 return( status );
784}
785
786/* Common checks for both mbedtls_psa_aead_finish() and
787 mbedtls_psa_aead_verify() */
788static psa_status_t mbedtls_psa_aead_finish_checks( psa_aead_operation_t *operation,
789 size_t output_size,
790 size_t tag_size,
791 size_t *finish_output_size,
792 size_t *output_tag_length )
793{
794 if( !operation->key_set || !operation->nonce_set
795 || !operation->ad_started || !operation->body_started)
796 {
797 return( PSA_ERROR_BAD_STATE );
798 }
799
800 if( operation->lengths_set )
801 {
802 if( operation->ad_remaining != 0 || operation->body_remaining != 0 )
803 {
804 return( PSA_ERROR_BAD_STATE );
805 }
806 }
807
808 *output_tag_length = operation->tag_length;
809
810 if( tag_size < *output_tag_length)
811 {
812 return ( PSA_ERROR_BUFFER_TOO_SMALL );
813 }
814
815 if( operation->is_encrypt )
816 {
817 *finish_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE(operation->key_type,
818 operation->alg);
819 }
820 else
821 {
822 *finish_output_size = PSA_AEAD_VERIFY_OUTPUT_SIZE(operation->key_type,
823 operation->alg);
824 }
825
826 if( output_size < *finish_output_size )
827 {
828 return ( PSA_ERROR_BUFFER_TOO_SMALL );
829 }
830
831 return ( PSA_SUCCESS );
832
833}
834
835/* Finish encrypting a message in a multipart AEAD operation. */
836psa_status_t mbedtls_psa_aead_finish( psa_aead_operation_t *operation,
837 uint8_t *ciphertext,
838 size_t ciphertext_size,
839 size_t *ciphertext_length,
840 uint8_t *tag,
841 size_t tag_size,
842 size_t *tag_length )
843{
844 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
845 size_t output_tag_length;
846 size_t finish_output_size;
847
848 status = mbedtls_psa_aead_finish_checks( operation, ciphertext_size, tag_size, &finish_output_size,
849 &output_tag_length);
850
851 if( status != PSA_SUCCESS )
852 {
853 return status;
854 }
855
856#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
857 if( operation->alg == PSA_ALG_GCM )
858 {
859 /* We will need to do final GCM pass in here when multipart is done. */
860 status = mbedtls_to_psa_error( mbedtls_gcm_finish( &operation->ctx.gcm,
861 tag,
862 tag_size ) );
863 }
864 else
865#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
866#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
867 if( operation->alg == PSA_ALG_CCM )
868 {
869 if( !operation->ad_buffer || !operation->data_buffer )
870 {
871 return( PSA_ERROR_BAD_STATE );
872 }
873
874 /* Perform oneshot CCM encryption with data already stored, as
875 CCM does not support multipart yet.*/
876 status = mbedtls_to_psa_error( mbedtls_ccm_encrypt_and_tag( &operation->ctx.ccm,
877 operation->data_length,
878 operation->nonce,
879 operation->nonce_length,
880 operation->ad_buffer,
881 operation->ad_length,
882 operation->data_buffer,
883 ciphertext,
884 tag, tag_size ) );
885
886 /* Even if the above operation fails, we no longer need the data */
887 mbedtls_free(operation->ad_buffer);
888 operation->ad_buffer = NULL;
889 operation->ad_length = 0;
890
891 mbedtls_free(operation->data_buffer);
892 operation->data_buffer = NULL;
893 operation->data_length = 0;
894 }
895 else
896#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
897#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
898 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
899 {
900 status = mbedtls_to_psa_error( mbedtls_chachapoly_finish( &operation->ctx.chachapoly,
901 tag ) );
902 }
903 else
904#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
905 {
906 ( void ) ciphertext;
907 ( void ) ciphertext_size;
908 ( void ) ciphertext_length;
909 ( void ) tag;
910 ( void ) tag_size;
911 ( void ) tag_length;
912
913 return ( PSA_ERROR_NOT_SUPPORTED );
914 }
915
916 if( status == PSA_SUCCESS )
917 {
918 *ciphertext_length = finish_output_size;
919 *tag_length = output_tag_length;
920 }
921
922 mbedtls_psa_aead_abort(operation);
923
924 return ( status );
925}
926
927/* Finish authenticating and decrypting a message in a multipart AEAD
928 * operation.*/
929psa_status_t mbedtls_psa_aead_verify( psa_aead_operation_t *operation,
930 uint8_t *plaintext,
931 size_t plaintext_size,
932 size_t *plaintext_length,
933 const uint8_t *tag,
934 size_t tag_length )
935{
936 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
937 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
938
939 size_t finish_output_size;
940 size_t output_tag_length;
941
942 int do_tag_check = 1;
943 uint8_t check_tag[16];
944
945 status = mbedtls_psa_aead_finish_checks( operation, plaintext_size, tag_length, &finish_output_size,
946 &output_tag_length);
947
948 if( status != PSA_SUCCESS )
949 {
950 return status;
951 }
952
953#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
954 if( operation->alg == PSA_ALG_GCM )
955 {
956 /* Call finish to get the tag for comparison */
957 status = mbedtls_to_psa_error( mbedtls_gcm_finish( &operation->ctx.gcm,
958 check_tag,
959 16 ) );
960 }
961 else
962#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
963#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
964 if( operation->alg == PSA_ALG_CCM )
965 {
966 if( !operation->ad_buffer || !operation->data_buffer )
967 {
968 return( PSA_ERROR_BAD_STATE );
969 }
970
971 /* Perform oneshot CCM decryption with data already stored, as
972 CCM does not support multipart yet.*/
973
974 ret = mbedtls_ccm_auth_decrypt( &operation->ctx.ccm, operation->data_length,
975 operation->nonce, operation->nonce_length,
976 operation->ad_buffer, operation->ad_length,
977 operation->data_buffer, plaintext,
978 tag, tag_length );
979
980 if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
981 {
982 status = PSA_ERROR_INVALID_SIGNATURE;
983 }
984 else
985 {
986 status = mbedtls_to_psa_error( ret );
987 do_tag_check = 0;
988 }
989
990 /* Even if the above operation fails, we no longer need the data */
991 mbedtls_free(operation->ad_buffer);
992 operation->ad_buffer = NULL;
993 operation->ad_length = 0;
994
995 mbedtls_free(operation->data_buffer);
996 operation->data_buffer = NULL;
997 operation->data_length = 0;
998 }
999 else
1000#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
1001#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
1002 if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
1003 {
1004 // call finish to get the tag for comparison.
1005 status = mbedtls_to_psa_error( mbedtls_chachapoly_finish( &operation->ctx.chachapoly,
1006 check_tag ) );
1007 }
1008 else
1009#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
1010 {
1011 ( void ) plaintext;
1012 ( void ) plaintext_size;
1013 ( void ) plaintext_length;
1014 ( void ) tag;
1015 ( void ) tag_length;
1016
1017 return ( PSA_ERROR_NOT_SUPPORTED );
1018 }
1019
1020 if( status == PSA_SUCCESS )
1021 {
1022 if( do_tag_check && safer_memcmp(tag, check_tag, tag_length) != 0 )
1023 {
1024 status = MBEDTLS_ERR_GCM_AUTH_FAILED;
1025 }
1026 }
1027
1028 mbedtls_psa_aead_abort(operation);
1029
1030 return ( status );
1031}
1032
1033/* Abort an AEAD operation */
1034psa_status_t mbedtls_psa_aead_abort( psa_aead_operation_t *operation )
1035{
1036 switch( operation->alg )
1037 {
1038#if defined(MBEDTLS_CCM_C)
1039 case MBEDTLS_PSA_BUILTIN_ALG_CCM:
1040 mbedtls_ccm_free( &operation->ctx.ccm );
1041 break;
1042#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
1043#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
1044 case PSA_ALG_GCM:
1045 mbedtls_gcm_free( &operation->ctx.gcm );
1046 break;
1047#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
1048#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
1049 case PSA_ALG_CHACHA20_POLY1305:
1050 mbedtls_chachapoly_free( &operation->ctx.chachapoly );
1051 break;
1052#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
1053 }
1054
1055 return( PSA_SUCCESS );
1056}
1057
Ronald Cron7ceee8d2021-03-17 16:55:43 +01001058#endif /* MBEDTLS_PSA_CRYPTO_C */
1059