666 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			666 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | /*
 | ||
|  |  *  PSA AEAD entry points | ||
|  |  */ | ||
|  | /*
 | ||
|  |  *  Copyright The Mbed TLS Contributors | ||
|  |  *  SPDX-License-Identifier: Apache-2.0 | ||
|  |  * | ||
|  |  *  Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
|  |  *  not use this file except in compliance with the License. | ||
|  |  *  You may obtain a copy of the License at | ||
|  |  * | ||
|  |  *  http://www.apache.org/licenses/LICENSE-2.0
 | ||
|  |  * | ||
|  |  *  Unless required by applicable law or agreed to in writing, software | ||
|  |  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
|  |  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  |  *  See the License for the specific language governing permissions and | ||
|  |  *  limitations under the License. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include "common.h"
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_CRYPTO_C)
 | ||
|  | 
 | ||
|  | #include "psa_crypto_aead.h"
 | ||
|  | #include "psa_crypto_core.h"
 | ||
|  | #include "psa_crypto_cipher.h"
 | ||
|  | 
 | ||
|  | #include <string.h>
 | ||
|  | #include "mbedtls/platform.h"
 | ||
|  | 
 | ||
|  | #include "mbedtls/ccm.h"
 | ||
|  | #include "mbedtls/chachapoly.h"
 | ||
|  | #include "mbedtls/cipher.h"
 | ||
|  | #include "mbedtls/gcm.h"
 | ||
|  | #include "mbedtls/error.h"
 | ||
|  | 
 | ||
|  | static psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     size_t key_bits; | ||
|  |     const mbedtls_cipher_info_t *cipher_info; | ||
|  |     mbedtls_cipher_id_t cipher_id; | ||
|  | 
 | ||
|  |     (void) key_buffer_size; | ||
|  | 
 | ||
|  |     key_bits = attributes->core.bits; | ||
|  | 
 | ||
|  |     cipher_info = mbedtls_cipher_info_from_psa(alg, | ||
|  |                                                attributes->core.type, key_bits, | ||
|  |                                                &cipher_id); | ||
|  |     if (cipher_info == NULL) { | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): | ||
|  |             operation->alg = PSA_ALG_CCM; | ||
|  |             /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
 | ||
|  |              * The call to mbedtls_ccm_encrypt_and_tag or | ||
|  |              * mbedtls_ccm_auth_decrypt will validate the tag length. */ | ||
|  |             if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) { | ||
|  |                 return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |             } | ||
|  | 
 | ||
|  |             mbedtls_ccm_init(&operation->ctx.ccm); | ||
|  |             status = mbedtls_to_psa_error( | ||
|  |                 mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id, | ||
|  |                                    key_buffer, (unsigned int) key_bits)); | ||
|  |             if (status != PSA_SUCCESS) { | ||
|  |                 return status; | ||
|  |             } | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): | ||
|  |             operation->alg = PSA_ALG_GCM; | ||
|  |             /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
 | ||
|  |              * The call to mbedtls_gcm_crypt_and_tag or | ||
|  |              * mbedtls_gcm_auth_decrypt will validate the tag length. */ | ||
|  |             if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) { | ||
|  |                 return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |             } | ||
|  | 
 | ||
|  |             mbedtls_gcm_init(&operation->ctx.gcm); | ||
|  |             status = mbedtls_to_psa_error( | ||
|  |                 mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id, | ||
|  |                                    key_buffer, (unsigned int) key_bits)); | ||
|  |             if (status != PSA_SUCCESS) { | ||
|  |                 return status; | ||
|  |             } | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |         case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): | ||
|  |             operation->alg = PSA_ALG_CHACHA20_POLY1305; | ||
|  |             /* We only support the default tag length. */ | ||
|  |             if (alg != PSA_ALG_CHACHA20_POLY1305) { | ||
|  |                 return PSA_ERROR_NOT_SUPPORTED; | ||
|  |             } | ||
|  | 
 | ||
|  |             mbedtls_chachapoly_init(&operation->ctx.chachapoly); | ||
|  |             status = mbedtls_to_psa_error( | ||
|  |                 mbedtls_chachapoly_setkey(&operation->ctx.chachapoly, | ||
|  |                                           key_buffer)); | ||
|  |             if (status != PSA_SUCCESS) { | ||
|  |                 return status; | ||
|  |             } | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  | 
 | ||
|  |         default: | ||
|  |             (void) status; | ||
|  |             (void) key_buffer; | ||
|  |             return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     operation->key_type = psa_get_key_type(attributes); | ||
|  | 
 | ||
|  |     operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); | ||
|  | 
 | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; | ||
|  |     uint8_t *tag; | ||
|  | 
 | ||
|  |     status = psa_aead_setup(&operation, attributes, key_buffer, | ||
|  |                             key_buffer_size, alg); | ||
|  | 
 | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto exit; | ||
|  |     } | ||
|  | 
 | ||
|  |     /* For all currently supported modes, the tag is at the end of the
 | ||
|  |      * ciphertext. */ | ||
|  |     if (ciphertext_size < (plaintext_length + operation.tag_length)) { | ||
|  |         status = PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         goto exit; | ||
|  |     } | ||
|  |     tag = ciphertext + plaintext_length; | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation.alg == PSA_ALG_CCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, | ||
|  |                                         plaintext_length, | ||
|  |                                         nonce, nonce_length, | ||
|  |                                         additional_data, | ||
|  |                                         additional_data_length, | ||
|  |                                         plaintext, ciphertext, | ||
|  |                                         tag, operation.tag_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation.alg == PSA_ALG_GCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, | ||
|  |                                       MBEDTLS_GCM_ENCRYPT, | ||
|  |                                       plaintext_length, | ||
|  |                                       nonce, nonce_length, | ||
|  |                                       additional_data, additional_data_length, | ||
|  |                                       plaintext, ciphertext, | ||
|  |                                       operation.tag_length, tag)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         if (operation.tag_length != 16) { | ||
|  |             status = PSA_ERROR_NOT_SUPPORTED; | ||
|  |             goto exit; | ||
|  |         } | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly, | ||
|  |                                                plaintext_length, | ||
|  |                                                nonce, | ||
|  |                                                additional_data, | ||
|  |                                                additional_data_length, | ||
|  |                                                plaintext, | ||
|  |                                                ciphertext, | ||
|  |                                                tag)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) tag; | ||
|  |         (void) nonce; | ||
|  |         (void) nonce_length; | ||
|  |         (void) additional_data; | ||
|  |         (void) additional_data_length; | ||
|  |         (void) plaintext; | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         *ciphertext_length = plaintext_length + operation.tag_length; | ||
|  |     } | ||
|  | 
 | ||
|  | exit: | ||
|  |     mbedtls_psa_aead_abort(&operation); | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Locate the tag in a ciphertext buffer containing the encrypted data
 | ||
|  |  * followed by the tag. Return the length of the part preceding the tag in | ||
|  |  * *plaintext_length. This is the size of the plaintext in modes where | ||
|  |  * the encrypted data has the same size as the plaintext, such as | ||
|  |  * CCM and GCM. */ | ||
|  | static psa_status_t 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) | ||
|  | { | ||
|  |     size_t payload_length; | ||
|  |     if (tag_length > ciphertext_length) { | ||
|  |         return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |     } | ||
|  |     payload_length = ciphertext_length - tag_length; | ||
|  |     if (payload_length > plaintext_size) { | ||
|  |         return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |     } | ||
|  |     *p_tag = ciphertext + payload_length; | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; | ||
|  |     const uint8_t *tag = NULL; | ||
|  | 
 | ||
|  |     status = psa_aead_setup(&operation, attributes, key_buffer, | ||
|  |                             key_buffer_size, alg); | ||
|  | 
 | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto exit; | ||
|  |     } | ||
|  | 
 | ||
|  |     status = psa_aead_unpadded_locate_tag(operation.tag_length, | ||
|  |                                           ciphertext, ciphertext_length, | ||
|  |                                           plaintext_size, &tag); | ||
|  |     if (status != PSA_SUCCESS) { | ||
|  |         goto exit; | ||
|  |     } | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation.alg == PSA_ALG_CCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, | ||
|  |                                      ciphertext_length - operation.tag_length, | ||
|  |                                      nonce, nonce_length, | ||
|  |                                      additional_data, | ||
|  |                                      additional_data_length, | ||
|  |                                      ciphertext, plaintext, | ||
|  |                                      tag, operation.tag_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation.alg == PSA_ALG_GCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, | ||
|  |                                      ciphertext_length - operation.tag_length, | ||
|  |                                      nonce, nonce_length, | ||
|  |                                      additional_data, | ||
|  |                                      additional_data_length, | ||
|  |                                      tag, operation.tag_length, | ||
|  |                                      ciphertext, plaintext)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         if (operation.tag_length != 16) { | ||
|  |             status = PSA_ERROR_NOT_SUPPORTED; | ||
|  |             goto exit; | ||
|  |         } | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly, | ||
|  |                                             ciphertext_length - operation.tag_length, | ||
|  |                                             nonce, | ||
|  |                                             additional_data, | ||
|  |                                             additional_data_length, | ||
|  |                                             tag, | ||
|  |                                             ciphertext, | ||
|  |                                             plaintext)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) nonce; | ||
|  |         (void) nonce_length; | ||
|  |         (void) additional_data; | ||
|  |         (void) additional_data_length; | ||
|  |         (void) plaintext; | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         *plaintext_length = ciphertext_length - operation.tag_length; | ||
|  |     } | ||
|  | 
 | ||
|  | exit: | ||
|  |     mbedtls_psa_aead_abort(&operation); | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         *plaintext_length = ciphertext_length - operation.tag_length; | ||
|  |     } | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Set the key and algorithm for a multipart authenticated encryption
 | ||
|  |  * operation. */ | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  |     status = psa_aead_setup(operation, attributes, key_buffer, | ||
|  |                             key_buffer_size, alg); | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         operation->is_encrypt = 1; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Set the key and algorithm for a multipart authenticated decryption
 | ||
|  |  * operation. */ | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  |     status = psa_aead_setup(operation, attributes, key_buffer, | ||
|  |                             key_buffer_size, alg); | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         operation->is_encrypt = 0; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Set a nonce for the multipart AEAD operation*/ | ||
|  | psa_status_t mbedtls_psa_aead_set_nonce( | ||
|  |     mbedtls_psa_aead_operation_t *operation, | ||
|  |     const uint8_t *nonce, | ||
|  |     size_t nonce_length) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation->alg == PSA_ALG_GCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_starts(&operation->ctx.gcm, | ||
|  |                                operation->is_encrypt ? | ||
|  |                                MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, | ||
|  |                                nonce, | ||
|  |                                nonce_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation->alg == PSA_ALG_CCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_starts(&operation->ctx.ccm, | ||
|  |                                operation->is_encrypt ? | ||
|  |                                MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, | ||
|  |                                nonce, | ||
|  |                                nonce_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
 | ||
|  |          * allocate a buffer in the operation, copy the nonce to it and pad | ||
|  |          * it, so for now check the nonce is 12 bytes, as | ||
|  |          * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the | ||
|  |          * passed in buffer. */ | ||
|  |         if (nonce_length != 12) { | ||
|  |             return PSA_ERROR_INVALID_ARGUMENT; | ||
|  |         } | ||
|  | 
 | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_starts(&operation->ctx.chachapoly, | ||
|  |                                       nonce, | ||
|  |                                       operation->is_encrypt ? | ||
|  |                                       MBEDTLS_CHACHAPOLY_ENCRYPT : | ||
|  |                                       MBEDTLS_CHACHAPOLY_DECRYPT)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) operation; | ||
|  |         (void) nonce; | ||
|  |         (void) nonce_length; | ||
|  | 
 | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Declare the lengths of the message and additional data for AEAD. */ | ||
|  | psa_status_t mbedtls_psa_aead_set_lengths( | ||
|  |     mbedtls_psa_aead_operation_t *operation, | ||
|  |     size_t ad_length, | ||
|  |     size_t plaintext_length) | ||
|  | { | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation->alg == PSA_ALG_CCM) { | ||
|  |         return mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_set_lengths(&operation->ctx.ccm, | ||
|  |                                     ad_length, | ||
|  |                                     plaintext_length, | ||
|  |                                     operation->tag_length)); | ||
|  | 
 | ||
|  |     } | ||
|  | #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  |     (void) operation; | ||
|  |     (void) ad_length; | ||
|  |     (void) plaintext_length; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | 
 | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | /* Pass additional data to an active multipart AEAD operation. */ | ||
|  | psa_status_t mbedtls_psa_aead_update_ad( | ||
|  |     mbedtls_psa_aead_operation_t *operation, | ||
|  |     const uint8_t *input, | ||
|  |     size_t input_length) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation->alg == PSA_ALG_GCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation->alg == PSA_ALG_CCM) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, | ||
|  |                                           input, | ||
|  |                                           input_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) operation; | ||
|  |         (void) input; | ||
|  |         (void) input_length; | ||
|  | 
 | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Encrypt or decrypt a message fragment in an active multipart AEAD
 | ||
|  |  * operation.*/ | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     size_t update_output_length; | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  | 
 | ||
|  |     update_output_length = input_length; | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation->alg == PSA_ALG_GCM) { | ||
|  |         status =  mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_update(&operation->ctx.gcm, | ||
|  |                                input, input_length, | ||
|  |                                output, output_size, | ||
|  |                                &update_output_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation->alg == PSA_ALG_CCM) { | ||
|  |         if (output_size < input_length) { | ||
|  |             return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         } | ||
|  | 
 | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_update(&operation->ctx.ccm, | ||
|  |                                input, input_length, | ||
|  |                                output, output_size, | ||
|  |                                &update_output_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         if (output_size < input_length) { | ||
|  |             return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         } | ||
|  | 
 | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_update(&operation->ctx.chachapoly, | ||
|  |                                       input_length, | ||
|  |                                       input, | ||
|  |                                       output)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) operation; | ||
|  |         (void) input; | ||
|  |         (void) output; | ||
|  |         (void) output_size; | ||
|  | 
 | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         *output_length = update_output_length; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Finish encrypting a message in a multipart AEAD operation. */ | ||
|  | psa_status_t 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) | ||
|  | { | ||
|  |     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; | ||
|  |     size_t finish_output_size = 0; | ||
|  | 
 | ||
|  |     if (tag_size < operation->tag_length) { | ||
|  |         return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |     } | ||
|  | 
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |     if (operation->alg == PSA_ALG_GCM) { | ||
|  |         status =  mbedtls_to_psa_error( | ||
|  |             mbedtls_gcm_finish(&operation->ctx.gcm, | ||
|  |                                ciphertext, ciphertext_size, ciphertext_length, | ||
|  |                                tag, operation->tag_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |     if (operation->alg == PSA_ALG_CCM) { | ||
|  |         /* tag must be big enough to store a tag of size passed into set
 | ||
|  |          * lengths. */ | ||
|  |         if (tag_size < operation->tag_length) { | ||
|  |             return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         } | ||
|  | 
 | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_ccm_finish(&operation->ctx.ccm, | ||
|  |                                tag, operation->tag_length)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |     if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { | ||
|  |         /* Belt and braces. Although the above tag_size check should have
 | ||
|  |          * already done this, if we later start supporting smaller tag sizes | ||
|  |          * for chachapoly, then passing a tag buffer smaller than 16 into here | ||
|  |          * could cause a buffer overflow, so better safe than sorry. */ | ||
|  |         if (tag_size < 16) { | ||
|  |             return PSA_ERROR_BUFFER_TOO_SMALL; | ||
|  |         } | ||
|  | 
 | ||
|  |         status = mbedtls_to_psa_error( | ||
|  |             mbedtls_chachapoly_finish(&operation->ctx.chachapoly, | ||
|  |                                       tag)); | ||
|  |     } else | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     { | ||
|  |         (void) ciphertext; | ||
|  |         (void) ciphertext_size; | ||
|  |         (void) ciphertext_length; | ||
|  |         (void) tag; | ||
|  |         (void) tag_size; | ||
|  |         (void) tag_length; | ||
|  | 
 | ||
|  |         return PSA_ERROR_NOT_SUPPORTED; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (status == PSA_SUCCESS) { | ||
|  |         /* This will be zero for all supported algorithms currently, but left
 | ||
|  |          * here for future support. */ | ||
|  |         *ciphertext_length = finish_output_size; | ||
|  |         *tag_length = operation->tag_length; | ||
|  |     } | ||
|  | 
 | ||
|  |     return status; | ||
|  | } | ||
|  | 
 | ||
|  | /* Abort an AEAD operation */ | ||
|  | psa_status_t mbedtls_psa_aead_abort( | ||
|  |     mbedtls_psa_aead_operation_t *operation) | ||
|  | { | ||
|  |     switch (operation->alg) { | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
 | ||
|  |         case PSA_ALG_CCM: | ||
|  |             mbedtls_ccm_free(&operation->ctx.ccm); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
 | ||
|  |         case PSA_ALG_GCM: | ||
|  |             mbedtls_gcm_free(&operation->ctx.gcm); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 | ||
|  | #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
 | ||
|  |         case PSA_ALG_CHACHA20_POLY1305: | ||
|  |             mbedtls_chachapoly_free(&operation->ctx.chachapoly); | ||
|  |             break; | ||
|  | #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
 | ||
|  |     } | ||
|  | 
 | ||
|  |     operation->is_encrypt = 0; | ||
|  | 
 | ||
|  |     return PSA_SUCCESS; | ||
|  | } | ||
|  | 
 | ||
|  | #endif /* MBEDTLS_PSA_CRYPTO_C */
 |