diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 491d952d0..52f4973c0 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -136,6 +136,14 @@ static inline struct psa_mac_operation_s psa_mac_operation_init( void ) return( v ); } +typedef struct { + /** Context structure for the Mbed TLS cipher implementation. */ + psa_algorithm_t alg; + uint8_t iv_size; + uint8_t block_size; + mbedtls_cipher_context_t cipher; +} mbedtls_psa_cipher_operation_t; + struct psa_cipher_operation_s { /** Unique ID indicating which driver got assigned to do the @@ -146,20 +154,17 @@ struct psa_cipher_operation_s * any driver (i.e. none of the driver contexts are active). */ unsigned int id; - psa_algorithm_t alg; unsigned int iv_required : 1; unsigned int iv_set : 1; - uint8_t iv_size; - uint8_t block_size; union { unsigned dummy; /* Enable easier initializing of the union. */ - mbedtls_cipher_context_t cipher; + mbedtls_psa_cipher_operation_t mbedtls_ctx; psa_operation_driver_context_t driver; } ctx; }; -#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}} static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) { const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index f4d8a3e43..38b18fd24 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3409,10 +3409,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, * is used to indicate to psa_cipher_abort that there are resources to free, * so we only set it (in the driver wrapper) after resources have been * allocated/initialized. */ - operation->alg = alg; operation->iv_set = 0; - operation->iv_size = 0; - operation->block_size = 0; if( alg == PSA_ALG_ECB_NO_PADDING ) operation->iv_required = 0; else @@ -3587,18 +3584,10 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) return( PSA_SUCCESS ); } - /* Sanity check (shouldn't happen: operation->alg should - * always have been initialized to a valid value). */ - if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) - return( PSA_ERROR_BAD_STATE ); - psa_driver_wrapper_cipher_abort( operation ); operation->id = 0; - operation->alg = 0; operation->iv_set = 0; - operation->iv_size = 0; - operation->block_size = 0; operation->iv_required = 0; return( PSA_SUCCESS ); diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c index 340f674cf..a2b29423c 100644 --- a/library/psa_crypto_cipher.c +++ b/library/psa_crypto_cipher.c @@ -42,21 +42,22 @@ static psa_status_t cipher_setup( size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; psa_key_type_t key_type = attributes->core.type; + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; (void)key_buffer_size; /* Proceed with initializing an mbed TLS cipher context if no driver is * available for the given algorithm & key. */ - mbedtls_cipher_init( &operation->ctx.cipher ); + mbedtls_cipher_init( &mbedtls_ctx->cipher ); - operation->alg = alg; + mbedtls_ctx->alg = alg; key_bits = attributes->core.bits; cipher_info = mbedtls_cipher_info_from_psa( alg, key_type, key_bits, NULL ); if( cipher_info == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); - ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info ); + ret = mbedtls_cipher_setup( &mbedtls_ctx->cipher, cipher_info ); if( ret != 0 ) goto exit; @@ -67,14 +68,14 @@ static psa_status_t cipher_setup( uint8_t keys[24]; memcpy( keys, key_buffer, 16 ); memcpy( keys + 16, key_buffer, 8 ); - ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + ret = mbedtls_cipher_setkey( &mbedtls_ctx->cipher, keys, 192, cipher_operation ); } else #endif { - ret = mbedtls_cipher_setkey( &operation->ctx.cipher, key_buffer, + ret = mbedtls_cipher_setkey( &mbedtls_ctx->cipher, key_buffer, (int) key_bits, cipher_operation ); } if( ret != 0 ) @@ -85,11 +86,11 @@ static psa_status_t cipher_setup( switch( alg ) { case PSA_ALG_CBC_NO_PADDING: - ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + ret = mbedtls_cipher_set_padding_mode( &mbedtls_ctx->cipher, MBEDTLS_PADDING_NONE ); break; case PSA_ALG_CBC_PKCS7: - ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + ret = mbedtls_cipher_set_padding_mode( &mbedtls_ctx->cipher, MBEDTLS_PADDING_PKCS7 ); break; default: @@ -101,18 +102,18 @@ static psa_status_t cipher_setup( goto exit; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */ - operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : + mbedtls_ctx->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) ); if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 && alg != PSA_ALG_ECB_NO_PADDING ) { - operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ); + mbedtls_ctx->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ); } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) else if( ( alg == PSA_ALG_STREAM_CIPHER ) && ( key_type == PSA_KEY_TYPE_CHACHA20 ) ) - operation->iv_size = 12; + mbedtls_ctx->iv_size = 12; #endif exit: @@ -146,16 +147,17 @@ psa_status_t mbedtls_psa_cipher_generate_iv( uint8_t *iv, size_t iv_size, size_t *iv_length ) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; - if( iv_size < operation->iv_size ) + if( iv_size < mbedtls_ctx->iv_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, - iv, operation->iv_size ); + iv, mbedtls_ctx->iv_size ); if( ret != 0 ) return( mbedtls_to_psa_error( ret ) ); - *iv_length = operation->iv_size; + *iv_length = mbedtls_ctx->iv_size; return( mbedtls_psa_cipher_set_iv( operation, iv, *iv_length ) ); } @@ -164,11 +166,13 @@ psa_status_t mbedtls_psa_cipher_set_iv( psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length ) { - if( iv_length != operation->iv_size ) + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; + + if( iv_length != mbedtls_ctx->iv_size ) return( PSA_ERROR_INVALID_ARGUMENT ); return( mbedtls_to_psa_error( - mbedtls_cipher_set_iv( &operation->ctx.cipher, + mbedtls_cipher_set_iv( &mbedtls_ctx->cipher, iv, iv_length ) ) ); } @@ -268,17 +272,18 @@ psa_status_t mbedtls_psa_cipher_update( psa_cipher_operation_t *operation, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; size_t expected_output_size; - if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) + if( ! PSA_ALG_IS_STREAM_CIPHER( mbedtls_ctx->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; + ( mbedtls_ctx->cipher.unprocessed_len + input_length ) + / mbedtls_ctx->block_size * mbedtls_ctx->block_size; } else { @@ -288,12 +293,12 @@ psa_status_t mbedtls_psa_cipher_update( psa_cipher_operation_t *operation, if( output_size < expected_output_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); - if( operation->alg == PSA_ALG_ECB_NO_PADDING ) + if( mbedtls_ctx->alg == PSA_ALG_ECB_NO_PADDING ) { /* mbedtls_cipher_update has an API inconsistency: it will only * process a single block at a time in ECB mode. Abstract away that * inconsistency here to match the PSA API behaviour. */ - status = psa_cipher_update_ecb( &operation->ctx.cipher, + status = psa_cipher_update_ecb( &mbedtls_ctx->cipher, input, input_length, output, @@ -303,7 +308,7 @@ psa_status_t mbedtls_psa_cipher_update( psa_cipher_operation_t *operation, else { status = mbedtls_to_psa_error( - mbedtls_cipher_update( &operation->ctx.cipher, input, + mbedtls_cipher_update( &mbedtls_ctx->cipher, input, input_length, output, output_length ) ); } @@ -316,12 +321,13 @@ psa_status_t mbedtls_psa_cipher_finish( psa_cipher_operation_t *operation, size_t *output_length ) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; - if( operation->ctx.cipher.unprocessed_len != 0 ) + if( mbedtls_ctx->cipher.unprocessed_len != 0 ) { - if( operation->alg == PSA_ALG_ECB_NO_PADDING || - operation->alg == PSA_ALG_CBC_NO_PADDING ) + if( mbedtls_ctx->alg == PSA_ALG_ECB_NO_PADDING || + mbedtls_ctx->alg == PSA_ALG_CBC_NO_PADDING ) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; @@ -329,7 +335,7 @@ psa_status_t mbedtls_psa_cipher_finish( psa_cipher_operation_t *operation, } status = mbedtls_to_psa_error( - mbedtls_cipher_finish( &operation->ctx.cipher, + mbedtls_cipher_finish( &mbedtls_ctx->cipher, temp_output_buffer, output_length ) ); if( status != PSA_SUCCESS ) @@ -351,7 +357,14 @@ exit: psa_status_t mbedtls_psa_cipher_abort( psa_cipher_operation_t *operation ) { - mbedtls_cipher_free( &operation->ctx.cipher ); + mbedtls_psa_cipher_operation_t *mbedtls_ctx = &operation->ctx.mbedtls_ctx; + + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + if( ! PSA_ALG_IS_CIPHER( mbedtls_ctx->alg ) ) + return( PSA_ERROR_BAD_STATE ); + + mbedtls_cipher_free( &mbedtls_ctx->cipher ); return( PSA_SUCCESS ); }