Merge remote-tracking branch 'psa/psa-wrapper-apis-march-12' into feature-psa

This commit is contained in:
Gilles Peskine 2018-06-08 18:40:39 +02:00 committed by itayzafrir
commit 3aa8efb230
5 changed files with 885 additions and 13 deletions

View file

@ -301,8 +301,6 @@ static psa_status_t mbedtls_to_psa_error( int ret )
}
}
/****************************************************************/
/* Key management */
/****************************************************************/
@ -920,7 +918,9 @@ static const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
{
if( PSA_ALG_IS_BLOCK_CIPHER( alg ) )
alg &= ~PSA_ALG_BLOCK_CIPHER_MODE_MASK;
{
alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
}
switch( alg )
{
case PSA_ALG_STREAM_CIPHER:
@ -996,11 +996,13 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
#endif /* MBEDTLS_MD_C */
return( PSA_ERROR_NOT_SUPPORTED );
}
operation->alg = 0;
operation->key_set = 0;
operation->iv_set = 0;
operation->iv_required = 0;
operation->has_input = 0;
return( PSA_SUCCESS );
}
@ -1378,6 +1380,269 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key,
}
/****************************************************************/
/* Symmetric cryptography */
/****************************************************************/
static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg,
mbedtls_operation_t cipher_operation )
{
int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
psa_status_t status;
key_slot_t *slot;
psa_key_type_t key_type;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info = NULL;
operation->alg = alg;
operation->key_set = 0;
operation->iv_set = 0;
operation->iv_required = 1;
operation->iv_size = 0;
operation->block_size = 0;
status = psa_get_key_information( key, &key_type, &key_bits );
if( status != PSA_SUCCESS )
return( status );
slot = &global_data.key_slots[key];
cipher_info = mbedtls_cipher_info_from_psa( alg, key_type, key_bits );
if( cipher_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
mbedtls_cipher_init( &operation->ctx.cipher );
ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
ret = mbedtls_cipher_setkey( &operation->ctx.cipher, slot->data.raw.data,
key_bits, cipher_operation );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
if( ( alg & ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK ) == PSA_ALG_CBC_BASE )
{
psa_algorithm_t padding_mode = alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
mbedtls_cipher_padding_t mode;
switch ( padding_mode )
{
case PSA_ALG_BLOCK_CIPHER_PAD_PKCS7:
mode = MBEDTLS_PADDING_PKCS7;
break;
case PSA_ALG_BLOCK_CIPHER_PAD_NONE:
mode = MBEDTLS_PADDING_NONE;
break;
default:
psa_cipher_abort( operation );
return( PSA_ERROR_INVALID_ARGUMENT );
}
ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, mode );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
}
#endif //MBEDTLS_CIPHER_MODE_WITH_PADDING
operation->key_set = 1;
operation->alg = alg;
operation->block_size = ( PSA_ALG_IS_BLOCK_CIPHER( alg ) ?
PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) :
1 );
if( PSA_ALG_IS_BLOCK_CIPHER( alg ) || ( alg == PSA_ALG_CTR ) )
{
operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
}
return( PSA_SUCCESS );
}
psa_status_t psa_encrypt_setup( psa_cipher_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg )
{
return psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT );
}
psa_status_t psa_decrypt_setup( psa_cipher_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg )
{
return psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT );
}
psa_status_t psa_encrypt_generate_iv( psa_cipher_operation_t *operation,
unsigned char *iv,
size_t iv_size,
size_t *iv_length )
{
int ret = PSA_SUCCESS;
if( operation->iv_set || !( operation->iv_required ) )
return( PSA_ERROR_BAD_STATE );
if( iv_size < operation->iv_size )
{
ret = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
iv, operation->iv_size );
if( ret != 0 )
{
ret = mbedtls_to_psa_error( ret );
goto exit;
}
*iv_length = operation->iv_size;
ret = psa_encrypt_set_iv( operation, iv, *iv_length );
exit:
if( ret != PSA_SUCCESS )
psa_cipher_abort( operation );
return( ret );
}
psa_status_t psa_encrypt_set_iv( psa_cipher_operation_t *operation,
const unsigned char *iv,
size_t iv_length )
{
int ret = PSA_SUCCESS;
if( operation->iv_set || !( operation->iv_required ) )
return( PSA_ERROR_BAD_STATE );
if( iv_length != operation->iv_size )
{
psa_cipher_abort( operation );
return( PSA_ERROR_INVALID_ARGUMENT );
}
ret = mbedtls_cipher_set_iv( &operation->ctx.cipher, iv, iv_length );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
operation->iv_set = 1;
return( PSA_SUCCESS );
}
psa_status_t psa_cipher_update( psa_cipher_operation_t *operation,
const uint8_t *input,
size_t input_length,
unsigned char *output,
size_t output_size,
size_t *output_length )
{
int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
size_t expected_output_size;
if( PSA_ALG_IS_BLOCK_CIPHER( operation->alg ) )
{
/* Take the unprocessed partial block left over from previous
* update calls, if any, plus the input to this call. Remove
* the last partial block, if any. You get the data that will be
* output in this call. */
expected_output_size =
( operation->ctx.cipher.unprocessed_len + input_length )
/ operation->block_size * operation->block_size;
}
else
{
expected_output_size = input_length;
}
if( output_size < expected_output_size )
return( PSA_ERROR_BUFFER_TOO_SMALL );
ret = mbedtls_cipher_update( &operation->ctx.cipher, input,
input_length, output, output_length );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
return( PSA_SUCCESS );
}
psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length )
{
int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
if( ! operation->key_set )
{
psa_cipher_abort( operation );
return( PSA_ERROR_BAD_STATE );
}
if( operation->iv_required && ! operation->iv_set )
{
psa_cipher_abort( operation );
return( PSA_ERROR_BAD_STATE );
}
if( operation->ctx.cipher.operation == MBEDTLS_ENCRYPT &&
PSA_ALG_IS_BLOCK_CIPHER( operation->alg ) )
{
psa_algorithm_t padding_mode =
operation->alg & PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
if( operation->ctx.cipher.unprocessed_len >= operation->block_size )
{
psa_cipher_abort( operation );
return( PSA_ERROR_TAMPERING_DETECTED );
}
if( padding_mode == PSA_ALG_BLOCK_CIPHER_PAD_NONE )
{
if( operation->ctx.cipher.unprocessed_len != 0 )
{
psa_cipher_abort( operation );
return( PSA_ERROR_INVALID_ARGUMENT );
}
}
}
ret = mbedtls_cipher_finish( &operation->ctx.cipher, temp_output_buffer,
output_length );
if( ret != 0 )
{
psa_cipher_abort( operation );
return( mbedtls_to_psa_error( ret ) );
}
if( output_size >= *output_length )
memcpy( output, temp_output_buffer, *output_length );
else
{
psa_cipher_abort( operation );
return( PSA_ERROR_BUFFER_TOO_SMALL );
}
return( PSA_SUCCESS );
}
psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation )
{
mbedtls_cipher_free( &operation->ctx.cipher );
operation->alg = 0;
operation->key_set = 0;
operation->iv_set = 0;
operation->iv_size = 0;
operation->block_size = 0;
operation->iv_required = 0;
return( PSA_SUCCESS );
}
/****************************************************************/
/* Key Policy */