Add internal implementation of multipart AEAD
For the time being CCM and GCM are not entirely implemented correctly due to issues with their underlying implentations, which would be difficult to fix in 2.x, and thus require all the AD and data to be passed in in one go. Signed-off-by: Paul Elliott <paul.elliott@arm.com>
This commit is contained in:
parent
07a30c4c00
commit
adb8b16b16
@ -154,10 +154,32 @@ static inline struct psa_mac_operation_s psa_mac_operation_init( void )
|
||||
struct psa_aead_operation_s
|
||||
{
|
||||
psa_algorithm_t alg;
|
||||
psa_key_type_t key_type;
|
||||
|
||||
unsigned int key_set : 1;
|
||||
unsigned int nonce_set : 1;
|
||||
unsigned int lengths_set : 1;
|
||||
unsigned int is_encrypt : 1;
|
||||
unsigned int ad_started : 1;
|
||||
unsigned int body_started : 1;
|
||||
|
||||
uint8_t tag_length;
|
||||
uint8_t nonce_length;
|
||||
|
||||
size_t ad_remaining;
|
||||
size_t body_remaining;
|
||||
|
||||
/* Buffers for AD/data - only required until CCM gets proper multipart
|
||||
support. */
|
||||
uint8_t* ad_buffer;
|
||||
size_t ad_length;
|
||||
|
||||
uint8_t* data_buffer;
|
||||
size_t data_length;
|
||||
|
||||
/* buffer to store Nonce - only required until CCM and GCM get proper
|
||||
multipart support. */
|
||||
uint8_t nonce[PSA_AEAD_NONCE_MAX_SIZE];
|
||||
|
||||
union
|
||||
{
|
||||
@ -175,7 +197,7 @@ struct psa_aead_operation_s
|
||||
} ctx;
|
||||
};
|
||||
|
||||
#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, {0}}
|
||||
#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}, {0}}
|
||||
static inline struct psa_aead_operation_s psa_aead_operation_init( void )
|
||||
{
|
||||
const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;
|
||||
|
@ -20,39 +20,40 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_C)
|
||||
|
||||
#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"
|
||||
#include "mbedtls/error.h"
|
||||
|
||||
|
||||
static void psa_aead_abort_internal( psa_aead_operation_t *operation )
|
||||
/* Constant-time buffer comparison. This is duplication of code from
|
||||
* psa_crypto.c, but has nowhere private I can put it for the minute. Really
|
||||
belongs in the constant time module, when that gets implemented */
|
||||
static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
|
||||
{
|
||||
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 */
|
||||
}
|
||||
size_t i;
|
||||
unsigned char diff = 0;
|
||||
|
||||
for( i = 0; i < n; i++ )
|
||||
diff |= a[i] ^ b[i];
|
||||
|
||||
return( diff );
|
||||
}
|
||||
|
||||
|
||||
static psa_status_t psa_aead_setup(
|
||||
psa_aead_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
@ -65,6 +66,12 @@ static psa_status_t psa_aead_setup(
|
||||
mbedtls_cipher_id_t cipher_id;
|
||||
size_t full_tag_length = 0;
|
||||
|
||||
if( operation->key_set || operation->nonce_set ||
|
||||
operation->ad_started || operation->body_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
key_bits = attributes->core.bits;
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_psa( alg,
|
||||
@ -143,6 +150,8 @@ static psa_status_t psa_aead_setup(
|
||||
key_bits,
|
||||
alg );
|
||||
|
||||
operation->key_set = 1;
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
@ -230,7 +239,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 );
|
||||
}
|
||||
@ -336,12 +345,715 @@ 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( 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;
|
||||
|
||||
(void) key_buffer_size;
|
||||
|
||||
status = psa_aead_setup( operation, attributes, key_buffer, 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( 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;
|
||||
|
||||
(void) key_buffer_size;
|
||||
|
||||
status = psa_aead_setup( operation, attributes, key_buffer, alg );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
operation->is_encrypt = 0;
|
||||
}
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
/* Generate a random nonce / IV for multipart AEAD operation */
|
||||
psa_status_t mbedtls_psa_aead_generate_nonce( psa_aead_operation_t *operation,
|
||||
uint8_t *nonce,
|
||||
size_t nonce_size,
|
||||
size_t *nonce_length )
|
||||
{
|
||||
psa_status_t status;
|
||||
size_t required_nonce_size = nonce_size;
|
||||
|
||||
if( !operation->key_set || operation->nonce_set ||
|
||||
operation->ad_started || operation->body_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, operation->alg);
|
||||
|
||||
if( nonce_size == 0 || nonce_size < required_nonce_size )
|
||||
{
|
||||
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
|
||||
status = psa_generate_random( nonce, required_nonce_size );
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = mbedtls_psa_aead_set_nonce( operation, nonce, required_nonce_size );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
*nonce_length = required_nonce_size;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set a nonce for the multipart AEAD operation*/
|
||||
psa_status_t mbedtls_psa_aead_set_nonce( psa_aead_operation_t *operation,
|
||||
const uint8_t *nonce,
|
||||
size_t nonce_length )
|
||||
{
|
||||
psa_status_t status;
|
||||
|
||||
if( !operation->key_set || operation->nonce_set ||
|
||||
operation->ad_started || operation->body_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* Restricting to a nominal safe length for nonces even though some
|
||||
algorithms can handle longer nonces, but not without collision */
|
||||
if( nonce_length > PSA_AEAD_NONCE_MAX_SIZE )
|
||||
{
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
/* GCM sets nonce once additional data has been supplied */
|
||||
memcpy(operation->nonce, nonce, nonce_length);
|
||||
|
||||
/* We know that nonce size cannot exceed the uint8_t size */
|
||||
operation->nonce_length = ( uint8_t ) nonce_length;
|
||||
status = PSA_SUCCESS;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
/* Multipart CCM not supported as yet, so CCM is basically operating
|
||||
in oneshot mode. Store the nonce as we need this later */
|
||||
memcpy(operation->nonce, nonce, nonce_length);
|
||||
|
||||
/* We know that nonce size cannot exceed the uint8_t size */
|
||||
operation->nonce_length = ( uint8_t ) nonce_length;
|
||||
status = PSA_SUCCESS;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
|
||||
if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
|
||||
{
|
||||
if( nonce_length != 12 && nonce_length != 8)
|
||||
{
|
||||
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;
|
||||
( void ) nonce_length;
|
||||
|
||||
return ( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
operation->nonce_set = 1;
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
/* Declare the lengths of the message and additional data for AEAD. */
|
||||
psa_status_t mbedtls_psa_aead_set_lengths( psa_aead_operation_t *operation,
|
||||
size_t ad_length,
|
||||
size_t plaintext_length )
|
||||
{
|
||||
|
||||
if( !operation->key_set || operation->lengths_set )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if( ( (uint64_t) ad_length ) >> 61 != 0 ||
|
||||
( (uint64_t) plaintext_length ) > 0xFFFFFFFE0ull )
|
||||
{
|
||||
return ( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
if( ad_length > 0xFF00 )
|
||||
{
|
||||
return ( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
|
||||
if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
|
||||
{
|
||||
/* No length restrictions for ChaChaPoly. */
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
|
||||
{
|
||||
( void ) ad_length;
|
||||
( void ) plaintext_length;
|
||||
|
||||
return ( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
operation->ad_remaining = ad_length;
|
||||
operation->body_remaining = plaintext_length;
|
||||
operation->lengths_set = 1;
|
||||
|
||||
return ( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/* Pass additional data to an active multipart AEAD operation. */
|
||||
psa_status_t mbedtls_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->nonce_set || !operation->key_set )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
if( operation->lengths_set )
|
||||
{
|
||||
if ( operation->ad_remaining < input_length )
|
||||
{
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
operation->ad_remaining -= input_length;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
if( !operation->lengths_set || operation->ad_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* GCM currently requires all the additional data to be passed in in
|
||||
* one contigious buffer, so until that is re-done, we have to enforce
|
||||
* this, as we cannot allocate a buffer to collate multiple calls into.
|
||||
*/
|
||||
if( input_length != operation->ad_remaining )
|
||||
{
|
||||
return ( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
status = mbedtls_to_psa_error( mbedtls_gcm_starts( &operation->ctx.gcm,
|
||||
operation->is_encrypt ?
|
||||
MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
|
||||
operation->nonce,
|
||||
operation->nonce_length,
|
||||
input,
|
||||
input_length ) );
|
||||
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
/* CCM requires all additional data to be passed in in one go at the
|
||||
minute, as we are basically operating in oneshot mode. */
|
||||
if( !operation->lengths_set || operation->ad_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* Save the additional data for later, this will be passed in
|
||||
when we have the body. */
|
||||
operation->ad_buffer = ( uint8_t * ) mbedtls_calloc(1, input_length );
|
||||
|
||||
if( operation->ad_buffer )
|
||||
{
|
||||
memcpy( operation->ad_buffer, input, input_length );
|
||||
operation->ad_length = input_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( PSA_ERROR_INSUFFICIENT_MEMORY );
|
||||
}
|
||||
}
|
||||
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) input;
|
||||
(void) input_length;
|
||||
|
||||
return ( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
operation->ad_started = 1;
|
||||
}
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
/* Encrypt or decrypt a message fragment in an active multipart AEAD
|
||||
* operation.*/
|
||||
psa_status_t mbedtls_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 )
|
||||
{
|
||||
size_t update_output_size;
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if( !operation->nonce_set || !operation->key_set || !operation->ad_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
update_output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(operation->key_type,
|
||||
operation->alg, input_length);
|
||||
|
||||
if(update_output_size > output_size )
|
||||
{
|
||||
return ( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
|
||||
if( operation->lengths_set)
|
||||
{
|
||||
/* Additional data length was supplied, but not all the additional
|
||||
data was supplied.*/
|
||||
if( operation->ad_remaining != 0 )
|
||||
{
|
||||
return ( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
/* Too much data provided. */
|
||||
if( operation->body_remaining < input_length )
|
||||
{
|
||||
return ( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
operation->body_remaining -= input_length;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
/* For the time being set the requirement that all of the body data
|
||||
* must be passed in in one update, rather than deal with the complexity
|
||||
* of non block size aligned updates. This will be fixed in 3.0 when
|
||||
we can change the signature of the GCM multipart functions */
|
||||
if( !operation->lengths_set || operation->body_remaining != 0 )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
if( operation->ad_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
status = mbedtls_to_psa_error( mbedtls_gcm_update( &operation->ctx.gcm,
|
||||
input_length,
|
||||
input,
|
||||
output ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
/* CCM dooes not support multipart yet, so all the input has to be
|
||||
passed in in one go. Store the data for the final step.*/
|
||||
if( operation->ad_started )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* Save the additional data for later, this will be passed in
|
||||
when we have the body. */
|
||||
operation->data_buffer = ( uint8_t * ) mbedtls_calloc(1, input_length );
|
||||
|
||||
if( operation->data_buffer )
|
||||
{
|
||||
memcpy( operation->data_buffer, input, input_length );
|
||||
operation->data_length = input_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( PSA_ERROR_INSUFFICIENT_MEMORY );
|
||||
}
|
||||
|
||||
}
|
||||
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( &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_size;
|
||||
operation->body_started = 1;
|
||||
}
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
/* Common checks for both mbedtls_psa_aead_finish() and
|
||||
mbedtls_psa_aead_verify() */
|
||||
static psa_status_t mbedtls_psa_aead_finish_checks( psa_aead_operation_t *operation,
|
||||
size_t output_size,
|
||||
size_t tag_size,
|
||||
size_t *finish_output_size,
|
||||
size_t *output_tag_length )
|
||||
{
|
||||
if( !operation->key_set || !operation->nonce_set
|
||||
|| !operation->ad_started || !operation->body_started)
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
if( operation->lengths_set )
|
||||
{
|
||||
if( operation->ad_remaining != 0 || operation->body_remaining != 0 )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
}
|
||||
|
||||
*output_tag_length = operation->tag_length;
|
||||
|
||||
if( tag_size < *output_tag_length)
|
||||
{
|
||||
return ( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
|
||||
if( operation->is_encrypt )
|
||||
{
|
||||
*finish_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE(operation->key_type,
|
||||
operation->alg);
|
||||
}
|
||||
else
|
||||
{
|
||||
*finish_output_size = PSA_AEAD_VERIFY_OUTPUT_SIZE(operation->key_type,
|
||||
operation->alg);
|
||||
}
|
||||
|
||||
if( output_size < *finish_output_size )
|
||||
{
|
||||
return ( PSA_ERROR_BUFFER_TOO_SMALL );
|
||||
}
|
||||
|
||||
return ( PSA_SUCCESS );
|
||||
|
||||
}
|
||||
|
||||
/* Finish encrypting a message in a multipart AEAD operation. */
|
||||
psa_status_t mbedtls_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;
|
||||
size_t output_tag_length;
|
||||
size_t finish_output_size;
|
||||
|
||||
status = mbedtls_psa_aead_finish_checks( operation, ciphertext_size, tag_size, &finish_output_size,
|
||||
&output_tag_length);
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
/* We will need to do final GCM pass in here when multipart is done. */
|
||||
status = mbedtls_to_psa_error( mbedtls_gcm_finish( &operation->ctx.gcm,
|
||||
tag,
|
||||
tag_size ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
if( !operation->ad_buffer || !operation->data_buffer )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* Perform oneshot CCM encryption with data already stored, as
|
||||
CCM does not support multipart yet.*/
|
||||
status = mbedtls_to_psa_error( mbedtls_ccm_encrypt_and_tag( &operation->ctx.ccm,
|
||||
operation->data_length,
|
||||
operation->nonce,
|
||||
operation->nonce_length,
|
||||
operation->ad_buffer,
|
||||
operation->ad_length,
|
||||
operation->data_buffer,
|
||||
ciphertext,
|
||||
tag, tag_size ) );
|
||||
|
||||
/* Even if the above operation fails, we no longer need the data */
|
||||
mbedtls_free(operation->ad_buffer);
|
||||
operation->ad_buffer = NULL;
|
||||
operation->ad_length = 0;
|
||||
|
||||
mbedtls_free(operation->data_buffer);
|
||||
operation->data_buffer = NULL;
|
||||
operation->data_length = 0;
|
||||
}
|
||||
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_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 )
|
||||
{
|
||||
*ciphertext_length = finish_output_size;
|
||||
*tag_length = output_tag_length;
|
||||
}
|
||||
|
||||
mbedtls_psa_aead_abort(operation);
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
/* Finish authenticating and decrypting a message in a multipart AEAD
|
||||
* operation.*/
|
||||
psa_status_t mbedtls_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;
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t finish_output_size;
|
||||
size_t output_tag_length;
|
||||
|
||||
int do_tag_check = 1;
|
||||
uint8_t check_tag[16];
|
||||
|
||||
status = mbedtls_psa_aead_finish_checks( operation, plaintext_size, tag_length, &finish_output_size,
|
||||
&output_tag_length);
|
||||
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
|
||||
if( operation->alg == PSA_ALG_GCM )
|
||||
{
|
||||
/* Call finish to get the tag for comparison */
|
||||
status = mbedtls_to_psa_error( mbedtls_gcm_finish( &operation->ctx.gcm,
|
||||
check_tag,
|
||||
16 ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
|
||||
if( operation->alg == PSA_ALG_CCM )
|
||||
{
|
||||
if( !operation->ad_buffer || !operation->data_buffer )
|
||||
{
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
}
|
||||
|
||||
/* Perform oneshot CCM decryption with data already stored, as
|
||||
CCM does not support multipart yet.*/
|
||||
|
||||
ret = mbedtls_ccm_auth_decrypt( &operation->ctx.ccm, operation->data_length,
|
||||
operation->nonce, operation->nonce_length,
|
||||
operation->ad_buffer, operation->ad_length,
|
||||
operation->data_buffer, plaintext,
|
||||
tag, tag_length );
|
||||
|
||||
if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
|
||||
{
|
||||
status = PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = mbedtls_to_psa_error( ret );
|
||||
do_tag_check = 0;
|
||||
}
|
||||
|
||||
/* Even if the above operation fails, we no longer need the data */
|
||||
mbedtls_free(operation->ad_buffer);
|
||||
operation->ad_buffer = NULL;
|
||||
operation->ad_length = 0;
|
||||
|
||||
mbedtls_free(operation->data_buffer);
|
||||
operation->data_buffer = NULL;
|
||||
operation->data_length = 0;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
|
||||
if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
|
||||
{
|
||||
// call finish to get the tag for comparison.
|
||||
status = mbedtls_to_psa_error( mbedtls_chachapoly_finish( &operation->ctx.chachapoly,
|
||||
check_tag ) );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
|
||||
{
|
||||
( void ) plaintext;
|
||||
( void ) plaintext_size;
|
||||
( void ) plaintext_length;
|
||||
( void ) tag;
|
||||
( void ) tag_length;
|
||||
|
||||
return ( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
{
|
||||
if( do_tag_check && safer_memcmp(tag, check_tag, tag_length) != 0 )
|
||||
{
|
||||
status = MBEDTLS_ERR_GCM_AUTH_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
mbedtls_psa_aead_abort(operation);
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
/* Abort an AEAD operation */
|
||||
psa_status_t mbedtls_psa_aead_abort( psa_aead_operation_t *operation )
|
||||
{
|
||||
switch( operation->alg )
|
||||
{
|
||||
#if defined(MBEDTLS_CCM_C)
|
||||
case MBEDTLS_PSA_BUILTIN_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 */
|
||||
}
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_PSA_CRYPTO_C */
|
||||
|
||||
|
@ -148,4 +148,644 @@ 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.
|
||||
*
|
||||
* The sequence of operations to encrypt a message with authentication
|
||||
* is as follows:
|
||||
* -# Allocate an operation object which will be passed to all the functions
|
||||
* listed here.
|
||||
* -# Initialize the operation object with one of the methods described in the
|
||||
* documentation for #psa_aead_operation_t, e.g.
|
||||
* #PSA_AEAD_OPERATION_INIT.
|
||||
* -# Call mbedtls_psa_aead_encrypt_setup() to specify the algorithm and key.
|
||||
* -# If needed, call mbedtls_psa_aead_set_lengths() to specify the length of
|
||||
* the inputs to the subsequent calls to mbedtls_psa_aead_update_ad() and
|
||||
* mbedtls_psa_aead_update(). See the documentation of mbedtls_psa_aead_set_lengths()
|
||||
* for details.
|
||||
* -# Call either mbedtls_psa_aead_generate_nonce() or mbedtls_psa_aead_set_nonce() to
|
||||
* generate or set the nonce. You should use
|
||||
* mbedtls_psa_aead_generate_nonce() unless the protocol you are implementing
|
||||
* requires a specific nonce value.
|
||||
* -# Call mbedtls_psa_aead_update_ad() zero, one or more times, passing a fragment
|
||||
* of the non-encrypted additional authenticated data each time.
|
||||
* -# Call mbedtls_psa_aead_update() zero, one or more times, passing a fragment
|
||||
* of the message to encrypt each time.
|
||||
* -# Call mbedtls_psa_aead_finish().
|
||||
*
|
||||
* If an error occurs at any step after a call to mbedtls_psa_aead_encrypt_setup(),
|
||||
* the operation will need to be reset by a call to mbedtls_psa_aead_abort(). The
|
||||
* application may call mbedtls_psa_aead_abort() at any time after the operation
|
||||
* has been initialized.
|
||||
*
|
||||
* After a successful call to mbedtls_psa_aead_encrypt_setup(), the application must
|
||||
* eventually terminate the operation. The following events terminate an
|
||||
* operation:
|
||||
* - A successful call to mbedtls_psa_aead_finish().
|
||||
* - A call to mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \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.
|
||||
* \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_BAD_STATE
|
||||
* The operation state is not valid (it must be inactive).
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \p key is not compatible with \p alg.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \p alg is not supported or is not an AEAD algorithm.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_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);
|
||||
|
||||
/** 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.
|
||||
*
|
||||
* The sequence of operations to decrypt a message with authentication
|
||||
* is as follows:
|
||||
* -# Allocate an operation object which will be passed to all the functions
|
||||
* listed here.
|
||||
* -# Initialize the operation object with one of the methods described in the
|
||||
* documentation for #psa_aead_operation_t, e.g.
|
||||
* #PSA_AEAD_OPERATION_INIT.
|
||||
* -# Call mbedtls_psa_aead_decrypt_setup() to specify the algorithm and key.
|
||||
* -# If needed, call mbedtls_psa_aead_set_lengths() to specify the length of the
|
||||
* inputs to the subsequent calls to mbedtls_psa_aead_update_ad() and
|
||||
* mbedtls_psa_aead_update(). See the documentation of mbedtls_psa_aead_set_lengths()
|
||||
* for details.
|
||||
* -# Call mbedtls_psa_aead_set_nonce() with the nonce for the decryption.
|
||||
* -# Call mbedtls_psa_aead_update_ad() zero, one or more times, passing a fragment
|
||||
* of the non-encrypted additional authenticated data each time.
|
||||
* -# Call mbedtls_psa_aead_update() zero, one or more times, passing a fragment
|
||||
* of the ciphertext to decrypt each time.
|
||||
* -# Call mbedtls_psa_aead_verify().
|
||||
*
|
||||
* If an error occurs at any step after a call to mbedtls_psa_aead_decrypt_setup(),
|
||||
* the operation will need to be reset by a call to mbedtls_psa_aead_abort(). The
|
||||
* application may call mbedtls_psa_aead_abort() at any time after the operation
|
||||
* has been initialized.
|
||||
*
|
||||
* After a successful call to mbedtls_psa_aead_decrypt_setup(), the application must
|
||||
* eventually terminate the operation. The following events terminate an
|
||||
* operation:
|
||||
* - A successful call to mbedtls_psa_aead_verify().
|
||||
* - A call to mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \param[in,out] operation The operation object to set up. It must have
|
||||
* been initialized as per the documentation for
|
||||
* #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.
|
||||
* \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_BAD_STATE
|
||||
* The operation state is not valid (it must be inactive).
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \p key is not compatible with \p alg.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \p alg is not supported or is not an AEAD algorithm.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_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);
|
||||
|
||||
/** Generate a random nonce for an authenticated encryption operation.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* aead_generate_nonce entry point. This function behaves as an
|
||||
* aead_generate_nonce entry point as defined in the PSA driver interface
|
||||
* specification for transparent drivers.
|
||||
*
|
||||
* This function generates a random nonce for the authenticated encryption
|
||||
* operation with an appropriate size for the chosen algorithm, key type
|
||||
* and key size.
|
||||
*
|
||||
* The application must call mbedtls_psa_aead_encrypt_setup() before
|
||||
* calling this function.
|
||||
*
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \param[in,out] operation Active AEAD operation.
|
||||
* \param[out] nonce Buffer where the generated nonce is to be
|
||||
* written.
|
||||
* \param nonce_size Size of the \p nonce buffer in bytes.
|
||||
* \param[out] nonce_length On success, the number of bytes of the
|
||||
* generated nonce.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The operation state is not valid (it must be an active aead encrypt
|
||||
* operation, with no nonce set).
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p nonce buffer is too small.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_aead_generate_nonce(psa_aead_operation_t *operation,
|
||||
uint8_t *nonce,
|
||||
size_t nonce_size,
|
||||
size_t *nonce_length);
|
||||
|
||||
/** Set the nonce for an authenticated encryption or decryption operation.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* psa_aead_set_nonce entry point. This function behaves as an
|
||||
* psa_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 application must call mbedtls_psa_aead_encrypt_setup() or
|
||||
* mbedtls_psa_aead_decrypt_setup() before calling this function.
|
||||
*
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \note When encrypting, applications should use mbedtls_psa_aead_generate_nonce()
|
||||
* instead of this function, unless implementing a protocol that requires
|
||||
* a non-random IV.
|
||||
*
|
||||
* \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_BAD_STATE
|
||||
* The operation state is not valid (it must be active, with no nonce
|
||||
* set).
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The size of \p nonce is not acceptable for the chosen algorithm.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_aead_set_nonce(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
|
||||
* psa_aead_set_lengths entry point. This function behaves as an
|
||||
* psa_aead_set_lengths entry point as defined in the PSA driver interface
|
||||
* specification for transparent drivers.
|
||||
*
|
||||
* The application must call 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.
|
||||
*
|
||||
* You may call this function before or after setting the nonce with
|
||||
* mbedtls_psa_aead_set_nonce() or mbedtls_psa_aead_generate_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.
|
||||
* - For vendor-defined algorithm, refer to the vendor documentation.
|
||||
*
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling 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_BAD_STATE
|
||||
* The operation state is not valid (it must be active, and
|
||||
* mbedtls_psa_aead_update_ad() and mbedtls_psa_aead_update() must not have been
|
||||
* called yet).
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* At least one of the lengths is not acceptable for the chosen
|
||||
* algorithm.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_aead_set_lengths(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.
|
||||
*
|
||||
* You may call this function multiple times to pass successive fragments
|
||||
* of the additional data. You may not call this function after passing
|
||||
* data to encrypt or decrypt with mbedtls_psa_aead_update().
|
||||
*
|
||||
* Before calling this function, you must:
|
||||
* 1. Call either mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup().
|
||||
* 2. Set the nonce with mbedtls_psa_aead_generate_nonce() or
|
||||
* mbedtls_psa_aead_set_nonce().
|
||||
*
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \warning When decrypting, until mbedtls_psa_aead_verify() has returned #PSA_SUCCESS,
|
||||
* there is no guarantee that the input is valid. Therefore, until
|
||||
* you have called mbedtls_psa_aead_verify() and it has returned #PSA_SUCCESS,
|
||||
* treat the input as untrusted and prepare to undo any action that
|
||||
* depends on the input if mbedtls_psa_aead_verify() returns an error status.
|
||||
*
|
||||
* \note For the time being #PSA_ALG_CCM and #PSA_ALG_GCM require the entire
|
||||
* additional data to be passed in in one go, i.e. only call
|
||||
* mbedtls_mbedtls_psa_aead_update_ad() once.
|
||||
*
|
||||
* \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_BAD_STATE
|
||||
* The operation state is not valid (it must be active, have a nonce
|
||||
* set, have lengths set if required by the algorithm, and
|
||||
* mbedtls_psa_aead_update() must not have been called yet).
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total input length overflows the additional data length that
|
||||
* was previously specified with mbedtls_psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_aead_update_ad(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, you must:
|
||||
* 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_generate_nonce() or 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 operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \warning When decrypting, until mbedtls_psa_aead_verify() has returned
|
||||
* #PSA_SUCCESS, there is no guarantee that the input is valid.
|
||||
* Therefore, until you have called mbedtls_psa_aead_verify() and it
|
||||
* has returned #PSA_SUCCESS:
|
||||
* - Do not use the output in any way other than storing it in a
|
||||
* confidential location. If you take any action that depends
|
||||
* on the tentative decrypted data, this action will need to be
|
||||
* undone if the input turns out not to be valid. Furthermore,
|
||||
* if an adversary can observe that this action took place
|
||||
* (for example through timing), they may be able to use this
|
||||
* fact as an oracle to decrypt any message encrypted with the
|
||||
* same key.
|
||||
* - In particular, do not copy the output anywhere but to a
|
||||
* memory or storage space that you have exclusive access to.
|
||||
*
|
||||
* 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() or
|
||||
* mbedtls_psa_aead_verify() provides sufficient input. The amount of data that
|
||||
* can be delayed in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
|
||||
*
|
||||
* \note For the time being #PSA_ALG_CCM and #PSA_ALG_GCM require the entire
|
||||
* data to be passed in in one go, i.e. only call
|
||||
* mbedtls_mbedtls_psa_aead_update() once.
|
||||
*
|
||||
* \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 at least
|
||||
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg,
|
||||
* \p input_length) where \c alg is the
|
||||
* algorithm that is being calculated.
|
||||
* \param[out] output_length On success, the number of bytes
|
||||
* that make up the returned output.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The operation state is not valid (it must be active, have a nonce
|
||||
* set, and have lengths set if required by the algorithm).
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p output buffer is too small.
|
||||
* You can determine a sufficient buffer size by calling
|
||||
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length)
|
||||
* where \c alg is the algorithm that is being calculated.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total length of input to mbedtls_psa_aead_update_ad() so far is
|
||||
* less than the additional data length that was previously
|
||||
* specified with mbedtls_psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total input length overflows the plaintext length that
|
||||
* was previously specified with mbedtls_psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_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);
|
||||
|
||||
/** 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 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. Its length is always
|
||||
* #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm
|
||||
* that the operation performs.
|
||||
*
|
||||
* When this function returns successfuly, the operation becomes inactive.
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \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 at least
|
||||
* #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where
|
||||
* \c alg is the algorithm that is being
|
||||
* calculated.
|
||||
* \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 at least
|
||||
* #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is
|
||||
* the algorithm that is being calculated.
|
||||
* \param[out] tag_length On success, the number of bytes
|
||||
* that make up the returned tag.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The operation state is not valid (it must be an active encryption
|
||||
* operation with a nonce set).
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p ciphertext or \p tag buffer is too small.
|
||||
* You can determine a sufficient buffer size for \p ciphertext by
|
||||
* calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg)
|
||||
* where \c alg is the algorithm that is being calculated.
|
||||
* You can determine a sufficient buffer size for \p tag by
|
||||
* calling #PSA_AEAD_TAG_LENGTH(\c alg).
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total length of input to psa_aead_update_ad() so far is
|
||||
* less than the additional data length that was previously
|
||||
* specified with psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total length of input to mbedtls_psa_aead_update() so far is
|
||||
* less than the plaintext length that was previously
|
||||
* specified with mbedtls_psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_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);
|
||||
|
||||
/** Finish authenticating and decrypting a message in an AEAD operation.
|
||||
*
|
||||
* \note The signature of this function is that of a PSA driver
|
||||
* aead_verify entry point. This function behaves as an aead_verify entry
|
||||
* point as defined in the PSA driver interface specification for
|
||||
* transparent drivers.
|
||||
*
|
||||
* The operation must have been set up with mbedtls_psa_aead_decrypt_setup().
|
||||
*
|
||||
* This function finishes the authenticated decryption of the message
|
||||
* components:
|
||||
*
|
||||
* - The additional data consisting of the concatenation of the inputs
|
||||
* passed to preceding calls to mbedtls_psa_aead_update_ad().
|
||||
* - The ciphertext consisting of the concatenation of the inputs passed to
|
||||
* preceding calls to mbedtls_psa_aead_update().
|
||||
* - The tag passed to this function call.
|
||||
*
|
||||
* If the authentication tag is correct, this function outputs any remaining
|
||||
* plaintext and reports success. If the authentication tag is not correct,
|
||||
* this function returns #PSA_ERROR_INVALID_SIGNATURE.
|
||||
*
|
||||
* When this function returns successfuly, the operation becomes inactive.
|
||||
* If this function returns an error status, the operation enters an error
|
||||
* state and must be aborted by calling mbedtls_psa_aead_abort().
|
||||
*
|
||||
* \note Implementations shall make the best effort to ensure that the
|
||||
* comparison between the actual tag and the expected tag is performed
|
||||
* in constant time.
|
||||
*
|
||||
* \param[in,out] operation Active AEAD operation.
|
||||
* \param[out] plaintext Buffer where the last part of the plaintext
|
||||
* is to be written. This is the remaining data
|
||||
* from previous calls to mbedtls_psa_aead_update()
|
||||
* that could not be processed until the end
|
||||
* of the input.
|
||||
* \param plaintext_size Size of the \p plaintext buffer in bytes.
|
||||
* This must be at least
|
||||
* #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where
|
||||
* \c alg is the algorithm that is being
|
||||
* calculated.
|
||||
* \param[out] plaintext_length On success, the number of bytes of
|
||||
* returned plaintext.
|
||||
* \param[in] tag Buffer containing the authentication tag.
|
||||
* \param tag_length Size of the \p tag buffer in bytes.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* \retval #PSA_ERROR_INVALID_SIGNATURE
|
||||
* The calculations were successful, but the authentication tag is
|
||||
* not correct.
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The operation state is not valid (it must be an active decryption
|
||||
* operation with a nonce set).
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p plaintext buffer is too small.
|
||||
* You can determine a sufficient buffer size for \p plaintext by
|
||||
* calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg)
|
||||
* where \c alg is the algorithm that is being calculated.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total length of input to mbedtls_psa_aead_update_ad() so far is
|
||||
* less than the additional data length that was previously
|
||||
* specified with mbedtls_psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The total length of input to mbedtls_psa_aead_update() so far is
|
||||
* less than the plaintext length that was previously
|
||||
* specified with psa_aead_set_lengths().
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_STORAGE_FAILURE
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_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);
|
||||
|
||||
/** 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 calling
|
||||
* mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.
|
||||
*
|
||||
* You may call this function any time after the operation object has
|
||||
* been initialized as described in #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(), mbedtls_psa_aead_finish() or
|
||||
* mbedtls_psa_aead_verify() is safe and has no effect.
|
||||
*
|
||||
* \param[in,out] operation Initialized AEAD operation.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_CORRUPTION_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_aead_abort(psa_aead_operation_t *operation);
|
||||
|
||||
|
||||
#endif /* PSA_CRYPTO_AEAD */
|
||||
|
Loading…
Reference in New Issue
Block a user