1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-10-24 13:32:59 +03:00

Merge pull request #4338 from paul-elliott-arm/psa-m-aead

Implement multipart PSA AEAD
This commit is contained in:
Ronald Cron
2021-09-29 22:48:33 +02:00
committed by GitHub
14 changed files with 4179 additions and 80 deletions

View File

@@ -3609,6 +3609,50 @@ exit:
/* AEAD */
/****************************************************************/
/* Helper function to get the base algorithm from its variants. */
static psa_algorithm_t psa_aead_get_base_algorithm( psa_algorithm_t alg )
{
return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( alg );
}
/* Helper function to perform common nonce length checks. */
static psa_status_t psa_aead_check_nonce_length( psa_algorithm_t alg,
size_t nonce_length )
{
psa_algorithm_t base_alg = psa_aead_get_base_algorithm( alg );
#if defined(PSA_WANT_ALG_GCM)
if( base_alg == PSA_ALG_GCM )
{
/* Not checking max nonce size here as GCM spec allows almost
* arbitrarily large nonces. Please note that we do not generally
* recommend the usage of nonces of greater length than
* PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
* size, which can then lead to collisions if you encrypt a very
* large number of messages.*/
if( nonce_length != 0 )
return( PSA_SUCCESS );
}
#endif /* PSA_WANT_ALG_GCM */
#if defined(PSA_WANT_ALG_CCM)
if( base_alg == PSA_ALG_CCM )
{
if( nonce_length >= 7 && nonce_length <= 13 )
return( PSA_SUCCESS );
}
else
#endif /* PSA_WANT_ALG_CCM */
#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
if( base_alg == PSA_ALG_CHACHA20_POLY1305 )
{
if( nonce_length == 12 )
return( PSA_SUCCESS );
}
#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
return( PSA_ERROR_NOT_SUPPORTED );
}
psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
psa_algorithm_t alg,
const uint8_t *nonce,
@@ -3638,6 +3682,10 @@ psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
.core = slot->attr
};
status = psa_aead_check_nonce_length( alg, nonce_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_driver_wrapper_aead_encrypt(
&attributes, slot->key.data, slot->key.bytes,
alg,
@@ -3649,6 +3697,7 @@ psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
if( status != PSA_SUCCESS && ciphertext_size != 0 )
memset( ciphertext, 0, ciphertext_size );
exit:
psa_unlock_key_slot( slot );
return( status );
@@ -3683,6 +3732,10 @@ psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
.core = slot->attr
};
status = psa_aead_check_nonce_length( alg, nonce_length );
if( status != PSA_SUCCESS )
goto exit;
status = psa_driver_wrapper_aead_decrypt(
&attributes, slot->key.data, slot->key.bytes,
alg,
@@ -3694,11 +3747,474 @@ psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
if( status != PSA_SUCCESS && plaintext_size != 0 )
memset( plaintext, 0, plaintext_size );
exit:
psa_unlock_key_slot( slot );
return( status );
}
/* Set the key for a multipart authenticated operation. */
static psa_status_t psa_aead_setup( psa_aead_operation_t *operation,
int is_encrypt,
mbedtls_svc_key_id_t key,
psa_algorithm_t alg )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL;
psa_key_usage_t key_usage = 0;
if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if( operation->id != 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->nonce_set || operation->lengths_set ||
operation->ad_started || operation->body_started )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( is_encrypt )
key_usage = PSA_KEY_USAGE_ENCRYPT;
else
key_usage = PSA_KEY_USAGE_DECRYPT;
status = psa_get_and_lock_key_slot_with_policy( key, &slot, key_usage,
alg );
if( status != PSA_SUCCESS )
goto exit;
psa_key_attributes_t attributes = {
.core = slot->attr
};
if( is_encrypt )
status = psa_driver_wrapper_aead_encrypt_setup( operation,
&attributes,
slot->key.data,
slot->key.bytes,
alg );
else
status = psa_driver_wrapper_aead_decrypt_setup( operation,
&attributes,
slot->key.data,
slot->key.bytes,
alg );
if( status != PSA_SUCCESS )
goto exit;
operation->key_type = psa_get_key_type( &attributes );
exit:
unlock_status = psa_unlock_key_slot( slot );
if( status == PSA_SUCCESS )
{
status = unlock_status;
operation->alg = psa_aead_get_base_algorithm( alg );
operation->is_encrypt = is_encrypt;
}
else
psa_aead_abort( operation );
return( status );
}
/* Set the key for a multipart authenticated encryption operation. */
psa_status_t psa_aead_encrypt_setup( psa_aead_operation_t *operation,
mbedtls_svc_key_id_t key,
psa_algorithm_t alg )
{
return( psa_aead_setup( operation, 1, key, alg ) );
}
/* Set the key for a multipart authenticated decryption operation. */
psa_status_t psa_aead_decrypt_setup( psa_aead_operation_t *operation,
mbedtls_svc_key_id_t key,
psa_algorithm_t alg )
{
return( psa_aead_setup( operation, 0, key, alg ) );
}
/* Generate a random nonce / IV for multipart AEAD operation */
psa_status_t psa_aead_generate_nonce( psa_aead_operation_t *operation,
uint8_t *nonce,
size_t nonce_size,
size_t *nonce_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t required_nonce_size;
*nonce_length = 0;
if( operation->id == 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->nonce_set || !operation->is_encrypt )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
required_nonce_size = PSA_AEAD_NONCE_LENGTH( operation->key_type,
operation->alg );
if( nonce_size < required_nonce_size )
{
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
status = psa_generate_random( nonce, required_nonce_size );
if( status != PSA_SUCCESS )
goto exit;
status = psa_aead_set_nonce( operation, nonce, required_nonce_size );
exit:
if( status == PSA_SUCCESS )
*nonce_length = required_nonce_size;
else
psa_aead_abort( operation );
return( status );
}
/* Set the nonce for a multipart authenticated encryption or decryption
operation.*/
psa_status_t psa_aead_set_nonce( psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if( operation->id == 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->nonce_set )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
status = psa_aead_check_nonce_length( operation->alg, nonce_length );
if( status != PSA_SUCCESS )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
status = psa_driver_wrapper_aead_set_nonce( operation, nonce,
nonce_length );
exit:
if( status == PSA_SUCCESS )
operation->nonce_set = 1;
else
psa_aead_abort( operation );
return( status );
}
/* Declare the lengths of the message and additional data for multipart AEAD. */
psa_status_t psa_aead_set_lengths( psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if( operation->id == 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->lengths_set || operation->ad_started ||
operation->body_started )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
#if defined(PSA_WANT_ALG_GCM)
if( operation->alg == PSA_ALG_GCM )
{
/* Lengths can only be too large for GCM if size_t is bigger than 32
* bits. Without the guard this code will generate warnings on 32bit
* builds. */
#if SIZE_MAX > UINT32_MAX
if( (( uint64_t ) ad_length ) >> 61 != 0 ||
(( uint64_t ) plaintext_length ) > 0xFFFFFFFE0ull )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
#endif
}
else
#endif /* PSA_WANT_ALG_GCM */
#if defined(PSA_WANT_ALG_CCM)
if( operation->alg == PSA_ALG_CCM )
{
if( ad_length > 0xFF00 )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
}
else
#endif /* PSA_WANT_ALG_CCM */
#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
{
/* No length restrictions for ChaChaPoly. */
}
#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
status = psa_driver_wrapper_aead_set_lengths( operation, ad_length,
plaintext_length );
exit:
if( status == PSA_SUCCESS )
{
operation->ad_remaining = ad_length;
operation->body_remaining = plaintext_length;
operation->lengths_set = 1;
}
else
psa_aead_abort( operation );
return( status );
}
/* Pass additional data to an active multipart AEAD operation. */
psa_status_t psa_aead_update_ad( psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if( operation->id == 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( !operation->nonce_set || operation->body_started )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->lengths_set )
{
if( operation->ad_remaining < input_length )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
operation->ad_remaining -= input_length;
}
status = psa_driver_wrapper_aead_update_ad( operation, input,
input_length );
exit:
if( status == PSA_SUCCESS )
operation->ad_started = 1;
else
psa_aead_abort( operation );
return( status );
}
/* Encrypt or decrypt a message fragment in an active multipart AEAD
operation.*/
psa_status_t psa_aead_update( psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
*output_length = 0;
if( operation->id == 0 )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( !operation->nonce_set )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
if( operation->lengths_set )
{
/* Additional data length was supplied, but not all the additional
data was supplied.*/
if( operation->ad_remaining != 0 )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* Too much data provided. */
if( operation->body_remaining < input_length )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
operation->body_remaining -= input_length;
}
status = psa_driver_wrapper_aead_update( operation, input, input_length,
output, output_size,
output_length );
exit:
if( status == PSA_SUCCESS )
operation->body_started = 1;
else
psa_aead_abort( operation );
return( status );
}
static psa_status_t psa_aead_final_checks( const psa_aead_operation_t *operation )
{
if( operation->id == 0 || !operation->nonce_set )
return( PSA_ERROR_BAD_STATE );
if( operation->lengths_set && ( operation->ad_remaining != 0 ||
operation->body_remaining != 0 ) )
return( PSA_ERROR_INVALID_ARGUMENT );
return( PSA_SUCCESS );
}
/* Finish encrypting a message in a multipart AEAD operation. */
psa_status_t psa_aead_finish( 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;
*ciphertext_length = 0;
*tag_length = tag_size;
status = psa_aead_final_checks( operation );
if( status != PSA_SUCCESS )
goto exit;
if( !operation->is_encrypt )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
status = psa_driver_wrapper_aead_finish( operation, ciphertext,
ciphertext_size,
ciphertext_length,
tag, tag_size, tag_length );
exit:
/* In case the operation fails and the user fails to check for failure or
* the zero tag size, make sure the tag is set to something implausible.
* Even if the operation succeeds, make sure we clear the rest of the
* buffer to prevent potential leakage of anything previously placed in
* the same buffer.*/
if( tag != NULL )
{
if( status != PSA_SUCCESS )
memset( tag, '!', tag_size );
else if( *tag_length < tag_size )
memset( tag + *tag_length, '!', ( tag_size - *tag_length ) );
}
psa_aead_abort( operation );
return( status );
}
/* Finish authenticating and decrypting a message in a multipart AEAD
operation.*/
psa_status_t psa_aead_verify( psa_aead_operation_t *operation,
uint8_t *plaintext,
size_t plaintext_size,
size_t *plaintext_length,
const uint8_t *tag,
size_t tag_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
*plaintext_length = 0;
status = psa_aead_final_checks( operation );
if( status != PSA_SUCCESS )
goto exit;
if( operation->is_encrypt )
{
status = PSA_ERROR_BAD_STATE;
goto exit;
}
status = psa_driver_wrapper_aead_verify( operation, plaintext,
plaintext_size,
plaintext_length,
tag, tag_length );
exit:
psa_aead_abort( operation );
return( status );
}
/* Abort an AEAD operation. */
psa_status_t psa_aead_abort( psa_aead_operation_t *operation )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if( operation->id == 0 )
{
/* The object has (apparently) been initialized but it is not (yet)
* in use. It's ok to call abort on such an object, and there's
* nothing to do. */
return( PSA_SUCCESS );
}
status = psa_driver_wrapper_aead_abort( operation );
memset( operation, 0, sizeof( *operation ) );
return( status );
}
/****************************************************************/
/* Generators */
/****************************************************************/

View File

@@ -25,58 +25,24 @@
#include "psa_crypto_aead.h"
#include "psa_crypto_core.h"
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include "mbedtls/ccm.h"
#include "mbedtls/chachapoly.h"
#include "mbedtls/cipher.h"
#include "mbedtls/gcm.h"
typedef struct
{
union
{
unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
mbedtls_ccm_context ccm;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
mbedtls_gcm_context gcm;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
mbedtls_chachapoly_context chachapoly;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
} ctx;
psa_algorithm_t core_alg;
uint8_t tag_length;
} aead_operation_t;
#define AEAD_OPERATION_INIT {{0}, 0, 0}
static void psa_aead_abort_internal( aead_operation_t *operation )
{
switch( operation->core_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 */
}
}
#include "mbedtls/error.h"
static psa_status_t psa_aead_setup(
aead_operation_t *operation,
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;
@@ -85,6 +51,8 @@ static psa_status_t psa_aead_setup(
mbedtls_cipher_id_t cipher_id;
size_t full_tag_length = 0;
( void ) key_buffer_size;
key_bits = attributes->core.bits;
cipher_info = mbedtls_cipher_info_from_psa( alg,
@@ -97,7 +65,7 @@ static psa_status_t psa_aead_setup(
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
operation->core_alg = PSA_ALG_CCM;
operation->alg = PSA_ALG_CCM;
full_tag_length = 16;
/* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
* The call to mbedtls_ccm_encrypt_and_tag or
@@ -116,7 +84,7 @@ static psa_status_t psa_aead_setup(
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
operation->core_alg = PSA_ALG_GCM;
operation->alg = PSA_ALG_GCM;
full_tag_length = 16;
/* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
* The call to mbedtls_gcm_crypt_and_tag or
@@ -135,7 +103,7 @@ static psa_status_t psa_aead_setup(
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
operation->alg = PSA_ALG_CHACHA20_POLY1305;
full_tag_length = 16;
/* We only support the default tag length. */
if( alg != PSA_ALG_CHACHA20_POLY1305 )
@@ -159,7 +127,9 @@ static psa_status_t psa_aead_setup(
> full_tag_length )
return( PSA_ERROR_INVALID_ARGUMENT );
operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
operation->key_type = psa_get_key_type( attributes );
operation->tag_length = PSA_AEAD_TAG_LENGTH( operation->key_type,
key_bits,
alg );
@@ -176,11 +146,12 @@ psa_status_t mbedtls_psa_aead_encrypt(
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
aead_operation_t operation = AEAD_OPERATION_INIT;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
uint8_t *tag;
(void) key_buffer_size;
status = psa_aead_setup( &operation, attributes, key_buffer, alg );
status = psa_aead_setup( &operation, attributes, key_buffer,
key_buffer_size, alg );
if( status != PSA_SUCCESS )
goto exit;
@@ -194,7 +165,7 @@ psa_status_t mbedtls_psa_aead_encrypt(
tag = ciphertext + plaintext_length;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if( operation.core_alg == PSA_ALG_CCM )
if( operation.alg == PSA_ALG_CCM )
{
status = mbedtls_to_psa_error(
mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
@@ -208,7 +179,7 @@ psa_status_t mbedtls_psa_aead_encrypt(
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if( operation.core_alg == PSA_ALG_GCM )
if( operation.alg == PSA_ALG_GCM )
{
status = mbedtls_to_psa_error(
mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
@@ -222,9 +193,9 @@ psa_status_t mbedtls_psa_aead_encrypt(
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
{
if( nonce_length != 12 || operation.tag_length != 16 )
if( operation.tag_length != 16 )
{
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
@@ -250,7 +221,7 @@ psa_status_t mbedtls_psa_aead_encrypt(
*ciphertext_length = plaintext_length + operation.tag_length;
exit:
psa_aead_abort_internal( &operation );
mbedtls_psa_aead_abort( &operation );
return( status );
}
@@ -286,11 +257,12 @@ psa_status_t mbedtls_psa_aead_decrypt(
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
aead_operation_t operation = AEAD_OPERATION_INIT;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
const uint8_t *tag = NULL;
(void) key_buffer_size;
status = psa_aead_setup( &operation, attributes, key_buffer, alg );
status = psa_aead_setup( &operation, attributes, key_buffer,
key_buffer_size, alg );
if( status != PSA_SUCCESS )
goto exit;
@@ -301,7 +273,7 @@ psa_status_t mbedtls_psa_aead_decrypt(
goto exit;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if( operation.core_alg == PSA_ALG_CCM )
if( operation.alg == PSA_ALG_CCM )
{
status = mbedtls_to_psa_error(
mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
@@ -315,7 +287,7 @@ psa_status_t mbedtls_psa_aead_decrypt(
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if( operation.core_alg == PSA_ALG_GCM )
if( operation.alg == PSA_ALG_GCM )
{
status = mbedtls_to_psa_error(
mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
@@ -329,9 +301,9 @@ psa_status_t mbedtls_psa_aead_decrypt(
else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
{
if( nonce_length != 12 || operation.tag_length != 16 )
if( operation.tag_length != 16 )
{
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
@@ -356,12 +328,320 @@ psa_status_t mbedtls_psa_aead_decrypt(
*plaintext_length = ciphertext_length - operation.tag_length;
exit:
psa_aead_abort_internal( &operation );
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;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if( operation->alg == PSA_ALG_CCM )
{
return( PSA_ERROR_NOT_SUPPORTED );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
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;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if( operation->alg == PSA_ALG_CCM )
{
return( PSA_ERROR_NOT_SUPPORTED );
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
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_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 ) nonce;
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 )
{
/* Nothing here yet, work is currently done in PSA Core, however support
* for CCM will require this function. */
( void ) operation;
( void ) ad_length;
( void ) plaintext_length;
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_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 )
{
if( output_size < input_length )
return( PSA_ERROR_BUFFER_TOO_SMALL );
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_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 ) input;
( void ) input_length;
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 )
{
if( ciphertext_size < 15 )
return( PSA_ERROR_BUFFER_TOO_SMALL );
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_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 */

View File

@@ -148,4 +148,364 @@ psa_status_t mbedtls_psa_aead_decrypt(
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
/** Set the key for a multipart authenticated encryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_encrypt_setup entry point. This function behaves as an
* aead_encrypt_setup entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* If an error occurs at any step after a call to
* mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a
* call to mbedtls_psa_aead_abort(). The PSA core may call
* mbedtls_psa_aead_abort() at any time after the operation has been
* initialized, and is required to when the operation is no longer needed.
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized as per the documentation for
* #mbedtls_psa_aead_operation_t and not yet in
* use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
It must be consistent with the size in bits
recorded in \p attributes.
* \param alg The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An invalid block length was supplied.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Failed to allocate memory for key material
*/
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 );
/** Set the key for a multipart authenticated decryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_decrypt_setup entry point. This function behaves as an
* aead_decrypt_setup entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* If an error occurs at any step after a call to
* mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a
* call to mbedtls_psa_aead_abort(). The PSA core may call
* mbedtls_psa_aead_abort() at any time after the operation has been
* initialized, and is required to when the operation is no longer needed.
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized as per the documentation for
* #mbedtls_psa_aead_operation_t and not yet in
* use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
It must be consistent with the size in bits
recorded in \p attributes.
* \param alg The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An invalid block length was supplied.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Failed to allocate memory for key material
*/
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 );
/** Set the nonce for an authenticated encryption or decryption operation.
*
* \note The signature of this function is that of a PSA driver aead_set_nonce
* entry point. This function behaves as an aead_set_nonce entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* This function sets the nonce for the authenticated
* encryption or decryption operation.
*
* The PSA core calls mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup() before calling this function.
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param[in] nonce Buffer containing the nonce to use.
* \param nonce_length Size of the nonce in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size of \p nonce is not acceptable for the chosen algorithm.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_set_nonce(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length );
/** Declare the lengths of the message and additional data for AEAD.
*
* \note The signature of this function is that of a PSA driver aead_set_lengths
* entry point. This function behaves as an aead_set_lengths entry point
* as defined in the PSA driver interface specification for transparent
* drivers.
*
* The PSA core calls this function before calling mbedtls_psa_aead_update_ad()
* or mbedtls_psa_aead_update() if the algorithm for the operation requires it.
* If the algorithm does not require it, calling this function is optional, but
* if this function is called then the implementation must enforce the lengths.
*
* The PSA core may call this function before or after setting the nonce with
* mbedtls_psa_aead_set_nonce().
*
* - For #PSA_ALG_CCM, calling this function is required.
* - For the other AEAD algorithms defined in this specification, calling
* this function is not required.
*
* If this function returns an error status, the PSA core calls
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param ad_length Size of the non-encrypted additional
* authenticated data in bytes.
* \param plaintext_length Size of the plaintext to encrypt in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* At least one of the lengths is not acceptable for the chosen
* algorithm.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_set_lengths(
mbedtls_psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length );
/** Pass additional data to an active AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_update_ad entry point. This function behaves as an aead_update_ad
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Additional data is authenticated, but not encrypted.
*
* The PSA core can call this function multiple times to pass successive
* fragments of the additional data. It will not call this function after
* passing data to encrypt or decrypt with mbedtls_psa_aead_update().
*
* Before calling this function, the PSA core will:
* 1. Call either mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup().
* 2. Set the nonce with mbedtls_psa_aead_set_nonce().
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param[in] input Buffer containing the fragment of
* additional data.
* \param input_length Size of the \p input buffer in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_update_ad(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length );
/** Encrypt or decrypt a message fragment in an active AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_update entry point. This function behaves as an aead_update entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Before calling this function, the PSA core will:
* 1. Call either mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup(). The choice of setup function
* determines whether this function encrypts or decrypts its input.
* 2. Set the nonce with mbedtls_psa_aead_set_nonce().
* 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data.
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* This function does not require the input to be aligned to any
* particular block boundary. If the implementation can only process
* a whole block at a time, it must consume all the input provided, but
* it may delay the end of the corresponding output until a subsequent
* call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides
* sufficient input. The amount of data that can be delayed in this way is
* bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
*
* \param[in,out] operation Active AEAD operation.
* \param[in] input Buffer containing the message fragment to
* encrypt or decrypt.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] output Buffer where the output is to be written.
* \param output_size Size of the \p output buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - A sufficient output size is
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type,
* \c alg, \p input_length) where
* \c key_type is the type of key and \c alg is
* the algorithm that were used to set up the
* operation.
* - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p
* input_length) evaluates to the maximum
* output size of any supported AEAD
* algorithm.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS
* Success.
*
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or
* #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to
* determine the required buffer size.
*/
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 );
/** Finish encrypting a message in an AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_finish entry point. This function behaves as an aead_finish entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* The operation must have been set up by the PSA core with
* mbedtls_psa_aead_encrypt_setup().
*
* This function finishes the authentication of the additional data
* formed by concatenating the inputs passed to preceding calls to
* mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the
* inputs passed to preceding calls to mbedtls_psa_aead_update().
*
* This function has two output buffers:
* - \p ciphertext contains trailing ciphertext that was buffered from
* preceding calls to mbedtls_psa_aead_update().
* - \p tag contains the authentication tag.
*
* Whether or not this function returns successfuly, the PSA core subsequently
* calls mbedtls_psa_aead_abort() to deactivate the operation.
*
* \param[in,out] operation Active AEAD operation.
* \param[out] ciphertext Buffer where the last part of the ciphertext
* is to be written.
* \param ciphertext_size Size of the \p ciphertext buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - A sufficient output size is
* #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type,
* \c alg) where \c key_type is the type of key
* and \c alg is the algorithm that were used to
* set up the operation.
* - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to
* the maximum output size of any supported AEAD
* algorithm.
* \param[out] ciphertext_length On success, the number of bytes of
* returned ciphertext.
* \param[out] tag Buffer where the authentication tag is
* to be written.
* \param tag_size Size of the \p tag buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c
* key_type, \c key_bits, \c alg) where
* \c key_type and \c key_bits are the type and
* bit-size of the key, and \c alg are the
* algorithm that were used in the call to
* mbedtls_psa_aead_encrypt_setup().
* - #PSA_AEAD_TAG_MAX_SIZE evaluates to the
* maximum tag size of any supported AEAD
* algorithm.
* \param[out] tag_length On success, the number of bytes
* that make up the returned tag.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p tag buffer is too small.
* #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or
* #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag
* buffer size.
*/
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 );
/** Abort an AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_abort entry point. This function behaves as an aead_abort entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Aborting an operation frees all associated resources except for the
* \p operation structure itself. Once aborted, the operation object
* can be reused for another operation by the PSA core by it calling
* mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.
*
* The PSA core may call this function any time after the operation object has
* been initialized as described in #mbedtls_psa_aead_operation_t.
*
* In particular, calling mbedtls_psa_aead_abort() after the operation has been
* terminated by a call to mbedtls_psa_aead_abort() or
* mbedtls_psa_aead_finish() is safe and has no effect.
*
* \param[in,out] operation Initialized AEAD operation.
*
* \retval #PSA_SUCCESS
* Success.
*/
psa_status_t mbedtls_psa_aead_abort(
mbedtls_psa_aead_operation_t *operation );
#endif /* PSA_CRYPTO_AEAD */

View File

@@ -1565,6 +1565,381 @@ psa_status_t psa_driver_wrapper_aead_decrypt(
}
}
psa_status_t psa_driver_wrapper_aead_encrypt_setup(
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;
psa_key_location_t location =
PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
switch( location )
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
/* Key is stored in the slot in export representation, so
* cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
status = mbedtls_test_transparent_aead_encrypt_setup(
&operation->ctx.transparent_test_driver_ctx,
attributes, key_buffer, key_buffer_size,
alg );
/* Declared with fallback == true */
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
/* Fell through, meaning no accelerator supports this operation */
operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
status = mbedtls_psa_aead_encrypt_setup(
&operation->ctx.mbedtls_ctx, attributes,
key_buffer, key_buffer_size,
alg );
return( status );
/* Add cases for opaque driver here */
default:
/* Key is declared with a lifetime not known to us */
(void)status;
return( PSA_ERROR_INVALID_ARGUMENT );
}
}
psa_status_t psa_driver_wrapper_aead_decrypt_setup(
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;
psa_key_location_t location =
PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
switch( location )
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
/* Key is stored in the slot in export representation, so
* cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
status = mbedtls_test_transparent_aead_decrypt_setup(
&operation->ctx.transparent_test_driver_ctx,
attributes,
key_buffer, key_buffer_size,
alg );
/* Declared with fallback == true */
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
/* Fell through, meaning no accelerator supports this operation */
operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
status = mbedtls_psa_aead_decrypt_setup(
&operation->ctx.mbedtls_ctx,
attributes,
key_buffer, key_buffer_size,
alg );
return( status );
/* Add cases for opaque driver here */
default:
/* Key is declared with a lifetime not known to us */
(void)status;
return( PSA_ERROR_INVALID_ARGUMENT );
}
}
psa_status_t psa_driver_wrapper_aead_set_nonce(
psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx,
nonce,
nonce_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_set_nonce(
&operation->ctx.transparent_test_driver_ctx,
nonce, nonce_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)nonce;
(void)nonce_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_set_lengths(
psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx,
ad_length,
plaintext_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_set_lengths(
&operation->ctx.transparent_test_driver_ctx,
ad_length, plaintext_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)ad_length;
(void)plaintext_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_update_ad(
psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx,
input,
input_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_update_ad(
&operation->ctx.transparent_test_driver_ctx,
input, input_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)input;
(void)input_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_update(
psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx,
input, input_length,
output, output_size,
output_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_update(
&operation->ctx.transparent_test_driver_ctx,
input, input_length, output, output_size,
output_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)input;
(void)input_length;
(void)output;
(void)output_size;
(void)output_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_finish(
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 )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
ciphertext,
ciphertext_size,
ciphertext_length, tag,
tag_size, tag_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_finish(
&operation->ctx.transparent_test_driver_ctx,
ciphertext, ciphertext_size,
ciphertext_length, tag, tag_size, tag_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)ciphertext;
(void)ciphertext_size;
(void)ciphertext_length;
(void)tag;
(void)tag_size;
(void)tag_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_verify(
psa_aead_operation_t *operation,
uint8_t *plaintext,
size_t plaintext_size,
size_t *plaintext_length,
const uint8_t *tag,
size_t tag_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];
size_t check_tag_length;
status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
plaintext,
plaintext_size,
plaintext_length,
check_tag,
sizeof( check_tag ),
&check_tag_length );
if( status == PSA_SUCCESS )
{
if( tag_length != check_tag_length ||
mbedtls_psa_safer_memcmp( tag, check_tag, tag_length )
!= 0 )
status = PSA_ERROR_INVALID_SIGNATURE;
}
mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) );
return( status );
}
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_verify(
&operation->ctx.transparent_test_driver_ctx,
plaintext, plaintext_size,
plaintext_length, tag, tag_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)plaintext;
(void)plaintext_size;
(void)plaintext_length;
(void)tag;
(void)tag_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_abort(
psa_aead_operation_t *operation )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) );
#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
return( mbedtls_test_transparent_aead_abort(
&operation->ctx.transparent_test_driver_ctx ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
return( PSA_ERROR_INVALID_ARGUMENT );
}
/*
* MAC functions

View File

@@ -219,6 +219,61 @@ psa_status_t psa_driver_wrapper_aead_decrypt(
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
psa_status_t psa_driver_wrapper_aead_encrypt_setup(
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 psa_driver_wrapper_aead_decrypt_setup(
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 psa_driver_wrapper_aead_set_nonce(
psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length );
psa_status_t psa_driver_wrapper_aead_set_lengths(
psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length );
psa_status_t psa_driver_wrapper_aead_update_ad(
psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length );
psa_status_t psa_driver_wrapper_aead_update(
psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length );
psa_status_t psa_driver_wrapper_aead_finish(
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 psa_driver_wrapper_aead_verify(
psa_aead_operation_t *operation,
uint8_t *plaintext,
size_t plaintext_size,
size_t *plaintext_length,
const uint8_t *tag,
size_t tag_length );
psa_status_t psa_driver_wrapper_aead_abort(
psa_aead_operation_t *operation );
/*
* MAC functions
*/