Implement multipart AEAD PSA interface

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
This commit is contained in:
Paul Elliott 2021-04-20 18:10:30 +01:00
parent 6504aa6451
commit 302ff6bdd6
5 changed files with 257 additions and 165 deletions

View file

@ -3214,6 +3214,255 @@ psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
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 )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
return( PSA_ERROR_NOT_SUPPORTED );
status = psa_get_and_lock_key_slot_with_policy(
key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
if( status != PSA_SUCCESS )
{
return( status );
}
psa_key_attributes_t attributes = {
.core = slot->attr
};
status = psa_driver_wrapper_aead_encrypt_setup( operation,
&attributes, slot->key.data,
slot->key.bytes, alg );
unlock_status = psa_unlock_key_slot( slot );
if( unlock_status != PSA_SUCCESS )
{
return( unlock_status );
}
return( status );
}
/* 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 )
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
return( PSA_ERROR_NOT_SUPPORTED );
status = psa_get_and_lock_key_slot_with_policy(
key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
if( status != PSA_SUCCESS )
{
return( status );
}
psa_key_attributes_t attributes = {
.core = slot->attr
};
status = psa_driver_wrapper_aead_decrypt_setup( operation,
&attributes, slot->key.data,
slot->key.bytes, alg );
unlock_status = psa_unlock_key_slot( slot );
if( unlock_status != PSA_SUCCESS )
{
return( unlock_status );
}
return( status );
}
/* 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_size;
*nonce_length = 0;
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 = psa_driver_wrapper_aead_set_nonce( operation, nonce, required_nonce_size );
if( status == PSA_SUCCESS )
{
*nonce_length = required_nonce_size;
}
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 )
{
if( !operation->key_set || operation->nonce_set ||
operation->ad_started || operation->body_started )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_set_nonce( operation, nonce, nonce_length ) );
}
/* 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 )
{
if( !operation->key_set || operation->lengths_set )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_set_lengths( operation, ad_length, plaintext_length ) );
}
/* 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 )
{
if( !operation->nonce_set || !operation->key_set )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_update_ad( operation, input, input_length ) );
}
/* 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 )
{
*output_length = 0;
if( !operation->nonce_set || !operation->key_set || !operation->ad_started )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_update( operation, input, input_length, output, output_size,
output_length ) );
}
/* 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 )
{
*ciphertext_length = 0;
*tag_length = 0;
if( !operation->key_set || !operation->nonce_set ||
!operation->ad_started || !operation->body_started )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_finish( operation, ciphertext, ciphertext_size,
ciphertext_length, tag, tag_size, tag_length ) );
}
/* 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 )
{
*plaintext_length = 0;
if( !operation->key_set || !operation->nonce_set ||
!operation->ad_started || !operation->body_started )
{
return( PSA_ERROR_BAD_STATE );
}
return( psa_driver_wrapper_aead_verify( operation, plaintext, plaintext_size, plaintext_length,
tag, tag_length ) );
}
/* 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 );
operation->id = 0;
operation->key_set = 0;
operation->nonce_set = 0;
operation->lengths_set = 0;
operation->is_encrypt = 0;
operation->ad_started = 0;
operation->body_started = 0;
return( status );
}
/****************************************************************/
/* Generators */
/****************************************************************/

View file

@ -394,45 +394,6 @@ psa_status_t mbedtls_psa_aead_decrypt_setup( psa_aead_operation_t *operation,
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,
@ -440,19 +401,6 @@ psa_status_t mbedtls_psa_aead_set_nonce( psa_aead_operation_t *operation,
{
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 )
{
@ -514,11 +462,6 @@ psa_status_t mbedtls_psa_aead_set_lengths( psa_aead_operation_t *operation,
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 )
{
@ -570,11 +513,6 @@ psa_status_t mbedtls_psa_aead_update_ad( psa_aead_operation_t *operation,
{
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 )
@ -675,11 +613,6 @@ psa_status_t mbedtls_psa_aead_update( psa_aead_operation_t *operation,
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);
@ -791,12 +724,6 @@ static psa_status_t mbedtls_psa_aead_finish_checks( psa_aead_operation_t *operat
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 )

View file

@ -167,9 +167,9 @@ psa_status_t mbedtls_psa_aead_decrypt(
* 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
* -# Call either psa_aead_generate_nonce() or
* mbedtls_psa_aead_set_nonce() to generate or set the nonce. You should use
* 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.
@ -297,52 +297,6 @@ psa_status_t mbedtls_psa_aead_decrypt_setup(psa_aead_operation_t *operation,
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
@ -402,7 +356,7 @@ psa_status_t mbedtls_psa_aead_set_nonce(psa_aead_operation_t *operation,
* 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().
* mbedtls_psa_aead_set_nonce() or psa_aead_generate_nonce().
*
* - For #PSA_ALG_CCM, calling this function is required.
* - For the other AEAD algorithms defined in this specification, calling
@ -454,7 +408,7 @@ psa_status_t mbedtls_psa_aead_set_lengths(psa_aead_operation_t *operation,
*
* 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
* 2. Set the nonce with psa_aead_generate_nonce() or
* mbedtls_psa_aead_set_nonce().
*
* If this function returns an error status, the operation enters an error
@ -509,8 +463,9 @@ psa_status_t mbedtls_psa_aead_update_ad(psa_aead_operation_t *operation,
* 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.
* 2. Set the nonce with 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().

View file

@ -1394,39 +1394,6 @@ psa_status_t psa_driver_wrapper_aead_decrypt_setup(
}
}
psa_status_t psa_driver_wrapper_aead_generate_nonce(
psa_aead_operation_t *operation,
uint8_t *nonce,
size_t nonce_size,
size_t *nonce_length )
{
switch( operation->id )
{
#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
return( mbedtls_psa_aead_generate_nonce( operation, nonce, nonce_size,
nonce_length ) );
#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
// return( test_transparent_aead_generate_nonce(
// operation, nonce, nonce_size, nonce_length ) );
/* Add cases for opaque driver here */
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
}
(void)nonce;
(void)nonce_size;
(void)nonce_length;
return( PSA_ERROR_INVALID_ARGUMENT );
}
psa_status_t psa_driver_wrapper_aead_set_nonce(
psa_aead_operation_t *operation,
const uint8_t *nonce,

View file

@ -195,12 +195,6 @@ psa_status_t psa_driver_wrapper_aead_decrypt_setup(
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg );
psa_status_t psa_driver_wrapper_aead_generate_nonce(
psa_aead_operation_t *operation,
uint8_t *nonce,
size_t nonce_size,
size_t *nonce_length );
psa_status_t psa_driver_wrapper_aead_set_nonce(
psa_aead_operation_t *operation,
const uint8_t *nonce,